From 7245e629dcaaf308f1868aeffa218e9849c77893 Mon Sep 17 00:00:00 2001 From: Alexandr Sapozhnikov Date: Wed, 15 Feb 2023 20:15:49 +0300 Subject: [PATCH 001/778] drm/cirrus: NULL-check pipe->plane.state->fb in cirrus_pipe_update() After having been compared to NULL value at cirrus.c:455, pointer 'pipe->plane.state->fb' is passed as 1st parameter in call to function 'cirrus_fb_blit_rect' at cirrus.c:461, where it is dereferenced at cirrus.c:316. Found by Linux Verification Center (linuxtesting.org) with SVACE. v2: * aligned commit message to line-length limits Signed-off-by: Alexandr Sapozhnikov Reviewed-by: Thomas Zimmermann Signed-off-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/20230215171549.16305-1-alsp705@gmail.com --- drivers/gpu/drm/tiny/cirrus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/tiny/cirrus.c b/drivers/gpu/drm/tiny/cirrus.c index 678c2ef1cae7..ffa7e61dd183 100644 --- a/drivers/gpu/drm/tiny/cirrus.c +++ b/drivers/gpu/drm/tiny/cirrus.c @@ -455,7 +455,7 @@ static void cirrus_pipe_update(struct drm_simple_display_pipe *pipe, if (state->fb && cirrus->cpp != cirrus_cpp(state->fb)) cirrus_mode_set(cirrus, &crtc->mode, state->fb); - if (drm_atomic_helper_damage_merged(old_state, state, &rect)) + if (state->fb && drm_atomic_helper_damage_merged(old_state, state, &rect)) cirrus_fb_blit_rect(state->fb, &shadow_plane_state->data[0], &rect); } From 3638a820c5c3b52f327cebb174fd4274bee08aa7 Mon Sep 17 00:00:00 2001 From: "Jiri Slaby (SUSE)" Date: Mon, 31 Oct 2022 12:42:29 +0100 Subject: [PATCH 002/778] drm/nouveau/kms/nv50: fix nv50_wndw_new_ prototype gcc-13 warns about mismatching types for enums. That revealed switched arguments of nv50_wndw_new_(): drivers/gpu/drm/nouveau/dispnv50/wndw.c:696:1: error: conflicting types for 'nv50_wndw_new_' due to enum/integer mismatch; have 'int(const struct nv50_wndw_func *, struct drm_device *, enum drm_plane_type, const char *, int, const u32 *, u32, enum nv50_disp_interlock_type, u32, struct nv50_wndw **)' drivers/gpu/drm/nouveau/dispnv50/wndw.h:36:5: note: previous declaration of 'nv50_wndw_new_' with type 'int(const struct nv50_wndw_func *, struct drm_device *, enum drm_plane_type, const char *, int, const u32 *, enum nv50_disp_interlock_type, u32, u32, struct nv50_wndw **)' It can be barely visible, but the declaration says about the parameters in the middle: enum nv50_disp_interlock_type, u32 interlock_data, u32 heads, While the definition states differently: u32 heads, enum nv50_disp_interlock_type interlock_type, u32 interlock_data, Unify/fix the declaration to match the definition. Fixes: 53e0a3e70de6 ("drm/nouveau/kms/nv50-: simplify tracking of channel interlocks") Cc: Martin Liska Cc: Ben Skeggs Cc: Karol Herbst Cc: Lyude Paul Cc: David Airlie Cc: Daniel Vetter Cc: dri-devel@lists.freedesktop.org Cc: nouveau@lists.freedesktop.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Jiri Slaby (SUSE) Signed-off-by: Karol Herbst Link: https://patchwork.freedesktop.org/patch/msgid/20221031114229.10289-1-jirislaby@kernel.org --- drivers/gpu/drm/nouveau/dispnv50/wndw.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndw.h b/drivers/gpu/drm/nouveau/dispnv50/wndw.h index 591c852f326b..76a6ae5d5652 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/wndw.h +++ b/drivers/gpu/drm/nouveau/dispnv50/wndw.h @@ -35,8 +35,9 @@ struct nv50_wndw { int nv50_wndw_new_(const struct nv50_wndw_func *, struct drm_device *, enum drm_plane_type, const char *name, int index, - const u32 *format, enum nv50_disp_interlock_type, - u32 interlock_data, u32 heads, struct nv50_wndw **); + const u32 *format, u32 heads, + enum nv50_disp_interlock_type, u32 interlock_data, + struct nv50_wndw **); void nv50_wndw_flush_set(struct nv50_wndw *, u32 *interlock, struct nv50_wndw_atom *); void nv50_wndw_flush_clr(struct nv50_wndw *, u32 *interlock, bool flush, From 1b9b4f922f96108da3bb5d87b2d603f5dfbc5650 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 20 Feb 2023 14:39:21 +1000 Subject: [PATCH 003/778] drm/nouveau/fb/gp102-: cache scrubber binary on first load During system shutdown nouveau might not be able to request firmware from Userspace, which then leads to a regression preventing the system from shutting down. Cache the scrubber binary for this case. Fixes: 0e44c21708761 ("drm/nouveau/flcn: new code to load+boot simple HS FWs (VPR scrubber)") Signed-off-by: Ben Skeggs Signed-off-by: Karol Herbst Link: https://patchwork.freedesktop.org/patch/msgid/CACAvsv7Uf5=K44y8YLsiy0aMnc1zvGEQdeDe7RQF=AV+fxxzuQ@mail.gmail.com --- .../gpu/drm/nouveau/include/nvkm/subdev/fb.h | 3 +- drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c | 8 +++- .../gpu/drm/nouveau/nvkm/subdev/fb/ga100.c | 2 +- .../gpu/drm/nouveau/nvkm/subdev/fb/ga102.c | 21 ++++------ .../gpu/drm/nouveau/nvkm/subdev/fb/gp102.c | 41 +++++++------------ .../gpu/drm/nouveau/nvkm/subdev/fb/gv100.c | 4 +- drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h | 3 +- .../gpu/drm/nouveau/nvkm/subdev/fb/tu102.c | 4 +- 8 files changed, 36 insertions(+), 50 deletions(-) diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h index c5a4f49ee206..01a22a13b452 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h @@ -2,6 +2,7 @@ #ifndef __NVKM_FB_H__ #define __NVKM_FB_H__ #include +#include #include /* memory type/access flags, do not match hardware values */ @@ -33,7 +34,7 @@ struct nvkm_fb { const struct nvkm_fb_func *func; struct nvkm_subdev subdev; - struct nvkm_blob vpr_scrubber; + struct nvkm_falcon_fw vpr_scrubber; struct { struct page *flush_page; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c index bac7dcc4c2c1..0955340cc421 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c @@ -143,6 +143,10 @@ nvkm_fb_mem_unlock(struct nvkm_fb *fb) if (!fb->func->vpr.scrub_required) return 0; + ret = nvkm_subdev_oneinit(subdev); + if (ret) + return ret; + if (!fb->func->vpr.scrub_required(fb)) { nvkm_debug(subdev, "VPR not locked\n"); return 0; @@ -150,7 +154,7 @@ nvkm_fb_mem_unlock(struct nvkm_fb *fb) nvkm_debug(subdev, "VPR locked, running scrubber binary\n"); - if (!fb->vpr_scrubber.size) { + if (!fb->vpr_scrubber.fw.img) { nvkm_warn(subdev, "VPR locked, but no scrubber binary!\n"); return 0; } @@ -229,7 +233,7 @@ nvkm_fb_dtor(struct nvkm_subdev *subdev) nvkm_ram_del(&fb->ram); - nvkm_blob_dtor(&fb->vpr_scrubber); + nvkm_falcon_fw_dtor(&fb->vpr_scrubber); if (fb->sysmem.flush_page) { dma_unmap_page(subdev->device->dev, fb->sysmem.flush_page_addr, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga100.c index 5098f219e3e6..a7456e786463 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga100.c @@ -37,5 +37,5 @@ ga100_fb = { int ga100_fb_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fb **pfb) { - return gp102_fb_new_(&ga100_fb, device, type, inst, pfb); + return gf100_fb_new_(&ga100_fb, device, type, inst, pfb); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga102.c index 5a21b0ae4595..dd476e079fe1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga102.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga102.c @@ -25,25 +25,20 @@ #include static int -ga102_fb_vpr_scrub(struct nvkm_fb *fb) +ga102_fb_oneinit(struct nvkm_fb *fb) { - struct nvkm_falcon_fw fw = {}; - int ret; + struct nvkm_subdev *subdev = &fb->subdev; - ret = nvkm_falcon_fw_ctor_hs_v2(&ga102_flcn_fw, "mem-unlock", &fb->subdev, "nvdec/scrubber", - 0, &fb->subdev.device->nvdec[0]->falcon, &fw); - if (ret) - return ret; + nvkm_falcon_fw_ctor_hs_v2(&ga102_flcn_fw, "mem-unlock", subdev, "nvdec/scrubber", + 0, &subdev->device->nvdec[0]->falcon, &fb->vpr_scrubber); - ret = nvkm_falcon_fw_boot(&fw, &fb->subdev, true, NULL, NULL, 0, 0); - nvkm_falcon_fw_dtor(&fw); - return ret; + return gf100_fb_oneinit(fb); } static const struct nvkm_fb_func ga102_fb = { .dtor = gf100_fb_dtor, - .oneinit = gf100_fb_oneinit, + .oneinit = ga102_fb_oneinit, .init = gm200_fb_init, .init_page = gv100_fb_init_page, .init_unkn = gp100_fb_init_unkn, @@ -51,13 +46,13 @@ ga102_fb = { .ram_new = ga102_ram_new, .default_bigpage = 16, .vpr.scrub_required = tu102_fb_vpr_scrub_required, - .vpr.scrub = ga102_fb_vpr_scrub, + .vpr.scrub = gp102_fb_vpr_scrub, }; int ga102_fb_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fb **pfb) { - return gp102_fb_new_(&ga102_fb, device, type, inst, pfb); + return gf100_fb_new_(&ga102_fb, device, type, inst, pfb); } MODULE_FIRMWARE("nvidia/ga102/nvdec/scrubber.bin"); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c index 2658481d575b..14d942e8b857 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c @@ -29,18 +29,7 @@ int gp102_fb_vpr_scrub(struct nvkm_fb *fb) { - struct nvkm_subdev *subdev = &fb->subdev; - struct nvkm_falcon_fw fw = {}; - int ret; - - ret = nvkm_falcon_fw_ctor_hs(&gm200_flcn_fw, "mem-unlock", subdev, NULL, - "nvdec/scrubber", 0, &subdev->device->nvdec[0]->falcon, &fw); - if (ret) - return ret; - - ret = nvkm_falcon_fw_boot(&fw, subdev, true, NULL, NULL, 0, 0x00000000); - nvkm_falcon_fw_dtor(&fw); - return ret; + return nvkm_falcon_fw_boot(&fb->vpr_scrubber, &fb->subdev, true, NULL, NULL, 0, 0x00000000); } bool @@ -51,10 +40,21 @@ gp102_fb_vpr_scrub_required(struct nvkm_fb *fb) return (nvkm_rd32(device, 0x100cd0) & 0x00000010) != 0; } +int +gp102_fb_oneinit(struct nvkm_fb *fb) +{ + struct nvkm_subdev *subdev = &fb->subdev; + + nvkm_falcon_fw_ctor_hs(&gm200_flcn_fw, "mem-unlock", subdev, NULL, "nvdec/scrubber", + 0, &subdev->device->nvdec[0]->falcon, &fb->vpr_scrubber); + + return gf100_fb_oneinit(fb); +} + static const struct nvkm_fb_func gp102_fb = { .dtor = gf100_fb_dtor, - .oneinit = gf100_fb_oneinit, + .oneinit = gp102_fb_oneinit, .init = gm200_fb_init, .init_remapper = gp100_fb_init_remapper, .init_page = gm200_fb_init_page, @@ -64,23 +64,10 @@ gp102_fb = { .ram_new = gp100_ram_new, }; -int -gp102_fb_new_(const struct nvkm_fb_func *func, struct nvkm_device *device, - enum nvkm_subdev_type type, int inst, struct nvkm_fb **pfb) -{ - int ret = gf100_fb_new_(func, device, type, inst, pfb); - if (ret) - return ret; - - nvkm_firmware_load_blob(&(*pfb)->subdev, "nvdec/scrubber", "", 0, - &(*pfb)->vpr_scrubber); - return 0; -} - int gp102_fb_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fb **pfb) { - return gp102_fb_new_(&gp102_fb, device, type, inst, pfb); + return gf100_fb_new_(&gp102_fb, device, type, inst, pfb); } MODULE_FIRMWARE("nvidia/gp102/nvdec/scrubber.bin"); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gv100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gv100.c index 0e3c0a8f5d71..4d8a286a7a34 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gv100.c @@ -31,7 +31,7 @@ gv100_fb_init_page(struct nvkm_fb *fb) static const struct nvkm_fb_func gv100_fb = { .dtor = gf100_fb_dtor, - .oneinit = gf100_fb_oneinit, + .oneinit = gp102_fb_oneinit, .init = gm200_fb_init, .init_page = gv100_fb_init_page, .init_unkn = gp100_fb_init_unkn, @@ -45,7 +45,7 @@ gv100_fb = { int gv100_fb_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fb **pfb) { - return gp102_fb_new_(&gv100_fb, device, type, inst, pfb); + return gf100_fb_new_(&gv100_fb, device, type, inst, pfb); } MODULE_FIRMWARE("nvidia/gv100/nvdec/scrubber.bin"); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h index f517751f94ac..726c30c8bf95 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h @@ -83,8 +83,7 @@ int gm200_fb_init_page(struct nvkm_fb *); void gp100_fb_init_remapper(struct nvkm_fb *); void gp100_fb_init_unkn(struct nvkm_fb *); -int gp102_fb_new_(const struct nvkm_fb_func *, struct nvkm_device *, enum nvkm_subdev_type, int, - struct nvkm_fb **); +int gp102_fb_oneinit(struct nvkm_fb *); bool gp102_fb_vpr_scrub_required(struct nvkm_fb *); int gp102_fb_vpr_scrub(struct nvkm_fb *); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/tu102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/tu102.c index be82af0364ee..b8803c124c3b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/tu102.c @@ -31,7 +31,7 @@ tu102_fb_vpr_scrub_required(struct nvkm_fb *fb) static const struct nvkm_fb_func tu102_fb = { .dtor = gf100_fb_dtor, - .oneinit = gf100_fb_oneinit, + .oneinit = gp102_fb_oneinit, .init = gm200_fb_init, .init_page = gv100_fb_init_page, .init_unkn = gp100_fb_init_unkn, @@ -45,7 +45,7 @@ tu102_fb = { int tu102_fb_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fb **pfb) { - return gp102_fb_new_(&tu102_fb, device, type, inst, pfb); + return gf100_fb_new_(&tu102_fb, device, type, inst, pfb); } MODULE_FIRMWARE("nvidia/tu102/nvdec/scrubber.bin"); From b48279af636de613e9dd03857d9cadd4beca8e7e Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Sat, 18 Feb 2023 08:27:24 -0800 Subject: [PATCH 004/778] perf test: Fix offcpu test prev_state check On Fedora 36, the 'perf record' offcpu profiling tests are failing. It was because the BPF checks the prev task's state being S or D but actually it has more bits set. Let's check the LSB 8 bits for the purpose of offcpu profiling. Reported-by: Arnaldo Carvalho de Melo Signed-off-by: Namhyung Kim Acked-by: Ian Rogers Tested-by: Arnaldo Carvalho de Melo Cc: Adrian Hunter Cc: Ingo Molnar Cc: Jiri Olsa Cc: Peter Zijlstra Link: https://lore.kernel.org/r/20230218162724.1292657-1-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/bpf_skel/off_cpu.bpf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/bpf_skel/off_cpu.bpf.c b/tools/perf/util/bpf_skel/off_cpu.bpf.c index 38e3b287dbb2..d877a0a9731f 100644 --- a/tools/perf/util/bpf_skel/off_cpu.bpf.c +++ b/tools/perf/util/bpf_skel/off_cpu.bpf.c @@ -277,7 +277,7 @@ int on_switch(u64 *ctx) else prev_state = get_task_state(prev); - return off_cpu_stat(ctx, prev, next, prev_state); + return off_cpu_stat(ctx, prev, next, prev_state & 0xff); } char LICENSE[] SEC("license") = "Dual BSD/GPL"; From 8a86f213f4426f19511a16d886871805b35c3acf Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Wed, 15 Feb 2023 15:50:48 -0800 Subject: [PATCH 005/778] drm/msm: Fix potential invalid ptr free The error path cleanup expects that chain and syncobj are either NULL or valid pointers. But post_deps was not allocated with __GFP_ZERO. Fixes: ab723b7a992a ("drm/msm: Add syncobj support.") Signed-off-by: Rob Clark Reviewed-by: Dmitry Baryshkov Reviewed-by: Dmitry Osipenko Patchwork: https://patchwork.freedesktop.org/patch/523051/ Link: https://lore.kernel.org/r/20230215235048.1166484-1-robdclark@gmail.com --- drivers/gpu/drm/msm/msm_gem_submit.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c index be4bf77103cd..ac8ed731f76d 100644 --- a/drivers/gpu/drm/msm/msm_gem_submit.c +++ b/drivers/gpu/drm/msm/msm_gem_submit.c @@ -637,8 +637,8 @@ static struct msm_submit_post_dep *msm_parse_post_deps(struct drm_device *dev, int ret = 0; uint32_t i, j; - post_deps = kmalloc_array(nr_syncobjs, sizeof(*post_deps), - GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY); + post_deps = kcalloc(nr_syncobjs, sizeof(*post_deps), + GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY); if (!post_deps) return ERR_PTR(-ENOMEM); @@ -653,7 +653,6 @@ static struct msm_submit_post_dep *msm_parse_post_deps(struct drm_device *dev, } post_deps[i].point = syncobj_desc.point; - post_deps[i].chain = NULL; if (syncobj_desc.flags) { ret = -EINVAL; From 796762f0506077c4f048b4eb05de2f587f488bce Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Wed, 22 Feb 2023 13:37:12 +0100 Subject: [PATCH 006/778] drm/msm: Fix possible uninitialized access in fbdev Do not run drm_fb_helper_unprepare() if fbdev allocation fails. Avoids access to an uninitialized pointer. Original bug report is at [1]. Reported-by: kernel test robot Signed-off-by: Thomas Zimmermann Fixes: 3fb1f62f80a1 ("drm/fb-helper: Remove drm_fb_helper_unprepare() from drm_fb_helper_fini()") Link: https://lore.kernel.org/oe-kbuild-all/202302220810.9dymwCQ8-lkp@intel.com/ # 1 Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/523715/ Link: https://lore.kernel.org/r/20230222123712.5049-1-tzimmermann@suse.de Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/msm_fbdev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_fbdev.c b/drivers/gpu/drm/msm/msm_fbdev.c index 31e1e30cb52a..dd7d0b965f85 100644 --- a/drivers/gpu/drm/msm/msm_fbdev.c +++ b/drivers/gpu/drm/msm/msm_fbdev.c @@ -136,13 +136,13 @@ static const struct drm_fb_helper_funcs msm_fb_helper_funcs = { struct drm_fb_helper *msm_fbdev_init(struct drm_device *dev) { struct msm_drm_private *priv = dev->dev_private; - struct msm_fbdev *fbdev = NULL; + struct msm_fbdev *fbdev; struct drm_fb_helper *helper; int ret; fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL); if (!fbdev) - goto fail; + return NULL; helper = &fbdev->base; From 4cd15a3e8b36a94c4afa6af064ebe09d387ae034 Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Thu, 2 Feb 2023 10:48:43 -0800 Subject: [PATCH 007/778] drm/msm/a6xx: Make GPU destroy a bit safer If, for whatever reason, we're trying process adreno_runtime_resume() at the same time that a6xx_destroy() is running then things can go boom. Specifically adreno_runtime_resume() will eventually call a6xx_pm_resume() and that may try to resume the gmu. Let's grab the GMU lock as we're destroying the GMU. That will solve the race because a6xx_pm_resume() grabs the same lock. That makes the access of `gmu->initialized` in a6xx_gmu_resume() safe. We'll also return an error code in a6xx_gmu_resume() if we see that `gmu->initialized` was false. If this happens we'll bail out of the rest of a6xx_pm_resume(), which is good because the rest of that function is also not good to do if we're racing with a6xx_destroy(). Signed-off-by: Douglas Anderson Patchwork: https://patchwork.freedesktop.org/patch/521232/ Link: https://lore.kernel.org/r/20230202104822.1.I0e49003bf4dd1dead9be4a29dbee41f3b1236e48@changeid Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 2 +- drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c index f3c9600221d4..7f5bc73b2040 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c @@ -974,7 +974,7 @@ int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu) int status, ret; if (WARN(!gmu->initialized, "The GMU is not set up yet\n")) - return 0; + return -EINVAL; gmu->hung = false; diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index aae60cbd9164..6faea5049f76 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -1746,7 +1746,9 @@ static void a6xx_destroy(struct msm_gpu *gpu) a6xx_llc_slices_destroy(a6xx_gpu); + mutex_lock(&a6xx_gpu->gmu.lock); a6xx_gmu_remove(a6xx_gpu); + mutex_unlock(&a6xx_gpu->gmu.lock); adreno_gpu_cleanup(adreno_gpu); From a7a4c19c36de1e4b99b06e4060ccc8ab837725bc Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Tue, 14 Feb 2023 05:09:53 +0300 Subject: [PATCH 008/778] drm/msm/a5xx: fix setting of the CP_PREEMPT_ENABLE_LOCAL register Rather than writing CP_PREEMPT_ENABLE_GLOBAL twice, follow the vendor kernel and set CP_PREEMPT_ENABLE_LOCAL register instead. a5xx_submit() will override it during submission, but let's get the sequence correct. Fixes: b1fc2839d2f9 ("drm/msm: Implement preemption for A5XX targets") Signed-off-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/522638/ Link: https://lore.kernel.org/r/20230214020956.164473-2-dmitry.baryshkov@linaro.org Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c index 660ba0db8900..8b2df12d8681 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c @@ -151,8 +151,8 @@ static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) OUT_RING(ring, 1); /* Enable local preemption for finegrain preemption */ - OUT_PKT7(ring, CP_PREEMPT_ENABLE_GLOBAL, 1); - OUT_RING(ring, 0x02); + OUT_PKT7(ring, CP_PREEMPT_ENABLE_LOCAL, 1); + OUT_RING(ring, 0x1); /* Allow CP_CONTEXT_SWITCH_YIELD packets in the IB2 */ OUT_PKT7(ring, CP_YIELD_ENABLE, 1); From 141f66ebbfa17cc7e2075f06c50107da978c965b Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Tue, 14 Feb 2023 05:09:54 +0300 Subject: [PATCH 009/778] drm/msm/a5xx: fix highest bank bit for a530 A530 has highest bank bit equal to 15 (like A540). Fix values written to REG_A5XX_RB_MODE_CNTL and REG_A5XX_TPL1_MODE_CNTL registers. Fixes: 1d832ab30ce6 ("drm/msm/a5xx: Add support for Adreno 508, 509, 512 GPUs") Signed-off-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/522639/ Link: https://lore.kernel.org/r/20230214020956.164473-3-dmitry.baryshkov@linaro.org Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c index 8b2df12d8681..047c5e8c87ff 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c @@ -806,7 +806,7 @@ static int a5xx_hw_init(struct msm_gpu *gpu) gpu_write(gpu, REG_A5XX_RBBM_AHB_CNTL2, 0x0000003F); /* Set the highest bank bit */ - if (adreno_is_a540(adreno_gpu)) + if (adreno_is_a540(adreno_gpu) || adreno_is_a530(adreno_gpu)) regbit = 2; else regbit = 1; From b4fb748f0b734ce1d2e7834998cc599fcbd25d67 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Tue, 14 Feb 2023 05:09:55 +0300 Subject: [PATCH 010/778] drm/msm/a5xx: fix the emptyness check in the preempt code Quoting Yassine: ring->memptrs->rptr is never updated and stays 0, so the comparison always evaluates to false and get_next_ring always returns ring 0 thinking it isn't empty. Fix this by calling get_rptr() instead of reading rptr directly. Reported-by: Yassine Oudjana Fixes: b1fc2839d2f9 ("drm/msm: Implement preemption for A5XX targets") Signed-off-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/522642/ Link: https://lore.kernel.org/r/20230214020956.164473-4-dmitry.baryshkov@linaro.org Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a5xx_preempt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/adreno/a5xx_preempt.c b/drivers/gpu/drm/msm/adreno/a5xx_preempt.c index 7658e89844b4..7e0affd60993 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_preempt.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_preempt.c @@ -63,7 +63,7 @@ static struct msm_ringbuffer *get_next_ring(struct msm_gpu *gpu) struct msm_ringbuffer *ring = gpu->rb[i]; spin_lock_irqsave(&ring->preempt_lock, flags); - empty = (get_wptr(ring) == ring->memptrs->rptr); + empty = (get_wptr(ring) == gpu->funcs->get_rptr(gpu, ring)); spin_unlock_irqrestore(&ring->preempt_lock, flags); if (!empty) From 32e7083429d46f29080626fe387ff90c086b1fbe Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Tue, 14 Feb 2023 05:09:56 +0300 Subject: [PATCH 011/778] drm/msm/a5xx: fix context faults during ring switch The rptr_addr is set in the preempt_init_ring(), which is called from a5xx_gpu_init(). It uses shadowptr() to set the address, however the shadow_iova is not yet initialized at that time. Move the rptr_addr setting to the a5xx_preempt_hw_init() which is called after setting the shadow_iova, getting the correct value for the address. Fixes: 8907afb476ac ("drm/msm: Allow a5xx to mark the RPTR shadow as privileged") Suggested-by: Rob Clark Signed-off-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/522640/ Link: https://lore.kernel.org/r/20230214020956.164473-5-dmitry.baryshkov@linaro.org Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a5xx_preempt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/adreno/a5xx_preempt.c b/drivers/gpu/drm/msm/adreno/a5xx_preempt.c index 7e0affd60993..f58dd564d122 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_preempt.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_preempt.c @@ -207,6 +207,7 @@ void a5xx_preempt_hw_init(struct msm_gpu *gpu) a5xx_gpu->preempt[i]->wptr = 0; a5xx_gpu->preempt[i]->rptr = 0; a5xx_gpu->preempt[i]->rbase = gpu->rb[i]->iova; + a5xx_gpu->preempt[i]->rptr_addr = shadowptr(a5xx_gpu, gpu->rb[i]); } /* Write a 0 to signal that we aren't switching pagetables */ @@ -257,7 +258,6 @@ static int preempt_init_ring(struct a5xx_gpu *a5xx_gpu, ptr->data = 0; ptr->cntl = MSM_GPU_RB_CNTL_DEFAULT | AXXX_CP_RB_CNTL_NO_UPDATE; - ptr->rptr_addr = shadowptr(a5xx_gpu, ring); ptr->counter = counters_iova; return 0; From 6153c44392b04ff2da1e9aa82ba87da9ab9a0fc1 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 21 Feb 2023 11:14:27 +0100 Subject: [PATCH 012/778] drm/msm/adreno: fix runtime PM imbalance at unbind A recent commit moved enabling of runtime PM from adreno_gpu_init() to adreno_load_gpu() (called on first open()), which means that unbind() may now be called with runtime PM disabled in case the device was never opened in between. Make sure to only forcibly suspend and disable runtime PM at unbind() in case runtime PM has been enabled to prevent a disable count imbalance. This specifically avoids leaving runtime PM disabled when the device is later opened after a successful bind: msm_dpu ae01000.display-controller: [drm:adreno_load_gpu [msm]] *ERROR* Couldn't power up the GPU: -13 Fixes: 4b18299b3365 ("drm/msm/adreno: Defer enabling runpm until hw_init()") Reported-by: Bjorn Andersson Link: https://lore.kernel.org/lkml/20230203181245.3523937-1-quic_bjorande@quicinc.com Cc: stable@vger.kernel.org # 6.0 Signed-off-by: Johan Hovold Patchwork: https://patchwork.freedesktop.org/patch/523549/ Link: https://lore.kernel.org/r/20230221101430.14546-2-johan+linaro@kernel.org Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/adreno_device.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c index 36f062c7582f..c5c4c93b3689 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_device.c +++ b/drivers/gpu/drm/msm/adreno/adreno_device.c @@ -558,7 +558,8 @@ static void adreno_unbind(struct device *dev, struct device *master, struct msm_drm_private *priv = dev_get_drvdata(master); struct msm_gpu *gpu = dev_to_gpu(dev); - WARN_ON_ONCE(adreno_system_suspend(dev)); + if (pm_runtime_enabled(dev)) + WARN_ON_ONCE(adreno_system_suspend(dev)); gpu->funcs->destroy(gpu); priv->gpu_pdev = NULL; From 3ef9fec011d471a259935f2e2ff58ab12886d683 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 22 Feb 2023 16:17:36 -0300 Subject: [PATCH 013/778] tools arch x86: Sync the msr-index.h copy with the kernel sources To pick up the changes from these csets: 8c29f01654053258 ("x86/sev: Add SEV-SNP guest feature negotiation support") That cause no changes to tooling: $ tools/perf/trace/beauty/tracepoints/x86_msr.sh > before $ cp arch/x86/include/asm/msr-index.h tools/arch/x86/include/asm/msr-index.h $ tools/perf/trace/beauty/tracepoints/x86_msr.sh > after $ diff -u before after $ Just silences this perf build warning: Warning: Kernel ABI header at 'tools/arch/x86/include/asm/msr-index.h' differs from latest version at 'arch/x86/include/asm/msr-index.h' diff -u tools/arch/x86/include/asm/msr-index.h arch/x86/include/asm/msr-index.h Cc: Borislav Petkov (AMD) Cc: Nikunj A Dadhania Link: https://lore.kernel.org/lkml/Y%2FZrNvtcijPWagCp@kernel.org/ Signed-off-by: Arnaldo Carvalho de Melo --- tools/arch/x86/include/asm/msr-index.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tools/arch/x86/include/asm/msr-index.h b/tools/arch/x86/include/asm/msr-index.h index 37ff47552bcb..d3fe82c5d6b6 100644 --- a/tools/arch/x86/include/asm/msr-index.h +++ b/tools/arch/x86/include/asm/msr-index.h @@ -566,6 +566,26 @@ #define MSR_AMD64_SEV_ES_ENABLED BIT_ULL(MSR_AMD64_SEV_ES_ENABLED_BIT) #define MSR_AMD64_SEV_SNP_ENABLED BIT_ULL(MSR_AMD64_SEV_SNP_ENABLED_BIT) +/* SNP feature bits enabled by the hypervisor */ +#define MSR_AMD64_SNP_VTOM BIT_ULL(3) +#define MSR_AMD64_SNP_REFLECT_VC BIT_ULL(4) +#define MSR_AMD64_SNP_RESTRICTED_INJ BIT_ULL(5) +#define MSR_AMD64_SNP_ALT_INJ BIT_ULL(6) +#define MSR_AMD64_SNP_DEBUG_SWAP BIT_ULL(7) +#define MSR_AMD64_SNP_PREVENT_HOST_IBS BIT_ULL(8) +#define MSR_AMD64_SNP_BTB_ISOLATION BIT_ULL(9) +#define MSR_AMD64_SNP_VMPL_SSS BIT_ULL(10) +#define MSR_AMD64_SNP_SECURE_TSC BIT_ULL(11) +#define MSR_AMD64_SNP_VMGEXIT_PARAM BIT_ULL(12) +#define MSR_AMD64_SNP_IBS_VIRT BIT_ULL(14) +#define MSR_AMD64_SNP_VMSA_REG_PROTECTION BIT_ULL(16) +#define MSR_AMD64_SNP_SMT_PROTECTION BIT_ULL(17) + +/* SNP feature bits reserved for future use. */ +#define MSR_AMD64_SNP_RESERVED_BIT13 BIT_ULL(13) +#define MSR_AMD64_SNP_RESERVED_BIT15 BIT_ULL(15) +#define MSR_AMD64_SNP_RESERVED_MASK GENMASK_ULL(63, 18) + #define MSR_AMD64_VIRT_SPEC_CTRL 0xc001011f /* AMD Collaborative Processor Performance Control MSRs */ From b1a37ed00d7908a991c1d0f18a8cba3c2aa99bdc Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Mon, 23 Jan 2023 12:39:11 +0000 Subject: [PATCH 014/778] HID: core: Provide new max_buffer_size attribute to over-ride the default Presently, when a report is processed, its proposed size, provided by the user of the API (as Report Size * Report Count) is compared against the subsystem default HID_MAX_BUFFER_SIZE (16k). However, some low-level HID drivers allocate a reduced amount of memory to their buffers (e.g. UHID only allocates UHID_DATA_MAX (4k) buffers), rending this check inadequate in some cases. In these circumstances, if the received report ends up being smaller than the proposed report size, the remainder of the buffer is zeroed. That is, the space between sizeof(csize) (size of the current report) and the rsize (size proposed i.e. Report Size * Report Count), which can be handled up to HID_MAX_BUFFER_SIZE (16k). Meaning that memset() shoots straight past the end of the buffer boundary and starts zeroing out in-use values, often resulting in calamity. This patch introduces a new variable into 'struct hid_ll_driver' where individual low-level drivers can over-ride the default maximum value of HID_MAX_BUFFER_SIZE (16k) with something more sympathetic to the interface. Signed-off-by: Lee Jones Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 32 +++++++++++++++++++++++++------- include/linux/hid.h | 3 +++ 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 1ee623c26c49..7647a946340c 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -256,6 +256,7 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign { struct hid_report *report; struct hid_field *field; + unsigned int max_buffer_size = HID_MAX_BUFFER_SIZE; unsigned int usages; unsigned int offset; unsigned int i; @@ -286,8 +287,11 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign offset = report->size; report->size += parser->global.report_size * parser->global.report_count; + if (parser->device->ll_driver->max_buffer_size) + max_buffer_size = parser->device->ll_driver->max_buffer_size; + /* Total size check: Allow for possible report index byte */ - if (report->size > (HID_MAX_BUFFER_SIZE - 1) << 3) { + if (report->size > (max_buffer_size - 1) << 3) { hid_err(parser->device, "report is too long\n"); return -1; } @@ -1963,6 +1967,7 @@ int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 * struct hid_report_enum *report_enum = hid->report_enum + type; struct hid_report *report; struct hid_driver *hdrv; + int max_buffer_size = HID_MAX_BUFFER_SIZE; u32 rsize, csize = size; u8 *cdata = data; int ret = 0; @@ -1978,10 +1983,13 @@ int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 * rsize = hid_compute_report_size(report); - if (report_enum->numbered && rsize >= HID_MAX_BUFFER_SIZE) - rsize = HID_MAX_BUFFER_SIZE - 1; - else if (rsize > HID_MAX_BUFFER_SIZE) - rsize = HID_MAX_BUFFER_SIZE; + if (hid->ll_driver->max_buffer_size) + max_buffer_size = hid->ll_driver->max_buffer_size; + + if (report_enum->numbered && rsize >= max_buffer_size) + rsize = max_buffer_size - 1; + else if (rsize > max_buffer_size) + rsize = max_buffer_size; if (csize < rsize) { dbg_hid("report %d is too short, (%d < %d)\n", report->id, @@ -2396,7 +2404,12 @@ int hid_hw_raw_request(struct hid_device *hdev, unsigned char reportnum, __u8 *buf, size_t len, enum hid_report_type rtype, enum hid_class_request reqtype) { - if (len < 1 || len > HID_MAX_BUFFER_SIZE || !buf) + unsigned int max_buffer_size = HID_MAX_BUFFER_SIZE; + + if (hdev->ll_driver->max_buffer_size) + max_buffer_size = hdev->ll_driver->max_buffer_size; + + if (len < 1 || len > max_buffer_size || !buf) return -EINVAL; return hdev->ll_driver->raw_request(hdev, reportnum, buf, len, @@ -2415,7 +2428,12 @@ EXPORT_SYMBOL_GPL(hid_hw_raw_request); */ int hid_hw_output_report(struct hid_device *hdev, __u8 *buf, size_t len) { - if (len < 1 || len > HID_MAX_BUFFER_SIZE || !buf) + unsigned int max_buffer_size = HID_MAX_BUFFER_SIZE; + + if (hdev->ll_driver->max_buffer_size) + max_buffer_size = hdev->ll_driver->max_buffer_size; + + if (len < 1 || len > max_buffer_size || !buf) return -EINVAL; if (hdev->ll_driver->output_report) diff --git a/include/linux/hid.h b/include/linux/hid.h index eaf8ab177303..1ea8c7a3570b 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -834,6 +834,7 @@ struct hid_driver { * @output_report: send output report to device * @idle: send idle request to device * @may_wakeup: return if device may act as a wakeup source during system-suspend + * @max_buffer_size: over-ride maximum data buffer size (default: HID_MAX_BUFFER_SIZE) */ struct hid_ll_driver { int (*start)(struct hid_device *hdev); @@ -859,6 +860,8 @@ struct hid_ll_driver { int (*idle)(struct hid_device *hdev, int report, int idle, int reqtype); bool (*may_wakeup)(struct hid_device *hdev); + + unsigned int max_buffer_size; }; extern bool hid_is_usb(const struct hid_device *hdev); From 1c5d4221240a233df2440fe75c881465cdf8da07 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Mon, 23 Jan 2023 12:39:12 +0000 Subject: [PATCH 015/778] HID: uhid: Over-ride the default maximum data buffer value with our own The default maximum data buffer size for this interface is UHID_DATA_MAX (4k). When data buffers are being processed, ensure this value is used when ensuring the sanity, rather than a value between the user provided value and HID_MAX_BUFFER_SIZE (16k). Signed-off-by: Lee Jones Signed-off-by: Jiri Kosina --- drivers/hid/uhid.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/hid/uhid.c b/drivers/hid/uhid.c index f161c95a1ad2..4588d2cd4ea4 100644 --- a/drivers/hid/uhid.c +++ b/drivers/hid/uhid.c @@ -395,6 +395,7 @@ static const struct hid_ll_driver uhid_hid_driver = { .parse = uhid_hid_parse, .raw_request = uhid_hid_raw_request, .output_report = uhid_hid_output_report, + .max_buffer_size = UHID_DATA_MAX, }; #ifdef CONFIG_COMPAT From ce9f1c05d2edfa6cdf2c1a510495d333e11810a8 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Wed, 22 Feb 2023 23:01:55 -0800 Subject: [PATCH 016/778] perf inject: Fix --buildid-all not to eat up MMAP2 When MMAP2 has the PERF_RECORD_MISC_MMAP_BUILD_ID flag, it means the record already has the build-id info. So it marks the DSO as hit, to skip if the same DSO is not processed if it happens to miss the build-id later. But it missed to copy the MMAP2 record itself so it'd fail to symbolize samples for those regions. For example, the following generates 249 MMAP2 events. $ perf record --buildid-mmap -o- true | perf report --stat -i- | grep MMAP2 MMAP2 events: 249 (86.8%) Adding perf inject should not change the number of events like this $ perf record --buildid-mmap -o- true | perf inject -b | \ > perf report --stat -i- | grep MMAP2 MMAP2 events: 249 (86.5%) But when --buildid-all is used, it eats most of the MMAP2 events. $ perf record --buildid-mmap -o- true | perf inject -b --buildid-all | \ > perf report --stat -i- | grep MMAP2 MMAP2 events: 1 ( 2.5%) With this patch, it shows the original number now. $ perf record --buildid-mmap -o- true | perf inject -b --buildid-all | \ > perf report --stat -i- | grep MMAP2 MMAP2 events: 249 (86.5%) Committer testing: Before: $ perf record --buildid-mmap -o- perf stat --null sleep 1 2> /dev/null | perf inject -b | perf report --stat -i- | grep MMAP2 MMAP2 events: 58 (36.2%) $ perf record --buildid-mmap -o- perf stat --null sleep 1 2> /dev/null | perf report --stat -i- | grep MMAP2 MMAP2 events: 58 (36.2%) $ perf record --buildid-mmap -o- perf stat --null sleep 1 2> /dev/null | perf inject -b --buildid-all | perf report --stat -i- | grep MMAP2 MMAP2 events: 2 ( 1.9%) $ After: $ perf record --buildid-mmap -o- perf stat --null sleep 1 2> /dev/null | perf inject -b | perf report --stat -i- | grep MMAP2 MMAP2 events: 58 (29.3%) $ perf record --buildid-mmap -o- perf stat --null sleep 1 2> /dev/null | perf report --stat -i- | grep MMAP2 MMAP2 events: 58 (34.3%) $ perf record --buildid-mmap -o- perf stat --null sleep 1 2> /dev/null | perf inject -b --buildid-all | perf report --stat -i- | grep MMAP2 MMAP2 events: 58 (38.4%) $ Fixes: f7fc0d1c915a74ff ("perf inject: Do not inject BUILD_ID record if MMAP2 has it") Signed-off-by: Namhyung Kim Tested-by: Arnaldo Carvalho de Melo Cc: Adrian Hunter Cc: Ian Rogers Cc: Ingo Molnar Cc: Jiri Olsa Cc: Peter Zijlstra Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20230223070155.54251-1-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-inject.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index f8182417b734..10bb1d494258 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c @@ -538,6 +538,7 @@ static int perf_event__repipe_buildid_mmap2(struct perf_tool *tool, dso->hit = 1; } dso__put(dso); + perf_event__repipe(tool, event, sample, machine); return 0; } From d3e104bb024e01a7da6af3b270a7b46054b74ac9 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 22 Feb 2023 23:18:17 -0800 Subject: [PATCH 017/778] perf tests stat+csv_output: Switch CSV separator to @ Commas may appear in events like: cpu/INT_MISC.RECOVERY_CYCLES,cmask=1,edge/ which causes the commachecker to see more fields than expected. Use @ as the CSV separator to avoid this. Signed-off-by: Ian Rogers Cc: Alexander Shishkin Cc: Athira Rajeev Cc: Claire Jensen Cc: Ingo Molnar Cc: Jiri Olsa Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Sumanth Korikkar Cc: Thomas Richter Link: https://lore.kernel.org/r/20230223071818.329671-1-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/shell/stat+csv_output.sh | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/tools/perf/tests/shell/stat+csv_output.sh b/tools/perf/tests/shell/stat+csv_output.sh index b7f050aa6210..324fc9e6edd7 100755 --- a/tools/perf/tests/shell/stat+csv_output.sh +++ b/tools/perf/tests/shell/stat+csv_output.sh @@ -7,6 +7,7 @@ set -e skip_test=0 +csv_sep=@ function commachecker() { @@ -34,7 +35,7 @@ function commachecker() [ "$x" = "Failed" ] && continue # Count the number of commas - x=$(echo $line | tr -d -c ',') + x=$(echo $line | tr -d -c $csv_sep) cnt="${#x}" # echo $line $cnt [[ ! "$cnt" =~ $exp ]] && { @@ -54,7 +55,7 @@ function ParanoidAndNotRoot() check_no_args() { echo -n "Checking CSV output: no args " - perf stat -x, true 2>&1 | commachecker --no-args + perf stat -x$csv_sep true 2>&1 | commachecker --no-args echo "[Success]" } @@ -66,7 +67,7 @@ check_system_wide() echo "[Skip] paranoid and not root" return fi - perf stat -x, -a true 2>&1 | commachecker --system-wide + perf stat -x$csv_sep -a true 2>&1 | commachecker --system-wide echo "[Success]" } @@ -79,14 +80,14 @@ check_system_wide_no_aggr() return fi echo -n "Checking CSV output: system wide no aggregation " - perf stat -x, -A -a --no-merge true 2>&1 | commachecker --system-wide-no-aggr + perf stat -x$csv_sep -A -a --no-merge true 2>&1 | commachecker --system-wide-no-aggr echo "[Success]" } check_interval() { echo -n "Checking CSV output: interval " - perf stat -x, -I 1000 true 2>&1 | commachecker --interval + perf stat -x$csv_sep -I 1000 true 2>&1 | commachecker --interval echo "[Success]" } @@ -94,7 +95,7 @@ check_interval() check_event() { echo -n "Checking CSV output: event " - perf stat -x, -e cpu-clock true 2>&1 | commachecker --event + perf stat -x$csv_sep -e cpu-clock true 2>&1 | commachecker --event echo "[Success]" } @@ -106,7 +107,7 @@ check_per_core() echo "[Skip] paranoid and not root" return fi - perf stat -x, --per-core -a true 2>&1 | commachecker --per-core + perf stat -x$csv_sep --per-core -a true 2>&1 | commachecker --per-core echo "[Success]" } @@ -118,7 +119,7 @@ check_per_thread() echo "[Skip] paranoid and not root" return fi - perf stat -x, --per-thread -a true 2>&1 | commachecker --per-thread + perf stat -x$csv_sep --per-thread -a true 2>&1 | commachecker --per-thread echo "[Success]" } @@ -130,7 +131,7 @@ check_per_die() echo "[Skip] paranoid and not root" return fi - perf stat -x, --per-die -a true 2>&1 | commachecker --per-die + perf stat -x$csv_sep --per-die -a true 2>&1 | commachecker --per-die echo "[Success]" } @@ -142,7 +143,7 @@ check_per_node() echo "[Skip] paranoid and not root" return fi - perf stat -x, --per-node -a true 2>&1 | commachecker --per-node + perf stat -x$csv_sep --per-node -a true 2>&1 | commachecker --per-node echo "[Success]" } @@ -154,7 +155,7 @@ check_per_socket() echo "[Skip] paranoid and not root" return fi - perf stat -x, --per-socket -a true 2>&1 | commachecker --per-socket + perf stat -x$csv_sep --per-socket -a true 2>&1 | commachecker --per-socket echo "[Success]" } From 3de34f85bf437e47556044191f0bd7d0eb644e21 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 22 Feb 2023 23:18:18 -0800 Subject: [PATCH 018/778] perf test: Avoid counting commas in json linter Commas may appear in events like: cpu/INT_MISC.RECOVERY_CYCLES,cmask=1,edge/ which causes the count of commas to see more items than expected. Switch to counting the entries in the dictionary, which is 1 more than the number of commas. Signed-off-by: Ian Rogers Cc: Alexander Shishkin Cc: Athira Rajeev Cc: Claire Jensen Cc: Ingo Molnar Cc: Jiri Olsa Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Sumanth Korikkar Cc: Thomas Richter Link: https://lore.kernel.org/r/20230223071818.329671-2-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- .../tests/shell/lib/perf_json_output_lint.py | 29 +++++++++---------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/tools/perf/tests/shell/lib/perf_json_output_lint.py b/tools/perf/tests/shell/lib/perf_json_output_lint.py index d90f8d102eb9..97598d14e532 100644 --- a/tools/perf/tests/shell/lib/perf_json_output_lint.py +++ b/tools/perf/tests/shell/lib/perf_json_output_lint.py @@ -40,19 +40,6 @@ def is_counter_value(num): return isfloat(num) or num == '' or num == '' def check_json_output(expected_items): - if expected_items != -1: - for line in Lines: - if 'failed' not in line: - count = 0 - count = line.count(',') - if count != expected_items and count >= 1 and count <= 3 and 'metric-value' in line: - # Events that generate >1 metric may have isolated metric - # values and possibly other prefixes like interval, core and - # aggregate-number. - continue - if count != expected_items: - raise RuntimeError(f'wrong number of fields. counted {count} expected {expected_items}' - f' in \'{line}\'') checks = { 'aggregate-number': lambda x: isfloat(x), 'core': lambda x: True, @@ -73,6 +60,16 @@ def check_json_output(expected_items): } input = '[\n' + ','.join(Lines) + '\n]' for item in json.loads(input): + if expected_items != -1: + count = len(item) + if count != expected_items and count >= 1 and count <= 4 and 'metric-value' in item: + # Events that generate >1 metric may have isolated metric + # values and possibly other prefixes like interval, core and + # aggregate-number. + pass + elif count != expected_items: + raise RuntimeError(f'wrong number of fields. counted {count} expected {expected_items}' + f' in \'{item}\'') for key, value in item.items(): if key not in checks: raise RuntimeError(f'Unexpected key: key={key} value={value}') @@ -82,11 +79,11 @@ def check_json_output(expected_items): try: if args.no_args or args.system_wide or args.event: - expected_items = 6 - elif args.interval or args.per_thread or args.system_wide_no_aggr: expected_items = 7 - elif args.per_core or args.per_socket or args.per_node or args.per_die: + elif args.interval or args.per_thread or args.system_wide_no_aggr: expected_items = 8 + elif args.per_core or args.per_socket or args.per_node or args.per_die: + expected_items = 9 else: # If no option is specified, don't check the number of items. expected_items = -1 From 22ef7d7be4dc071712ddf0ae09df6ee39b4901a0 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Thu, 23 Feb 2023 15:17:26 +0100 Subject: [PATCH 019/778] selftest: hid: fix hid_bpf not set in config Now that CONFIG_HID_BPF is not automatically implied by HID, we need to set it properly in the selftests config. Signed-off-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- tools/testing/selftests/hid/config | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/testing/selftests/hid/config b/tools/testing/selftests/hid/config index 9c5a55abca6b..5b5cef445b54 100644 --- a/tools/testing/selftests/hid/config +++ b/tools/testing/selftests/hid/config @@ -17,5 +17,6 @@ CONFIG_FTRACE_SYSCALLS=y CONFIG_FUNCTION_TRACER=y CONFIG_HIDRAW=y CONFIG_HID=y +CONFIG_HID_BPF=y CONFIG_INPUT_EVDEV=y CONFIG_UHID=y From 37f5b858a66543b2b67c0288280af623985abc29 Mon Sep 17 00:00:00 2001 From: Danny Kaehn Date: Fri, 10 Feb 2023 11:00:44 -0600 Subject: [PATCH 020/778] HID: cp2112: Fix driver not registering GPIO IRQ chip as threaded The CP2112 generates interrupts from a polling routine on a thread, and can only support threaded interrupts. This patch configures the gpiochip irq chip with this flag, disallowing consumers to request a hard IRQ from this driver, which resulted in a segfault previously. Signed-off-by: Danny Kaehn Link: https://lore.kernel.org/r/20230210170044.11835-1-kaehndan@gmail.com Signed-off-by: Benjamin Tissoires --- drivers/hid/hid-cp2112.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/hid/hid-cp2112.c b/drivers/hid/hid-cp2112.c index 1e16b0fa310d..27cadadda7c9 100644 --- a/drivers/hid/hid-cp2112.c +++ b/drivers/hid/hid-cp2112.c @@ -1354,6 +1354,7 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id) girq->parents = NULL; girq->default_type = IRQ_TYPE_NONE; girq->handler = handle_simple_irq; + girq->threaded = true; ret = gpiochip_add_data(&dev->gc, dev); if (ret < 0) { From a07484c083eabc809e45a198bd639bfd37ac70b6 Mon Sep 17 00:00:00 2001 From: Bagas Sanjaya Date: Wed, 22 Feb 2023 15:35:30 +0700 Subject: [PATCH 021/778] bpf, docs: Fix link to BTF doc Ross reported broken link to BTF documentation (Documentation/bpf/btf.rst) in Documentation/bpf/bpf_devel_QA.rst. The link in question is written using external link syntax, with the target refers to BTF doc in reST source (btf.rst), which doesn't exist in resulting HTML output. Fix the link by replacing external link syntax with simply writing out the target doc, which the link will be generated to the correct HTML doc target. Fixes: 6736aa793c2b5f ("selftests/bpf: Add general instructions for test execution") Reported-by: Ross Zwisler Signed-off-by: Bagas Sanjaya Signed-off-by: Daniel Borkmann Acked-by: Ross Zwisler Link: https://lore.kernel.org/linux-doc/Y++09LKx25dtR4Ow@google.com/ Link: https://lore.kernel.org/bpf/20230222083530.26136-1-bagasdotme@gmail.com --- Documentation/bpf/bpf_devel_QA.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Documentation/bpf/bpf_devel_QA.rst b/Documentation/bpf/bpf_devel_QA.rst index 03d4993eda6f..715f7321020f 100644 --- a/Documentation/bpf/bpf_devel_QA.rst +++ b/Documentation/bpf/bpf_devel_QA.rst @@ -469,7 +469,7 @@ under test should match the config file fragment in tools/testing/selftests/bpf as closely as possible. Finally to ensure support for latest BPF Type Format features - -discussed in `Documentation/bpf/btf.rst`_ - pahole version 1.16 +discussed in Documentation/bpf/btf.rst - pahole version 1.16 is required for kernels built with CONFIG_DEBUG_INFO_BTF=y. pahole is delivered in the dwarves package or can be built from source at @@ -690,6 +690,5 @@ when: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/tools/testing/selftests/bpf/ .. _Documentation/dev-tools/kselftest.rst: https://www.kernel.org/doc/html/latest/dev-tools/kselftest.html -.. _Documentation/bpf/btf.rst: btf.rst Happy BPF hacking! From 2d311f480b52eeb2e1fd432d64b78d82952c3808 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sun, 26 Feb 2023 23:20:16 -0800 Subject: [PATCH 022/778] riscv, bpf: Fix patch_text implicit declaration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit bpf_jit_comp64.c uses patch_text(), so add to it to prevent the build error: ../arch/riscv/net/bpf_jit_comp64.c: In function 'bpf_arch_text_poke': ../arch/riscv/net/bpf_jit_comp64.c:691:23: error: implicit declaration of function 'patch_text'; did you mean 'path_get'? [-Werror=implicit-function-declaration] 691 | ret = patch_text(ip, new_insns, ninsns); | ^~~~~~~~~~ Fixes: 596f2e6f9cf4 ("riscv, bpf: Add bpf_arch_text_poke support for RV64") Reported-by: kernel test robot Signed-off-by: Randy Dunlap Signed-off-by: Daniel Borkmann Acked-by: Pu Lehui Acked-by: Björn Töpel Link: https://lore.kernel.org/r/202302271000.Aj4nMXbZ-lkp@intel.com Link: https://lore.kernel.org/bpf/20230227072016.14618-1-rdunlap@infradead.org --- arch/riscv/net/bpf_jit_comp64.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/riscv/net/bpf_jit_comp64.c b/arch/riscv/net/bpf_jit_comp64.c index f5a668736c79..acdc3f040195 100644 --- a/arch/riscv/net/bpf_jit_comp64.c +++ b/arch/riscv/net/bpf_jit_comp64.c @@ -10,6 +10,7 @@ #include #include #include +#include #include "bpf_jit.h" #define RV_REG_TCC RV_REG_A6 From f99e6d7c4ed3be2531bd576425a5bd07fb133bd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Mon, 27 Feb 2023 10:11:56 +0100 Subject: [PATCH 023/778] bgmac: fix *initial* chip reset to support BCM5358 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While bringing hardware up we should perform a full reset including the switch bit (BGMAC_BCMA_IOCTL_SW_RESET aka SICF_SWRST). It's what specification says and what reference driver does. This seems to be critical for the BCM5358. Without this hardware doesn't get initialized properly and doesn't seem to transmit or receive any packets. Originally bgmac was calling bgmac_chip_reset() before setting "has_robosw" property which resulted in expected behaviour. That has changed as a side effect of adding platform device support which regressed BCM5358 support. Fixes: f6a95a24957a ("net: ethernet: bgmac: Add platform device support") Cc: Jon Mason Signed-off-by: Rafał Miłecki Reviewed-by: Leon Romanovsky Reviewed-by: Florian Fainelli Link: https://lore.kernel.org/r/20230227091156.19509-1-zajec5@gmail.com Signed-off-by: Paolo Abeni --- drivers/net/ethernet/broadcom/bgmac.c | 8 ++++++-- drivers/net/ethernet/broadcom/bgmac.h | 2 ++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c index 3038386a5afd..1761df8fb7f9 100644 --- a/drivers/net/ethernet/broadcom/bgmac.c +++ b/drivers/net/ethernet/broadcom/bgmac.c @@ -890,13 +890,13 @@ static void bgmac_chip_reset_idm_config(struct bgmac *bgmac) if (iost & BGMAC_BCMA_IOST_ATTACHED) { flags = BGMAC_BCMA_IOCTL_SW_CLKEN; - if (!bgmac->has_robosw) + if (bgmac->in_init || !bgmac->has_robosw) flags |= BGMAC_BCMA_IOCTL_SW_RESET; } bgmac_clk_enable(bgmac, flags); } - if (iost & BGMAC_BCMA_IOST_ATTACHED && !bgmac->has_robosw) + if (iost & BGMAC_BCMA_IOST_ATTACHED && (bgmac->in_init || !bgmac->has_robosw)) bgmac_idm_write(bgmac, BCMA_IOCTL, bgmac_idm_read(bgmac, BCMA_IOCTL) & ~BGMAC_BCMA_IOCTL_SW_RESET); @@ -1490,6 +1490,8 @@ int bgmac_enet_probe(struct bgmac *bgmac) struct net_device *net_dev = bgmac->net_dev; int err; + bgmac->in_init = true; + bgmac_chip_intrs_off(bgmac); net_dev->irq = bgmac->irq; @@ -1542,6 +1544,8 @@ int bgmac_enet_probe(struct bgmac *bgmac) /* Omit FCS from max MTU size */ net_dev->max_mtu = BGMAC_RX_MAX_FRAME_SIZE - ETH_FCS_LEN; + bgmac->in_init = false; + err = register_netdev(bgmac->net_dev); if (err) { dev_err(bgmac->dev, "Cannot register net device\n"); diff --git a/drivers/net/ethernet/broadcom/bgmac.h b/drivers/net/ethernet/broadcom/bgmac.h index e05ac92c0650..d73ef262991d 100644 --- a/drivers/net/ethernet/broadcom/bgmac.h +++ b/drivers/net/ethernet/broadcom/bgmac.h @@ -472,6 +472,8 @@ struct bgmac { int irq; u32 int_mask; + bool in_init; + /* Current MAC state */ int mac_speed; int mac_duplex; From 11f180a5d62a51b484e9648f9b310e1bd50b1a57 Mon Sep 17 00:00:00 2001 From: Kang Chen Date: Mon, 27 Feb 2023 17:30:37 +0800 Subject: [PATCH 024/778] nfc: fdp: add null check of devm_kmalloc_array in fdp_nci_i2c_read_device_properties devm_kmalloc_array may fails, *fw_vsc_cfg might be null and cause out-of-bounds write in device_property_read_u8_array later. Fixes: a06347c04c13 ("NFC: Add Intel Fields Peak NFC solution driver") Signed-off-by: Kang Chen Reviewed-by: Krzysztof Kozlowski Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/20230227093037.907654-1-void0red@gmail.com Signed-off-by: Paolo Abeni --- drivers/nfc/fdp/i2c.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/nfc/fdp/i2c.c b/drivers/nfc/fdp/i2c.c index 2d53e0f88d2f..1e0f2297f9c6 100644 --- a/drivers/nfc/fdp/i2c.c +++ b/drivers/nfc/fdp/i2c.c @@ -247,6 +247,9 @@ static void fdp_nci_i2c_read_device_properties(struct device *dev, len, sizeof(**fw_vsc_cfg), GFP_KERNEL); + if (!*fw_vsc_cfg) + goto alloc_err; + r = device_property_read_u8_array(dev, FDP_DP_FW_VSC_CFG_NAME, *fw_vsc_cfg, len); @@ -260,6 +263,7 @@ vsc_read_err: *fw_vsc_cfg = NULL; } +alloc_err: dev_dbg(dev, "Clock type: %d, clock frequency: %d, VSC: %s", *clock_type, *clock_freq, *fw_vsc_cfg != NULL ? "yes" : "no"); } From 8f9850dd8d23c1290cb642ce9548a440da5771ec Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 27 Feb 2023 13:03:22 +0300 Subject: [PATCH 025/778] net: phy: unlock on error in phy_probe() If genphy_c45_read_eee_adv() fails then we need to do a reset and unlock the &phydev->lock mutex before returning. Fixes: 3eeca4e199ce ("net: phy: do not force EEE support") Signed-off-by: Dan Carpenter Reviewed-by: Oleksij Rempel Link: https://lore.kernel.org/r/Y/x/6kHCjnQHqOpF@kili Signed-off-by: Paolo Abeni --- drivers/net/phy/phy_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 3f8a64fb9d71..9e9fd8ff00f6 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -3146,7 +3146,7 @@ static int phy_probe(struct device *dev) */ err = genphy_c45_read_eee_adv(phydev, phydev->advertising_eee); if (err) - return err; + goto out; /* There is no "enabled" flag. If PHY is advertising, assume it is * kind of enabled. From ae44f1c9d1fc54aeceb335fedb1e73b2c3ee4561 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Fri, 24 Feb 2023 17:59:39 +0200 Subject: [PATCH 026/778] powerpc: dts: t1040rdb: fix compatible string for Rev A boards It looks like U-Boot fails to start the kernel properly when the compatible string of the board isn't fsl,T1040RDB, so stop overriding it from the rev-a.dts. Fixes: 5ebb74749202 ("powerpc: dts: t1040rdb: fix ports names for Seville Ethernet switch") Signed-off-by: Vladimir Oltean Signed-off-by: Jakub Kicinski --- arch/powerpc/boot/dts/fsl/t1040rdb-rev-a.dts | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/powerpc/boot/dts/fsl/t1040rdb-rev-a.dts b/arch/powerpc/boot/dts/fsl/t1040rdb-rev-a.dts index 73f8c998c64d..d4f5f159d6f2 100644 --- a/arch/powerpc/boot/dts/fsl/t1040rdb-rev-a.dts +++ b/arch/powerpc/boot/dts/fsl/t1040rdb-rev-a.dts @@ -10,7 +10,6 @@ / { model = "fsl,T1040RDB-REV-A"; - compatible = "fsl,T1040RDB-REV-A"; }; &seville_port0 { From 8b322f9fdb35ecee0d4a40de8af923444bd624ea Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Fri, 24 Feb 2023 17:59:40 +0200 Subject: [PATCH 027/778] powerpc: dts: t1040rdb: enable both CPU ports Since commit eca70102cfb1 ("net: dsa: felix: add support for changing DSA master") included in kernel v6.1, the driver supports 2 CPU ports, and they can be put in a LAG, for example (see Documentation/networking/dsa/configuration.rst for more details). Defining the second CPU port in the device tree should not cause any compatibility issue, because the default CPU port was &seville_port8 before this change, and still is &seville_port8 now (the numerically first CPU port is used by default). Signed-off-by: Vladimir Oltean Signed-off-by: Jakub Kicinski --- arch/powerpc/boot/dts/fsl/t1040rdb.dts | 5 ++++- arch/powerpc/boot/dts/fsl/t1040si-post.dtsi | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/boot/dts/fsl/t1040rdb.dts b/arch/powerpc/boot/dts/fsl/t1040rdb.dts index b6733e7e6580..dd3aab81e9de 100644 --- a/arch/powerpc/boot/dts/fsl/t1040rdb.dts +++ b/arch/powerpc/boot/dts/fsl/t1040rdb.dts @@ -180,6 +180,9 @@ }; &seville_port8 { - ethernet = <&enet0>; + status = "okay"; +}; + +&seville_port9 { status = "okay"; }; diff --git a/arch/powerpc/boot/dts/fsl/t1040si-post.dtsi b/arch/powerpc/boot/dts/fsl/t1040si-post.dtsi index f58eb820eb5e..ad0ab33336b8 100644 --- a/arch/powerpc/boot/dts/fsl/t1040si-post.dtsi +++ b/arch/powerpc/boot/dts/fsl/t1040si-post.dtsi @@ -686,6 +686,7 @@ seville_port8: port@8 { reg = <8>; phy-mode = "internal"; + ethernet = <&enet0>; status = "disabled"; fixed-link { @@ -697,6 +698,7 @@ seville_port9: port@9 { reg = <9>; phy-mode = "internal"; + ethernet = <&enet1>; status = "disabled"; fixed-link { From 4d42cd6bc2ac1b9be50ade13771daec90c9d18b1 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Mon, 27 Feb 2023 10:12:01 -0800 Subject: [PATCH 028/778] tls: rx: fix return value for async crypto Gaurav reports that TLS Rx is broken with async crypto accelerators. The commit under fixes missed updating the retval byte counting logic when updating how records are stored. Even tho both before and after the change 'decrypted' was updated inside the main loop, it was completely overwritten when processing the async completions. Now that the rx_list only holds non-zero-copy records we need to add, not overwrite. Reported-and-bisected-by: Gaurav Jain Fixes: cbbdee9918a2 ("tls: rx: async: don't put async zc on the list") Link: https://bugzilla.kernel.org/show_bug.cgi?id=217064 Tested-by: Gaurav Jain Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/20230227181201.1793772-1-kuba@kernel.org Signed-off-by: Jakub Kicinski --- net/tls/tls_sw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c index 782d3701b86f..021d760f9133 100644 --- a/net/tls/tls_sw.c +++ b/net/tls/tls_sw.c @@ -2127,7 +2127,7 @@ recv_end: else err = process_rx_list(ctx, msg, &control, 0, async_copy_bytes, is_peek); - decrypted = max(err, 0); + decrypted += max(err, 0); } copied += decrypted; From 0df979f4b93569dfb908d195f8e7d4c3cef4eaeb Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sun, 12 Feb 2023 01:12:10 +0200 Subject: [PATCH 029/778] drm/msm/dpu: set DPU_MDP_PERIPH_0_REMOVED for sc8280xp The SC8280XP also has a black hole at the top of MDP_TOP region. Set corresponding bit to disable access to that region. Fixes: 4a352c2fc15a ("drm/msm/dpu: Introduce SC8280XP") Reviewed-by: Abhinav Kumar Reviewed-by: Neil Armstrong Signed-off-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/522207/ Link: https://lore.kernel.org/r/20230211231259.1308718-2-dmitry.baryshkov@linaro.org Signed-off-by: Abhinav Kumar --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c index cf053e8f081e..84d974458e0d 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -696,7 +696,7 @@ static const struct dpu_mdp_cfg sc8280xp_mdp[] = { { .name = "top_0", .id = MDP_TOP, .base = 0x0, .len = 0x494, - .features = 0, + .features = BIT(DPU_MDP_PERIPH_0_REMOVED), .highest_bank_bit = 2, .ubwc_swizzle = 6, .clk_ctrls[DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2ac, .bit_off = 0}, From a2a448b4d9bcb5bff0e0f687b7932a7be9ca898a Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sun, 12 Feb 2023 01:12:11 +0200 Subject: [PATCH 030/778] drm/msm/dpu: disable features unsupported by QCM2290 QCM2290 doesn't seem to support reg-dma, UBWC and CSC. Drop corresponding features being incorrectly enabled for qcm2290. Cc: Loic Poulain Fixes: 5334087ee743 ("drm/msm: add support for QCM2290 MDSS") Reviewed-by: Abhinav Kumar Signed-off-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/522209/ Link: https://lore.kernel.org/r/20230211231259.1308718-3-dmitry.baryshkov@linaro.org Signed-off-by: Abhinav Kumar --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c index 84d974458e0d..eea026cf3ac2 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -12,11 +12,15 @@ #include "dpu_hw_catalog.h" #include "dpu_kms.h" -#define VIG_MASK \ +#define VIG_BASE_MASK \ (BIT(DPU_SSPP_SRC) | BIT(DPU_SSPP_QOS) |\ - BIT(DPU_SSPP_CSC_10BIT) | BIT(DPU_SSPP_CDP) |\ + BIT(DPU_SSPP_CDP) |\ BIT(DPU_SSPP_TS_PREFILL) | BIT(DPU_SSPP_EXCL_RECT)) +#define VIG_MASK \ + (VIG_BASE_MASK | \ + BIT(DPU_SSPP_CSC_10BIT)) + #define VIG_MSM8998_MASK \ (VIG_MASK | BIT(DPU_SSPP_SCALER_QSEED3)) @@ -29,7 +33,7 @@ #define VIG_SM8250_MASK \ (VIG_MASK | BIT(DPU_SSPP_QOS_8LVL) | BIT(DPU_SSPP_SCALER_QSEED3LITE)) -#define VIG_QCM2290_MASK (VIG_MASK | BIT(DPU_SSPP_QOS_8LVL)) +#define VIG_QCM2290_MASK (VIG_BASE_MASK | BIT(DPU_SSPP_QOS_8LVL)) #define DMA_MSM8998_MASK \ (BIT(DPU_SSPP_SRC) | BIT(DPU_SSPP_QOS) |\ @@ -317,7 +321,6 @@ static const struct dpu_caps qcm2290_dpu_caps = { .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .max_mixer_blendstages = 0x4, .smart_dma_rev = DPU_SSPP_SMART_DMA_V2, - .ubwc_version = DPU_HW_UBWC_VER_20, .has_dim_layer = true, .has_idle_pc = true, .max_linewidth = 2160, @@ -2841,8 +2844,6 @@ static const struct dpu_mdss_cfg qcm2290_dpu_cfg = { .intf = qcm2290_intf, .vbif_count = ARRAY_SIZE(sdm845_vbif), .vbif = sdm845_vbif, - .reg_dma_count = 1, - .dma_cfg = &sdm845_regdma, .perf = &qcm2290_perf_data, .mdss_irqs = IRQ_SC7180_MASK, }; From 880ce5f20033cd6ecb2c0edfe0376c9e45220012 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 27 Feb 2023 14:17:06 +0000 Subject: [PATCH 031/778] net: avoid skb end_offset change in __skb_unclone_keeptruesize() Once initial skb->head has been allocated from skb_small_head_cache, we need to make sure to use the same strategy whenever skb->head has to be re-allocated, as found by syzbot [1] This means kmalloc_reserve() can not fallback from using skb_small_head_cache to generic (power-of-two) kmem caches. It seems that we probably want to rework things in the future, to partially revert following patch, because we no longer use ksize() for skb allocated in TX path. 2b88cba55883 ("net: preserve skb_end_offset() in skb_unclone_keeptruesize()") Ideally, TCP stack should never put payload in skb->head, this effort has to be completed. In the mean time, add a sanity check. [1] BUG: KASAN: invalid-free in slab_free mm/slub.c:3787 [inline] BUG: KASAN: invalid-free in kmem_cache_free+0xee/0x5c0 mm/slub.c:3809 Free of addr ffff88806cdee800 by task syz-executor239/5189 CPU: 0 PID: 5189 Comm: syz-executor239 Not tainted 6.2.0-rc8-syzkaller-02400-gd1fabc68f8e0 #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/21/2023 Call Trace: __dump_stack lib/dump_stack.c:88 [inline] dump_stack_lvl+0xd1/0x138 lib/dump_stack.c:106 print_address_description mm/kasan/report.c:306 [inline] print_report+0x15e/0x45d mm/kasan/report.c:417 kasan_report_invalid_free+0x9b/0x1b0 mm/kasan/report.c:482 ____kasan_slab_free+0x1a5/0x1c0 mm/kasan/common.c:216 kasan_slab_free include/linux/kasan.h:177 [inline] slab_free_hook mm/slub.c:1781 [inline] slab_free_freelist_hook+0x8b/0x1c0 mm/slub.c:1807 slab_free mm/slub.c:3787 [inline] kmem_cache_free+0xee/0x5c0 mm/slub.c:3809 skb_kfree_head net/core/skbuff.c:857 [inline] skb_kfree_head net/core/skbuff.c:853 [inline] skb_free_head+0x16f/0x1a0 net/core/skbuff.c:872 skb_release_data+0x57a/0x820 net/core/skbuff.c:901 skb_release_all net/core/skbuff.c:966 [inline] __kfree_skb+0x4f/0x70 net/core/skbuff.c:980 tcp_wmem_free_skb include/net/tcp.h:302 [inline] tcp_rtx_queue_purge net/ipv4/tcp.c:3061 [inline] tcp_write_queue_purge+0x617/0xcf0 net/ipv4/tcp.c:3074 tcp_v4_destroy_sock+0x125/0x810 net/ipv4/tcp_ipv4.c:2302 inet_csk_destroy_sock+0x19a/0x440 net/ipv4/inet_connection_sock.c:1195 __tcp_close+0xb96/0xf50 net/ipv4/tcp.c:3021 tcp_close+0x2d/0xc0 net/ipv4/tcp.c:3033 inet_release+0x132/0x270 net/ipv4/af_inet.c:426 __sock_release+0xcd/0x280 net/socket.c:651 sock_close+0x1c/0x20 net/socket.c:1393 __fput+0x27c/0xa90 fs/file_table.c:320 task_work_run+0x16f/0x270 kernel/task_work.c:179 resume_user_mode_work include/linux/resume_user_mode.h:49 [inline] exit_to_user_mode_loop kernel/entry/common.c:171 [inline] exit_to_user_mode_prepare+0x23c/0x250 kernel/entry/common.c:203 __syscall_exit_to_user_mode_work kernel/entry/common.c:285 [inline] syscall_exit_to_user_mode+0x1d/0x50 kernel/entry/common.c:296 do_syscall_64+0x46/0xb0 arch/x86/entry/common.c:86 entry_SYSCALL_64_after_hwframe+0x63/0xcd RIP: 0033:0x7f2511f546c3 Code: c7 c2 c0 ff ff ff f7 d8 64 89 02 48 c7 c0 ff ff ff ff eb b7 0f 1f 00 64 8b 04 25 18 00 00 00 85 c0 75 14 b8 03 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 45 c3 0f 1f 40 00 48 83 ec 18 89 7c 24 0c e8 RSP: 002b:00007ffef0103d48 EFLAGS: 00000246 ORIG_RAX: 0000000000000003 RAX: 0000000000000000 RBX: 0000000000000004 RCX: 00007f2511f546c3 RDX: 0000000000000978 RSI: 00000000200000c0 RDI: 0000000000000003 RBP: 0000000000000000 R08: 0000000000000002 R09: 0000000000003434 R10: 0000000000000000 R11: 0000000000000246 R12: 00007ffef0103d6c R13: 00007ffef0103d80 R14: 00007ffef0103dc0 R15: 0000000000000003 Allocated by task 5189: kasan_save_stack+0x22/0x40 mm/kasan/common.c:45 kasan_set_track+0x25/0x30 mm/kasan/common.c:52 ____kasan_kmalloc mm/kasan/common.c:374 [inline] ____kasan_kmalloc mm/kasan/common.c:333 [inline] __kasan_kmalloc+0xa5/0xb0 mm/kasan/common.c:383 kasan_kmalloc include/linux/kasan.h:211 [inline] __do_kmalloc_node mm/slab_common.c:968 [inline] __kmalloc_node_track_caller+0x5b/0xc0 mm/slab_common.c:988 kmalloc_reserve+0xf1/0x230 net/core/skbuff.c:539 pskb_expand_head+0x237/0x1160 net/core/skbuff.c:1995 __skb_unclone_keeptruesize+0x93/0x220 net/core/skbuff.c:2094 skb_unclone_keeptruesize include/linux/skbuff.h:1910 [inline] skb_prepare_for_shift net/core/skbuff.c:3804 [inline] skb_shift+0xef8/0x1e20 net/core/skbuff.c:3877 tcp_skb_shift net/ipv4/tcp_input.c:1538 [inline] tcp_shift_skb_data net/ipv4/tcp_input.c:1646 [inline] tcp_sacktag_walk+0x93b/0x18a0 net/ipv4/tcp_input.c:1713 tcp_sacktag_write_queue+0x1599/0x31d0 net/ipv4/tcp_input.c:1974 tcp_ack+0x2e9f/0x5a10 net/ipv4/tcp_input.c:3847 tcp_rcv_established+0x667/0x2230 net/ipv4/tcp_input.c:6006 tcp_v4_do_rcv+0x670/0x9b0 net/ipv4/tcp_ipv4.c:1721 sk_backlog_rcv include/net/sock.h:1113 [inline] __release_sock+0x133/0x3b0 net/core/sock.c:2921 release_sock+0x58/0x1b0 net/core/sock.c:3488 tcp_sendmsg+0x3a/0x50 net/ipv4/tcp.c:1485 inet_sendmsg+0x9d/0xe0 net/ipv4/af_inet.c:825 sock_sendmsg_nosec net/socket.c:722 [inline] sock_sendmsg+0xde/0x190 net/socket.c:745 sock_write_iter+0x295/0x3d0 net/socket.c:1136 call_write_iter include/linux/fs.h:2189 [inline] new_sync_write fs/read_write.c:491 [inline] vfs_write+0x9ed/0xdd0 fs/read_write.c:584 ksys_write+0x1ec/0x250 fs/read_write.c:637 do_syscall_x64 arch/x86/entry/common.c:50 [inline] do_syscall_64+0x39/0xb0 arch/x86/entry/common.c:80 entry_SYSCALL_64_after_hwframe+0x63/0xcd The buggy address belongs to the object at ffff88806cdee800 which belongs to the cache kmalloc-1k of size 1024 The buggy address is located 0 bytes inside of 1024-byte region [ffff88806cdee800, ffff88806cdeec00) The buggy address belongs to the physical page: page:ffffea0001b37a00 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x6cde8 head:ffffea0001b37a00 order:3 compound_mapcount:0 subpages_mapcount:0 compound_pincount:0 flags: 0xfff00000010200(slab|head|node=0|zone=1|lastcpupid=0x7ff) raw: 00fff00000010200 ffff888012441dc0 dead000000000122 0000000000000000 raw: 0000000000000000 0000000000100010 00000001ffffffff 0000000000000000 page dumped because: kasan: bad access detected page_owner tracks the page as allocated page last allocated via order 3, migratetype Unmovable, gfp_mask 0x1f2a20(GFP_ATOMIC|__GFP_NOWARN|__GFP_NORETRY|__GFP_COMP|__GFP_NOMEMALLOC|__GFP_MEMALLOC|__GFP_HARDWALL), pid 75, tgid 75 (kworker/u4:4), ts 96369578780, free_ts 26734162530 prep_new_page mm/page_alloc.c:2531 [inline] get_page_from_freelist+0x119c/0x2ce0 mm/page_alloc.c:4283 __alloc_pages+0x1cb/0x5b0 mm/page_alloc.c:5549 alloc_pages+0x1aa/0x270 mm/mempolicy.c:2287 alloc_slab_page mm/slub.c:1851 [inline] allocate_slab+0x25f/0x350 mm/slub.c:1998 new_slab mm/slub.c:2051 [inline] ___slab_alloc+0xa91/0x1400 mm/slub.c:3193 __slab_alloc.constprop.0+0x56/0xa0 mm/slub.c:3292 __slab_alloc_node mm/slub.c:3345 [inline] slab_alloc_node mm/slub.c:3442 [inline] __kmem_cache_alloc_node+0x1a4/0x430 mm/slub.c:3491 __do_kmalloc_node mm/slab_common.c:967 [inline] __kmalloc_node_track_caller+0x4b/0xc0 mm/slab_common.c:988 kmalloc_reserve+0xf1/0x230 net/core/skbuff.c:539 __alloc_skb+0x129/0x330 net/core/skbuff.c:608 __netdev_alloc_skb+0x74/0x410 net/core/skbuff.c:672 __netdev_alloc_skb_ip_align include/linux/skbuff.h:3203 [inline] netdev_alloc_skb_ip_align include/linux/skbuff.h:3213 [inline] batadv_iv_ogm_aggregate_new+0x106/0x4e0 net/batman-adv/bat_iv_ogm.c:558 batadv_iv_ogm_queue_add net/batman-adv/bat_iv_ogm.c:670 [inline] batadv_iv_ogm_schedule_buff+0xe6b/0x1450 net/batman-adv/bat_iv_ogm.c:849 batadv_iv_ogm_schedule net/batman-adv/bat_iv_ogm.c:868 [inline] batadv_iv_ogm_schedule net/batman-adv/bat_iv_ogm.c:861 [inline] batadv_iv_send_outstanding_bat_ogm_packet+0x744/0x910 net/batman-adv/bat_iv_ogm.c:1712 process_one_work+0x9bf/0x1710 kernel/workqueue.c:2289 worker_thread+0x669/0x1090 kernel/workqueue.c:2436 page last free stack trace: reset_page_owner include/linux/page_owner.h:24 [inline] free_pages_prepare mm/page_alloc.c:1446 [inline] free_pcp_prepare+0x66a/0xc20 mm/page_alloc.c:1496 free_unref_page_prepare mm/page_alloc.c:3369 [inline] free_unref_page+0x1d/0x490 mm/page_alloc.c:3464 free_contig_range+0xb5/0x180 mm/page_alloc.c:9488 destroy_args+0xa8/0x64c mm/debug_vm_pgtable.c:998 debug_vm_pgtable+0x28de/0x296f mm/debug_vm_pgtable.c:1318 do_one_initcall+0x141/0x790 init/main.c:1306 do_initcall_level init/main.c:1379 [inline] do_initcalls init/main.c:1395 [inline] do_basic_setup init/main.c:1414 [inline] kernel_init_freeable+0x6f9/0x782 init/main.c:1634 kernel_init+0x1e/0x1d0 init/main.c:1522 ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:308 Memory state around the buggy address: ffff88806cdee700: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc ffff88806cdee780: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc >ffff88806cdee800: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ^ ffff88806cdee880: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 Fixes: bf9f1baa279f ("net: add dedicated kmem_cache for typical/small skb->head") Reported-by: syzbot Signed-off-by: Eric Dumazet Tested-by: Christoph Paasch Signed-off-by: David S. Miller --- net/core/skbuff.c | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/net/core/skbuff.c b/net/core/skbuff.c index eb7d33b41e71..1a31815104d6 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -517,18 +517,16 @@ static void *kmalloc_reserve(unsigned int *size, gfp_t flags, int node, #ifdef HAVE_SKB_SMALL_HEAD_CACHE if (obj_size <= SKB_SMALL_HEAD_CACHE_SIZE && !(flags & KMALLOC_NOT_NORMAL_BITS)) { - - /* skb_small_head_cache has non power of two size, - * likely forcing SLUB to use order-3 pages. - * We deliberately attempt a NOMEMALLOC allocation only. - */ obj = kmem_cache_alloc_node(skb_small_head_cache, flags | __GFP_NOMEMALLOC | __GFP_NOWARN, node); - if (obj) { - *size = SKB_SMALL_HEAD_CACHE_SIZE; + *size = SKB_SMALL_HEAD_CACHE_SIZE; + if (obj || !(gfp_pfmemalloc_allowed(flags))) goto out; - } + /* Try again but now we are using pfmemalloc reserves */ + ret_pfmemalloc = true; + obj = kmem_cache_alloc_node(skb_small_head_cache, flags, node); + goto out; } #endif *size = obj_size = kmalloc_size_roundup(obj_size); @@ -2082,6 +2080,7 @@ struct sk_buff *skb_realloc_headroom(struct sk_buff *skb, unsigned int headroom) } EXPORT_SYMBOL(skb_realloc_headroom); +/* Note: We plan to rework this in linux-6.4 */ int __skb_unclone_keeptruesize(struct sk_buff *skb, gfp_t pri) { unsigned int saved_end_offset, saved_truesize; @@ -2100,6 +2099,22 @@ int __skb_unclone_keeptruesize(struct sk_buff *skb, gfp_t pri) if (likely(skb_end_offset(skb) == saved_end_offset)) return 0; +#ifdef HAVE_SKB_SMALL_HEAD_CACHE + /* We can not change skb->end if the original or new value + * is SKB_SMALL_HEAD_HEADROOM, as it might break skb_kfree_head(). + */ + if (saved_end_offset == SKB_SMALL_HEAD_HEADROOM || + skb_end_offset(skb) == SKB_SMALL_HEAD_HEADROOM) { + /* We think this path should not be taken. + * Add a temporary trace to warn us just in case. + */ + pr_err_once("__skb_unclone_keeptruesize() skb_end_offset() %u -> %u\n", + saved_end_offset, skb_end_offset(skb)); + WARN_ON_ONCE(1); + return 0; + } +#endif + shinfo = skb_shinfo(skb); /* We are about to change back skb->end, From fb07390463c95e6eef254044d6dde050bfb9807a Mon Sep 17 00:00:00 2001 From: Pedro Tammela Date: Mon, 27 Feb 2023 12:23:52 -0300 Subject: [PATCH 032/778] net/sched: act_connmark: handle errno on tcf_idr_check_alloc Smatch reports that 'ci' can be used uninitialized. The current code ignores errno coming from tcf_idr_check_alloc, which will lead to the incorrect usage of 'ci'. Handle the errno as it should. Fixes: 288864effe33 ("net/sched: act_connmark: transition to percpu stats and rcu") Reviewed-by: Jamal Hadi Salim Signed-off-by: Pedro Tammela Reviewed-by: Simon Horman Signed-off-by: David S. Miller --- net/sched/act_connmark.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/sched/act_connmark.c b/net/sched/act_connmark.c index 8dabfb52ea3d..0d7aee8933c5 100644 --- a/net/sched/act_connmark.c +++ b/net/sched/act_connmark.c @@ -158,6 +158,9 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla, nparms->zone = parm->zone; ret = 0; + } else { + err = ret; + goto out_free; } err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack); From 693aa2c0d9b6d5b1f2745d31b6e70d09dbbaf06e Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 27 Feb 2023 15:30:24 +0000 Subject: [PATCH 033/778] ila: do not generate empty messages in ila_xlat_nl_cmd_get_mapping() ila_xlat_nl_cmd_get_mapping() generates an empty skb, triggerring a recent sanity check [1]. Instead, return an error code, so that user space can get it. [1] skb_assert_len WARNING: CPU: 0 PID: 5923 at include/linux/skbuff.h:2527 skb_assert_len include/linux/skbuff.h:2527 [inline] WARNING: CPU: 0 PID: 5923 at include/linux/skbuff.h:2527 __dev_queue_xmit+0x1bc0/0x3488 net/core/dev.c:4156 Modules linked in: CPU: 0 PID: 5923 Comm: syz-executor269 Not tainted 6.2.0-syzkaller-18300-g2ebd1fbb946d #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/21/2023 pstate: 60400005 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : skb_assert_len include/linux/skbuff.h:2527 [inline] pc : __dev_queue_xmit+0x1bc0/0x3488 net/core/dev.c:4156 lr : skb_assert_len include/linux/skbuff.h:2527 [inline] lr : __dev_queue_xmit+0x1bc0/0x3488 net/core/dev.c:4156 sp : ffff80001e0d6c40 x29: ffff80001e0d6e60 x28: dfff800000000000 x27: ffff0000c86328c0 x26: dfff800000000000 x25: ffff0000c8632990 x24: ffff0000c8632a00 x23: 0000000000000000 x22: 1fffe000190c6542 x21: ffff0000c8632a10 x20: ffff0000c8632a00 x19: ffff80001856e000 x18: ffff80001e0d5fc0 x17: 0000000000000000 x16: ffff80001235d16c x15: 0000000000000000 x14: 0000000000000000 x13: 0000000000000001 x12: 0000000000000001 x11: ff80800008353a30 x10: 0000000000000000 x9 : 21567eaf25bfb600 x8 : 21567eaf25bfb600 x7 : 0000000000000001 x6 : 0000000000000001 x5 : ffff80001e0d6558 x4 : ffff800015c74760 x3 : ffff800008596744 x2 : 0000000000000001 x1 : 0000000100000000 x0 : 000000000000000e Call trace: skb_assert_len include/linux/skbuff.h:2527 [inline] __dev_queue_xmit+0x1bc0/0x3488 net/core/dev.c:4156 dev_queue_xmit include/linux/netdevice.h:3033 [inline] __netlink_deliver_tap_skb net/netlink/af_netlink.c:307 [inline] __netlink_deliver_tap+0x45c/0x6f8 net/netlink/af_netlink.c:325 netlink_deliver_tap+0xf4/0x174 net/netlink/af_netlink.c:338 __netlink_sendskb net/netlink/af_netlink.c:1283 [inline] netlink_sendskb+0x6c/0x154 net/netlink/af_netlink.c:1292 netlink_unicast+0x334/0x8d4 net/netlink/af_netlink.c:1380 nlmsg_unicast include/net/netlink.h:1099 [inline] genlmsg_unicast include/net/genetlink.h:433 [inline] genlmsg_reply include/net/genetlink.h:443 [inline] ila_xlat_nl_cmd_get_mapping+0x620/0x7d0 net/ipv6/ila/ila_xlat.c:493 genl_family_rcv_msg_doit net/netlink/genetlink.c:968 [inline] genl_family_rcv_msg net/netlink/genetlink.c:1048 [inline] genl_rcv_msg+0x938/0xc1c net/netlink/genetlink.c:1065 netlink_rcv_skb+0x214/0x3c4 net/netlink/af_netlink.c:2574 genl_rcv+0x38/0x50 net/netlink/genetlink.c:1076 netlink_unicast_kernel net/netlink/af_netlink.c:1339 [inline] netlink_unicast+0x660/0x8d4 net/netlink/af_netlink.c:1365 netlink_sendmsg+0x800/0xae0 net/netlink/af_netlink.c:1942 sock_sendmsg_nosec net/socket.c:714 [inline] sock_sendmsg net/socket.c:734 [inline] ____sys_sendmsg+0x558/0x844 net/socket.c:2479 ___sys_sendmsg net/socket.c:2533 [inline] __sys_sendmsg+0x26c/0x33c net/socket.c:2562 __do_sys_sendmsg net/socket.c:2571 [inline] __se_sys_sendmsg net/socket.c:2569 [inline] __arm64_sys_sendmsg+0x80/0x94 net/socket.c:2569 __invoke_syscall arch/arm64/kernel/syscall.c:38 [inline] invoke_syscall+0x98/0x2c0 arch/arm64/kernel/syscall.c:52 el0_svc_common+0x138/0x258 arch/arm64/kernel/syscall.c:142 do_el0_svc+0x64/0x198 arch/arm64/kernel/syscall.c:193 el0_svc+0x58/0x168 arch/arm64/kernel/entry-common.c:637 el0t_64_sync_handler+0x84/0xf0 arch/arm64/kernel/entry-common.c:655 el0t_64_sync+0x190/0x194 arch/arm64/kernel/entry.S:591 irq event stamp: 136484 hardirqs last enabled at (136483): [] __up_console_sem+0x60/0xb4 kernel/printk/printk.c:345 hardirqs last disabled at (136484): [] el1_dbg+0x24/0x80 arch/arm64/kernel/entry-common.c:405 softirqs last enabled at (136418): [] softirq_handle_end kernel/softirq.c:414 [inline] softirqs last enabled at (136418): [] __do_softirq+0xd4c/0xfa4 kernel/softirq.c:600 softirqs last disabled at (136371): [] ____do_softirq+0x14/0x20 arch/arm64/kernel/irq.c:80 ---[ end trace 0000000000000000 ]--- skb len=0 headroom=0 headlen=0 tailroom=192 mac=(0,0) net=(0,-1) trans=-1 shinfo(txflags=0 nr_frags=0 gso(size=0 type=0 segs=0)) csum(0x0 ip_summed=0 complete_sw=0 valid=0 level=0) hash(0x0 sw=0 l4=0) proto=0x0010 pkttype=6 iif=0 dev name=nlmon0 feat=0x0000000000005861 Fixes: 7f00feaf1076 ("ila: Add generic ILA translation facility") Reported-by: syzbot Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv6/ila/ila_xlat.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/ipv6/ila/ila_xlat.c b/net/ipv6/ila/ila_xlat.c index 47447f0241df..bee45dfeb187 100644 --- a/net/ipv6/ila/ila_xlat.c +++ b/net/ipv6/ila/ila_xlat.c @@ -477,6 +477,7 @@ int ila_xlat_nl_cmd_get_mapping(struct sk_buff *skb, struct genl_info *info) rcu_read_lock(); + ret = -ESRCH; ila = ila_lookup_by_params(&xp, ilan); if (ila) { ret = ila_dump_info(ila, From dfd2f0eb2347dbdf391fd5b8255fefc58a745472 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 27 Feb 2023 18:44:36 +0000 Subject: [PATCH 034/778] net/sched: flower: fix fl_change() error recovery path The two "goto errout;" paths in fl_change() became wrong after cited commit. Indeed we only must not call __fl_put() until the net pointer has been set in tcf_exts_init_ex() This is a minimal fix. We might in the future validate TCA_FLOWER_FLAGS before we allocate @fnew. BUG: KASAN: null-ptr-deref in instrument_atomic_read include/linux/instrumented.h:72 [inline] BUG: KASAN: null-ptr-deref in atomic_read include/linux/atomic/atomic-instrumented.h:27 [inline] BUG: KASAN: null-ptr-deref in refcount_read include/linux/refcount.h:147 [inline] BUG: KASAN: null-ptr-deref in __refcount_add_not_zero include/linux/refcount.h:152 [inline] BUG: KASAN: null-ptr-deref in __refcount_inc_not_zero include/linux/refcount.h:227 [inline] BUG: KASAN: null-ptr-deref in refcount_inc_not_zero include/linux/refcount.h:245 [inline] BUG: KASAN: null-ptr-deref in maybe_get_net include/net/net_namespace.h:269 [inline] BUG: KASAN: null-ptr-deref in tcf_exts_get_net include/net/pkt_cls.h:260 [inline] BUG: KASAN: null-ptr-deref in __fl_put net/sched/cls_flower.c:513 [inline] BUG: KASAN: null-ptr-deref in __fl_put+0x13e/0x3b0 net/sched/cls_flower.c:508 Read of size 4 at addr 000000000000014c by task syz-executor548/5082 CPU: 0 PID: 5082 Comm: syz-executor548 Not tainted 6.2.0-syzkaller-05251-g5b7c4cabbb65 #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/21/2023 Call Trace: __dump_stack lib/dump_stack.c:88 [inline] dump_stack_lvl+0xd9/0x150 lib/dump_stack.c:106 print_report mm/kasan/report.c:420 [inline] kasan_report+0xec/0x130 mm/kasan/report.c:517 check_region_inline mm/kasan/generic.c:183 [inline] kasan_check_range+0x141/0x190 mm/kasan/generic.c:189 instrument_atomic_read include/linux/instrumented.h:72 [inline] atomic_read include/linux/atomic/atomic-instrumented.h:27 [inline] refcount_read include/linux/refcount.h:147 [inline] __refcount_add_not_zero include/linux/refcount.h:152 [inline] __refcount_inc_not_zero include/linux/refcount.h:227 [inline] refcount_inc_not_zero include/linux/refcount.h:245 [inline] maybe_get_net include/net/net_namespace.h:269 [inline] tcf_exts_get_net include/net/pkt_cls.h:260 [inline] __fl_put net/sched/cls_flower.c:513 [inline] __fl_put+0x13e/0x3b0 net/sched/cls_flower.c:508 fl_change+0x101b/0x4ab0 net/sched/cls_flower.c:2341 tc_new_tfilter+0x97c/0x2290 net/sched/cls_api.c:2310 rtnetlink_rcv_msg+0x996/0xd50 net/core/rtnetlink.c:6165 netlink_rcv_skb+0x165/0x440 net/netlink/af_netlink.c:2574 netlink_unicast_kernel net/netlink/af_netlink.c:1339 [inline] netlink_unicast+0x547/0x7f0 net/netlink/af_netlink.c:1365 netlink_sendmsg+0x925/0xe30 net/netlink/af_netlink.c:1942 sock_sendmsg_nosec net/socket.c:722 [inline] sock_sendmsg+0xde/0x190 net/socket.c:745 ____sys_sendmsg+0x334/0x900 net/socket.c:2504 ___sys_sendmsg+0x110/0x1b0 net/socket.c:2558 __sys_sendmmsg+0x18f/0x460 net/socket.c:2644 __do_sys_sendmmsg net/socket.c:2673 [inline] __se_sys_sendmmsg net/socket.c:2670 [inline] __x64_sys_sendmmsg+0x9d/0x100 net/socket.c:2670 Fixes: 08a0063df3ae ("net/sched: flower: Move filter handle initialization earlier") Reported-by: syzbot+baabf3efa7c1e57d28b2@syzkaller.appspotmail.com Reported-by: syzbot Signed-off-by: Eric Dumazet Cc: Paul Blakey Reviewed-by: Simon Horman Signed-off-by: David S. Miller --- net/sched/cls_flower.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c index e960a46b0520..475fe222a855 100644 --- a/net/sched/cls_flower.c +++ b/net/sched/cls_flower.c @@ -2200,8 +2200,9 @@ static int fl_change(struct net *net, struct sk_buff *in_skb, fnew->flags = nla_get_u32(tb[TCA_FLOWER_FLAGS]); if (!tc_flags_valid(fnew->flags)) { + kfree(fnew); err = -EINVAL; - goto errout; + goto errout_tb; } } @@ -2226,8 +2227,10 @@ static int fl_change(struct net *net, struct sk_buff *in_skb, } spin_unlock(&tp->lock); - if (err) - goto errout; + if (err) { + kfree(fnew); + goto errout_tb; + } } fnew->handle = handle; @@ -2337,7 +2340,6 @@ errout_mask: fl_mask_put(head, fnew->mask); errout_idr: idr_remove(&head->handle_idr, fnew->handle); -errout: __fl_put(fnew); errout_tb: kfree(tb); From 81563d8548b0478075c720666be348d4199b8591 Mon Sep 17 00:00:00 2001 From: Horatiu Vultur Date: Tue, 28 Feb 2023 21:47:42 +0100 Subject: [PATCH 035/778] net: lan966x: Fix port police support using tc-matchall When the police was removed from the port, then it was trying to remove the police from the police id and not from the actual police index. The police id represents the id of the police and police index represents the position in HW where the police is situated. The port police id can be any number while the port police index is a number based on the port chip port. Fix this by deleting the police from HW that is situated at the police index and not police id. Fixes: 5390334b59a3 ("net: lan966x: Add port police support using tc-matchall") Signed-off-by: Horatiu Vultur Reviewed-by: Simon Horman Reviewed-by: Vladimir Oltean Signed-off-by: David S. Miller --- drivers/net/ethernet/microchip/lan966x/lan966x_police.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_police.c b/drivers/net/ethernet/microchip/lan966x/lan966x_police.c index a9aec900d608..7d66fe75cd3b 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_police.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_police.c @@ -194,7 +194,7 @@ int lan966x_police_port_del(struct lan966x_port *port, return -EINVAL; } - err = lan966x_police_del(port, port->tc.police_id); + err = lan966x_police_del(port, POL_IDX_PORT + port->chip_port); if (err) { NL_SET_ERR_MSG_MOD(extack, "Failed to add policer to port"); From 2067e7a00aa604b94de31d64f29b8893b1696f26 Mon Sep 17 00:00:00 2001 From: Hangbin Liu Date: Mon, 27 Feb 2023 17:36:46 +0800 Subject: [PATCH 036/778] selftests: nft_nat: ensuring the listening side is up before starting the client The test_local_dnat_portonly() function initiates the client-side as soon as it sets the listening side to the background. This could lead to a race condition where the server may not be ready to listen. To ensure that the server-side is up and running before initiating the client-side, a delay is introduced to the test_local_dnat_portonly() function. Before the fix: # ./nft_nat.sh PASS: netns routing/connectivity: ns0-rthlYrBU can reach ns1-rthlYrBU and ns2-rthlYrBU PASS: ping to ns1-rthlYrBU was ip NATted to ns2-rthlYrBU PASS: ping to ns1-rthlYrBU OK after ip nat output chain flush PASS: ipv6 ping to ns1-rthlYrBU was ip6 NATted to ns2-rthlYrBU 2023/02/27 04:11:03 socat[6055] E connect(5, AF=2 10.0.1.99:2000, 16): Connection refused ERROR: inet port rewrite After the fix: # ./nft_nat.sh PASS: netns routing/connectivity: ns0-9sPJV6JJ can reach ns1-9sPJV6JJ and ns2-9sPJV6JJ PASS: ping to ns1-9sPJV6JJ was ip NATted to ns2-9sPJV6JJ PASS: ping to ns1-9sPJV6JJ OK after ip nat output chain flush PASS: ipv6 ping to ns1-9sPJV6JJ was ip6 NATted to ns2-9sPJV6JJ PASS: inet port rewrite without l3 address Fixes: 282e5f8fe907 ("netfilter: nat: really support inet nat without l3 address") Signed-off-by: Hangbin Liu Signed-off-by: Pablo Neira Ayuso --- tools/testing/selftests/netfilter/nft_nat.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/testing/selftests/netfilter/nft_nat.sh b/tools/testing/selftests/netfilter/nft_nat.sh index 924ecb3f1f73..dd40d9f6f259 100755 --- a/tools/testing/selftests/netfilter/nft_nat.sh +++ b/tools/testing/selftests/netfilter/nft_nat.sh @@ -404,6 +404,8 @@ EOF echo SERVER-$family | ip netns exec "$ns1" timeout 5 socat -u STDIN TCP-LISTEN:2000 & sc_s=$! + sleep 1 + result=$(ip netns exec "$ns0" timeout 1 socat TCP:$daddr:2000 STDOUT) if [ "$result" = "SERVER-inet" ];then From 860e874290fb3be08e966c9c8ffc510c5b0f2bd8 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 28 Feb 2023 17:09:03 +0100 Subject: [PATCH 037/778] netfilter: nft_last: copy content when cloning expression If the ruleset contains last timestamps, restore them accordingly. Otherwise, listing after restoration shows never used items. Fixes: 33a24de37e81 ("netfilter: nft_last: move stateful fields out of expression data") Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nft_last.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/netfilter/nft_last.c b/net/netfilter/nft_last.c index 7f2bda6641bd..8e6d7eaf9dc8 100644 --- a/net/netfilter/nft_last.c +++ b/net/netfilter/nft_last.c @@ -105,11 +105,15 @@ static void nft_last_destroy(const struct nft_ctx *ctx, static int nft_last_clone(struct nft_expr *dst, const struct nft_expr *src) { struct nft_last_priv *priv_dst = nft_expr_priv(dst); + struct nft_last_priv *priv_src = nft_expr_priv(src); priv_dst->last = kzalloc(sizeof(*priv_dst->last), GFP_ATOMIC); if (!priv_dst->last) return -ENOMEM; + priv_dst->last->set = priv_src->last->set; + priv_dst->last->jiffies = priv_src->last->jiffies; + return 0; } From aabef97a35160461e9c576848ded737558d89055 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 28 Feb 2023 20:43:02 +0100 Subject: [PATCH 038/778] netfilter: nft_quota: copy content when cloning expression If the ruleset contains consumed quota, restore them accordingly. Otherwise, listing after restoration shows never used items. Restore the user-defined quota and flags too. Fixes: ed0a0c60f0e5 ("netfilter: nft_quota: move stateful fields out of expression data") Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nft_quota.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/net/netfilter/nft_quota.c b/net/netfilter/nft_quota.c index 123578e28917..3ba12a7471b0 100644 --- a/net/netfilter/nft_quota.c +++ b/net/netfilter/nft_quota.c @@ -236,12 +236,16 @@ static void nft_quota_destroy(const struct nft_ctx *ctx, static int nft_quota_clone(struct nft_expr *dst, const struct nft_expr *src) { struct nft_quota *priv_dst = nft_expr_priv(dst); + struct nft_quota *priv_src = nft_expr_priv(src); + + priv_dst->quota = priv_src->quota; + priv_dst->flags = priv_src->flags; priv_dst->consumed = kmalloc(sizeof(*priv_dst->consumed), GFP_ATOMIC); if (!priv_dst->consumed) return -ENOMEM; - atomic64_set(priv_dst->consumed, 0); + *priv_dst->consumed = *priv_src->consumed; return 0; } From fcd9531b305288dc2848d38567d466af4ee147b2 Mon Sep 17 00:00:00 2001 From: Boris Burkov Date: Wed, 15 Feb 2023 12:59:49 -0800 Subject: [PATCH 039/778] btrfs: sysfs: add size class stats Make it possible to see the distribution of size classes for block groups. Helpful for testing and debugging the allocator w.r.t. to size classes. The new stats can be found at the path: /sys/fs/btrfs//allocation//size_class but they will only be non-zero for bg-type = data. Signed-off-by: Boris Burkov Reviewed-by: David Sterba Signed-off-by: David Sterba --- fs/btrfs/sysfs.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c index 8c5efa5813b3..37fc58a7f27e 100644 --- a/fs/btrfs/sysfs.c +++ b/fs/btrfs/sysfs.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include "messages.h" #include "ctree.h" @@ -778,6 +779,45 @@ static ssize_t btrfs_chunk_size_store(struct kobject *kobj, return len; } +static ssize_t btrfs_size_classes_show(struct kobject *kobj, + struct kobj_attribute *a, char *buf) +{ + struct btrfs_space_info *sinfo = to_space_info(kobj); + struct btrfs_block_group *bg; + u32 none = 0; + u32 small = 0; + u32 medium = 0; + u32 large = 0; + + for (int i = 0; i < BTRFS_NR_RAID_TYPES; ++i) { + down_read(&sinfo->groups_sem); + list_for_each_entry(bg, &sinfo->block_groups[i], list) { + if (!btrfs_block_group_should_use_size_class(bg)) + continue; + switch (bg->size_class) { + case BTRFS_BG_SZ_NONE: + none++; + break; + case BTRFS_BG_SZ_SMALL: + small++; + break; + case BTRFS_BG_SZ_MEDIUM: + medium++; + break; + case BTRFS_BG_SZ_LARGE: + large++; + break; + } + } + up_read(&sinfo->groups_sem); + } + return sysfs_emit(buf, "none %u\n" + "small %u\n" + "medium %u\n" + "large %u\n", + none, small, medium, large); +} + #ifdef CONFIG_BTRFS_DEBUG /* * Request chunk allocation with current chunk size. @@ -835,6 +875,7 @@ SPACE_INFO_ATTR(bytes_zone_unusable); SPACE_INFO_ATTR(disk_used); SPACE_INFO_ATTR(disk_total); BTRFS_ATTR_RW(space_info, chunk_size, btrfs_chunk_size_show, btrfs_chunk_size_store); +BTRFS_ATTR(space_info, size_classes, btrfs_size_classes_show); static ssize_t btrfs_sinfo_bg_reclaim_threshold_show(struct kobject *kobj, struct kobj_attribute *a, @@ -887,6 +928,7 @@ static struct attribute *space_info_attrs[] = { BTRFS_ATTR_PTR(space_info, disk_total), BTRFS_ATTR_PTR(space_info, bg_reclaim_threshold), BTRFS_ATTR_PTR(space_info, chunk_size), + BTRFS_ATTR_PTR(space_info, size_classes), #ifdef CONFIG_BTRFS_DEBUG BTRFS_ATTR_PTR(space_info, force_chunk_alloc), #endif From 49c47cc21b5b7a3d8deb18fc57b0aa2ab1286962 Mon Sep 17 00:00:00 2001 From: Hangyu Hua Date: Tue, 28 Feb 2023 10:33:44 +0800 Subject: [PATCH 040/778] net: tls: fix possible race condition between do_tls_getsockopt_conf() and do_tls_setsockopt_conf() ctx->crypto_send.info is not protected by lock_sock in do_tls_getsockopt_conf(). A race condition between do_tls_getsockopt_conf() and error paths of do_tls_setsockopt_conf() may lead to a use-after-free or null-deref. More discussion: https://lore.kernel.org/all/Y/ht6gQL+u6fj3dG@hog/ Fixes: 3c4d7559159b ("tls: kernel TLS support") Signed-off-by: Hangyu Hua Link: https://lore.kernel.org/r/20230228023344.9623-1-hbh25y@gmail.com Signed-off-by: Jakub Kicinski --- net/tls/tls_main.c | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c index 3735cb00905d..b32c112984dd 100644 --- a/net/tls/tls_main.c +++ b/net/tls/tls_main.c @@ -405,13 +405,11 @@ static int do_tls_getsockopt_conf(struct sock *sk, char __user *optval, rc = -EINVAL; goto out; } - lock_sock(sk); memcpy(crypto_info_aes_gcm_128->iv, cctx->iv + TLS_CIPHER_AES_GCM_128_SALT_SIZE, TLS_CIPHER_AES_GCM_128_IV_SIZE); memcpy(crypto_info_aes_gcm_128->rec_seq, cctx->rec_seq, TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE); - release_sock(sk); if (copy_to_user(optval, crypto_info_aes_gcm_128, sizeof(*crypto_info_aes_gcm_128))) @@ -429,13 +427,11 @@ static int do_tls_getsockopt_conf(struct sock *sk, char __user *optval, rc = -EINVAL; goto out; } - lock_sock(sk); memcpy(crypto_info_aes_gcm_256->iv, cctx->iv + TLS_CIPHER_AES_GCM_256_SALT_SIZE, TLS_CIPHER_AES_GCM_256_IV_SIZE); memcpy(crypto_info_aes_gcm_256->rec_seq, cctx->rec_seq, TLS_CIPHER_AES_GCM_256_REC_SEQ_SIZE); - release_sock(sk); if (copy_to_user(optval, crypto_info_aes_gcm_256, sizeof(*crypto_info_aes_gcm_256))) @@ -451,13 +447,11 @@ static int do_tls_getsockopt_conf(struct sock *sk, char __user *optval, rc = -EINVAL; goto out; } - lock_sock(sk); memcpy(aes_ccm_128->iv, cctx->iv + TLS_CIPHER_AES_CCM_128_SALT_SIZE, TLS_CIPHER_AES_CCM_128_IV_SIZE); memcpy(aes_ccm_128->rec_seq, cctx->rec_seq, TLS_CIPHER_AES_CCM_128_REC_SEQ_SIZE); - release_sock(sk); if (copy_to_user(optval, aes_ccm_128, sizeof(*aes_ccm_128))) rc = -EFAULT; break; @@ -472,13 +466,11 @@ static int do_tls_getsockopt_conf(struct sock *sk, char __user *optval, rc = -EINVAL; goto out; } - lock_sock(sk); memcpy(chacha20_poly1305->iv, cctx->iv + TLS_CIPHER_CHACHA20_POLY1305_SALT_SIZE, TLS_CIPHER_CHACHA20_POLY1305_IV_SIZE); memcpy(chacha20_poly1305->rec_seq, cctx->rec_seq, TLS_CIPHER_CHACHA20_POLY1305_REC_SEQ_SIZE); - release_sock(sk); if (copy_to_user(optval, chacha20_poly1305, sizeof(*chacha20_poly1305))) rc = -EFAULT; @@ -493,13 +485,11 @@ static int do_tls_getsockopt_conf(struct sock *sk, char __user *optval, rc = -EINVAL; goto out; } - lock_sock(sk); memcpy(sm4_gcm_info->iv, cctx->iv + TLS_CIPHER_SM4_GCM_SALT_SIZE, TLS_CIPHER_SM4_GCM_IV_SIZE); memcpy(sm4_gcm_info->rec_seq, cctx->rec_seq, TLS_CIPHER_SM4_GCM_REC_SEQ_SIZE); - release_sock(sk); if (copy_to_user(optval, sm4_gcm_info, sizeof(*sm4_gcm_info))) rc = -EFAULT; break; @@ -513,13 +503,11 @@ static int do_tls_getsockopt_conf(struct sock *sk, char __user *optval, rc = -EINVAL; goto out; } - lock_sock(sk); memcpy(sm4_ccm_info->iv, cctx->iv + TLS_CIPHER_SM4_CCM_SALT_SIZE, TLS_CIPHER_SM4_CCM_IV_SIZE); memcpy(sm4_ccm_info->rec_seq, cctx->rec_seq, TLS_CIPHER_SM4_CCM_REC_SEQ_SIZE); - release_sock(sk); if (copy_to_user(optval, sm4_ccm_info, sizeof(*sm4_ccm_info))) rc = -EFAULT; break; @@ -535,13 +523,11 @@ static int do_tls_getsockopt_conf(struct sock *sk, char __user *optval, rc = -EINVAL; goto out; } - lock_sock(sk); memcpy(crypto_info_aria_gcm_128->iv, cctx->iv + TLS_CIPHER_ARIA_GCM_128_SALT_SIZE, TLS_CIPHER_ARIA_GCM_128_IV_SIZE); memcpy(crypto_info_aria_gcm_128->rec_seq, cctx->rec_seq, TLS_CIPHER_ARIA_GCM_128_REC_SEQ_SIZE); - release_sock(sk); if (copy_to_user(optval, crypto_info_aria_gcm_128, sizeof(*crypto_info_aria_gcm_128))) @@ -559,13 +545,11 @@ static int do_tls_getsockopt_conf(struct sock *sk, char __user *optval, rc = -EINVAL; goto out; } - lock_sock(sk); memcpy(crypto_info_aria_gcm_256->iv, cctx->iv + TLS_CIPHER_ARIA_GCM_256_SALT_SIZE, TLS_CIPHER_ARIA_GCM_256_IV_SIZE); memcpy(crypto_info_aria_gcm_256->rec_seq, cctx->rec_seq, TLS_CIPHER_ARIA_GCM_256_REC_SEQ_SIZE); - release_sock(sk); if (copy_to_user(optval, crypto_info_aria_gcm_256, sizeof(*crypto_info_aria_gcm_256))) @@ -614,11 +598,9 @@ static int do_tls_getsockopt_no_pad(struct sock *sk, char __user *optval, if (len < sizeof(value)) return -EINVAL; - lock_sock(sk); value = -EINVAL; if (ctx->rx_conf == TLS_SW || ctx->rx_conf == TLS_HW) value = ctx->rx_no_pad; - release_sock(sk); if (value < 0) return value; @@ -635,6 +617,8 @@ static int do_tls_getsockopt(struct sock *sk, int optname, { int rc = 0; + lock_sock(sk); + switch (optname) { case TLS_TX: case TLS_RX: @@ -651,6 +635,9 @@ static int do_tls_getsockopt(struct sock *sk, int optname, rc = -ENOPROTOOPT; break; } + + release_sock(sk); + return rc; } From f3221361dc85d4de22586ce8441ec2c67b454f5d Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 28 Feb 2023 16:28:57 -0800 Subject: [PATCH 041/778] net: tls: avoid hanging tasks on the tx_lock syzbot sent a hung task report and Eric explains that adversarial receiver may keep RWIN at 0 for a long time, so we are not guaranteed to make forward progress. Thread which took tx_lock and went to sleep may not release tx_lock for hours. Use interruptible sleep where possible and reschedule the work if it can't take the lock. Testing: existing selftest passes Reported-by: syzbot+9c0268252b8ef967c62e@syzkaller.appspotmail.com Fixes: 79ffe6087e91 ("net/tls: add a TX lock") Link: https://lore.kernel.org/all/000000000000e412e905f5b46201@google.com/ Cc: stable@vger.kernel.org # wait 4 weeks Reviewed-by: Eric Dumazet Link: https://lore.kernel.org/r/20230301002857.2101894-1-kuba@kernel.org Signed-off-by: Jakub Kicinski --- net/tls/tls_sw.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c index 021d760f9133..635b8bf6b937 100644 --- a/net/tls/tls_sw.c +++ b/net/tls/tls_sw.c @@ -956,7 +956,9 @@ int tls_sw_sendmsg(struct sock *sk, struct msghdr *msg, size_t size) MSG_CMSG_COMPAT)) return -EOPNOTSUPP; - mutex_lock(&tls_ctx->tx_lock); + ret = mutex_lock_interruptible(&tls_ctx->tx_lock); + if (ret) + return ret; lock_sock(sk); if (unlikely(msg->msg_controllen)) { @@ -1290,7 +1292,9 @@ int tls_sw_sendpage(struct sock *sk, struct page *page, MSG_SENDPAGE_NOTLAST | MSG_SENDPAGE_NOPOLICY)) return -EOPNOTSUPP; - mutex_lock(&tls_ctx->tx_lock); + ret = mutex_lock_interruptible(&tls_ctx->tx_lock); + if (ret) + return ret; lock_sock(sk); ret = tls_sw_do_sendpage(sk, page, offset, size, flags); release_sock(sk); @@ -2435,11 +2439,19 @@ static void tx_work_handler(struct work_struct *work) if (!test_and_clear_bit(BIT_TX_SCHEDULED, &ctx->tx_bitmask)) return; - mutex_lock(&tls_ctx->tx_lock); - lock_sock(sk); - tls_tx_records(sk, -1); - release_sock(sk); - mutex_unlock(&tls_ctx->tx_lock); + + if (mutex_trylock(&tls_ctx->tx_lock)) { + lock_sock(sk); + tls_tx_records(sk, -1); + release_sock(sk); + mutex_unlock(&tls_ctx->tx_lock); + } else if (!test_and_set_bit(BIT_TX_SCHEDULED, &ctx->tx_bitmask)) { + /* Someone is holding the tx_lock, they will likely run Tx + * and cancel the work on their way out of the lock section. + * Schedule a long delay just in case. + */ + schedule_delayed_work(&ctx->tx_work.work, msecs_to_jiffies(10)); + } } static bool tls_is_tx_ready(struct tls_sw_context_tx *ctx) From 5c1ebbfabcd61142a4551bfc0e51840f9bdae7af Mon Sep 17 00:00:00 2001 From: Brian Vazquez Date: Wed, 1 Mar 2023 13:32:47 +0000 Subject: [PATCH 042/778] net: use indirect calls helpers for sk_exit_memory_pressure() Florian reported a regression and sent a patch with the following changelog: There is a noticeable tcp performance regression (loopback or cross-netns), seen with iperf3 -Z (sendfile mode) when generic retpolines are needed. With SK_RECLAIM_THRESHOLD checks gone number of calls to enter/leave memory pressure happen much more often. For TCP indirect calls are used. We can't remove the if-set-return short-circuit check in tcp_enter_memory_pressure because there are callers other than sk_enter_memory_pressure. Doing a check in the sk wrapper too reduces the indirect calls enough to recover some performance. Before, 0.00-60.00 sec 322 GBytes 46.1 Gbits/sec receiver After: 0.00-60.04 sec 359 GBytes 51.4 Gbits/sec receiver "iperf3 -c $peer -t 60 -Z -f g", connected via veth in another netns. It seems we forgot to upstream this indirect call mitigation we had for years, lets do this instead. [edumazet] - It seems we forgot to upstream this indirect call mitigation we had for years, let's do this instead. - Changed to INDIRECT_CALL_INET_1() to avoid bots reports. Fixes: 4890b686f408 ("net: keep sk->sk_forward_alloc as small as possible") Reported-by: Florian Westphal Link: https://lore.kernel.org/netdev/20230227152741.4a53634b@kernel.org/T/ Signed-off-by: Brian Vazquez Signed-off-by: Eric Dumazet Link: https://lore.kernel.org/r/20230301133247.2346111-1-edumazet@google.com Signed-off-by: Paolo Abeni --- net/core/sock.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/core/sock.c b/net/core/sock.c index 341c565dbc26..c25888795390 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -2818,7 +2818,8 @@ static void sk_enter_memory_pressure(struct sock *sk) static void sk_leave_memory_pressure(struct sock *sk) { if (sk->sk_prot->leave_memory_pressure) { - sk->sk_prot->leave_memory_pressure(sk); + INDIRECT_CALL_INET_1(sk->sk_prot->leave_memory_pressure, + tcp_leave_memory_pressure, sk); } else { unsigned long *memory_pressure = sk->sk_prot->memory_pressure; From 6c993779ea1d0cccdb3a5d7d45446dd229e610a3 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Thu, 16 Feb 2023 23:25:04 -0500 Subject: [PATCH 043/778] ca8210: fix mac_len negative array access This patch fixes a buffer overflow access of skb->data if ieee802154_hdr_peek_addrs() fails. Reported-by: lianhui tang Signed-off-by: Alexander Aring Link: https://lore.kernel.org/r/20230217042504.3303396-1-aahringo@redhat.com Signed-off-by: Stefan Schmidt --- drivers/net/ieee802154/ca8210.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/ieee802154/ca8210.c b/drivers/net/ieee802154/ca8210.c index e1a569b99e4a..0b0c6c0764fe 100644 --- a/drivers/net/ieee802154/ca8210.c +++ b/drivers/net/ieee802154/ca8210.c @@ -1913,6 +1913,8 @@ static int ca8210_skb_tx( * packet */ mac_len = ieee802154_hdr_peek_addrs(skb, &header); + if (mac_len < 0) + return mac_len; secspec.security_level = header.sec.level; secspec.key_id_mode = header.sec.key_id_mode; From 02f18662f6c671382345fcb696e808d78f4c194a Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Wed, 1 Mar 2023 16:44:50 +0100 Subject: [PATCH 044/778] ieee802154: Prevent user from crashing the host Avoid crashing the machine by checking info->attrs[NL802154_ATTR_SCAN_TYPE] presence before de-referencing it, which was the primary intend of the blamed patch. Reported-by: Sanan Hasanov Suggested-by: Eric Dumazet Fixes: a0b6106672b5 ("ieee802154: Convert scan error messages to extack") Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/r/20230301154450.547716-1-miquel.raynal@bootlin.com Signed-off-by: Stefan Schmidt --- net/ieee802154/nl802154.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c index 2215f576ee37..d8f4379d4fa6 100644 --- a/net/ieee802154/nl802154.c +++ b/net/ieee802154/nl802154.c @@ -1412,7 +1412,7 @@ static int nl802154_trigger_scan(struct sk_buff *skb, struct genl_info *info) return -EOPNOTSUPP; } - if (!nla_get_u8(info->attrs[NL802154_ATTR_SCAN_TYPE])) { + if (!info->attrs[NL802154_ATTR_SCAN_TYPE]) { NL_SET_ERR_MSG(info->extack, "Malformed request, missing scan type"); return -EINVAL; } From a98c0710b47d7dd44a351d08542360ff23f78330 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 23 Feb 2023 10:54:41 -0300 Subject: [PATCH 045/778] tools headers svm: Sync svm headers with the kernel sources To pick the changes in: 8c29f01654053258 ("x86/sev: Add SEV-SNP guest feature negotiation support") That triggers: CC /tmp/build/perf-tools/arch/x86/util/kvm-stat.o CC /tmp/build/perf-tools/util/header.o LD /tmp/build/perf-tools/arch/x86/util/perf-in.o LD /tmp/build/perf-tools/arch/x86/perf-in.o LD /tmp/build/perf-tools/arch/perf-in.o LD /tmp/build/perf-tools/util/perf-in.o LD /tmp/build/perf-tools/perf-in.o LINK /tmp/build/perf-tools/perf But this time causes no changes in tooling results, as the introduced SVM_VMGEXIT_TERM_REQUEST exit reason wasn't added to SVM_EXIT_REASONS, that is used in kvm-stat.c. And addresses this perf build warning: Warning: Kernel ABI header at 'tools/arch/x86/include/uapi/asm/svm.h' differs from latest version at 'arch/x86/include/uapi/asm/svm.h' diff -u tools/arch/x86/include/uapi/asm/svm.h arch/x86/include/uapi/asm/svm.h Cc: Adrian Hunter Cc: Borislav Petkov (AMD) Cc: Ian Rogers Cc: Jiri Olsa Cc: Namhyung Kim Cc: Nikunj A Dadhania Link: http://lore.kernel.org/lkml/ Signed-off-by: Arnaldo Carvalho de Melo --- tools/arch/x86/include/uapi/asm/svm.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/arch/x86/include/uapi/asm/svm.h b/tools/arch/x86/include/uapi/asm/svm.h index f69c168391aa..80e1df482337 100644 --- a/tools/arch/x86/include/uapi/asm/svm.h +++ b/tools/arch/x86/include/uapi/asm/svm.h @@ -116,6 +116,12 @@ #define SVM_VMGEXIT_AP_CREATE 1 #define SVM_VMGEXIT_AP_DESTROY 2 #define SVM_VMGEXIT_HV_FEATURES 0x8000fffd +#define SVM_VMGEXIT_TERM_REQUEST 0x8000fffe +#define SVM_VMGEXIT_TERM_REASON(reason_set, reason_code) \ + /* SW_EXITINFO1[3:0] */ \ + (((((u64)reason_set) & 0xf)) | \ + /* SW_EXITINFO1[11:4] */ \ + ((((u64)reason_code) & 0xff) << 4)) #define SVM_VMGEXIT_UNSUPPORTED_EVENT 0x8000ffff /* Exit code reserved for hypervisor/software use */ From 25f69c69bc3ca8c781a94473f28d443d745768e3 Mon Sep 17 00:00:00 2001 From: Changbin Du Date: Thu, 2 Mar 2023 11:11:44 +0800 Subject: [PATCH 046/778] perf stat: Fix counting when initial delay configured When creating counters with initial delay configured, the enable_on_exec field is not set. So we need to enable the counters later. The problem is, when a workload is specified the target__none() is true. So we also need to check stat_config.initial_delay. In this change, we add a new field 'initial_delay' for struct target which could be shared by other subcommands. And define target__enable_on_exec() which returns whether enable_on_exec should be set on normal cases. Before this fix the event is not counted: $ ./perf stat -e instructions -D 100 sleep 2 Events disabled Events enabled Performance counter stats for 'sleep 2': instructions 1.901661124 seconds time elapsed 0.001602000 seconds user 0.000000000 seconds sys After fix it works: $ ./perf stat -e instructions -D 100 sleep 2 Events disabled Events enabled Performance counter stats for 'sleep 2': 404,214 instructions 1.901743475 seconds time elapsed 0.001617000 seconds user 0.000000000 seconds sys Fixes: c587e77e100fa40e ("perf stat: Do not delay the workload with --delay") Signed-off-by: Changbin Du Acked-by: Namhyung Kim Cc: Alexander Shishkin Cc: Hui Wang Cc: Ingo Molnar Cc: Jiri Olsa Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Link: https://lore.kernel.org/r/20230302031146.2801588-2-changbin.du@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 15 +++++---------- tools/perf/util/stat.c | 6 +----- tools/perf/util/stat.h | 1 - tools/perf/util/target.h | 12 ++++++++++++ 4 files changed, 18 insertions(+), 16 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 5d18a5a6f662..fa7c40956d0f 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -539,12 +539,7 @@ static int enable_counters(void) return err; } - /* - * We need to enable counters only if: - * - we don't have tracee (attaching to task or cpu) - * - we have initial delay configured - */ - if (!target__none(&target)) { + if (!target__enable_on_exec(&target)) { if (!all_counters_use_bpf) evlist__enable(evsel_list); } @@ -914,7 +909,7 @@ try_again_reset: return err; } - if (stat_config.initial_delay) { + if (target.initial_delay) { pr_info(EVLIST_DISABLED_MSG); } else { err = enable_counters(); @@ -926,8 +921,8 @@ try_again_reset: if (forks) evlist__start_workload(evsel_list); - if (stat_config.initial_delay > 0) { - usleep(stat_config.initial_delay * USEC_PER_MSEC); + if (target.initial_delay > 0) { + usleep(target.initial_delay * USEC_PER_MSEC); err = enable_counters(); if (err) return -1; @@ -1248,7 +1243,7 @@ static struct option stat_options[] = { "aggregate counts per thread", AGGR_THREAD), OPT_SET_UINT(0, "per-node", &stat_config.aggr_mode, "aggregate counts per numa node", AGGR_NODE), - OPT_INTEGER('D', "delay", &stat_config.initial_delay, + OPT_INTEGER('D', "delay", &target.initial_delay, "ms to wait before starting measurement after program start (-1: start with events disabled)"), OPT_CALLBACK_NOOPT(0, "metric-only", &stat_config.metric_only, NULL, "Only print computed metrics. No raw values", enable_metric_only), diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c index 534d36d26fc3..a07473703c6d 100644 --- a/tools/perf/util/stat.c +++ b/tools/perf/util/stat.c @@ -842,11 +842,7 @@ int create_perf_stat_counter(struct evsel *evsel, if (evsel__is_group_leader(evsel)) { attr->disabled = 1; - /* - * In case of initial_delay we enable tracee - * events manually. - */ - if (target__none(target) && !config->initial_delay) + if (target__enable_on_exec(target)) attr->enable_on_exec = 1; } diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index b1c29156c560..bf1794ebc916 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h @@ -166,7 +166,6 @@ struct perf_stat_config { FILE *output; unsigned int interval; unsigned int timeout; - int initial_delay; unsigned int unit_width; unsigned int metric_only_len; int times; diff --git a/tools/perf/util/target.h b/tools/perf/util/target.h index daec6cba500d..880f1af7f6ad 100644 --- a/tools/perf/util/target.h +++ b/tools/perf/util/target.h @@ -18,6 +18,7 @@ struct target { bool per_thread; bool use_bpf; bool hybrid; + int initial_delay; const char *attr_map; }; @@ -72,6 +73,17 @@ static inline bool target__none(struct target *target) return !target__has_task(target) && !target__has_cpu(target); } +static inline bool target__enable_on_exec(struct target *target) +{ + /* + * Normally enable_on_exec should be set if: + * 1) The tracee process is forked (not attaching to existed task or cpu). + * 2) And initial_delay is not configured. + * Otherwise, we enable tracee events manually. + */ + return target__none(target) && !target->initial_delay; +} + static inline bool target__has_per_thread(struct target *target) { return target->system_wide && target->per_thread; From e57cf3639c323eeed05d3725fd82f91b349adca8 Mon Sep 17 00:00:00 2001 From: Yuiko Oshino Date: Wed, 1 Mar 2023 08:43:07 -0700 Subject: [PATCH 047/778] net: lan78xx: fix accessing the LAN7800's internal phy specific registers from the MAC driver Move the LAN7800 internal phy (phy ID 0x0007c132) specific register accesses to the phy driver (microchip.c). Fix the error reported by Enguerrand de Ribaucourt in December 2022, "Some operations during the cable switch workaround modify the register LAN88XX_INT_MASK of the PHY. However, this register is specific to the LAN8835 PHY. For instance, if a DP8322I PHY is connected to the LAN7801, that register (0x19), corresponds to the LED and MAC address configuration, resulting in unapropriate behavior." I did not test with the DP8322I PHY, but I tested with an EVB-LAN7800 with the internal PHY. Fixes: 14437e3fa284 ("lan78xx: workaround of forced 100 Full/Half duplex mode error") Signed-off-by: Yuiko Oshino Reviewed-by: Andrew Lunn Link: https://lore.kernel.org/r/20230301154307.30438-1-yuiko.oshino@microchip.com Signed-off-by: Jakub Kicinski --- drivers/net/phy/microchip.c | 32 ++++++++++++++++++++++++++++++++ drivers/net/usb/lan78xx.c | 27 +-------------------------- 2 files changed, 33 insertions(+), 26 deletions(-) diff --git a/drivers/net/phy/microchip.c b/drivers/net/phy/microchip.c index ccecee2524ce..0b88635f4fbc 100644 --- a/drivers/net/phy/microchip.c +++ b/drivers/net/phy/microchip.c @@ -342,6 +342,37 @@ static int lan88xx_config_aneg(struct phy_device *phydev) return genphy_config_aneg(phydev); } +static void lan88xx_link_change_notify(struct phy_device *phydev) +{ + int temp; + + /* At forced 100 F/H mode, chip may fail to set mode correctly + * when cable is switched between long(~50+m) and short one. + * As workaround, set to 10 before setting to 100 + * at forced 100 F/H mode. + */ + if (!phydev->autoneg && phydev->speed == 100) { + /* disable phy interrupt */ + temp = phy_read(phydev, LAN88XX_INT_MASK); + temp &= ~LAN88XX_INT_MASK_MDINTPIN_EN_; + phy_write(phydev, LAN88XX_INT_MASK, temp); + + temp = phy_read(phydev, MII_BMCR); + temp &= ~(BMCR_SPEED100 | BMCR_SPEED1000); + phy_write(phydev, MII_BMCR, temp); /* set to 10 first */ + temp |= BMCR_SPEED100; + phy_write(phydev, MII_BMCR, temp); /* set to 100 later */ + + /* clear pending interrupt generated while workaround */ + temp = phy_read(phydev, LAN88XX_INT_STS); + + /* enable phy interrupt back */ + temp = phy_read(phydev, LAN88XX_INT_MASK); + temp |= LAN88XX_INT_MASK_MDINTPIN_EN_; + phy_write(phydev, LAN88XX_INT_MASK, temp); + } +} + static struct phy_driver microchip_phy_driver[] = { { .phy_id = 0x0007c132, @@ -359,6 +390,7 @@ static struct phy_driver microchip_phy_driver[] = { .config_init = lan88xx_config_init, .config_aneg = lan88xx_config_aneg, + .link_change_notify = lan88xx_link_change_notify, .config_intr = lan88xx_phy_config_intr, .handle_interrupt = lan88xx_handle_interrupt, diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c index f18ab8e220db..068488890d57 100644 --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c @@ -2115,33 +2115,8 @@ static void lan78xx_remove_mdio(struct lan78xx_net *dev) static void lan78xx_link_status_change(struct net_device *net) { struct phy_device *phydev = net->phydev; - int temp; - /* At forced 100 F/H mode, chip may fail to set mode correctly - * when cable is switched between long(~50+m) and short one. - * As workaround, set to 10 before setting to 100 - * at forced 100 F/H mode. - */ - if (!phydev->autoneg && (phydev->speed == 100)) { - /* disable phy interrupt */ - temp = phy_read(phydev, LAN88XX_INT_MASK); - temp &= ~LAN88XX_INT_MASK_MDINTPIN_EN_; - phy_write(phydev, LAN88XX_INT_MASK, temp); - - temp = phy_read(phydev, MII_BMCR); - temp &= ~(BMCR_SPEED100 | BMCR_SPEED1000); - phy_write(phydev, MII_BMCR, temp); /* set to 10 first */ - temp |= BMCR_SPEED100; - phy_write(phydev, MII_BMCR, temp); /* set to 100 later */ - - /* clear pending interrupt generated while workaround */ - temp = phy_read(phydev, LAN88XX_INT_STS); - - /* enable phy interrupt back */ - temp = phy_read(phydev, LAN88XX_INT_MASK); - temp |= LAN88XX_INT_MASK_MDINTPIN_EN_; - phy_write(phydev, LAN88XX_INT_MASK, temp); - } + phy_print_status(phydev); } static int irq_map(struct irq_domain *d, unsigned int irq, From 9781e98a97110f5e76999058368b4be76a788484 Mon Sep 17 00:00:00 2001 From: Shigeru Yoshida Date: Thu, 2 Mar 2023 01:39:13 +0900 Subject: [PATCH 048/778] net: caif: Fix use-after-free in cfusbl_device_notify() syzbot reported use-after-free in cfusbl_device_notify() [1]. This causes a stack trace like below: BUG: KASAN: use-after-free in cfusbl_device_notify+0x7c9/0x870 net/caif/caif_usb.c:138 Read of size 8 at addr ffff88807ac4e6f0 by task kworker/u4:6/1214 CPU: 0 PID: 1214 Comm: kworker/u4:6 Not tainted 5.19.0-rc3-syzkaller-00146-g92f20ff72066 #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 Workqueue: netns cleanup_net Call Trace: __dump_stack lib/dump_stack.c:88 [inline] dump_stack_lvl+0xcd/0x134 lib/dump_stack.c:106 print_address_description.constprop.0.cold+0xeb/0x467 mm/kasan/report.c:313 print_report mm/kasan/report.c:429 [inline] kasan_report.cold+0xf4/0x1c6 mm/kasan/report.c:491 cfusbl_device_notify+0x7c9/0x870 net/caif/caif_usb.c:138 notifier_call_chain+0xb5/0x200 kernel/notifier.c:87 call_netdevice_notifiers_info+0xb5/0x130 net/core/dev.c:1945 call_netdevice_notifiers_extack net/core/dev.c:1983 [inline] call_netdevice_notifiers net/core/dev.c:1997 [inline] netdev_wait_allrefs_any net/core/dev.c:10227 [inline] netdev_run_todo+0xbc0/0x10f0 net/core/dev.c:10341 default_device_exit_batch+0x44e/0x590 net/core/dev.c:11334 ops_exit_list+0x125/0x170 net/core/net_namespace.c:167 cleanup_net+0x4ea/0xb00 net/core/net_namespace.c:594 process_one_work+0x996/0x1610 kernel/workqueue.c:2289 worker_thread+0x665/0x1080 kernel/workqueue.c:2436 kthread+0x2e9/0x3a0 kernel/kthread.c:376 ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:302 When unregistering a net device, unregister_netdevice_many_notify() sets the device's reg_state to NETREG_UNREGISTERING, calls notifiers with NETDEV_UNREGISTER, and adds the device to the todo list. Later on, devices in the todo list are processed by netdev_run_todo(). netdev_run_todo() waits devices' reference count become 1 while rebdoadcasting NETDEV_UNREGISTER notification. When cfusbl_device_notify() is called with NETDEV_UNREGISTER multiple times, the parent device might be freed. This could cause UAF. Processing NETDEV_UNREGISTER multiple times also causes inbalance of reference count for the module. This patch fixes the issue by accepting only first NETDEV_UNREGISTER notification. Fixes: 7ad65bf68d70 ("caif: Add support for CAIF over CDC NCM USB interface") CC: sjur.brandeland@stericsson.com Reported-by: syzbot+b563d33852b893653a9e@syzkaller.appspotmail.com Link: https://syzkaller.appspot.com/bug?id=c3bfd8e2450adab3bffe4d80821fbbced600407f [1] Signed-off-by: Shigeru Yoshida Link: https://lore.kernel.org/r/20230301163913.391304-1-syoshida@redhat.com Signed-off-by: Jakub Kicinski --- net/caif/caif_usb.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/caif/caif_usb.c b/net/caif/caif_usb.c index ebc202ffdd8d..bf61ea4b8132 100644 --- a/net/caif/caif_usb.c +++ b/net/caif/caif_usb.c @@ -134,6 +134,9 @@ static int cfusbl_device_notify(struct notifier_block *me, unsigned long what, struct usb_device *usbdev; int res; + if (what == NETDEV_UNREGISTER && dev->reg_state >= NETREG_UNREGISTERED) + return 0; + /* Check whether we have a NCM device, and find its VID/PID. */ if (!(dev->dev.parent && dev->dev.parent->driver && strcmp(dev->dev.parent->driver->name, "cdc_ncm") == 0)) From 7cf93538e087a792cb476008a757ab7c1c23b68c Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Wed, 1 Mar 2023 10:36:40 -0800 Subject: [PATCH 049/778] tools: ynl: fully inherit attrs in subsets To avoid having to repeat the entire definition of an attribute (including the value) use the Attr object from the original set. In fact this is already the documented expectation. Fixes: be5bea1cc0bf ("net: add basic C code generators for Netlink") Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- Documentation/userspace-api/netlink/specs.rst | 3 ++- tools/net/ynl/lib/nlspec.py | 23 ++++++++++++------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/Documentation/userspace-api/netlink/specs.rst b/Documentation/userspace-api/netlink/specs.rst index 6ffe8137cd90..1424ab1b9b33 100644 --- a/Documentation/userspace-api/netlink/specs.rst +++ b/Documentation/userspace-api/netlink/specs.rst @@ -199,7 +199,8 @@ The ``value`` property can be skipped, in which case the attribute ID will be the value of the previous attribute plus one (recursively) and ``0`` for the first attribute in the attribute set. -Note that the ``value`` of an attribute is defined only in its main set. +Note that the ``value`` of an attribute is defined only in its main set +(not in subsets). enum ~~~~ diff --git a/tools/net/ynl/lib/nlspec.py b/tools/net/ynl/lib/nlspec.py index 71da568e2c28..dff31dad36c5 100644 --- a/tools/net/ynl/lib/nlspec.py +++ b/tools/net/ynl/lib/nlspec.py @@ -95,15 +95,22 @@ class SpecAttrSet(SpecElement): self.attrs = collections.OrderedDict() self.attrs_by_val = collections.OrderedDict() - val = 0 - for elem in self.yaml['attributes']: - if 'value' in elem: - val = elem['value'] + if self.subset_of is None: + val = 0 + for elem in self.yaml['attributes']: + if 'value' in elem: + val = elem['value'] - attr = self.new_attr(elem, val) - self.attrs[attr.name] = attr - self.attrs_by_val[attr.value] = attr - val += 1 + attr = self.new_attr(elem, val) + self.attrs[attr.name] = attr + self.attrs_by_val[attr.value] = attr + val += 1 + else: + real_set = family.attr_sets[self.subset_of] + for elem in self.yaml['attributes']: + attr = real_set[elem['name']] + self.attrs[attr.name] = attr + self.attrs_by_val[attr.value] = attr def new_attr(self, elem, value): return SpecAttr(self.family, self, elem, value) From ad4fafcde5bc1badb8fc2c7f260a5d6b83a038e4 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Wed, 1 Mar 2023 10:36:41 -0800 Subject: [PATCH 050/778] tools: ynl: use 1 as the default for first entry in attrs/ops Pretty much all families use value: 1 or reserve as unspec the first entry in attribute set and the first operation. Make this the default. Update documentation (the doc for values of operations just refers back to doc for attrs so updating only attrs). Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- Documentation/userspace-api/netlink/specs.rst | 7 ++++++- tools/net/ynl/lib/nlspec.py | 6 +++--- tools/net/ynl/ynl-gen-c.py | 7 +++++-- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/Documentation/userspace-api/netlink/specs.rst b/Documentation/userspace-api/netlink/specs.rst index 1424ab1b9b33..32e53328d113 100644 --- a/Documentation/userspace-api/netlink/specs.rst +++ b/Documentation/userspace-api/netlink/specs.rst @@ -197,7 +197,12 @@ value Numerical attribute ID, used in serialized Netlink messages. The ``value`` property can be skipped, in which case the attribute ID will be the value of the previous attribute plus one (recursively) -and ``0`` for the first attribute in the attribute set. +and ``1`` for the first attribute in the attribute set. + +Attributes (and operations) use ``1`` as the default value for the first +entry (unlike enums in definitions which start from ``0``) because +entry ``0`` is almost always reserved as undefined. Spec can explicitly +set value to ``0`` if needed. Note that the ``value`` of an attribute is defined only in its main set (not in subsets). diff --git a/tools/net/ynl/lib/nlspec.py b/tools/net/ynl/lib/nlspec.py index dff31dad36c5..9d394e50de23 100644 --- a/tools/net/ynl/lib/nlspec.py +++ b/tools/net/ynl/lib/nlspec.py @@ -96,7 +96,7 @@ class SpecAttrSet(SpecElement): self.attrs_by_val = collections.OrderedDict() if self.subset_of is None: - val = 0 + val = 1 for elem in self.yaml['attributes']: if 'value' in elem: val = elem['value'] @@ -252,7 +252,7 @@ class SpecFamily(SpecElement): self._resolution_list.append(elem) def _dictify_ops_unified(self): - val = 0 + val = 1 for elem in self.yaml['operations']['list']: if 'value' in elem: val = elem['value'] @@ -263,7 +263,7 @@ class SpecFamily(SpecElement): self.msgs[op.name] = op def _dictify_ops_directional(self): - req_val = rsp_val = 0 + req_val = rsp_val = 1 for elem in self.yaml['operations']['list']: if 'notify' in elem: if 'value' in elem: diff --git a/tools/net/ynl/ynl-gen-c.py b/tools/net/ynl/ynl-gen-c.py index 274e9c566f61..62f8f2c3c56c 100755 --- a/tools/net/ynl/ynl-gen-c.py +++ b/tools/net/ynl/ynl-gen-c.py @@ -2044,14 +2044,17 @@ def render_uapi(family, cw): max_value = f"({cnt_name} - 1)" uapi_enum_start(family, cw, family['operations'], 'enum-name') + val = 0 for op in family.msgs.values(): if separate_ntf and ('notify' in op or 'event' in op): continue suffix = ',' - if 'value' in op: - suffix = f" = {op['value']}," + if op.value != val: + suffix = f" = {op.value}," + val = op.value cw.p(op.enum_name + suffix) + val += 1 cw.nl() cw.p(cnt_name + ('' if max_by_define else ',')) if not max_by_define: From bcec7171eba901cc5f427ebbad9fe17ed4749b8f Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Wed, 1 Mar 2023 10:36:42 -0800 Subject: [PATCH 051/778] netlink: specs: update for codegen enumerating from 1 Now that the codegen rules had been changed we can update the specs to reflect the new default. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- Documentation/netlink/specs/ethtool.yaml | 15 --------------- Documentation/netlink/specs/fou.yaml | 2 ++ Documentation/netlink/specs/netdev.yaml | 2 -- 3 files changed, 2 insertions(+), 17 deletions(-) diff --git a/Documentation/netlink/specs/ethtool.yaml b/Documentation/netlink/specs/ethtool.yaml index 08b776908d15..35c462bce56f 100644 --- a/Documentation/netlink/specs/ethtool.yaml +++ b/Documentation/netlink/specs/ethtool.yaml @@ -11,7 +11,6 @@ attribute-sets: - name: dev-index type: u32 - value: 1 - name: dev-name type: string @@ -25,7 +24,6 @@ attribute-sets: - name: index type: u32 - value: 1 - name: name type: string @@ -39,14 +37,12 @@ attribute-sets: name: bit type: nest nested-attributes: bitset-bit - value: 1 - name: bitset attributes: - name: nomask type: flag - value: 1 - name: size type: u32 @@ -61,7 +57,6 @@ attribute-sets: - name: index type: u32 - value: 1 - name: value type: string @@ -71,7 +66,6 @@ attribute-sets: - name: string type: nest - value: 1 multi-attr: true nested-attributes: string - @@ -80,7 +74,6 @@ attribute-sets: - name: id type: u32 - value: 1 - name: count type: u32 @@ -96,14 +89,12 @@ attribute-sets: name: stringset type: nest multi-attr: true - value: 1 nested-attributes: stringset - name: strset attributes: - name: header - value: 1 type: nest nested-attributes: header - @@ -119,7 +110,6 @@ attribute-sets: attributes: - name: header - value: 1 type: nest nested-attributes: header - @@ -132,7 +122,6 @@ attribute-sets: attributes: - name: header - value: 1 type: nest nested-attributes: header - @@ -180,7 +169,6 @@ attribute-sets: attributes: - name: pad - value: 1 type: pad - name: reassembly-errors @@ -205,7 +193,6 @@ attribute-sets: attributes: - name: header - value: 1 type: nest nested-attributes: header - @@ -251,13 +238,11 @@ operations: do: &strset-get-op request: - value: 1 attributes: - header - stringsets - counts-only reply: - value: 1 attributes: - header - stringsets diff --git a/Documentation/netlink/specs/fou.yaml b/Documentation/netlink/specs/fou.yaml index 266c386eedf3..cca4cf98f03a 100644 --- a/Documentation/netlink/specs/fou.yaml +++ b/Documentation/netlink/specs/fou.yaml @@ -26,6 +26,7 @@ attribute-sets: - name: unspec type: unused + value: 0 - name: port type: u16 @@ -71,6 +72,7 @@ operations: - name: unspec doc: unused + value: 0 - name: add diff --git a/Documentation/netlink/specs/netdev.yaml b/Documentation/netlink/specs/netdev.yaml index cffef09729f1..ba9ee13cf729 100644 --- a/Documentation/netlink/specs/netdev.yaml +++ b/Documentation/netlink/specs/netdev.yaml @@ -48,7 +48,6 @@ attribute-sets: name: ifindex doc: netdev ifindex type: u32 - value: 1 checks: min: 1 - @@ -66,7 +65,6 @@ operations: - name: dev-get doc: Get / dump information about a netdev. - value: 1 attribute-set: dev do: request: From 84cba1840e68430325ac133a11be06bfb2f7acd8 Mon Sep 17 00:00:00 2001 From: Petr Oros Date: Wed, 1 Mar 2023 21:47:07 +0100 Subject: [PATCH 052/778] ice: copy last block omitted in ice_get_module_eeprom() ice_get_module_eeprom() is broken since commit e9c9692c8a81 ("ice: Reimplement module reads used by ethtool") In this refactor, ice_get_module_eeprom() reads the eeprom in blocks of size 8. But the condition that should protect the buffer overflow ignores the last block. The last block always contains zeros. Bug uncovered by ethtool upstream commit 9538f384b535 ("netlink: eeprom: Defer page requests to individual parsers") After this commit, ethtool reads a block with length = 1; to read the SFF-8024 identifier value. unpatched driver: $ ethtool -m enp65s0f0np0 offset 0x90 length 8 Offset Values ------ ------ 0x0090: 00 00 00 00 00 00 00 00 $ ethtool -m enp65s0f0np0 offset 0x90 length 12 Offset Values ------ ------ 0x0090: 00 00 01 a0 4d 65 6c 6c 00 00 00 00 $ $ ethtool -m enp65s0f0np0 Offset Values ------ ------ 0x0000: 11 06 06 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0060: 00 00 00 00 00 00 00 00 00 00 00 00 00 01 08 00 0x0070: 00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 patched driver: $ ethtool -m enp65s0f0np0 offset 0x90 length 8 Offset Values ------ ------ 0x0090: 00 00 01 a0 4d 65 6c 6c $ ethtool -m enp65s0f0np0 offset 0x90 length 12 Offset Values ------ ------ 0x0090: 00 00 01 a0 4d 65 6c 6c 61 6e 6f 78 $ ethtool -m enp65s0f0np0 Identifier : 0x11 (QSFP28) Extended identifier : 0x00 Extended identifier description : 1.5W max. Power consumption Extended identifier description : No CDR in TX, No CDR in RX Extended identifier description : High Power Class (> 3.5 W) not enabled Connector : 0x23 (No separable connector) Transceiver codes : 0x88 0x00 0x00 0x00 0x00 0x00 0x00 0x00 Transceiver type : 40G Ethernet: 40G Base-CR4 Transceiver type : 25G Ethernet: 25G Base-CR CA-N Encoding : 0x05 (64B/66B) BR, Nominal : 25500Mbps Rate identifier : 0x00 Length (SMF,km) : 0km Length (OM3 50um) : 0m Length (OM2 50um) : 0m Length (OM1 62.5um) : 0m Length (Copper or Active cable) : 1m Transmitter technology : 0xa0 (Copper cable unequalized) Attenuation at 2.5GHz : 4db Attenuation at 5.0GHz : 5db Attenuation at 7.0GHz : 7db Attenuation at 12.9GHz : 10db ........ .... Fixes: e9c9692c8a81 ("ice: Reimplement module reads used by ethtool") Signed-off-by: Petr Oros Reviewed-by: Jesse Brandeburg Tested-by: Jesse Brandeburg Signed-off-by: David S. Miller --- drivers/net/ethernet/intel/ice/ice_ethtool.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c index b360bd8f1599..f86e814354a3 100644 --- a/drivers/net/ethernet/intel/ice/ice_ethtool.c +++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c @@ -4331,6 +4331,8 @@ ice_get_module_eeprom(struct net_device *netdev, * SFP modules only ever use page 0. */ if (page == 0 || !(data[0x2] & 0x4)) { + u32 copy_len; + /* If i2c bus is busy due to slow page change or * link management access, call can fail. This is normal. * So we retry this a few times. @@ -4354,8 +4356,8 @@ ice_get_module_eeprom(struct net_device *netdev, } /* Make sure we have enough room for the new block */ - if ((i + SFF_READ_BLOCK_SIZE) < ee->len) - memcpy(data + i, value, SFF_READ_BLOCK_SIZE); + copy_len = min_t(u32, SFF_READ_BLOCK_SIZE, ee->len - i); + memcpy(data + i, value, copy_len); } } return 0; From 3e04419cbe2d0bc10ffc20c006c6513ffa4b1ca3 Mon Sep 17 00:00:00 2001 From: Huanhuan Wang Date: Thu, 2 Mar 2023 10:58:28 +0100 Subject: [PATCH 053/778] nfp: fix incorrectly set csum flag for nfd3 path The csum flag of IPsec packet are set repeatedly. Therefore, the csum flag set of IPsec and non-IPsec packet need to be distinguished. As the ipv6 header does not have a csum field, so l3-csum flag is not required to be set for ipv6 case. L4-csum flag include the tcp csum flag and udp csum flag, we shouldn't set the udp and tcp csum flag at the same time for one packet, should set l4-csum flag according to the transport layer is tcp or udp. Fixes: 57f273adbcd4 ("nfp: add framework to support ipsec offloading") Signed-off-by: Huanhuan Wang Reviewed-by: Louis Peens Signed-off-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/nfd3/dp.c | 7 +++--- .../net/ethernet/netronome/nfp/nfd3/ipsec.c | 25 +++++++++++++++++-- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/netronome/nfp/nfd3/dp.c b/drivers/net/ethernet/netronome/nfp/nfd3/dp.c index 59fb0583cc08..0cc026b0aefd 100644 --- a/drivers/net/ethernet/netronome/nfp/nfd3/dp.c +++ b/drivers/net/ethernet/netronome/nfp/nfd3/dp.c @@ -324,14 +324,15 @@ netdev_tx_t nfp_nfd3_tx(struct sk_buff *skb, struct net_device *netdev) /* Do not reorder - tso may adjust pkt cnt, vlan may override fields */ nfp_nfd3_tx_tso(r_vec, txbuf, txd, skb, md_bytes); - nfp_nfd3_tx_csum(dp, r_vec, txbuf, txd, skb); + if (ipsec) + nfp_nfd3_ipsec_tx(txd, skb); + else + nfp_nfd3_tx_csum(dp, r_vec, txbuf, txd, skb); if (skb_vlan_tag_present(skb) && dp->ctrl & NFP_NET_CFG_CTRL_TXVLAN) { txd->flags |= NFD3_DESC_TX_VLAN; txd->vlan = cpu_to_le16(skb_vlan_tag_get(skb)); } - if (ipsec) - nfp_nfd3_ipsec_tx(txd, skb); /* Gather DMA */ if (nr_frags > 0) { __le64 second_half; diff --git a/drivers/net/ethernet/netronome/nfp/nfd3/ipsec.c b/drivers/net/ethernet/netronome/nfp/nfd3/ipsec.c index e90f8c975903..51087693072c 100644 --- a/drivers/net/ethernet/netronome/nfp/nfd3/ipsec.c +++ b/drivers/net/ethernet/netronome/nfp/nfd3/ipsec.c @@ -10,9 +10,30 @@ void nfp_nfd3_ipsec_tx(struct nfp_nfd3_tx_desc *txd, struct sk_buff *skb) { struct xfrm_state *x = xfrm_input_state(skb); + struct xfrm_offload *xo = xfrm_offload(skb); + struct iphdr *iph = ip_hdr(skb); + int l4_proto; if (x->xso.dev && (x->xso.dev->features & NETIF_F_HW_ESP_TX_CSUM)) { - txd->flags |= NFD3_DESC_TX_CSUM | NFD3_DESC_TX_IP4_CSUM | - NFD3_DESC_TX_TCP_CSUM | NFD3_DESC_TX_UDP_CSUM; + txd->flags |= NFD3_DESC_TX_CSUM; + + if (iph->version == 4) + txd->flags |= NFD3_DESC_TX_IP4_CSUM; + + if (x->props.mode == XFRM_MODE_TRANSPORT) + l4_proto = xo->proto; + else if (x->props.mode == XFRM_MODE_TUNNEL) + l4_proto = xo->inner_ipproto; + else + return; + + switch (l4_proto) { + case IPPROTO_UDP: + txd->flags |= NFD3_DESC_TX_UDP_CSUM; + return; + case IPPROTO_TCP: + txd->flags |= NFD3_DESC_TX_TCP_CSUM; + return; + } } } From 8b46168ca79c3aad04bc20605e523127266624d4 Mon Sep 17 00:00:00 2001 From: Huanhuan Wang Date: Thu, 2 Mar 2023 10:58:29 +0100 Subject: [PATCH 054/778] nfp: fix incorrectly set csum flag for nfdk path The csum flag of IPsec packet are set repeatedly. Therefore, the csum flag set of IPsec and non-IPsec packet need to be distinguished. As the ipv6 header does not have a csum field, so l3-csum flag is not required to be set for ipv6 case. Fixes: 436396f26d50 ("nfp: support IPsec offloading for NFP3800") Signed-off-by: Huanhuan Wang Reviewed-by: Louis Peens Signed-off-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/nfdk/dp.c | 6 ++++-- drivers/net/ethernet/netronome/nfp/nfdk/ipsec.c | 8 ++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/netronome/nfp/nfdk/dp.c b/drivers/net/ethernet/netronome/nfp/nfdk/dp.c index d60c0e991a91..33b6d74adb4b 100644 --- a/drivers/net/ethernet/netronome/nfp/nfdk/dp.c +++ b/drivers/net/ethernet/netronome/nfp/nfdk/dp.c @@ -387,7 +387,8 @@ netdev_tx_t nfp_nfdk_tx(struct sk_buff *skb, struct net_device *netdev) if (!skb_is_gso(skb)) { real_len = skb->len; /* Metadata desc */ - metadata = nfp_nfdk_tx_csum(dp, r_vec, 1, skb, metadata); + if (!ipsec) + metadata = nfp_nfdk_tx_csum(dp, r_vec, 1, skb, metadata); txd->raw = cpu_to_le64(metadata); txd++; } else { @@ -395,7 +396,8 @@ netdev_tx_t nfp_nfdk_tx(struct sk_buff *skb, struct net_device *netdev) (txd + 1)->raw = nfp_nfdk_tx_tso(r_vec, txbuf, skb); real_len = txbuf->real_len; /* Metadata desc */ - metadata = nfp_nfdk_tx_csum(dp, r_vec, txbuf->pkt_cnt, skb, metadata); + if (!ipsec) + metadata = nfp_nfdk_tx_csum(dp, r_vec, txbuf->pkt_cnt, skb, metadata); txd->raw = cpu_to_le64(metadata); txd += 2; txbuf++; diff --git a/drivers/net/ethernet/netronome/nfp/nfdk/ipsec.c b/drivers/net/ethernet/netronome/nfp/nfdk/ipsec.c index 58d8f59eb885..cec199f4c852 100644 --- a/drivers/net/ethernet/netronome/nfp/nfdk/ipsec.c +++ b/drivers/net/ethernet/netronome/nfp/nfdk/ipsec.c @@ -9,9 +9,13 @@ u64 nfp_nfdk_ipsec_tx(u64 flags, struct sk_buff *skb) { struct xfrm_state *x = xfrm_input_state(skb); + struct iphdr *iph = ip_hdr(skb); - if (x->xso.dev && (x->xso.dev->features & NETIF_F_HW_ESP_TX_CSUM)) - flags |= NFDK_DESC_TX_L3_CSUM | NFDK_DESC_TX_L4_CSUM; + if (x->xso.dev && (x->xso.dev->features & NETIF_F_HW_ESP_TX_CSUM)) { + if (iph->version == 4) + flags |= NFDK_DESC_TX_L3_CSUM; + flags |= NFDK_DESC_TX_L4_CSUM; + } return flags; } From 1cf78d4c4144ffdbc2c9d505db482cb204bb480b Mon Sep 17 00:00:00 2001 From: Huanhuan Wang Date: Thu, 2 Mar 2023 10:58:30 +0100 Subject: [PATCH 055/778] nfp: fix esp-tx-csum-offload doesn't take effect When esp-tx-csum-offload is set to on, the protocol stack shouldn't calculate the IPsec offload packet's csum, but it does. Because the callback `.ndo_features_check` incorrectly masked NETIF_F_CSUM_MASK bit. Fixes: 57f273adbcd4 ("nfp: add framework to support ipsec offloading") Signed-off-by: Huanhuan Wang Signed-off-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/nfp_net_common.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index 81b7ca0ad222..62f0bf91d1e1 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -38,6 +38,7 @@ #include #include #include +#include #include "nfpcore/nfp_dev.h" #include "nfpcore/nfp_nsp.h" @@ -1897,6 +1898,9 @@ nfp_net_features_check(struct sk_buff *skb, struct net_device *dev, features &= ~NETIF_F_GSO_MASK; } + if (xfrm_offload(skb)) + return features; + /* VXLAN/GRE check */ switch (vlan_get_protocol(skb)) { case htons(ETH_P_IP): From db50f7a3983f0154e730f1147ef729e0c5c2f90c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Szalecki?= Date: Wed, 1 Mar 2023 02:23:56 +0100 Subject: [PATCH 056/778] HID: logitech-hidpp: Add support for Logitech MX Master 3S mouse MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add signature for the Logitech MX Master 3S mouse over Bluetooth. Signed-off-by: Rafał Szalecki Reviewed-by: Bastien Nocera Signed-off-by: Jiri Kosina --- drivers/hid/hid-logitech-hidpp.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c index 25dcda76d6c7..5fc88a063297 100644 --- a/drivers/hid/hid-logitech-hidpp.c +++ b/drivers/hid/hid-logitech-hidpp.c @@ -4399,6 +4399,8 @@ static const struct hid_device_id hidpp_devices[] = { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb02a) }, { /* MX Master 3 mouse over Bluetooth */ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb023) }, + { /* MX Master 3S mouse over Bluetooth */ + HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb034) }, {} }; From 8ae2f2b0a28416ed2f6d8478ac8b9f7862f36785 Mon Sep 17 00:00:00 2001 From: Reka Norman Date: Mon, 27 Feb 2023 13:49:38 +1100 Subject: [PATCH 057/778] HID: intel-ish-hid: ipc: Fix potential use-after-free in work function When a reset notify IPC message is received, the ISR schedules a work function and passes the ISHTP device to it via a global pointer ishtp_dev. If ish_probe() fails, the devm-managed device resources including ishtp_dev are freed, but the work is not cancelled, causing a use-after-free when the work function tries to access ishtp_dev. Use devm_work_autocancel() instead, so that the work is automatically cancelled if probe fails. Signed-off-by: Reka Norman Acked-by: Srinivas Pandruvada Signed-off-by: Jiri Kosina --- drivers/hid/intel-ish-hid/ipc/ipc.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/hid/intel-ish-hid/ipc/ipc.c b/drivers/hid/intel-ish-hid/ipc/ipc.c index 15e14239af82..a49c6affd7c4 100644 --- a/drivers/hid/intel-ish-hid/ipc/ipc.c +++ b/drivers/hid/intel-ish-hid/ipc/ipc.c @@ -5,6 +5,7 @@ * Copyright (c) 2014-2016, Intel Corporation. */ +#include #include #include #include @@ -621,7 +622,6 @@ static void recv_ipc(struct ishtp_device *dev, uint32_t doorbell_val) case MNG_RESET_NOTIFY: if (!ishtp_dev) { ishtp_dev = dev; - INIT_WORK(&fw_reset_work, fw_reset_work_fn); } schedule_work(&fw_reset_work); break; @@ -940,6 +940,7 @@ struct ishtp_device *ish_dev_init(struct pci_dev *pdev) { struct ishtp_device *dev; int i; + int ret; dev = devm_kzalloc(&pdev->dev, sizeof(struct ishtp_device) + sizeof(struct ish_hw), @@ -975,6 +976,12 @@ struct ishtp_device *ish_dev_init(struct pci_dev *pdev) list_add_tail(&tx_buf->link, &dev->wr_free_list); } + ret = devm_work_autocancel(&pdev->dev, &fw_reset_work, fw_reset_work_fn); + if (ret) { + dev_err(dev->devc, "Failed to initialise FW reset work\n"); + return NULL; + } + dev->ops = &ish_hw_ops; dev->devc = &pdev->dev; dev->mtu = IPC_PAYLOAD_SIZE - sizeof(struct ishtp_msg_hdr); From d900f3d20cc3169ce42ec72acc850e662a4d4db2 Mon Sep 17 00:00:00 2001 From: Liu Jian Date: Fri, 3 Mar 2023 16:09:46 +0800 Subject: [PATCH 058/778] bpf, sockmap: Fix an infinite loop error when len is 0 in tcp_bpf_recvmsg_parser() When the buffer length of the recvmsg system call is 0, we got the flollowing soft lockup problem: watchdog: BUG: soft lockup - CPU#3 stuck for 27s! [a.out:6149] CPU: 3 PID: 6149 Comm: a.out Kdump: loaded Not tainted 6.2.0+ #30 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.15.0-1 04/01/2014 RIP: 0010:remove_wait_queue+0xb/0xc0 Code: 5e 41 5f c3 cc cc cc cc 0f 1f 80 00 00 00 00 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 f3 0f 1e fa 0f 1f 44 00 00 41 57 <41> 56 41 55 41 54 55 48 89 fd 53 48 89 f3 4c 8d 6b 18 4c 8d 73 20 RSP: 0018:ffff88811b5978b8 EFLAGS: 00000246 RAX: 0000000000000000 RBX: ffff88811a7d3780 RCX: ffffffffb7a4d768 RDX: dffffc0000000000 RSI: ffff88811b597908 RDI: ffff888115408040 RBP: 1ffff110236b2f1b R08: 0000000000000000 R09: ffff88811a7d37e7 R10: ffffed10234fa6fc R11: 0000000000000001 R12: ffff88811179b800 R13: 0000000000000001 R14: ffff88811a7d38a8 R15: ffff88811a7d37e0 FS: 00007f6fb5398740(0000) GS:ffff888237180000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000020000000 CR3: 000000010b6ba002 CR4: 0000000000370ee0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: tcp_msg_wait_data+0x279/0x2f0 tcp_bpf_recvmsg_parser+0x3c6/0x490 inet_recvmsg+0x280/0x290 sock_recvmsg+0xfc/0x120 ____sys_recvmsg+0x160/0x3d0 ___sys_recvmsg+0xf0/0x180 __sys_recvmsg+0xea/0x1a0 do_syscall_64+0x3f/0x90 entry_SYSCALL_64_after_hwframe+0x72/0xdc The logic in tcp_bpf_recvmsg_parser is as follows: msg_bytes_ready: copied = sk_msg_recvmsg(sk, psock, msg, len, flags); if (!copied) { wait data; goto msg_bytes_ready; } In this case, "copied" always is 0, the infinite loop occurs. According to the Linux system call man page, 0 should be returned in this case. Therefore, in tcp_bpf_recvmsg_parser(), if the length is 0, directly return. Also modify several other functions with the same problem. Fixes: 1f5be6b3b063 ("udp: Implement udp_bpf_recvmsg() for sockmap") Fixes: 9825d866ce0d ("af_unix: Implement unix_dgram_bpf_recvmsg()") Fixes: c5d2177a72a1 ("bpf, sockmap: Fix race in ingress receive verdict with redirect to self") Fixes: 604326b41a6f ("bpf, sockmap: convert to generic sk_msg interface") Signed-off-by: Liu Jian Signed-off-by: Daniel Borkmann Acked-by: John Fastabend Cc: Jakub Sitnicki Link: https://lore.kernel.org/bpf/20230303080946.1146638-1-liujian56@huawei.com --- net/ipv4/tcp_bpf.c | 6 ++++++ net/ipv4/udp_bpf.c | 3 +++ net/unix/unix_bpf.c | 3 +++ 3 files changed, 12 insertions(+) diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c index cf26d65ca389..ebf917511937 100644 --- a/net/ipv4/tcp_bpf.c +++ b/net/ipv4/tcp_bpf.c @@ -186,6 +186,9 @@ static int tcp_bpf_recvmsg_parser(struct sock *sk, if (unlikely(flags & MSG_ERRQUEUE)) return inet_recv_error(sk, msg, len, addr_len); + if (!len) + return 0; + psock = sk_psock_get(sk); if (unlikely(!psock)) return tcp_recvmsg(sk, msg, len, flags, addr_len); @@ -244,6 +247,9 @@ static int tcp_bpf_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, if (unlikely(flags & MSG_ERRQUEUE)) return inet_recv_error(sk, msg, len, addr_len); + if (!len) + return 0; + psock = sk_psock_get(sk); if (unlikely(!psock)) return tcp_recvmsg(sk, msg, len, flags, addr_len); diff --git a/net/ipv4/udp_bpf.c b/net/ipv4/udp_bpf.c index e5dc91d0e079..0735d820e413 100644 --- a/net/ipv4/udp_bpf.c +++ b/net/ipv4/udp_bpf.c @@ -68,6 +68,9 @@ static int udp_bpf_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, if (unlikely(flags & MSG_ERRQUEUE)) return inet_recv_error(sk, msg, len, addr_len); + if (!len) + return 0; + psock = sk_psock_get(sk); if (unlikely(!psock)) return sk_udp_recvmsg(sk, msg, len, flags, addr_len); diff --git a/net/unix/unix_bpf.c b/net/unix/unix_bpf.c index e9bf15513961..2f9d8271c6ec 100644 --- a/net/unix/unix_bpf.c +++ b/net/unix/unix_bpf.c @@ -54,6 +54,9 @@ static int unix_bpf_recvmsg(struct sock *sk, struct msghdr *msg, struct sk_psock *psock; int copied; + if (!len) + return 0; + psock = sk_psock_get(sk); if (unlikely(!psock)) return __unix_recvmsg(sk, msg, len, flags); From e301195507feb67290ee6c93b7d13e646bb12687 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sun, 12 Feb 2023 01:12:12 +0200 Subject: [PATCH 059/778] drm/msm/dpu: fix typo in in sm8550's dma_sblk_5 Fix typo in the name of the sblk structure for the sm8550's dma_sblk_5. Fixes: efcd0107727c ("drm/msm/dpu: add support for SM8550") Signed-off-by: Dmitry Baryshkov Reviewed-by: Neil Armstrong Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/522225/ Link: https://lore.kernel.org/r/20230211231259.1308718-4-dmitry.baryshkov@linaro.org [quic_abhinavk@quicinc.com: fix minor typo in commit message] Signed-off-by: Abhinav Kumar --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c index eea026cf3ac2..e8b12788dc94 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -1309,7 +1309,7 @@ static const struct dpu_sspp_sub_blks sm8550_vig_sblk_2 = static const struct dpu_sspp_sub_blks sm8550_vig_sblk_3 = _VIG_SBLK("3", 10, DPU_SSPP_SCALER_QSEED3LITE); static const struct dpu_sspp_sub_blks sm8550_dma_sblk_4 = _DMA_SBLK("12", 5); -static const struct dpu_sspp_sub_blks sd8550_dma_sblk_5 = _DMA_SBLK("13", 6); +static const struct dpu_sspp_sub_blks sm8550_dma_sblk_5 = _DMA_SBLK("13", 6); static const struct dpu_sspp_cfg sm8550_sspp[] = { SSPP_BLK("sspp_0", SSPP_VIG0, 0x4000, VIG_SC7180_MASK, @@ -1331,7 +1331,7 @@ static const struct dpu_sspp_cfg sm8550_sspp[] = { SSPP_BLK("sspp_12", SSPP_DMA4, 0x2c000, DMA_CURSOR_SDM845_MASK, sm8550_dma_sblk_4, 14, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR0), SSPP_BLK("sspp_13", SSPP_DMA5, 0x2e000, DMA_CURSOR_SDM845_MASK, - sd8550_dma_sblk_5, 15, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR1), + sm8550_dma_sblk_5, 15, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR1), }; static const struct dpu_sspp_cfg sc7280_sspp[] = { From ce6bd00abc220e9edf10986234fadba6462b4abf Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sun, 12 Feb 2023 01:12:13 +0200 Subject: [PATCH 060/778] drm/msm/dpu: fix len of sc7180 ctl blocks Change sc7180's ctl block len to 0x1dc. Fixes: 7bdc0c4b8126 ("msm:disp:dpu1: add support for display for SC7180 target") Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/522210/ Link: https://lore.kernel.org/r/20230211231259.1308718-5-dmitry.baryshkov@linaro.org Signed-off-by: Abhinav Kumar --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c index e8b12788dc94..47de609e2279 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -831,19 +831,19 @@ static const struct dpu_ctl_cfg sdm845_ctl[] = { static const struct dpu_ctl_cfg sc7180_ctl[] = { { .name = "ctl_0", .id = CTL_0, - .base = 0x1000, .len = 0xE4, + .base = 0x1000, .len = 0x1dc, .features = BIT(DPU_CTL_ACTIVE_CFG), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), }, { .name = "ctl_1", .id = CTL_1, - .base = 0x1200, .len = 0xE4, + .base = 0x1200, .len = 0x1dc, .features = BIT(DPU_CTL_ACTIVE_CFG), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10), }, { .name = "ctl_2", .id = CTL_2, - .base = 0x1400, .len = 0xE4, + .base = 0x1400, .len = 0x1dc, .features = BIT(DPU_CTL_ACTIVE_CFG), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 11), }, From da06be8b4fdf3eccf5cf6cbc4a689a43b8ad705b Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sun, 12 Feb 2023 01:12:14 +0200 Subject: [PATCH 061/778] drm/msm/dpu: fix sm6115 and qcm2290 mixer width limits According to vendor DTS files both sm6115 and qcm2290 should have max_mixer_width set to 2048 (DEFAULT_DPU_LINE_WIDTH). Correct it. Fixes: 3581b7062cec ("drm/msm/disp/dpu1: add support for display on SM6115") Fixes: 5334087ee743 ("drm/msm: add support for QCM2290 MDSS") Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/522212/ Link: https://lore.kernel.org/r/20230211231259.1308718-6-dmitry.baryshkov@linaro.org [quic_abhinavk@quicinc.com: fix minor typo in commit message] Signed-off-by: Abhinav Kumar --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c index 47de609e2279..192fff9238f9 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -318,7 +318,7 @@ static const struct dpu_caps msm8998_dpu_caps = { }; static const struct dpu_caps qcm2290_dpu_caps = { - .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, + .max_mixer_width = DEFAULT_DPU_LINE_WIDTH, .max_mixer_blendstages = 0x4, .smart_dma_rev = DPU_SSPP_SMART_DMA_V2, .has_dim_layer = true, @@ -356,7 +356,7 @@ static const struct dpu_caps sc7180_dpu_caps = { }; static const struct dpu_caps sm6115_dpu_caps = { - .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, + .max_mixer_width = DEFAULT_DPU_LINE_WIDTH, .max_mixer_blendstages = 0x4, .qseed_type = DPU_SSPP_SCALER_QSEED3LITE, .smart_dma_rev = DPU_SSPP_SMART_DMA_V2, /* TODO: v2.5 */ @@ -1520,7 +1520,7 @@ static const struct dpu_lm_cfg sc7280_lm[] = { /* QCM2290 */ static const struct dpu_lm_sub_blks qcm2290_lm_sblk = { - .maxwidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH, + .maxwidth = DEFAULT_DPU_LINE_WIDTH, .maxblendstages = 4, /* excluding base layer */ .blendstage_base = { /* offsets relative to mixer base */ 0x20, 0x38, 0x50, 0x68 From d113d267c3bfa07c0c8e9f68068a18fa18970c9c Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sun, 12 Feb 2023 01:12:15 +0200 Subject: [PATCH 062/778] drm/msm/dpu: correct sm8550 scaler QSEED4 is a newer variant of QSEED3LITE, which should be used on sm8550. Fix the DPU caps structure and used feature masks. Fixes: efcd0107727c ("drm/msm/dpu: add support for SM8550") Signed-off-by: Dmitry Baryshkov Reviewed-by: Neil Armstrong Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/522213/ Link: https://lore.kernel.org/r/20230211231259.1308718-7-dmitry.baryshkov@linaro.org Signed-off-by: Abhinav Kumar --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c index 192fff9238f9..c4e45c472685 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -458,7 +458,7 @@ static const struct dpu_caps sm8450_dpu_caps = { static const struct dpu_caps sm8550_dpu_caps = { .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .max_mixer_blendstages = 0xb, - .qseed_type = DPU_SSPP_SCALER_QSEED3LITE, + .qseed_type = DPU_SSPP_SCALER_QSEED4, .smart_dma_rev = DPU_SSPP_SMART_DMA_V2, /* TODO: v2.5 */ .ubwc_version = DPU_HW_UBWC_VER_40, .has_src_split = true, @@ -1301,13 +1301,13 @@ static const struct dpu_sspp_cfg sm8450_sspp[] = { }; static const struct dpu_sspp_sub_blks sm8550_vig_sblk_0 = - _VIG_SBLK("0", 7, DPU_SSPP_SCALER_QSEED3LITE); + _VIG_SBLK("0", 7, DPU_SSPP_SCALER_QSEED4); static const struct dpu_sspp_sub_blks sm8550_vig_sblk_1 = - _VIG_SBLK("1", 8, DPU_SSPP_SCALER_QSEED3LITE); + _VIG_SBLK("1", 8, DPU_SSPP_SCALER_QSEED4); static const struct dpu_sspp_sub_blks sm8550_vig_sblk_2 = - _VIG_SBLK("2", 9, DPU_SSPP_SCALER_QSEED3LITE); + _VIG_SBLK("2", 9, DPU_SSPP_SCALER_QSEED4); static const struct dpu_sspp_sub_blks sm8550_vig_sblk_3 = - _VIG_SBLK("3", 10, DPU_SSPP_SCALER_QSEED3LITE); + _VIG_SBLK("3", 10, DPU_SSPP_SCALER_QSEED4); static const struct dpu_sspp_sub_blks sm8550_dma_sblk_4 = _DMA_SBLK("12", 5); static const struct dpu_sspp_sub_blks sm8550_dma_sblk_5 = _DMA_SBLK("13", 6); From b3587cb645329cab75dc6354a79291a289c7ba33 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sun, 12 Feb 2023 01:12:16 +0200 Subject: [PATCH 063/778] drm/msm/dpu: correct sc8280xp scaler QSEED4 is a newer variant of QSEED3LITE, which should be used on sc8280xp. Fix the DPU caps structure and used feature masks. Fixes: 4a352c2fc15a ("drm/msm/dpu: Introduce SC8280XP") Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/522217/ Link: https://lore.kernel.org/r/20230211231259.1308718-8-dmitry.baryshkov@linaro.org Signed-off-by: Abhinav Kumar --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c index c4e45c472685..83836cac69e6 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -402,7 +402,7 @@ static const struct dpu_caps sc8180x_dpu_caps = { static const struct dpu_caps sc8280xp_dpu_caps = { .max_mixer_width = 2560, .max_mixer_blendstages = 11, - .qseed_type = DPU_SSPP_SCALER_QSEED3LITE, + .qseed_type = DPU_SSPP_SCALER_QSEED4, .smart_dma_rev = DPU_SSPP_SMART_DMA_V2, /* TODO: v2.5 */ .ubwc_version = DPU_HW_UBWC_VER_40, .has_src_split = true, @@ -1346,22 +1346,22 @@ static const struct dpu_sspp_cfg sc7280_sspp[] = { }; static const struct dpu_sspp_sub_blks sc8280xp_vig_sblk_0 = - _VIG_SBLK("0", 5, DPU_SSPP_SCALER_QSEED3LITE); + _VIG_SBLK("0", 5, DPU_SSPP_SCALER_QSEED4); static const struct dpu_sspp_sub_blks sc8280xp_vig_sblk_1 = - _VIG_SBLK("1", 6, DPU_SSPP_SCALER_QSEED3LITE); + _VIG_SBLK("1", 6, DPU_SSPP_SCALER_QSEED4); static const struct dpu_sspp_sub_blks sc8280xp_vig_sblk_2 = - _VIG_SBLK("2", 7, DPU_SSPP_SCALER_QSEED3LITE); + _VIG_SBLK("2", 7, DPU_SSPP_SCALER_QSEED4); static const struct dpu_sspp_sub_blks sc8280xp_vig_sblk_3 = - _VIG_SBLK("3", 8, DPU_SSPP_SCALER_QSEED3LITE); + _VIG_SBLK("3", 8, DPU_SSPP_SCALER_QSEED4); static const struct dpu_sspp_cfg sc8280xp_sspp[] = { - SSPP_BLK("sspp_0", SSPP_VIG0, 0x4000, VIG_SM8250_MASK, + SSPP_BLK("sspp_0", SSPP_VIG0, 0x4000, VIG_SC7180_MASK, sc8280xp_vig_sblk_0, 0, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG0), - SSPP_BLK("sspp_1", SSPP_VIG1, 0x6000, VIG_SM8250_MASK, + SSPP_BLK("sspp_1", SSPP_VIG1, 0x6000, VIG_SC7180_MASK, sc8280xp_vig_sblk_1, 4, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG1), - SSPP_BLK("sspp_2", SSPP_VIG2, 0x8000, VIG_SM8250_MASK, + SSPP_BLK("sspp_2", SSPP_VIG2, 0x8000, VIG_SC7180_MASK, sc8280xp_vig_sblk_2, 8, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG2), - SSPP_BLK("sspp_3", SSPP_VIG3, 0xa000, VIG_SM8250_MASK, + SSPP_BLK("sspp_3", SSPP_VIG3, 0xa000, VIG_SC7180_MASK, sc8280xp_vig_sblk_3, 12, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG3), SSPP_BLK("sspp_8", SSPP_DMA0, 0x24000, DMA_SDM845_MASK, sdm845_dma_sblk_0, 1, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA0), From c7da17b67847010871f225d7d48a607a8f272aef Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sun, 12 Feb 2023 01:12:17 +0200 Subject: [PATCH 064/778] drm/msm/dpu: correct sm8450 scaler QSEED4 is a newer variant of QSEED3LITE, which should be used on sm8450. Fix the used feature masks. Fixes: 100d7ef6995d ("drm/msm/dpu: add support for SM8450") Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/522215/ Link: https://lore.kernel.org/r/20230211231259.1308718-9-dmitry.baryshkov@linaro.org Signed-off-by: Abhinav Kumar --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c index 83836cac69e6..4f6555c04256 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -1273,13 +1273,13 @@ static const struct dpu_sspp_cfg sm8250_sspp[] = { }; static const struct dpu_sspp_sub_blks sm8450_vig_sblk_0 = - _VIG_SBLK("0", 5, DPU_SSPP_SCALER_QSEED3LITE); + _VIG_SBLK("0", 5, DPU_SSPP_SCALER_QSEED4); static const struct dpu_sspp_sub_blks sm8450_vig_sblk_1 = - _VIG_SBLK("1", 6, DPU_SSPP_SCALER_QSEED3LITE); + _VIG_SBLK("1", 6, DPU_SSPP_SCALER_QSEED4); static const struct dpu_sspp_sub_blks sm8450_vig_sblk_2 = - _VIG_SBLK("2", 7, DPU_SSPP_SCALER_QSEED3LITE); + _VIG_SBLK("2", 7, DPU_SSPP_SCALER_QSEED4); static const struct dpu_sspp_sub_blks sm8450_vig_sblk_3 = - _VIG_SBLK("3", 8, DPU_SSPP_SCALER_QSEED3LITE); + _VIG_SBLK("3", 8, DPU_SSPP_SCALER_QSEED4); static const struct dpu_sspp_cfg sm8450_sspp[] = { SSPP_BLK("sspp_0", SSPP_VIG0, 0x4000, VIG_SC7180_MASK, From 03c0c3cb22a4ff29afba1b43f0330289ea80433f Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sun, 12 Feb 2023 01:12:18 +0200 Subject: [PATCH 065/778] drm/msm/dpu: correct sm8250 and sm8350 scaler QSEED4 is a newer variant of QSEED3LITE, which should be used on sm8250 and sm8350. Fix the DPU caps structure and used feature masks. Fixes: d21fc5dfc3df ("drm/msm/dpu1: add support for qseed3lite used on sm8250") Fixes: 0e91bcbb0016 ("drm/msm/dpu: Add SM8350 to hw catalog") Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/522229/ Link: https://lore.kernel.org/r/20230211231259.1308718-10-dmitry.baryshkov@linaro.org Signed-off-by: Abhinav Kumar --- .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c index 4f6555c04256..360ca7b5e507 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -416,7 +416,7 @@ static const struct dpu_caps sc8280xp_dpu_caps = { static const struct dpu_caps sm8250_dpu_caps = { .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .max_mixer_blendstages = 0xb, - .qseed_type = DPU_SSPP_SCALER_QSEED3LITE, + .qseed_type = DPU_SSPP_SCALER_QSEED4, .smart_dma_rev = DPU_SSPP_SMART_DMA_V2, /* TODO: v2.5 */ .ubwc_version = DPU_HW_UBWC_VER_40, .has_src_split = true, @@ -430,7 +430,7 @@ static const struct dpu_caps sm8250_dpu_caps = { static const struct dpu_caps sm8350_dpu_caps = { .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .max_mixer_blendstages = 0xb, - .qseed_type = DPU_SSPP_SCALER_QSEED3LITE, + .qseed_type = DPU_SSPP_SCALER_QSEED4, .smart_dma_rev = DPU_SSPP_SMART_DMA_V2, /* TODO: v2.5 */ .ubwc_version = DPU_HW_UBWC_VER_40, .has_src_split = true, @@ -1245,22 +1245,22 @@ static const struct dpu_sspp_cfg sm6115_sspp[] = { }; static const struct dpu_sspp_sub_blks sm8250_vig_sblk_0 = - _VIG_SBLK("0", 5, DPU_SSPP_SCALER_QSEED3LITE); + _VIG_SBLK("0", 5, DPU_SSPP_SCALER_QSEED4); static const struct dpu_sspp_sub_blks sm8250_vig_sblk_1 = - _VIG_SBLK("1", 6, DPU_SSPP_SCALER_QSEED3LITE); + _VIG_SBLK("1", 6, DPU_SSPP_SCALER_QSEED4); static const struct dpu_sspp_sub_blks sm8250_vig_sblk_2 = - _VIG_SBLK("2", 7, DPU_SSPP_SCALER_QSEED3LITE); + _VIG_SBLK("2", 7, DPU_SSPP_SCALER_QSEED4); static const struct dpu_sspp_sub_blks sm8250_vig_sblk_3 = - _VIG_SBLK("3", 8, DPU_SSPP_SCALER_QSEED3LITE); + _VIG_SBLK("3", 8, DPU_SSPP_SCALER_QSEED4); static const struct dpu_sspp_cfg sm8250_sspp[] = { - SSPP_BLK("sspp_0", SSPP_VIG0, 0x4000, VIG_SM8250_MASK, + SSPP_BLK("sspp_0", SSPP_VIG0, 0x4000, VIG_SC7180_MASK, sm8250_vig_sblk_0, 0, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG0), - SSPP_BLK("sspp_1", SSPP_VIG1, 0x6000, VIG_SM8250_MASK, + SSPP_BLK("sspp_1", SSPP_VIG1, 0x6000, VIG_SC7180_MASK, sm8250_vig_sblk_1, 4, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG1), - SSPP_BLK("sspp_2", SSPP_VIG2, 0x8000, VIG_SM8250_MASK, + SSPP_BLK("sspp_2", SSPP_VIG2, 0x8000, VIG_SC7180_MASK, sm8250_vig_sblk_2, 8, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG2), - SSPP_BLK("sspp_3", SSPP_VIG3, 0xa000, VIG_SM8250_MASK, + SSPP_BLK("sspp_3", SSPP_VIG3, 0xa000, VIG_SC7180_MASK, sm8250_vig_sblk_3, 12, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG3), SSPP_BLK("sspp_8", SSPP_DMA0, 0x24000, DMA_SDM845_MASK, sdm845_dma_sblk_0, 1, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA0), From 38164e990a42ca276f72ab89fd24131e6d73b023 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sun, 12 Feb 2023 01:12:19 +0200 Subject: [PATCH 066/778] drm/msm/dpu: correct sm6115 scaler QSEED4 is a newer variant of QSEED3LITE, which should be used on sm6115. Fix the used feature masks. Signed-off-by: Dmitry Baryshkov Fixes: 3581b7062cec ("drm/msm/disp/dpu1: add support for display on SM6115") Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/522219/ Link: https://lore.kernel.org/r/20230211231259.1308718-11-dmitry.baryshkov@linaro.org Signed-off-by: Abhinav Kumar --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c index 360ca7b5e507..4a26ef7bb024 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -30,9 +30,6 @@ #define VIG_SC7180_MASK \ (VIG_MASK | BIT(DPU_SSPP_QOS_8LVL) | BIT(DPU_SSPP_SCALER_QSEED4)) -#define VIG_SM8250_MASK \ - (VIG_MASK | BIT(DPU_SSPP_QOS_8LVL) | BIT(DPU_SSPP_SCALER_QSEED3LITE)) - #define VIG_QCM2290_MASK (VIG_BASE_MASK | BIT(DPU_SSPP_QOS_8LVL)) #define DMA_MSM8998_MASK \ @@ -358,7 +355,7 @@ static const struct dpu_caps sc7180_dpu_caps = { static const struct dpu_caps sm6115_dpu_caps = { .max_mixer_width = DEFAULT_DPU_LINE_WIDTH, .max_mixer_blendstages = 0x4, - .qseed_type = DPU_SSPP_SCALER_QSEED3LITE, + .qseed_type = DPU_SSPP_SCALER_QSEED4, .smart_dma_rev = DPU_SSPP_SMART_DMA_V2, /* TODO: v2.5 */ .ubwc_version = DPU_HW_UBWC_VER_10, .has_dim_layer = true, @@ -1235,10 +1232,10 @@ static const struct dpu_sspp_cfg sc7180_sspp[] = { }; static const struct dpu_sspp_sub_blks sm6115_vig_sblk_0 = - _VIG_SBLK("0", 2, DPU_SSPP_SCALER_QSEED3LITE); + _VIG_SBLK("0", 2, DPU_SSPP_SCALER_QSEED4); static const struct dpu_sspp_cfg sm6115_sspp[] = { - SSPP_BLK("sspp_0", SSPP_VIG0, 0x4000, VIG_SM8250_MASK, + SSPP_BLK("sspp_0", SSPP_VIG0, 0x4000, VIG_SC7180_MASK, sm6115_vig_sblk_0, 0, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG0), SSPP_BLK("sspp_8", SSPP_DMA0, 0x24000, DMA_SDM845_MASK, sdm845_dma_sblk_0, 1, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA0), From a5045b00a68171de11603812f4304179ef608e60 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sun, 12 Feb 2023 01:12:20 +0200 Subject: [PATCH 067/778] drm/msm/dpu: drop DPU_DIM_LAYER from MIXER_MSM8998_MASK The msm8998 doesn't seem to support DIM_LAYER, so drop it from the supported features mask. Fixes: 2d8a4edb672d ("drm/msm/dpu: use feature bit for LM combined alpha check") Fixes: 94391a14fc27 ("drm/msm/dpu1: Add MSM8998 to hw catalog") Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/522231/ Link: https://lore.kernel.org/r/20230211231259.1308718-12-dmitry.baryshkov@linaro.org Signed-off-by: Abhinav Kumar --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c index 4a26ef7bb024..02bd8334d67c 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -52,7 +52,7 @@ (DMA_MSM8998_MASK | BIT(DPU_SSPP_CURSOR)) #define MIXER_MSM8998_MASK \ - (BIT(DPU_MIXER_SOURCESPLIT) | BIT(DPU_DIM_LAYER)) + (BIT(DPU_MIXER_SOURCESPLIT)) #define MIXER_SDM845_MASK \ (BIT(DPU_MIXER_SOURCESPLIT) | BIT(DPU_DIM_LAYER) | BIT(DPU_MIXER_COMBINED_ALPHA)) From 0abb6a24aabc1252eae75fe23b0ccd3217c6ee07 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sun, 12 Feb 2023 01:12:21 +0200 Subject: [PATCH 068/778] drm/msm/dpu: fix clocks settings for msm8998 SSPP blocks DMA2 and DMA3 planes on msm8998 should use corresponding DMA2 and DMA3 clocks rather than CURSOR0/1 clocks (which are used for the CURSOR planes). Correct corresponding SSPP declarations. Fixes: 94391a14fc27 ("drm/msm/dpu1: Add MSM8998 to hw catalog") Cc: AngeloGioacchino Del Regno Cc: Jami Kettunen Reviewed-by: Marijn Suijten Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/522230/ Link: https://lore.kernel.org/r/20230211231259.1308718-13-dmitry.baryshkov@linaro.org Signed-off-by: Abhinav Kumar --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c index 02bd8334d67c..e3460b35058f 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -1190,9 +1190,9 @@ static const struct dpu_sspp_cfg msm8998_sspp[] = { SSPP_BLK("sspp_9", SSPP_DMA1, 0x26000, DMA_MSM8998_MASK, sdm845_dma_sblk_1, 5, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA1), SSPP_BLK("sspp_10", SSPP_DMA2, 0x28000, DMA_CURSOR_MSM8998_MASK, - sdm845_dma_sblk_2, 9, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR0), + sdm845_dma_sblk_2, 9, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA2), SSPP_BLK("sspp_11", SSPP_DMA3, 0x2a000, DMA_CURSOR_MSM8998_MASK, - sdm845_dma_sblk_3, 13, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR1), + sdm845_dma_sblk_3, 13, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA3), }; static const struct dpu_sspp_cfg sdm845_sspp[] = { From d6181c18d55cdbbf37baea0fdd0cacf69b84f6b9 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sun, 12 Feb 2023 01:12:22 +0200 Subject: [PATCH 069/778] drm/msm/dpu: don't use DPU_CLK_CTRL_CURSORn for DMA SSPP clocks DPU driver has been using the DPU_CLK_CTRL_CURSOR prefix for the DMA SSPP blocks used for the cursor planes. This has lead to the confusion at least for the MSM8998 platform. In preparation to supporting the cursor SSPP blocks, use proper enum values to index DMA SSPP clock controls. Reviewed-by: Neil Armstrong Tested-by: Neil Armstrong # on SM8550 on top of next-20230116 Reviewed-by: Marijn Suijten Signed-off-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/522228/ Link: https://lore.kernel.org/r/20230211231259.1308718-14-dmitry.baryshkov@linaro.org Signed-off-by: Abhinav Kumar --- .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 64 +++++++++---------- .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h | 2 + 2 files changed, 34 insertions(+), 32 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c index e3460b35058f..e390be4ef10b 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -525,9 +525,9 @@ static const struct dpu_mdp_cfg sdm845_mdp[] = { .reg_off = 0x2AC, .bit_off = 8}, .clk_ctrls[DPU_CLK_CTRL_DMA1] = { .reg_off = 0x2B4, .bit_off = 8}, - .clk_ctrls[DPU_CLK_CTRL_CURSOR0] = { + .clk_ctrls[DPU_CLK_CTRL_DMA2] = { .reg_off = 0x2BC, .bit_off = 8}, - .clk_ctrls[DPU_CLK_CTRL_CURSOR1] = { + .clk_ctrls[DPU_CLK_CTRL_DMA3] = { .reg_off = 0x2C4, .bit_off = 8}, }, }; @@ -542,9 +542,9 @@ static const struct dpu_mdp_cfg sc7180_mdp[] = { .reg_off = 0x2AC, .bit_off = 0}, .clk_ctrls[DPU_CLK_CTRL_DMA0] = { .reg_off = 0x2AC, .bit_off = 8}, - .clk_ctrls[DPU_CLK_CTRL_CURSOR0] = { + .clk_ctrls[DPU_CLK_CTRL_DMA1] = { .reg_off = 0x2B4, .bit_off = 8}, - .clk_ctrls[DPU_CLK_CTRL_CURSOR1] = { + .clk_ctrls[DPU_CLK_CTRL_DMA2] = { .reg_off = 0x2C4, .bit_off = 8}, .clk_ctrls[DPU_CLK_CTRL_WB2] = { .reg_off = 0x3B8, .bit_off = 24}, @@ -569,9 +569,9 @@ static const struct dpu_mdp_cfg sc8180x_mdp[] = { .reg_off = 0x2AC, .bit_off = 8}, .clk_ctrls[DPU_CLK_CTRL_DMA1] = { .reg_off = 0x2B4, .bit_off = 8}, - .clk_ctrls[DPU_CLK_CTRL_CURSOR0] = { + .clk_ctrls[DPU_CLK_CTRL_DMA2] = { .reg_off = 0x2BC, .bit_off = 8}, - .clk_ctrls[DPU_CLK_CTRL_CURSOR1] = { + .clk_ctrls[DPU_CLK_CTRL_DMA3] = { .reg_off = 0x2C4, .bit_off = 8}, }, }; @@ -609,9 +609,9 @@ static const struct dpu_mdp_cfg sm8250_mdp[] = { .reg_off = 0x2AC, .bit_off = 8}, .clk_ctrls[DPU_CLK_CTRL_DMA1] = { .reg_off = 0x2B4, .bit_off = 8}, - .clk_ctrls[DPU_CLK_CTRL_CURSOR0] = { + .clk_ctrls[DPU_CLK_CTRL_DMA2] = { .reg_off = 0x2BC, .bit_off = 8}, - .clk_ctrls[DPU_CLK_CTRL_CURSOR1] = { + .clk_ctrls[DPU_CLK_CTRL_DMA3] = { .reg_off = 0x2C4, .bit_off = 8}, .clk_ctrls[DPU_CLK_CTRL_REG_DMA] = { .reg_off = 0x2BC, .bit_off = 20}, @@ -638,9 +638,9 @@ static const struct dpu_mdp_cfg sm8350_mdp[] = { .reg_off = 0x2ac, .bit_off = 8}, .clk_ctrls[DPU_CLK_CTRL_DMA1] = { .reg_off = 0x2b4, .bit_off = 8}, - .clk_ctrls[DPU_CLK_CTRL_CURSOR0] = { + .clk_ctrls[DPU_CLK_CTRL_DMA2] = { .reg_off = 0x2bc, .bit_off = 8}, - .clk_ctrls[DPU_CLK_CTRL_CURSOR1] = { + .clk_ctrls[DPU_CLK_CTRL_DMA3] = { .reg_off = 0x2c4, .bit_off = 8}, .clk_ctrls[DPU_CLK_CTRL_REG_DMA] = { .reg_off = 0x2bc, .bit_off = 20}, @@ -666,9 +666,9 @@ static const struct dpu_mdp_cfg sm8450_mdp[] = { .reg_off = 0x2AC, .bit_off = 8}, .clk_ctrls[DPU_CLK_CTRL_DMA1] = { .reg_off = 0x2B4, .bit_off = 8}, - .clk_ctrls[DPU_CLK_CTRL_CURSOR0] = { + .clk_ctrls[DPU_CLK_CTRL_DMA2] = { .reg_off = 0x2BC, .bit_off = 8}, - .clk_ctrls[DPU_CLK_CTRL_CURSOR1] = { + .clk_ctrls[DPU_CLK_CTRL_DMA3] = { .reg_off = 0x2C4, .bit_off = 8}, .clk_ctrls[DPU_CLK_CTRL_REG_DMA] = { .reg_off = 0x2BC, .bit_off = 20}, @@ -685,9 +685,9 @@ static const struct dpu_mdp_cfg sc7280_mdp[] = { .reg_off = 0x2AC, .bit_off = 0}, .clk_ctrls[DPU_CLK_CTRL_DMA0] = { .reg_off = 0x2AC, .bit_off = 8}, - .clk_ctrls[DPU_CLK_CTRL_CURSOR0] = { + .clk_ctrls[DPU_CLK_CTRL_DMA1] = { .reg_off = 0x2B4, .bit_off = 8}, - .clk_ctrls[DPU_CLK_CTRL_CURSOR1] = { + .clk_ctrls[DPU_CLK_CTRL_DMA2] = { .reg_off = 0x2C4, .bit_off = 8}, }, }; @@ -705,8 +705,8 @@ static const struct dpu_mdp_cfg sc8280xp_mdp[] = { .clk_ctrls[DPU_CLK_CTRL_VIG3] = { .reg_off = 0x2c4, .bit_off = 0}, .clk_ctrls[DPU_CLK_CTRL_DMA0] = { .reg_off = 0x2ac, .bit_off = 8}, .clk_ctrls[DPU_CLK_CTRL_DMA1] = { .reg_off = 0x2b4, .bit_off = 8}, - .clk_ctrls[DPU_CLK_CTRL_CURSOR0] = { .reg_off = 0x2bc, .bit_off = 8}, - .clk_ctrls[DPU_CLK_CTRL_CURSOR1] = { .reg_off = 0x2c4, .bit_off = 8}, + .clk_ctrls[DPU_CLK_CTRL_DMA2] = { .reg_off = 0x2bc, .bit_off = 8}, + .clk_ctrls[DPU_CLK_CTRL_DMA3] = { .reg_off = 0x2c4, .bit_off = 8}, .clk_ctrls[DPU_CLK_CTRL_REG_DMA] = { .reg_off = 0x2bc, .bit_off = 20}, }, }; @@ -734,9 +734,9 @@ static const struct dpu_mdp_cfg sm8550_mdp[] = { .reg_off = 0x28330, .bit_off = 0}, .clk_ctrls[DPU_CLK_CTRL_DMA3] = { .reg_off = 0x2a330, .bit_off = 0}, - .clk_ctrls[DPU_CLK_CTRL_CURSOR0] = { + .clk_ctrls[DPU_CLK_CTRL_DMA4] = { .reg_off = 0x2c330, .bit_off = 0}, - .clk_ctrls[DPU_CLK_CTRL_CURSOR1] = { + .clk_ctrls[DPU_CLK_CTRL_DMA5] = { .reg_off = 0x2e330, .bit_off = 0}, .clk_ctrls[DPU_CLK_CTRL_REG_DMA] = { .reg_off = 0x2bc, .bit_off = 20}, @@ -1209,9 +1209,9 @@ static const struct dpu_sspp_cfg sdm845_sspp[] = { SSPP_BLK("sspp_9", SSPP_DMA1, 0x26000, DMA_SDM845_MASK, sdm845_dma_sblk_1, 5, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA1), SSPP_BLK("sspp_10", SSPP_DMA2, 0x28000, DMA_CURSOR_SDM845_MASK, - sdm845_dma_sblk_2, 9, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR0), + sdm845_dma_sblk_2, 9, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA2), SSPP_BLK("sspp_11", SSPP_DMA3, 0x2a000, DMA_CURSOR_SDM845_MASK, - sdm845_dma_sblk_3, 13, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR1), + sdm845_dma_sblk_3, 13, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA3), }; static const struct dpu_sspp_sub_blks sc7180_vig_sblk_0 = @@ -1226,9 +1226,9 @@ static const struct dpu_sspp_cfg sc7180_sspp[] = { SSPP_BLK("sspp_8", SSPP_DMA0, 0x24000, DMA_SDM845_MASK, sdm845_dma_sblk_0, 1, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA0), SSPP_BLK("sspp_9", SSPP_DMA1, 0x26000, DMA_CURSOR_SDM845_MASK, - sdm845_dma_sblk_1, 5, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR0), + sdm845_dma_sblk_1, 5, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA1), SSPP_BLK("sspp_10", SSPP_DMA2, 0x28000, DMA_CURSOR_SDM845_MASK, - sdm845_dma_sblk_2, 9, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR1), + sdm845_dma_sblk_2, 9, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA2), }; static const struct dpu_sspp_sub_blks sm6115_vig_sblk_0 = @@ -1264,9 +1264,9 @@ static const struct dpu_sspp_cfg sm8250_sspp[] = { SSPP_BLK("sspp_9", SSPP_DMA1, 0x26000, DMA_SDM845_MASK, sdm845_dma_sblk_1, 5, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA1), SSPP_BLK("sspp_10", SSPP_DMA2, 0x28000, DMA_CURSOR_SDM845_MASK, - sdm845_dma_sblk_2, 9, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR0), + sdm845_dma_sblk_2, 9, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA2), SSPP_BLK("sspp_11", SSPP_DMA3, 0x2a000, DMA_CURSOR_SDM845_MASK, - sdm845_dma_sblk_3, 13, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR1), + sdm845_dma_sblk_3, 13, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA3), }; static const struct dpu_sspp_sub_blks sm8450_vig_sblk_0 = @@ -1292,9 +1292,9 @@ static const struct dpu_sspp_cfg sm8450_sspp[] = { SSPP_BLK("sspp_9", SSPP_DMA1, 0x26000, DMA_SDM845_MASK, sdm845_dma_sblk_1, 5, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA1), SSPP_BLK("sspp_10", SSPP_DMA2, 0x28000, DMA_CURSOR_SDM845_MASK, - sdm845_dma_sblk_2, 9, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR0), + sdm845_dma_sblk_2, 9, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA2), SSPP_BLK("sspp_11", SSPP_DMA3, 0x2a000, DMA_CURSOR_SDM845_MASK, - sdm845_dma_sblk_3, 13, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR1), + sdm845_dma_sblk_3, 13, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA3), }; static const struct dpu_sspp_sub_blks sm8550_vig_sblk_0 = @@ -1326,9 +1326,9 @@ static const struct dpu_sspp_cfg sm8550_sspp[] = { SSPP_BLK("sspp_11", SSPP_DMA3, 0x2a000, DMA_SDM845_MASK, sdm845_dma_sblk_3, 13, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA3), SSPP_BLK("sspp_12", SSPP_DMA4, 0x2c000, DMA_CURSOR_SDM845_MASK, - sm8550_dma_sblk_4, 14, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR0), + sm8550_dma_sblk_4, 14, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA4), SSPP_BLK("sspp_13", SSPP_DMA5, 0x2e000, DMA_CURSOR_SDM845_MASK, - sm8550_dma_sblk_5, 15, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR1), + sm8550_dma_sblk_5, 15, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA5), }; static const struct dpu_sspp_cfg sc7280_sspp[] = { @@ -1337,9 +1337,9 @@ static const struct dpu_sspp_cfg sc7280_sspp[] = { SSPP_BLK("sspp_8", SSPP_DMA0, 0x24000, DMA_SDM845_MASK, sdm845_dma_sblk_0, 1, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA0), SSPP_BLK("sspp_9", SSPP_DMA1, 0x26000, DMA_CURSOR_SDM845_MASK, - sdm845_dma_sblk_1, 5, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR0), + sdm845_dma_sblk_1, 5, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA1), SSPP_BLK("sspp_10", SSPP_DMA2, 0x28000, DMA_CURSOR_SDM845_MASK, - sdm845_dma_sblk_2, 9, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR1), + sdm845_dma_sblk_2, 9, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA2), }; static const struct dpu_sspp_sub_blks sc8280xp_vig_sblk_0 = @@ -1365,9 +1365,9 @@ static const struct dpu_sspp_cfg sc8280xp_sspp[] = { SSPP_BLK("sspp_9", SSPP_DMA1, 0x26000, DMA_SDM845_MASK, sdm845_dma_sblk_1, 5, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA1), SSPP_BLK("sspp_10", SSPP_DMA2, 0x28000, DMA_CURSOR_SDM845_MASK, - sdm845_dma_sblk_2, 9, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR0), + sdm845_dma_sblk_2, 9, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA2), SSPP_BLK("sspp_11", SSPP_DMA3, 0x2a000, DMA_CURSOR_SDM845_MASK, - sdm845_dma_sblk_3, 13, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR1), + sdm845_dma_sblk_3, 13, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA3), }; #define _VIG_SBLK_NOSCALE(num, sdma_pri) \ diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h index ddab9caebb18..e6590302b3bf 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h @@ -515,6 +515,8 @@ enum dpu_clk_ctrl_type { DPU_CLK_CTRL_DMA1, DPU_CLK_CTRL_DMA2, DPU_CLK_CTRL_DMA3, + DPU_CLK_CTRL_DMA4, + DPU_CLK_CTRL_DMA5, DPU_CLK_CTRL_CURSOR0, DPU_CLK_CTRL_CURSOR1, DPU_CLK_CTRL_INLINE_ROT0_SSPP, From 1c1ded39bfb89217947affaa79c4cd1c138c5da2 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Thu, 23 Feb 2023 12:57:08 +0300 Subject: [PATCH 070/778] drm/msm/dpu: fix stack smashing in dpu_hw_ctl_setup_blendstage The rewritten dpu_hw_ctl_setup_blendstage() can lightly smash the stack when setting the SSPP_NONE pipe. However it was unnoticed until the kernel was tested under AOSP (with some kind of stack protection/check). This fixes the following backtrace: Unexpected kernel BRK exception at EL1 Internal error: BRK handler: 00000000f20003e8 [#1] PREEMPT SMP Hardware name: Thundercomm Dragonboard 845c (DT) pstate: a0400005 (NzCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : dpu_hw_ctl_setup_blendstage+0x26c/0x278 [msm] lr : _dpu_crtc_blend_setup+0x4b4/0x5a0 [msm] sp : ffffffc00bdcb720 x29: ffffffc00bdcb720 x28: ffffff8085debac0 x27: 0000000000000002 x26: ffffffd74af18320 x25: ffffff8083af75a0 x24: ffffffc00bdcb878 x23: 0000000000000001 x22: 0000000000000000 x21: ffffff8085a70000 x20: ffffff8083012dc0 x19: 0000000000000001 x18: 0000000000000000 x17: 000000040044ffff x16: 045000f4b5593519 x15: 0000000000000000 x14: 000000000000000b x13: 0000000000000001 x12: 0000000000000000 x11: 0000000000000001 x10: ffffffc00bdcb764 x9 : ffffffd74af06a08 x8 : 0000000000000001 x7 : 0000000000000001 x6 : 0000000000000000 x5 : ffffffc00bdcb878 x4 : 0000000000000002 x3 : ffffffffffffffff x2 : ffffffc00bdcb878 x1 : 0000000000000000 x0 : 0000000000000002 Call trace: dpu_hw_ctl_setup_blendstage+0x26c/0x278 [msm] _dpu_crtc_blend_setup+0x4b4/0x5a0 [msm] dpu_crtc_atomic_begin+0xd8/0x22c [msm] drm_atomic_helper_commit_planes+0x80/0x208 [drm_kms_helper] msm_atomic_commit_tail+0x134/0x6f0 [msm] commit_tail+0xa4/0x1a4 [drm_kms_helper] drm_atomic_helper_commit+0x170/0x184 [drm_kms_helper] drm_atomic_commit+0xac/0xe8 drm_mode_atomic_ioctl+0xbf0/0xdac drm_ioctl_kernel+0xc4/0x178 drm_ioctl+0x2c8/0x608 __arm64_sys_ioctl+0xa8/0xec invoke_syscall+0x44/0x104 el0_svc_common.constprop.0+0x44/0xec do_el0_svc+0x38/0x98 el0_svc+0x2c/0xb4 el0t_64_sync_handler+0xb8/0xbc el0t_64_sync+0x1a0/0x1a4 Code: 52800016 52800017 52800018 17ffffc7 (d4207d00) Fixes: 4488f71f6373 ("drm/msm/dpu: simplify blend configuration") Reported-by: Amit Pundir Signed-off-by: Dmitry Baryshkov Tested-by: Amit Pundir Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/523778/ Link: https://lore.kernel.org/r/20230223095708.3688148-1-dmitry.baryshkov@linaro.org Signed-off-by: Abhinav Kumar --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c index b88a2f3724e6..6c53ea560ffa 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c @@ -446,7 +446,9 @@ static void dpu_hw_ctl_setup_blendstage(struct dpu_hw_ctl *ctx, * CTL_LAYER has 3-bit field (and extra bits in EXT register), * all EXT registers has 4-bit fields. */ - if (cfg->idx == 0) { + if (cfg->idx == -1) { + continue; + } else if (cfg->idx == 0) { mixercfg[0] |= mix << cfg->shift; mixercfg[1] |= ext << cfg->ext_shift; } else { From ce68153edb5b36ddf87a19ed5a85131498690bbf Mon Sep 17 00:00:00 2001 From: Kuogee Hsieh Date: Mon, 27 Feb 2023 13:36:40 -0800 Subject: [PATCH 071/778] drm/msm/disp/dpu: fix sc7280_pp base offset At sc7280, pingpong block is used to management the dither effects to reduce distortion at panel. Currently pingpong-0 base offset is wrongly set at 0x59000. This mistake will not cause system to crash. However it will make dither not work. This patch correct sc7280 ping pong-0 block base offset. Changes in v2: -- add more details info n regrading of pingpong block at commit text Fixes: 591e34a091d1 ("drm/msm/disp/dpu1: add support for display for SC7280 target") Signed-off-by: Kuogee Hsieh Reviewed-by: Abhinav Kumar Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/524332/ Link: https://lore.kernel.org/r/1677533800-3125-1-git-send-email-quic_khsieh@quicinc.com Signed-off-by: Abhinav Kumar --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c index e390be4ef10b..497c9e1673ab 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -1714,7 +1714,7 @@ static const struct dpu_pingpong_cfg sm8350_pp[] = { }; static const struct dpu_pingpong_cfg sc7280_pp[] = { - PP_BLK("pingpong_0", PINGPONG_0, 0x59000, 0, sc7280_pp_sblk, -1, -1), + PP_BLK("pingpong_0", PINGPONG_0, 0x69000, 0, sc7280_pp_sblk, -1, -1), PP_BLK("pingpong_1", PINGPONG_1, 0x6a000, 0, sc7280_pp_sblk, -1, -1), PP_BLK("pingpong_2", PINGPONG_2, 0x6b000, 0, sc7280_pp_sblk, -1, -1), PP_BLK("pingpong_3", PINGPONG_3, 0x6c000, 0, sc7280_pp_sblk, -1, -1), From 5ec498ba86550909f2611b07087d57a71a78c336 Mon Sep 17 00:00:00 2001 From: Kalyan Thota Date: Mon, 13 Feb 2023 03:11:41 -0800 Subject: [PATCH 072/778] drm/msm/dpu: clear DSPP reservations in rm release Clear DSPP reservations from the global state during rm release Fixes: e47616df008b ("drm/msm/dpu: add support for color processing blocks in dpu driver") Signed-off-by: Kalyan Thota Reviewed-by: Dmitry Baryshkov Reviewed-by: Marijn Suijten Patchwork: https://patchwork.freedesktop.org/patch/522443/ Link: https://lore.kernel.org/r/1676286704-818-2-git-send-email-quic_kalyant@quicinc.com Signed-off-by: Abhinav Kumar --- drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c index 396429e63756..66c1b70d244f 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c @@ -577,6 +577,8 @@ void dpu_rm_release(struct dpu_global_state *global_state, ARRAY_SIZE(global_state->ctl_to_enc_id), enc->base.id); _dpu_rm_clear_mapping(global_state->dsc_to_enc_id, ARRAY_SIZE(global_state->dsc_to_enc_id), enc->base.id); + _dpu_rm_clear_mapping(global_state->dspp_to_enc_id, + ARRAY_SIZE(global_state->dspp_to_enc_id), enc->base.id); } int dpu_rm_reserve( From 52f04f10b9005ac4ce640da14a52ed7a146432fa Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Fri, 3 Mar 2023 08:19:09 -0800 Subject: [PATCH 073/778] thermal: intel: int340x: processor_thermal: Fix deadlock When user space updates the trip point there is a deadlock, which results in caller gets blocked forever. Commit 05eeee2b51b4 ("thermal/core: Protect sysfs accesses to thermal operations with thermal zone mutex"), added a mutex for tz->lock in the function trip_point_temp_store(). Hence, trip set callback() can't call any thermal zone API as they are protected with the same mutex lock. The callback here calling thermal_zone_device_enable(), which will result in deadlock. Move the thermal_zone_device_enable() to proc_thermal_pci_probe() to avoid this deadlock. Fixes: 05eeee2b51b4 ("thermal/core: Protect sysfs accesses to thermal operations with thermal zone mutex") Signed-off-by: Srinivas Pandruvada Cc: 6.2+ # 6.2+ Signed-off-by: Rafael J. Wysocki --- .../intel/int340x_thermal/processor_thermal_device_pci.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c index 40725cbc6eb0..90526f46c9b1 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c @@ -166,7 +166,6 @@ static int sys_set_trip_temp(struct thermal_zone_device *tzd, int trip, int temp proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_THRES_0, _temp); proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 1); - thermal_zone_device_enable(tzd); pci_info->stored_thres = temp; return 0; @@ -268,6 +267,10 @@ static int proc_thermal_pci_probe(struct pci_dev *pdev, const struct pci_device_ goto err_free_vectors; } + ret = thermal_zone_device_enable(pci_info->tzone); + if (ret) + goto err_free_vectors; + return 0; err_free_vectors: From 31d2e6b5d44e436969c15e4613e6b16c4c032d4d Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 3 Mar 2023 11:05:19 -0300 Subject: [PATCH 074/778] tools headers: Update the copy of x86's mem{cpy,set}_64.S used in 'perf bench' We also continue with SYM_TYPED_FUNC_START() in util/include/linux/linkage.h and with an exception in tools/perf/check_headers.sh's diff check to ignore the include cfi_types.h line when checking if the kernel original files drifted from the copies we carry. This is to get the changes from: 69d4c0d3218692ff ("entry, kasan, x86: Disallow overriding mem*() functions") That addresses these perf tools build warning: Warning: Kernel ABI header at 'tools/arch/x86/lib/memcpy_64.S' differs from latest version at 'arch/x86/lib/memcpy_64.S' diff -u tools/arch/x86/lib/memcpy_64.S arch/x86/lib/memcpy_64.S Warning: Kernel ABI header at 'tools/arch/x86/lib/memset_64.S' differs from latest version at 'arch/x86/lib/memset_64.S' diff -u tools/arch/x86/lib/memset_64.S arch/x86/lib/memset_64.S Cc: Adrian Hunter Cc: Ian Rogers Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Link: https://lore.kernel.org/lkml/ZAH%2FjsioJXGIOrkf@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/arch/x86/lib/memcpy_64.S | 5 ++--- tools/arch/x86/lib/memset_64.S | 4 +++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/tools/arch/x86/lib/memcpy_64.S b/tools/arch/x86/lib/memcpy_64.S index 5418e2f99834..a91ac666f758 100644 --- a/tools/arch/x86/lib/memcpy_64.S +++ b/tools/arch/x86/lib/memcpy_64.S @@ -7,7 +7,7 @@ #include #include -.pushsection .noinstr.text, "ax" +.section .noinstr.text, "ax" /* * We build a jump to memcpy_orig by default which gets NOPped out on @@ -42,7 +42,7 @@ SYM_TYPED_FUNC_START(__memcpy) SYM_FUNC_END(__memcpy) EXPORT_SYMBOL(__memcpy) -SYM_FUNC_ALIAS_WEAK(memcpy, __memcpy) +SYM_FUNC_ALIAS(memcpy, __memcpy) EXPORT_SYMBOL(memcpy) /* @@ -183,4 +183,3 @@ SYM_FUNC_START_LOCAL(memcpy_orig) RET SYM_FUNC_END(memcpy_orig) -.popsection diff --git a/tools/arch/x86/lib/memset_64.S b/tools/arch/x86/lib/memset_64.S index fc9ffd3ff3b2..6143b1a6fa2c 100644 --- a/tools/arch/x86/lib/memset_64.S +++ b/tools/arch/x86/lib/memset_64.S @@ -6,6 +6,8 @@ #include #include +.section .noinstr.text, "ax" + /* * ISO C memset - set a memory block to a byte value. This function uses fast * string to get better performance than the original function. The code is @@ -43,7 +45,7 @@ SYM_FUNC_START(__memset) SYM_FUNC_END(__memset) EXPORT_SYMBOL(__memset) -SYM_FUNC_ALIAS_WEAK(memset, __memset) +SYM_FUNC_ALIAS(memset, __memset) EXPORT_SYMBOL(memset) /* From df4b933e0e51e43bd27a495dc747db0851e6dd34 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 3 Mar 2023 11:48:09 -0300 Subject: [PATCH 075/778] tools headers UAPI: Sync linux/prctl.h with the kernel sources To pick new prctl options introduced in: b507808ebce23561 ("mm: implement memory-deny-write-execute as a prctl") That results in: $ diff -u tools/include/uapi/linux/prctl.h include/uapi/linux/prctl.h --- tools/include/uapi/linux/prctl.h 2022-06-20 17:54:43.884515663 -0300 +++ include/uapi/linux/prctl.h 2023-03-03 11:18:51.090923569 -0300 @@ -281,6 +281,12 @@ # define PR_SME_VL_LEN_MASK 0xffff # define PR_SME_VL_INHERIT (1 << 17) /* inherit across exec */ +/* Memory deny write / execute */ +#define PR_SET_MDWE 65 +# define PR_MDWE_REFUSE_EXEC_GAIN 1 + +#define PR_GET_MDWE 66 + #define PR_SET_VMA 0x53564d41 # define PR_SET_VMA_ANON_NAME 0 $ tools/perf/trace/beauty/prctl_option.sh > before $ cp include/uapi/linux/prctl.h tools/include/uapi/linux/prctl.h $ tools/perf/trace/beauty/prctl_option.sh > after $ diff -u before after --- before 2023-03-03 11:47:43.320013146 -0300 +++ after 2023-03-03 11:47:50.937216229 -0300 @@ -59,6 +59,8 @@ [62] = "SCHED_CORE", [63] = "SME_SET_VL", [64] = "SME_GET_VL", + [65] = "SET_MDWE", + [66] = "GET_MDWE", }; static const char *prctl_set_mm_options[] = { [1] = "START_CODE", $ Now users can do: # perf trace -e syscalls:sys_enter_prctl --filter "option==SET_MDWE||option==GET_MDWE" ^C# # trace -v -e syscalls:sys_enter_prctl --filter "option==SET_MDWE||option==GET_MDWE" New filter for syscalls:sys_enter_prctl: (option==65||option==66) && (common_pid != 5519 && common_pid != 3404) ^C# And when these prctl options appears in a session, they will be translated to the corresponding string. Cc: Adrian Hunter Cc: Andrew Morton Cc: Ian Rogers Cc: Jiri Olsa Cc: Joey Gouly Cc: Namhyung Kim Link: https://lore.kernel.org/lkml/ZAI%2FAoPXb%2Fsxz1%2Fm@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/include/uapi/linux/prctl.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/include/uapi/linux/prctl.h b/tools/include/uapi/linux/prctl.h index a5e06dcbba13..1312a137f7fb 100644 --- a/tools/include/uapi/linux/prctl.h +++ b/tools/include/uapi/linux/prctl.h @@ -281,6 +281,12 @@ struct prctl_mm_map { # define PR_SME_VL_LEN_MASK 0xffff # define PR_SME_VL_INHERIT (1 << 17) /* inherit across exec */ +/* Memory deny write / execute */ +#define PR_SET_MDWE 65 +# define PR_MDWE_REFUSE_EXEC_GAIN 1 + +#define PR_GET_MDWE 66 + #define PR_SET_VMA 0x53564d41 # define PR_SET_VMA_ANON_NAME 0 From 811f35ff59b6f99ae272d6f5b96bc9e974f88196 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 3 Mar 2023 16:49:20 -0300 Subject: [PATCH 076/778] tools headers: Synchronize {linux,vdso}/bits.h with the kernel sources To pick up the changes in this cset: cbdb1f163af2bb90 ("vdso/bits.h: Add BIT_ULL() for the sake of consistency") That just causes perf to rebuild, the macro included doesn't clash with anything in tools/{perf,objtool,bpf}. This addresses this perf build warning: Warning: Kernel ABI header at 'tools/include/linux/bits.h' differs from latest version at 'include/linux/bits.h' diff -u tools/include/linux/bits.h include/linux/bits.h Warning: Kernel ABI header at 'tools/include/vdso/bits.h' differs from latest version at 'include/vdso/bits.h' diff -u tools/include/vdso/bits.h include/vdso/bits.h Signed-off-by: Arnaldo Carvalho de Melo --- tools/include/linux/bits.h | 1 - tools/include/vdso/bits.h | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/include/linux/bits.h b/tools/include/linux/bits.h index 87d112650dfb..7c0cf5031abe 100644 --- a/tools/include/linux/bits.h +++ b/tools/include/linux/bits.h @@ -6,7 +6,6 @@ #include #include -#define BIT_ULL(nr) (ULL(1) << (nr)) #define BIT_MASK(nr) (UL(1) << ((nr) % BITS_PER_LONG)) #define BIT_WORD(nr) ((nr) / BITS_PER_LONG) #define BIT_ULL_MASK(nr) (ULL(1) << ((nr) % BITS_PER_LONG_LONG)) diff --git a/tools/include/vdso/bits.h b/tools/include/vdso/bits.h index 6d005a1f5d94..388b212088ea 100644 --- a/tools/include/vdso/bits.h +++ b/tools/include/vdso/bits.h @@ -5,5 +5,6 @@ #include #define BIT(nr) (UL(1) << (nr)) +#define BIT_ULL(nr) (ULL(1) << (nr)) #endif /* __VDSO_BITS_H */ From 5f800380af3881f1a0528d332838d4619a64593b Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 3 Mar 2023 16:57:50 -0300 Subject: [PATCH 077/778] tools include UAPI: Synchronize linux/fcntl.h with the kernel sources To pick up the changes in: 6fd7353829cafc40 ("mm/memfd: add F_SEAL_EXEC") That doesn't add or change any perf tools functionality, only addresses these build warnings: Warning: Kernel ABI header at 'tools/include/uapi/linux/fcntl.h' differs from latest version at 'include/uapi/linux/fcntl.h' diff -u tools/include/uapi/linux/fcntl.h include/uapi/linux/fcntl.h Signed-off-by: Arnaldo Carvalho de Melo --- tools/include/uapi/linux/fcntl.h | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/include/uapi/linux/fcntl.h b/tools/include/uapi/linux/fcntl.h index 2f86b2ad6d7e..e8c07da58c9f 100644 --- a/tools/include/uapi/linux/fcntl.h +++ b/tools/include/uapi/linux/fcntl.h @@ -43,6 +43,7 @@ #define F_SEAL_GROW 0x0004 /* prevent file from growing */ #define F_SEAL_WRITE 0x0008 /* prevent writes */ #define F_SEAL_FUTURE_WRITE 0x0010 /* prevent future writes while mapped */ +#define F_SEAL_EXEC 0x0020 /* prevent chmod modifying exec bits */ /* (1U << 31) is reserved for signed error codes */ /* From 33c53f9b5ac60c7d5c6acc91a6b6d933e0a417e3 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 3 Mar 2023 17:26:24 -0300 Subject: [PATCH 078/778] tools headers kvm: Sync uapi/{asm/linux} kvm.h headers with the kernel sources To pick up the changes in: 89b0e7de3451a17f ("KVM: arm64: nv: Introduce nested virtualization VCPU feature") 14329b825ffb7f27 ("KVM: x86/pmu: Introduce masked events to the pmu event filter") 6213b701a9df0472 ("KVM: x86: Replace 0-length arrays with flexible arrays") 3fd49805d19d1c56 ("KVM: s390: Extend MEM_OP ioctl by storage key checked cmpxchg") 14329b825ffb7f27 ("KVM: x86/pmu: Introduce masked events to the pmu event filter") That don't change functionality in tools/perf, as no new ioctl is added for the 'perf trace' scripts to harvest. This addresses these perf build warnings: Warning: Kernel ABI header at 'tools/include/uapi/linux/kvm.h' differs from latest version at 'include/uapi/linux/kvm.h' diff -u tools/include/uapi/linux/kvm.h include/uapi/linux/kvm.h Warning: Kernel ABI header at 'tools/arch/x86/include/uapi/asm/kvm.h' differs from latest version at 'arch/x86/include/uapi/asm/kvm.h' diff -u tools/arch/x86/include/uapi/asm/kvm.h arch/x86/include/uapi/asm/kvm.h Warning: Kernel ABI header at 'tools/arch/arm64/include/uapi/asm/kvm.h' differs from latest version at 'arch/arm64/include/uapi/asm/kvm.h' diff -u tools/arch/arm64/include/uapi/asm/kvm.h arch/arm64/include/uapi/asm/kvm.h Cc: Aaron Lewis Cc: Adrian Hunter Cc: Christoffer Dall Cc: Ian Rogers Cc: Janis Schoetterl-Glausch Cc: Janosch Frank Cc: Jiri Olsa Cc: Kees Kook Cc: Namhyung Kim Cc: Oliver Upton Cc: Sean Christopherson Link: https://lore.kernel.org/lkml/ZAJlg7%2FfWDVGX0F3@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/arch/arm64/include/uapi/asm/kvm.h | 1 + tools/arch/x86/include/uapi/asm/kvm.h | 34 +++++++++++++++++++++++-- tools/include/uapi/linux/kvm.h | 9 +++++++ 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/tools/arch/arm64/include/uapi/asm/kvm.h b/tools/arch/arm64/include/uapi/asm/kvm.h index a7a857f1784d..f8129c624b07 100644 --- a/tools/arch/arm64/include/uapi/asm/kvm.h +++ b/tools/arch/arm64/include/uapi/asm/kvm.h @@ -109,6 +109,7 @@ struct kvm_regs { #define KVM_ARM_VCPU_SVE 4 /* enable SVE for this CPU */ #define KVM_ARM_VCPU_PTRAUTH_ADDRESS 5 /* VCPU uses address authentication */ #define KVM_ARM_VCPU_PTRAUTH_GENERIC 6 /* VCPU uses generic authentication */ +#define KVM_ARM_VCPU_HAS_EL2 7 /* Support nested virtualization */ struct kvm_vcpu_init { __u32 target; diff --git a/tools/arch/x86/include/uapi/asm/kvm.h b/tools/arch/x86/include/uapi/asm/kvm.h index e48deab8901d..7f467fe05d42 100644 --- a/tools/arch/x86/include/uapi/asm/kvm.h +++ b/tools/arch/x86/include/uapi/asm/kvm.h @@ -9,6 +9,7 @@ #include #include +#include #define KVM_PIO_PAGE_OFFSET 1 #define KVM_COALESCED_MMIO_PAGE_OFFSET 2 @@ -507,8 +508,8 @@ struct kvm_nested_state { * KVM_{GET,PUT}_NESTED_STATE ioctl values. */ union { - struct kvm_vmx_nested_state_data vmx[0]; - struct kvm_svm_nested_state_data svm[0]; + __DECLARE_FLEX_ARRAY(struct kvm_vmx_nested_state_data, vmx); + __DECLARE_FLEX_ARRAY(struct kvm_svm_nested_state_data, svm); } data; }; @@ -525,6 +526,35 @@ struct kvm_pmu_event_filter { #define KVM_PMU_EVENT_ALLOW 0 #define KVM_PMU_EVENT_DENY 1 +#define KVM_PMU_EVENT_FLAG_MASKED_EVENTS BIT(0) +#define KVM_PMU_EVENT_FLAGS_VALID_MASK (KVM_PMU_EVENT_FLAG_MASKED_EVENTS) + +/* + * Masked event layout. + * Bits Description + * ---- ----------- + * 7:0 event select (low bits) + * 15:8 umask match + * 31:16 unused + * 35:32 event select (high bits) + * 36:54 unused + * 55 exclude bit + * 63:56 umask mask + */ + +#define KVM_PMU_ENCODE_MASKED_ENTRY(event_select, mask, match, exclude) \ + (((event_select) & 0xFFULL) | (((event_select) & 0XF00ULL) << 24) | \ + (((mask) & 0xFFULL) << 56) | \ + (((match) & 0xFFULL) << 8) | \ + ((__u64)(!!(exclude)) << 55)) + +#define KVM_PMU_MASKED_ENTRY_EVENT_SELECT \ + (GENMASK_ULL(7, 0) | GENMASK_ULL(35, 32)) +#define KVM_PMU_MASKED_ENTRY_UMASK_MASK (GENMASK_ULL(63, 56)) +#define KVM_PMU_MASKED_ENTRY_UMASK_MATCH (GENMASK_ULL(15, 8)) +#define KVM_PMU_MASKED_ENTRY_EXCLUDE (BIT_ULL(55)) +#define KVM_PMU_MASKED_ENTRY_UMASK_MASK_SHIFT (56) + /* for KVM_{GET,SET,HAS}_DEVICE_ATTR */ #define KVM_VCPU_TSC_CTRL 0 /* control group for the timestamp counter (TSC) */ #define KVM_VCPU_TSC_OFFSET 0 /* attribute for the TSC offset */ diff --git a/tools/include/uapi/linux/kvm.h b/tools/include/uapi/linux/kvm.h index 55155e262646..d77aef872a0a 100644 --- a/tools/include/uapi/linux/kvm.h +++ b/tools/include/uapi/linux/kvm.h @@ -583,6 +583,8 @@ struct kvm_s390_mem_op { struct { __u8 ar; /* the access register number */ __u8 key; /* access key, ignored if flag unset */ + __u8 pad1[6]; /* ignored */ + __u64 old_addr; /* ignored if cmpxchg flag unset */ }; __u32 sida_offset; /* offset into the sida */ __u8 reserved[32]; /* ignored */ @@ -595,11 +597,17 @@ struct kvm_s390_mem_op { #define KVM_S390_MEMOP_SIDA_WRITE 3 #define KVM_S390_MEMOP_ABSOLUTE_READ 4 #define KVM_S390_MEMOP_ABSOLUTE_WRITE 5 +#define KVM_S390_MEMOP_ABSOLUTE_CMPXCHG 6 + /* flags for kvm_s390_mem_op->flags */ #define KVM_S390_MEMOP_F_CHECK_ONLY (1ULL << 0) #define KVM_S390_MEMOP_F_INJECT_EXCEPTION (1ULL << 1) #define KVM_S390_MEMOP_F_SKEY_PROTECTION (1ULL << 2) +/* flags specifying extension support via KVM_CAP_S390_MEM_OP_EXTENSION */ +#define KVM_S390_MEMOP_EXTENSION_CAP_BASE (1 << 0) +#define KVM_S390_MEMOP_EXTENSION_CAP_CMPXCHG (1 << 1) + /* for KVM_INTERRUPT */ struct kvm_interrupt { /* in */ @@ -1175,6 +1183,7 @@ struct kvm_ppc_resize_hpt { #define KVM_CAP_DIRTY_LOG_RING_ACQ_REL 223 #define KVM_CAP_S390_PROTECTED_ASYNC_DISABLE 224 #define KVM_CAP_DIRTY_LOG_RING_WITH_BITMAP 225 +#define KVM_CAP_PMU_EVENT_MASKED_EVENTS 226 #ifdef KVM_CAP_IRQ_ROUTING From 3ee7cb4fdf37e3763b3b10da2a7715b7a7a2a783 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 3 Mar 2023 22:36:04 -0300 Subject: [PATCH 079/778] tools arch x86: Sync the msr-index.h copy with the kernel sources To pick up the changes in: e7862eda309ecfcc ("x86/cpu: Support AMD Automatic IBRS") 0125acda7d76b943 ("x86/bugs: Reset speculation control settings on init") 38aaf921e92dc5cf ("perf/x86: Add Meteor Lake support") 5b6fac3fa44bafee ("x86/resctrl: Detect and configure Slow Memory Bandwidth Allocation") dc2a3e857981f859 ("x86/resctrl: Add interface to read mbm_total_bytes_config") Addressing these tools/perf build warnings: diff -u tools/arch/x86/include/asm/msr-index.h arch/x86/include/asm/msr-index.h Warning: Kernel ABI header at 'tools/arch/x86/include/asm/msr-index.h' differs from latest version at 'arch/x86/include/asm/msr-index.h' That makes the beautification scripts to pick some new entries: $ tools/perf/trace/beauty/tracepoints/x86_msr.sh > before $ cp arch/x86/include/asm/msr-index.h tools/arch/x86/include/asm/msr-index.h $ tools/perf/trace/beauty/tracepoints/x86_msr.sh > after $ diff -u before after --- before 2023-03-03 18:26:51.766923522 -0300 +++ after 2023-03-03 18:27:09.987415481 -0300 @@ -267,9 +267,11 @@ [0xc000010e - x86_64_specific_MSRs_offset] = "AMD64_LBR_SELECT", [0xc000010f - x86_64_specific_MSRs_offset] = "AMD_DBG_EXTN_CFG", [0xc0000200 - x86_64_specific_MSRs_offset] = "IA32_MBA_BW_BASE", + [0xc0000280 - x86_64_specific_MSRs_offset] = "IA32_SMBA_BW_BASE", [0xc0000300 - x86_64_specific_MSRs_offset] = "AMD64_PERF_CNTR_GLOBAL_STATUS", [0xc0000301 - x86_64_specific_MSRs_offset] = "AMD64_PERF_CNTR_GLOBAL_CTL", [0xc0000302 - x86_64_specific_MSRs_offset] = "AMD64_PERF_CNTR_GLOBAL_STATUS_CLR", + [0xc0000400 - x86_64_specific_MSRs_offset] = "IA32_EVT_CFG_BASE", }; #define x86_AMD_V_KVM_MSRs_offset 0xc0010000 $ Now one can trace systemwide asking to see backtraces to where that MSR is being read/written, see this example with a previous update: # perf trace -e msr:*_msr/max-stack=32/ --filter="msr>=IA32_U_CET && msr<=IA32_INT_SSP_TAB" ^C# If we use -v (verbose mode) we can see what it does behind the scenes: # perf trace -v -e msr:*_msr/max-stack=32/ --filter="msr>=IA32_U_CET && msr<=IA32_INT_SSP_TAB" Using CPUID AuthenticAMD-25-21-0 0x6a0 0x6a8 New filter for msr:read_msr: (msr>=0x6a0 && msr<=0x6a8) && (common_pid != 597499 && common_pid != 3313) 0x6a0 0x6a8 New filter for msr:write_msr: (msr>=0x6a0 && msr<=0x6a8) && (common_pid != 597499 && common_pid != 3313) mmap size 528384B ^C# Example with a frequent msr: # perf trace -v -e msr:*_msr/max-stack=32/ --filter="msr==IA32_SPEC_CTRL" --max-events 2 Using CPUID AuthenticAMD-25-21-0 0x48 New filter for msr:read_msr: (msr==0x48) && (common_pid != 2612129 && common_pid != 3841) 0x48 New filter for msr:write_msr: (msr==0x48) && (common_pid != 2612129 && common_pid != 3841) mmap size 528384B Looking at the vmlinux_path (8 entries long) symsrc__init: build id mismatch for vmlinux. Using /proc/kcore for kernel data Using /proc/kallsyms for symbols 0.000 Timer/2525383 msr:write_msr(msr: IA32_SPEC_CTRL, val: 6) do_trace_write_msr ([kernel.kallsyms]) do_trace_write_msr ([kernel.kallsyms]) __switch_to_xtra ([kernel.kallsyms]) __switch_to ([kernel.kallsyms]) __schedule ([kernel.kallsyms]) schedule ([kernel.kallsyms]) futex_wait_queue_me ([kernel.kallsyms]) futex_wait ([kernel.kallsyms]) do_futex ([kernel.kallsyms]) __x64_sys_futex ([kernel.kallsyms]) do_syscall_64 ([kernel.kallsyms]) entry_SYSCALL_64_after_hwframe ([kernel.kallsyms]) __futex_abstimed_wait_common64 (/usr/lib64/libpthread-2.33.so) 0.030 :0/0 msr:write_msr(msr: IA32_SPEC_CTRL, val: 2) do_trace_write_msr ([kernel.kallsyms]) do_trace_write_msr ([kernel.kallsyms]) __switch_to_xtra ([kernel.kallsyms]) __switch_to ([kernel.kallsyms]) __schedule ([kernel.kallsyms]) schedule_idle ([kernel.kallsyms]) do_idle ([kernel.kallsyms]) cpu_startup_entry ([kernel.kallsyms]) secondary_startup_64_no_verify ([kernel.kallsyms]) # Cc: Adrian Hunter Cc: Babu Moger Cc: Borislav Petkov (AMD) Cc: Breno Leitao Cc: Ian Rogers Cc: Ingo Molnar Cc: Jiri Olsa Cc: Kan Liang Cc: Kim Phillips Cc: Namhyung Kim Cc: Nikunj A Dadhania Link: https://lore.kernel.org/lkml/ZAJoaZ41+rU5H0vL@kernel.org [ I had published the perf-tools branch before with the sync with ] [ 8c29f01654053258 ("x86/sev: Add SEV-SNP guest feature negotiation support") ] [ I removed it from this new sync ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/arch/x86/include/asm/msr-index.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tools/arch/x86/include/asm/msr-index.h b/tools/arch/x86/include/asm/msr-index.h index d3fe82c5d6b6..ad35355ee43e 100644 --- a/tools/arch/x86/include/asm/msr-index.h +++ b/tools/arch/x86/include/asm/msr-index.h @@ -25,6 +25,7 @@ #define _EFER_SVME 12 /* Enable virtualization */ #define _EFER_LMSLE 13 /* Long Mode Segment Limit Enable */ #define _EFER_FFXSR 14 /* Enable Fast FXSAVE/FXRSTOR */ +#define _EFER_AUTOIBRS 21 /* Enable Automatic IBRS */ #define EFER_SCE (1<<_EFER_SCE) #define EFER_LME (1<<_EFER_LME) @@ -33,6 +34,7 @@ #define EFER_SVME (1<<_EFER_SVME) #define EFER_LMSLE (1<<_EFER_LMSLE) #define EFER_FFXSR (1<<_EFER_FFXSR) +#define EFER_AUTOIBRS (1<<_EFER_AUTOIBRS) /* Intel MSRs. Some also available on other CPUs */ @@ -49,6 +51,10 @@ #define SPEC_CTRL_RRSBA_DIS_S_SHIFT 6 /* Disable RRSBA behavior */ #define SPEC_CTRL_RRSBA_DIS_S BIT(SPEC_CTRL_RRSBA_DIS_S_SHIFT) +/* A mask for bits which the kernel toggles when controlling mitigations */ +#define SPEC_CTRL_MITIGATIONS_MASK (SPEC_CTRL_IBRS | SPEC_CTRL_STIBP | SPEC_CTRL_SSBD \ + | SPEC_CTRL_RRSBA_DIS_S) + #define MSR_IA32_PRED_CMD 0x00000049 /* Prediction Command */ #define PRED_CMD_IBPB BIT(0) /* Indirect Branch Prediction Barrier */ @@ -189,6 +195,9 @@ #define MSR_TURBO_RATIO_LIMIT1 0x000001ae #define MSR_TURBO_RATIO_LIMIT2 0x000001af +#define MSR_SNOOP_RSP_0 0x00001328 +#define MSR_SNOOP_RSP_1 0x00001329 + #define MSR_LBR_SELECT 0x000001c8 #define MSR_LBR_TOS 0x000001c9 @@ -1081,6 +1090,8 @@ /* - AMD: */ #define MSR_IA32_MBA_BW_BASE 0xc0000200 +#define MSR_IA32_SMBA_BW_BASE 0xc0000280 +#define MSR_IA32_EVT_CFG_BASE 0xc0000400 /* MSR_IA32_VMX_MISC bits */ #define MSR_IA32_VMX_MISC_INTEL_PT (1ULL << 14) From 0c7273e494dd5121e20e160cb2f047a593ee14a8 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Sun, 5 Mar 2023 15:13:22 -0800 Subject: [PATCH 080/778] xfs: quotacheck failure can race with background inode inactivation The background inode inactivation can attached dquots to inodes, but this can race with a foreground quotacheck failure that leads to disabling quotas and freeing the mp->m_quotainfo structure. The background inode inactivation then tries to allocate a quota, tries to dereference mp->m_quotainfo, and crashes like so: XFS (loop1): Quotacheck: Unsuccessful (Error -5): Disabling quotas. xfs filesystem being mounted at /root/syzkaller.qCVHXV/0/file0 supports timestamps until 2038 (0x7fffffff) BUG: kernel NULL pointer dereference, address: 00000000000002a8 .... CPU: 0 PID: 161 Comm: kworker/0:4 Not tainted 6.2.0-c9c3395d5e3d #1 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.16.0-0-gd239552ce722-prebuilt.qemu.org 04/01/2014 Workqueue: xfs-inodegc/loop1 xfs_inodegc_worker RIP: 0010:xfs_dquot_alloc+0x95/0x1e0 .... Call Trace: xfs_qm_dqread+0x46/0x440 xfs_qm_dqget_inode+0x154/0x500 xfs_qm_dqattach_one+0x142/0x3c0 xfs_qm_dqattach_locked+0x14a/0x170 xfs_qm_dqattach+0x52/0x80 xfs_inactive+0x186/0x340 xfs_inodegc_worker+0xd3/0x430 process_one_work+0x3b1/0x960 worker_thread+0x52/0x660 kthread+0x161/0x1a0 ret_from_fork+0x29/0x50 .... Prevent this race by flushing all the queued background inode inactivations pending before purging all the cached dquots when quotacheck fails. Reported-by: Pengfei Xu Signed-off-by: Dave Chinner Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/xfs_qm.c | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c index 7dc0db7f5a76..6abcc34fafd8 100644 --- a/fs/xfs/xfs_qm.c +++ b/fs/xfs/xfs_qm.c @@ -1321,15 +1321,14 @@ xfs_qm_quotacheck( error = xfs_iwalk_threaded(mp, 0, 0, xfs_qm_dqusage_adjust, 0, true, NULL); - if (error) { - /* - * The inode walk may have partially populated the dquot - * caches. We must purge them before disabling quota and - * tearing down the quotainfo, or else the dquots will leak. - */ - xfs_qm_dqpurge_all(mp); - goto error_return; - } + + /* + * On error, the inode walk may have partially populated the dquot + * caches. We must purge them before disabling quota and tearing down + * the quotainfo, or else the dquots will leak. + */ + if (error) + goto error_purge; /* * We've made all the changes that we need to make incore. Flush them @@ -1363,10 +1362,8 @@ xfs_qm_quotacheck( * and turn quotaoff. The dquots won't be attached to any of the inodes * at this point (because we intentionally didn't in dqget_noattach). */ - if (error) { - xfs_qm_dqpurge_all(mp); - goto error_return; - } + if (error) + goto error_purge; /* * If one type of quotas is off, then it will lose its @@ -1376,7 +1373,7 @@ xfs_qm_quotacheck( mp->m_qflags &= ~XFS_ALL_QUOTA_CHKD; mp->m_qflags |= flags; - error_return: +error_return: xfs_buf_delwri_cancel(&buffer_list); if (error) { @@ -1395,6 +1392,21 @@ xfs_qm_quotacheck( } else xfs_notice(mp, "Quotacheck: Done."); return error; + +error_purge: + /* + * On error, we may have inodes queued for inactivation. This may try + * to attach dquots to the inode before running cleanup operations on + * the inode and this can race with the xfs_qm_destroy_quotainfo() call + * below that frees mp->m_quotainfo. To avoid this race, flush all the + * pending inodegc operations before we purge the dquots from memory, + * ensuring that background inactivation is idle whilst we turn off + * quotas. + */ + xfs_inodegc_flush(mp); + xfs_qm_dqpurge_all(mp); + goto error_return; + } /* From 8ac5b996bf5199f15b7687ceae989f8b2a410dda Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Sun, 5 Mar 2023 15:13:23 -0800 Subject: [PATCH 081/778] xfs: fix off-by-one-block in xfs_discard_folio() The recent writeback corruption fixes changed the code in xfs_discard_folio() to calculate a byte range to for punching delalloc extents. A mistake was made in using round_up(pos) for the end offset, because when pos points at the first byte of a block, it does not get rounded up to point to the end byte of the block. hence the punch range is short, and this leads to unexpected behaviour in certain cases in xfs_bmap_punch_delalloc_range. e.g. pos = 0 means we call xfs_bmap_punch_delalloc_range(0,0), so there is no previous extent and it rounds up the punch to the end of the delalloc extent it found at offset 0, not the end of the range given to xfs_bmap_punch_delalloc_range(). Fix this by handling the zero block offset case correctly. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=217030 Link: https://lore.kernel.org/linux-xfs/Y+vOfaxIWX1c%2Fyy9@bfoster/ Fixes: 7348b322332d ("xfs: xfs_bmap_punch_delalloc_range() should take a byte range") Reported-by: Pengfei Xu Found-by: Brian Foster Signed-off-by: Dave Chinner Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/xfs_aops.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index 41734202796f..2ef78aa1d3f6 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c @@ -449,15 +449,17 @@ xfs_prepare_ioend( } /* - * If the page has delalloc blocks on it, we need to punch them out before we - * invalidate the page. If we don't, we leave a stale delalloc mapping on the - * inode that can trip up a later direct I/O read operation on the same region. + * If the folio has delalloc blocks on it, the caller is asking us to punch them + * out. If we don't, we can leave a stale delalloc mapping covered by a clean + * page that needs to be dirtied again before the delalloc mapping can be + * converted. This stale delalloc mapping can trip up a later direct I/O read + * operation on the same region. * - * We prevent this by truncating away the delalloc regions on the page. Because + * We prevent this by truncating away the delalloc regions on the folio. Because * they are delalloc, we can do this without needing a transaction. Indeed - if * we get ENOSPC errors, we have to be able to do this truncation without a - * transaction as there is no space left for block reservation (typically why we - * see a ENOSPC in writeback). + * transaction as there is no space left for block reservation (typically why + * we see a ENOSPC in writeback). */ static void xfs_discard_folio( @@ -475,8 +477,13 @@ xfs_discard_folio( "page discard on page "PTR_FMT", inode 0x%llx, pos %llu.", folio, ip->i_ino, pos); + /* + * The end of the punch range is always the offset of the the first + * byte of the next folio. Hence the end offset is only dependent on the + * folio itself and not the start offset that is passed in. + */ error = xfs_bmap_punch_delalloc_range(ip, pos, - round_up(pos, folio_size(folio))); + folio_pos(folio) + folio_size(folio)); if (error && !xfs_is_shutdown(mp)) xfs_alert(mp, "page discard unable to remove delalloc mapping."); From 4658de99d43cd740e019e7fd124b4128f8f4027f Mon Sep 17 00:00:00 2001 From: Lucas Tanure Date: Thu, 23 Feb 2023 08:43:21 +0000 Subject: [PATCH 082/778] ASoC: cs35l41: Only disable internal boost In error situations, only the internal boost case should be disabled and re-enabled. Also, for other boost cases re-enabling the boost to the default internal boost config is incorrect. Fixes: 6450ef559056 ("ASoC: cs35l41: CS35L41 Boosted Smart Amplifier") Signed-off-by: Lucas Tanure Acked-by: Charles Keepax Reviewed-by: David Rhodes Link: https://lore.kernel.org/r/20230223084324.9076-2-lucas.tanure@collabora.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l41.c | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/sound/soc/codecs/cs35l41.c b/sound/soc/codecs/cs35l41.c index c223d83e02cf..f2b5032daa6a 100644 --- a/sound/soc/codecs/cs35l41.c +++ b/sound/soc/codecs/cs35l41.c @@ -356,6 +356,19 @@ static const struct snd_kcontrol_new cs35l41_aud_controls[] = { WM_ADSP_FW_CONTROL("DSP1", 0), }; +static void cs35l41_boost_enable(struct cs35l41_private *cs35l41, unsigned int enable) +{ + switch (cs35l41->hw_cfg.bst_type) { + case CS35L41_INT_BOOST: + enable = enable ? CS35L41_BST_EN_DEFAULT : CS35L41_BST_DIS_FET_OFF; + regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL2, CS35L41_BST_EN_MASK, + enable << CS35L41_BST_EN_SHIFT); + break; + default: + break; + } +} + static irqreturn_t cs35l41_irq(int irq, void *data) { struct cs35l41_private *cs35l41 = data; @@ -431,8 +444,7 @@ static irqreturn_t cs35l41_irq(int irq, void *data) if (status[0] & CS35L41_BST_OVP_ERR) { dev_crit_ratelimited(cs35l41->dev, "VBST Over Voltage error\n"); - regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL2, - CS35L41_BST_EN_MASK, 0); + cs35l41_boost_enable(cs35l41, 0); regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS1, CS35L41_BST_OVP_ERR); regmap_write(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, 0); @@ -441,16 +453,13 @@ static irqreturn_t cs35l41_irq(int irq, void *data) CS35L41_BST_OVP_ERR_RLS); regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, CS35L41_BST_OVP_ERR_RLS, 0); - regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL2, - CS35L41_BST_EN_MASK, - CS35L41_BST_EN_DEFAULT << CS35L41_BST_EN_SHIFT); + cs35l41_boost_enable(cs35l41, 1); ret = IRQ_HANDLED; } if (status[0] & CS35L41_BST_DCM_UVP_ERR) { dev_crit_ratelimited(cs35l41->dev, "DCM VBST Under Voltage Error\n"); - regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL2, - CS35L41_BST_EN_MASK, 0); + cs35l41_boost_enable(cs35l41, 0); regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS1, CS35L41_BST_DCM_UVP_ERR); regmap_write(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, 0); @@ -459,16 +468,13 @@ static irqreturn_t cs35l41_irq(int irq, void *data) CS35L41_BST_UVP_ERR_RLS); regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, CS35L41_BST_UVP_ERR_RLS, 0); - regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL2, - CS35L41_BST_EN_MASK, - CS35L41_BST_EN_DEFAULT << CS35L41_BST_EN_SHIFT); + cs35l41_boost_enable(cs35l41, 1); ret = IRQ_HANDLED; } if (status[0] & CS35L41_BST_SHORT_ERR) { dev_crit_ratelimited(cs35l41->dev, "LBST error: powering off!\n"); - regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL2, - CS35L41_BST_EN_MASK, 0); + cs35l41_boost_enable(cs35l41, 0); regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS1, CS35L41_BST_SHORT_ERR); regmap_write(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, 0); @@ -477,9 +483,7 @@ static irqreturn_t cs35l41_irq(int irq, void *data) CS35L41_BST_SHORT_ERR_RLS); regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, CS35L41_BST_SHORT_ERR_RLS, 0); - regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL2, - CS35L41_BST_EN_MASK, - CS35L41_BST_EN_DEFAULT << CS35L41_BST_EN_SHIFT); + cs35l41_boost_enable(cs35l41, 1); ret = IRQ_HANDLED; } From be9457f12e84437259707415364cc5fc96041ed6 Mon Sep 17 00:00:00 2001 From: Lucas Tanure Date: Thu, 23 Feb 2023 08:43:22 +0000 Subject: [PATCH 083/778] ASoC: cs35l41: Refactor error release code Add cs35l41_error_release function to handle error release sequences. Signed-off-by: Lucas Tanure Acked-by: Charles Keepax Reviewed-by: David Rhodes Link: https://lore.kernel.org/r/20230223084324.9076-3-lucas.tanure@collabora.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l41.c | 64 ++++++++++---------------------------- 1 file changed, 16 insertions(+), 48 deletions(-) diff --git a/sound/soc/codecs/cs35l41.c b/sound/soc/codecs/cs35l41.c index f2b5032daa6a..c006364e5335 100644 --- a/sound/soc/codecs/cs35l41.c +++ b/sound/soc/codecs/cs35l41.c @@ -369,6 +369,16 @@ static void cs35l41_boost_enable(struct cs35l41_private *cs35l41, unsigned int e } } + +static void cs35l41_error_release(struct cs35l41_private *cs35l41, unsigned int irq_err_bit, + unsigned int rel_err_bit) +{ + regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS1, irq_err_bit); + regmap_write(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, 0); + regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, rel_err_bit, rel_err_bit); + regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, rel_err_bit, 0); +} + static irqreturn_t cs35l41_irq(int irq, void *data) { struct cs35l41_private *cs35l41 = data; @@ -405,54 +415,26 @@ static irqreturn_t cs35l41_irq(int irq, void *data) */ if (status[0] & CS35L41_AMP_SHORT_ERR) { dev_crit_ratelimited(cs35l41->dev, "Amp short error\n"); - regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS1, - CS35L41_AMP_SHORT_ERR); - regmap_write(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, 0); - regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, - CS35L41_AMP_SHORT_ERR_RLS, - CS35L41_AMP_SHORT_ERR_RLS); - regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, - CS35L41_AMP_SHORT_ERR_RLS, 0); + cs35l41_error_release(cs35l41, CS35L41_AMP_SHORT_ERR, CS35L41_AMP_SHORT_ERR_RLS); ret = IRQ_HANDLED; } if (status[0] & CS35L41_TEMP_WARN) { dev_crit_ratelimited(cs35l41->dev, "Over temperature warning\n"); - regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS1, - CS35L41_TEMP_WARN); - regmap_write(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, 0); - regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, - CS35L41_TEMP_WARN_ERR_RLS, - CS35L41_TEMP_WARN_ERR_RLS); - regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, - CS35L41_TEMP_WARN_ERR_RLS, 0); + cs35l41_error_release(cs35l41, CS35L41_TEMP_WARN, CS35L41_TEMP_WARN_ERR_RLS); ret = IRQ_HANDLED; } if (status[0] & CS35L41_TEMP_ERR) { dev_crit_ratelimited(cs35l41->dev, "Over temperature error\n"); - regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS1, - CS35L41_TEMP_ERR); - regmap_write(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, 0); - regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, - CS35L41_TEMP_ERR_RLS, - CS35L41_TEMP_ERR_RLS); - regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, - CS35L41_TEMP_ERR_RLS, 0); + cs35l41_error_release(cs35l41, CS35L41_TEMP_ERR, CS35L41_TEMP_ERR_RLS); ret = IRQ_HANDLED; } if (status[0] & CS35L41_BST_OVP_ERR) { dev_crit_ratelimited(cs35l41->dev, "VBST Over Voltage error\n"); cs35l41_boost_enable(cs35l41, 0); - regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS1, - CS35L41_BST_OVP_ERR); - regmap_write(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, 0); - regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, - CS35L41_BST_OVP_ERR_RLS, - CS35L41_BST_OVP_ERR_RLS); - regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, - CS35L41_BST_OVP_ERR_RLS, 0); + cs35l41_error_release(cs35l41, CS35L41_BST_OVP_ERR, CS35L41_BST_OVP_ERR_RLS); cs35l41_boost_enable(cs35l41, 1); ret = IRQ_HANDLED; } @@ -460,14 +442,7 @@ static irqreturn_t cs35l41_irq(int irq, void *data) if (status[0] & CS35L41_BST_DCM_UVP_ERR) { dev_crit_ratelimited(cs35l41->dev, "DCM VBST Under Voltage Error\n"); cs35l41_boost_enable(cs35l41, 0); - regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS1, - CS35L41_BST_DCM_UVP_ERR); - regmap_write(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, 0); - regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, - CS35L41_BST_UVP_ERR_RLS, - CS35L41_BST_UVP_ERR_RLS); - regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, - CS35L41_BST_UVP_ERR_RLS, 0); + cs35l41_error_release(cs35l41, CS35L41_BST_DCM_UVP_ERR, CS35L41_BST_UVP_ERR_RLS); cs35l41_boost_enable(cs35l41, 1); ret = IRQ_HANDLED; } @@ -475,14 +450,7 @@ static irqreturn_t cs35l41_irq(int irq, void *data) if (status[0] & CS35L41_BST_SHORT_ERR) { dev_crit_ratelimited(cs35l41->dev, "LBST error: powering off!\n"); cs35l41_boost_enable(cs35l41, 0); - regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS1, - CS35L41_BST_SHORT_ERR); - regmap_write(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, 0); - regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, - CS35L41_BST_SHORT_ERR_RLS, - CS35L41_BST_SHORT_ERR_RLS); - regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, - CS35L41_BST_SHORT_ERR_RLS, 0); + cs35l41_error_release(cs35l41, CS35L41_BST_SHORT_ERR, CS35L41_BST_SHORT_ERR_RLS); cs35l41_boost_enable(cs35l41, 1); ret = IRQ_HANDLED; } From f5030564938be112183ba3df0cdd6dea3f694c2e Mon Sep 17 00:00:00 2001 From: Lucas Tanure Date: Thu, 23 Feb 2023 08:43:23 +0000 Subject: [PATCH 084/778] ALSA: cs35l41: Add shared boost feature Shared boost allows two amplifiers to share a single boost circuit by communicating on the MDSYNC bus. The passive amplifier does not control the boost and receives data from the active amplifier. Shared Boost is not supported in HDA Systems. Based on David Rhodes shared boost patches. Signed-off-by: Lucas Tanure Reviewed-by: David Rhodes Link: https://lore.kernel.org/r/20230223084324.9076-4-lucas.tanure@collabora.com Signed-off-by: Mark Brown --- include/sound/cs35l41.h | 13 +++++- sound/pci/hda/cs35l41_hda.c | 6 +-- sound/soc/codecs/cs35l41-lib.c | 73 +++++++++++++++++++++++++++++++++- sound/soc/codecs/cs35l41.c | 27 ++++++++++++- sound/soc/codecs/cs35l41.h | 1 + 5 files changed, 113 insertions(+), 7 deletions(-) diff --git a/include/sound/cs35l41.h b/include/sound/cs35l41.h index 9ac5918269a5..7239d943942c 100644 --- a/include/sound/cs35l41.h +++ b/include/sound/cs35l41.h @@ -11,6 +11,7 @@ #define __CS35L41_H #include +#include #include #define CS35L41_FIRSTREG 0x00000000 @@ -677,6 +678,7 @@ #define CS35L36_PUP_DONE_IRQ_UNMASK 0x5F #define CS35L36_PUP_DONE_IRQ_MASK 0xBF +#define CS35L41_SYNC_EN_MASK BIT(8) #define CS35L41_AMP_SHORT_ERR 0x80000000 #define CS35L41_BST_SHORT_ERR 0x0100 @@ -686,6 +688,7 @@ #define CS35L41_BST_DCM_UVP_ERR 0x80 #define CS35L41_OTP_BOOT_DONE 0x02 #define CS35L41_PLL_UNLOCK 0x10 +#define CS35L41_PLL_LOCK BIT(1) #define CS35L41_OTP_BOOT_ERR 0x80000000 #define CS35L41_AMP_SHORT_ERR_RLS 0x02 @@ -705,6 +708,8 @@ #define CS35L41_INT1_MASK_DEFAULT 0x7FFCFE3F #define CS35L41_INT1_UNMASK_PUP 0xFEFFFFFF #define CS35L41_INT1_UNMASK_PDN 0xFF7FFFFF +#define CS35L41_INT3_PLL_LOCK_SHIFT 1 +#define CS35L41_INT3_PLL_LOCK_MASK BIT(CS35L41_INT3_PLL_LOCK_SHIFT) #define CS35L41_GPIO_DIR_MASK 0x80000000 #define CS35L41_GPIO_DIR_SHIFT 31 @@ -742,6 +747,11 @@ enum cs35l41_boost_type { CS35L41_INT_BOOST, CS35L41_EXT_BOOST, + CS35L41_SHD_BOOST_ACTV, + CS35L41_SHD_BOOST_PASS, + + // Not present in Binding Documentation, so no system should use this value. + // This value is only used in CLSA0100 Laptop CS35L41_EXT_BOOST_NO_VSPK_SWITCH, }; @@ -891,6 +901,7 @@ int cs35l41_exit_hibernate(struct device *dev, struct regmap *regmap); int cs35l41_init_boost(struct device *dev, struct regmap *regmap, struct cs35l41_hw_cfg *hw_cfg); bool cs35l41_safe_reset(struct regmap *regmap, enum cs35l41_boost_type b_type); -int cs35l41_global_enable(struct regmap *regmap, enum cs35l41_boost_type b_type, int enable); +int cs35l41_global_enable(struct regmap *regmap, enum cs35l41_boost_type b_type, int enable, + struct completion *pll_lock); #endif /* __CS35L41_H */ diff --git a/sound/pci/hda/cs35l41_hda.c b/sound/pci/hda/cs35l41_hda.c index 75020edd39e7..b5210abb5141 100644 --- a/sound/pci/hda/cs35l41_hda.c +++ b/sound/pci/hda/cs35l41_hda.c @@ -514,13 +514,13 @@ static void cs35l41_hda_playback_hook(struct device *dev, int action) break; case HDA_GEN_PCM_ACT_PREPARE: mutex_lock(&cs35l41->fw_mutex); - ret = cs35l41_global_enable(reg, cs35l41->hw_cfg.bst_type, 1); + ret = cs35l41_global_enable(reg, cs35l41->hw_cfg.bst_type, 1, NULL); mutex_unlock(&cs35l41->fw_mutex); break; case HDA_GEN_PCM_ACT_CLEANUP: mutex_lock(&cs35l41->fw_mutex); regmap_multi_reg_write(reg, cs35l41_hda_mute, ARRAY_SIZE(cs35l41_hda_mute)); - ret = cs35l41_global_enable(reg, cs35l41->hw_cfg.bst_type, 0); + ret = cs35l41_global_enable(reg, cs35l41->hw_cfg.bst_type, 0, NULL); mutex_unlock(&cs35l41->fw_mutex); break; case HDA_GEN_PCM_ACT_CLOSE: @@ -672,7 +672,7 @@ static int cs35l41_runtime_suspend(struct device *dev) if (cs35l41->playback_started) { regmap_multi_reg_write(cs35l41->regmap, cs35l41_hda_mute, ARRAY_SIZE(cs35l41_hda_mute)); - cs35l41_global_enable(cs35l41->regmap, cs35l41->hw_cfg.bst_type, 0); + cs35l41_global_enable(cs35l41->regmap, cs35l41->hw_cfg.bst_type, 0, NULL); regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL2, CS35L41_AMP_EN_MASK, 0 << CS35L41_AMP_EN_SHIFT); if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST) diff --git a/sound/soc/codecs/cs35l41-lib.c b/sound/soc/codecs/cs35l41-lib.c index 04be71435491..8538e2871c5f 100644 --- a/sound/soc/codecs/cs35l41-lib.c +++ b/sound/soc/codecs/cs35l41-lib.c @@ -1114,12 +1114,31 @@ static const struct reg_sequence cs35l41_reset_to_safe[] = { { 0x00000040, 0x00000033 }, }; +static const struct reg_sequence cs35l41_actv_seq[] = { + /* SYNC_BST_CTL_RX_EN = 1; SYNC_BST_CTL_TX_EN = 1 */ + {CS35L41_MDSYNC_EN, 0x00003000}, + /* BST_CTL_SEL = MDSYNC */ + {CS35L41_BSTCVRT_VCTRL2, 0x00000002}, +}; + +static const struct reg_sequence cs35l41_pass_seq[] = { + /* SYNC_BST_CTL_RX_EN = 0; SYNC_BST_CTL_TX_EN = 1 */ + {CS35L41_MDSYNC_EN, 0x00001000}, + /* BST_EN = 0 */ + {CS35L41_PWR_CTRL2, 0x00003300}, + /* BST_CTL_SEL = MDSYNC */ + {CS35L41_BSTCVRT_VCTRL2, 0x00000002}, +}; + int cs35l41_init_boost(struct device *dev, struct regmap *regmap, struct cs35l41_hw_cfg *hw_cfg) { int ret; switch (hw_cfg->bst_type) { + case CS35L41_SHD_BOOST_ACTV: + regmap_multi_reg_write(regmap, cs35l41_actv_seq, ARRAY_SIZE(cs35l41_actv_seq)); + fallthrough; case CS35L41_INT_BOOST: ret = cs35l41_boost_config(dev, regmap, hw_cfg->bst_ind, hw_cfg->bst_cap, hw_cfg->bst_ipk); @@ -1138,6 +1157,10 @@ int cs35l41_init_boost(struct device *dev, struct regmap *regmap, ret = regmap_update_bits(regmap, CS35L41_PWR_CTRL2, CS35L41_BST_EN_MASK, CS35L41_BST_DIS_FET_OFF << CS35L41_BST_EN_SHIFT); break; + case CS35L41_SHD_BOOST_PASS: + ret = regmap_multi_reg_write(regmap, cs35l41_pass_seq, + ARRAY_SIZE(cs35l41_pass_seq)); + break; default: dev_err(dev, "Boost type %d not supported\n", hw_cfg->bst_type); ret = -EINVAL; @@ -1165,11 +1188,59 @@ bool cs35l41_safe_reset(struct regmap *regmap, enum cs35l41_boost_type b_type) } EXPORT_SYMBOL_GPL(cs35l41_safe_reset); -int cs35l41_global_enable(struct regmap *regmap, enum cs35l41_boost_type b_type, int enable) +int cs35l41_global_enable(struct regmap *regmap, enum cs35l41_boost_type b_type, int enable, + struct completion *pll_lock) { int ret; + unsigned int gpio1_func, pad_control, pwr_ctrl1, pwr_ctrl3; + struct reg_sequence cs35l41_mdsync_down_seq[] = { + {CS35L41_PWR_CTRL3, 0}, + {CS35L41_GPIO_PAD_CONTROL, 0}, + {CS35L41_PWR_CTRL1, 0, 3000}, + }; + struct reg_sequence cs35l41_mdsync_up_seq[] = { + {CS35L41_PWR_CTRL3, 0}, + {CS35L41_PWR_CTRL1, 0x00000000, 3000}, + {CS35L41_PWR_CTRL1, 0x00000001, 3000}, + }; switch (b_type) { + case CS35L41_SHD_BOOST_ACTV: + case CS35L41_SHD_BOOST_PASS: + regmap_read(regmap, CS35L41_PWR_CTRL3, &pwr_ctrl3); + regmap_read(regmap, CS35L41_GPIO_PAD_CONTROL, &pad_control); + + pwr_ctrl3 &= ~CS35L41_SYNC_EN_MASK; + pwr_ctrl1 = enable << CS35L41_GLOBAL_EN_SHIFT; + + gpio1_func = enable ? CS35L41_GPIO1_MDSYNC : CS35L41_GPIO1_HIZ; + gpio1_func <<= CS35L41_GPIO1_CTRL_SHIFT; + + pad_control &= ~CS35L41_GPIO1_CTRL_MASK; + pad_control |= gpio1_func & CS35L41_GPIO1_CTRL_MASK; + + cs35l41_mdsync_down_seq[0].def = pwr_ctrl3; + cs35l41_mdsync_down_seq[1].def = pad_control; + cs35l41_mdsync_down_seq[2].def = pwr_ctrl1; + ret = regmap_multi_reg_write(regmap, cs35l41_mdsync_down_seq, + ARRAY_SIZE(cs35l41_mdsync_down_seq)); + if (!enable) + break; + + if (!pll_lock) + return -EINVAL; + + ret = wait_for_completion_timeout(pll_lock, msecs_to_jiffies(1000)); + if (ret == 0) { + ret = -ETIMEDOUT; + } else { + regmap_read(regmap, CS35L41_PWR_CTRL3, &pwr_ctrl3); + pwr_ctrl3 |= CS35L41_SYNC_EN_MASK; + cs35l41_mdsync_up_seq[0].def = pwr_ctrl3; + ret = regmap_multi_reg_write(regmap, cs35l41_mdsync_up_seq, + ARRAY_SIZE(cs35l41_mdsync_up_seq)); + } + break; case CS35L41_INT_BOOST: ret = regmap_update_bits(regmap, CS35L41_PWR_CTRL1, CS35L41_GLOBAL_EN_MASK, enable << CS35L41_GLOBAL_EN_SHIFT); diff --git a/sound/soc/codecs/cs35l41.c b/sound/soc/codecs/cs35l41.c index c006364e5335..1624510d09c0 100644 --- a/sound/soc/codecs/cs35l41.c +++ b/sound/soc/codecs/cs35l41.c @@ -360,6 +360,7 @@ static void cs35l41_boost_enable(struct cs35l41_private *cs35l41, unsigned int e { switch (cs35l41->hw_cfg.bst_type) { case CS35L41_INT_BOOST: + case CS35L41_SHD_BOOST_ACTV: enable = enable ? CS35L41_BST_EN_DEFAULT : CS35L41_BST_DIS_FET_OFF; regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL2, CS35L41_BST_EN_MASK, enable << CS35L41_BST_EN_SHIFT); @@ -455,6 +456,12 @@ static irqreturn_t cs35l41_irq(int irq, void *data) ret = IRQ_HANDLED; } + if (status[2] & CS35L41_PLL_LOCK) { + regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS3, CS35L41_PLL_LOCK); + complete(&cs35l41->pll_lock); + ret = IRQ_HANDLED; + } + done: pm_runtime_mark_last_busy(cs35l41->dev); pm_runtime_put_autosuspend(cs35l41->dev); @@ -492,10 +499,12 @@ static int cs35l41_main_amp_event(struct snd_soc_dapm_widget *w, cs35l41_pup_patch, ARRAY_SIZE(cs35l41_pup_patch)); - cs35l41_global_enable(cs35l41->regmap, cs35l41->hw_cfg.bst_type, 1); + cs35l41_global_enable(cs35l41->regmap, cs35l41->hw_cfg.bst_type, 1, + &cs35l41->pll_lock); break; case SND_SOC_DAPM_POST_PMD: - cs35l41_global_enable(cs35l41->regmap, cs35l41->hw_cfg.bst_type, 0); + cs35l41_global_enable(cs35l41->regmap, cs35l41->hw_cfg.bst_type, 0, + &cs35l41->pll_lock); ret = regmap_read_poll_timeout(cs35l41->regmap, CS35L41_IRQ1_STATUS1, val, val & CS35L41_PDN_DONE_MASK, @@ -802,6 +811,10 @@ static const struct snd_pcm_hw_constraint_list cs35l41_constraints = { static int cs35l41_pcm_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { + struct cs35l41_private *cs35l41 = snd_soc_component_get_drvdata(dai->component); + + reinit_completion(&cs35l41->pll_lock); + if (substream->runtime) return snd_pcm_hw_constraint_list(substream->runtime, 0, SNDRV_PCM_HW_PARAM_RATE, @@ -1252,6 +1265,10 @@ int cs35l41_probe(struct cs35l41_private *cs35l41, const struct cs35l41_hw_cfg * /* Set interrupt masks for critical errors */ regmap_write(cs35l41->regmap, CS35L41_IRQ1_MASK1, CS35L41_INT1_MASK_DEFAULT); + if (cs35l41->hw_cfg.bst_type == CS35L41_SHD_BOOST_PASS || + cs35l41->hw_cfg.bst_type == CS35L41_SHD_BOOST_ACTV) + regmap_update_bits(cs35l41->regmap, CS35L41_IRQ1_MASK3, CS35L41_INT3_PLL_LOCK_MASK, + 0 << CS35L41_INT3_PLL_LOCK_SHIFT); ret = devm_request_threaded_irq(cs35l41->dev, cs35l41->irq, NULL, cs35l41_irq, IRQF_ONESHOT | IRQF_SHARED | irq_pol, @@ -1275,6 +1292,8 @@ int cs35l41_probe(struct cs35l41_private *cs35l41, const struct cs35l41_hw_cfg * if (ret < 0) goto err; + init_completion(&cs35l41->pll_lock); + pm_runtime_set_autosuspend_delay(cs35l41->dev, 3000); pm_runtime_use_autosuspend(cs35l41->dev); pm_runtime_mark_last_busy(cs35l41->dev); @@ -1317,6 +1336,10 @@ void cs35l41_remove(struct cs35l41_private *cs35l41) pm_runtime_disable(cs35l41->dev); regmap_write(cs35l41->regmap, CS35L41_IRQ1_MASK1, 0xFFFFFFFF); + if (cs35l41->hw_cfg.bst_type == CS35L41_SHD_BOOST_PASS || + cs35l41->hw_cfg.bst_type == CS35L41_SHD_BOOST_ACTV) + regmap_update_bits(cs35l41->regmap, CS35L41_IRQ1_MASK3, CS35L41_INT3_PLL_LOCK_MASK, + 1 << CS35L41_INT3_PLL_LOCK_SHIFT); kfree(cs35l41->dsp.system_name); wm_adsp2_remove(&cs35l41->dsp); cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type); diff --git a/sound/soc/codecs/cs35l41.h b/sound/soc/codecs/cs35l41.h index c85cbc1dd333..34d967d4372b 100644 --- a/sound/soc/codecs/cs35l41.h +++ b/sound/soc/codecs/cs35l41.h @@ -33,6 +33,7 @@ struct cs35l41_private { int irq; /* GPIO for /RST */ struct gpio_desc *reset_gpio; + struct completion pll_lock; }; int cs35l41_probe(struct cs35l41_private *cs35l41, const struct cs35l41_hw_cfg *hw_cfg); From 340307d7effd99303fe933cde3b7288f8f3c6677 Mon Sep 17 00:00:00 2001 From: Lucas Tanure Date: Thu, 23 Feb 2023 08:43:24 +0000 Subject: [PATCH 085/778] ASoC: dt-bindings: cirrus,cs35l41: Document CS35l41 shared boost Describe the properties used for shared boost configuration. Based on David Rhodes shared boost patches. Signed-off-by: Lucas Tanure Acked-by: Krzysztof Kozlowski Reviewed-by: David Rhodes Link: https://lore.kernel.org/r/20230223084324.9076-5-lucas.tanure@collabora.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/cirrus,cs35l41.yaml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/sound/cirrus,cs35l41.yaml b/Documentation/devicetree/bindings/sound/cirrus,cs35l41.yaml index 18fb471aa891..14dea1feefc5 100644 --- a/Documentation/devicetree/bindings/sound/cirrus,cs35l41.yaml +++ b/Documentation/devicetree/bindings/sound/cirrus,cs35l41.yaml @@ -85,11 +85,19 @@ properties: boost-cap-microfarad. External Boost must have GPIO1 as GPIO output. GPIO1 will be set high to enable boost voltage. + Shared boost allows two amplifiers to share a single boost circuit by + communicating on the MDSYNC bus. The active amplifier controls the boost + circuit using combined data from both amplifiers. GPIO1 should be + configured for Sync when shared boost is used. Shared boost is not + compatible with External boost. Active amplifier requires + boost-peak-milliamp, boost-ind-nanohenry and boost-cap-microfarad. 0 = Internal Boost 1 = External Boost + 2 = Shared Boost Active + 3 = Shared Boost Passive $ref: /schemas/types.yaml#/definitions/uint32 minimum: 0 - maximum: 1 + maximum: 3 cirrus,gpio1-polarity-invert: description: From 56a3840486ae22c42176828e25d4073712837bfd Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Fri, 17 Feb 2023 18:52:22 +0000 Subject: [PATCH 086/778] ASoC: dt-bindings: renesas,rz-ssi: Update interrupts and interrupt-names properties From R01UH0914EJ0120 Rev.1.20 HW manual, for full duplex channels (SSI0/1/3) dma_rt interrupt has now being marked as reserved and similarly for half duplex channel (SSI2) dma_rx and dma_tx interrupts have now being marked as reserved (this applies to RZ/G2L and alike SoC's). This patch updates the binding doc to match the same. While at it also updated the example node. Signed-off-by: Lad Prabhakar Reviewed-by: Biju Das Acked-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230217185225.43310-2-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Mark Brown --- .../bindings/sound/renesas,rz-ssi.yaml | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml b/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml index 196881d94396..3b5ae45eee4a 100644 --- a/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml +++ b/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml @@ -25,14 +25,18 @@ properties: maxItems: 1 interrupts: - maxItems: 4 + minItems: 2 + maxItems: 3 interrupt-names: - items: - - const: int_req - - const: dma_rx - - const: dma_tx - - const: dma_rt + oneOf: + - items: + - const: int_req + - const: dma_rx + - const: dma_tx + - items: + - const: int_req + - const: dma_rt clocks: maxItems: 4 @@ -106,9 +110,8 @@ examples: reg = <0x10049c00 0x400>; interrupts = , , - , - ; - interrupt-names = "int_req", "dma_rx", "dma_tx", "dma_rt"; + ; + interrupt-names = "int_req", "dma_rx", "dma_tx"; clocks = <&cpg CPG_MOD R9A07G044_SSI0_PCLK2>, <&cpg CPG_MOD R9A07G044_SSI0_PCLK_SFR>, <&audio_clk1>, From 38c042b59af0248a8b13f01b1a09d890997c9f6e Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Fri, 17 Feb 2023 18:52:23 +0000 Subject: [PATCH 087/778] ASoC: sh: rz-ssi: Update interrupt handling for half duplex channels For half duplex channels we dont have separate interrupts for Tx and Rx instead we have single interrupt Rt (where the signal for Rx and Tx is muxed). To handle such a case install a handler in case we have a dma_rt interrupt specified in the DT for the PIO mode. Note, for backward compatibility we check if the Rx and Tx interrupts are present first instead of checking Rt interrupt. Signed-off-by: Lad Prabhakar Reviewed-by: Biju Das Link: https://lore.kernel.org/r/20230217185225.43310-3-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Mark Brown --- sound/soc/sh/rz-ssi.c | 61 ++++++++++++++++++++++++++++++------------- 1 file changed, 43 insertions(+), 18 deletions(-) diff --git a/sound/soc/sh/rz-ssi.c b/sound/soc/sh/rz-ssi.c index 5d6bae33ae34..d502aa55c5a8 100644 --- a/sound/soc/sh/rz-ssi.c +++ b/sound/soc/sh/rz-ssi.c @@ -109,6 +109,7 @@ struct rz_ssi_priv { int irq_int; int irq_tx; int irq_rx; + int irq_rt; spinlock_t lock; @@ -565,6 +566,17 @@ static irqreturn_t rz_ssi_interrupt(int irq, void *data) rz_ssi_reg_mask_setl(ssi, SSIFSR, SSIFSR_RDF, 0); } + if (irq == ssi->irq_rt) { + struct snd_pcm_substream *substream = strm->substream; + + if (rz_ssi_stream_is_play(ssi, substream)) { + strm->transfer(ssi, &ssi->playback); + } else { + strm->transfer(ssi, &ssi->capture); + rz_ssi_reg_mask_setl(ssi, SSIFSR, SSIFSR_RDF, 0); + } + } + return IRQ_HANDLED; } @@ -993,26 +1005,39 @@ static int rz_ssi_probe(struct platform_device *pdev) if (!rz_ssi_is_dma_enabled(ssi)) { /* Tx and Rx interrupts (pio only) */ ssi->irq_tx = platform_get_irq_byname(pdev, "dma_tx"); - if (ssi->irq_tx < 0) - return ssi->irq_tx; - - ret = devm_request_irq(&pdev->dev, ssi->irq_tx, - &rz_ssi_interrupt, 0, - dev_name(&pdev->dev), ssi); - if (ret < 0) - return dev_err_probe(&pdev->dev, ret, - "irq request error (dma_tx)\n"); - ssi->irq_rx = platform_get_irq_byname(pdev, "dma_rx"); - if (ssi->irq_rx < 0) - return ssi->irq_rx; + if (ssi->irq_tx == -ENXIO && ssi->irq_rx == -ENXIO) { + ssi->irq_rt = platform_get_irq_byname(pdev, "dma_rt"); + if (ssi->irq_rt < 0) + return ssi->irq_rt; - ret = devm_request_irq(&pdev->dev, ssi->irq_rx, - &rz_ssi_interrupt, 0, - dev_name(&pdev->dev), ssi); - if (ret < 0) - return dev_err_probe(&pdev->dev, ret, - "irq request error (dma_rx)\n"); + ret = devm_request_irq(&pdev->dev, ssi->irq_rt, + &rz_ssi_interrupt, 0, + dev_name(&pdev->dev), ssi); + if (ret < 0) + return dev_err_probe(&pdev->dev, ret, + "irq request error (dma_tx)\n"); + } else { + if (ssi->irq_tx < 0) + return ssi->irq_tx; + + if (ssi->irq_rx < 0) + return ssi->irq_rx; + + ret = devm_request_irq(&pdev->dev, ssi->irq_tx, + &rz_ssi_interrupt, 0, + dev_name(&pdev->dev), ssi); + if (ret < 0) + return dev_err_probe(&pdev->dev, ret, + "irq request error (dma_tx)\n"); + + ret = devm_request_irq(&pdev->dev, ssi->irq_rx, + &rz_ssi_interrupt, 0, + dev_name(&pdev->dev), ssi); + if (ret < 0) + return dev_err_probe(&pdev->dev, ret, + "irq request error (dma_rx)\n"); + } } ssi->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL); From 95a29d5f626a37dbefd0883f294ec4e22a8a7911 Mon Sep 17 00:00:00 2001 From: Kamel Bouhara Date: Wed, 22 Feb 2023 09:32:59 +0100 Subject: [PATCH 088/778] ASoC: tas571x: add tas5733 compatible This adds the tas5733 to the TAS571X binding. Signed-off-by: Kamel Bouhara Acked-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230222083300.218523-2-kamel.bouhara@bootlin.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/tas571x.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/sound/tas571x.txt b/Documentation/devicetree/bindings/sound/tas571x.txt index 7c8fd37c2f9e..1addc75989d5 100644 --- a/Documentation/devicetree/bindings/sound/tas571x.txt +++ b/Documentation/devicetree/bindings/sound/tas571x.txt @@ -12,6 +12,7 @@ Required properties: - "ti,tas5717", - "ti,tas5719", - "ti,tas5721" + - "ti,tas5733" - reg: The I2C address of the device - #sound-dai-cells: must be equal to 0 From f5db4d00f73871988beba0277ea29cff73d38445 Mon Sep 17 00:00:00 2001 From: Kamel Bouhara Date: Wed, 22 Feb 2023 09:33:00 +0100 Subject: [PATCH 089/778] ASoC: tas571x: add support for TAS5733 This adds support for TAS5733. Signed-off-by: Kamel Bouhara Link: https://lore.kernel.org/r/20230222083300.218523-3-kamel.bouhara@bootlin.com Signed-off-by: Mark Brown --- sound/soc/codecs/tas571x.c | 59 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/sound/soc/codecs/tas571x.c b/sound/soc/codecs/tas571x.c index 84ec1b527646..f39c3273b2fd 100644 --- a/sound/soc/codecs/tas571x.c +++ b/sound/soc/codecs/tas571x.c @@ -718,6 +718,63 @@ static const struct regmap_config tas5721_regmap_config = { .volatile_table = &tas571x_volatile_regs, }; +static const char *const tas5733_supply_names[] = { + "AVDD", + "DVDD", + "PVDD", +}; + +static const struct reg_default tas5733_reg_defaults[] = { + {TAS571X_CLK_CTRL_REG, 0x6c}, + {TAS571X_DEV_ID_REG, 0x00}, + {TAS571X_ERR_STATUS_REG, 0x00}, + {TAS571X_SYS_CTRL_1_REG, 0xa0}, + {TAS571X_SDI_REG, 0x05}, + {TAS571X_SYS_CTRL_2_REG, 0x40}, + {TAS571X_SOFT_MUTE_REG, 0x07}, + {TAS571X_MVOL_REG, 0x03ff}, + {TAS571X_CH1_VOL_REG, 0x00c0}, + {TAS571X_CH2_VOL_REG, 0x00c0}, + {TAS571X_CH3_VOL_REG, 0x00c0}, + {TAS571X_VOL_CFG_REG, 0xf0}, + {TAS571X_MODULATION_LIMIT_REG, 0x07}, + {TAS571X_IC_DELAY_CH1_REG, 0xb8}, + {TAS571X_IC_DELAY_CH2_REG, 0x60}, + {TAS571X_IC_DELAY_CH3_REG, 0xa0}, + {TAS571X_IC_DELAY_CH4_REG, 0x48}, + {TAS571X_PWM_CH_SDN_GROUP_REG, 0x30}, + {TAS571X_START_STOP_PERIOD_REG, 0x68}, + {TAS571X_OSC_TRIM_REG, 0x82}, + {TAS571X_BKND_ERR_REG, 0x02}, + {TAS571X_INPUT_MUX_REG, 0x00897772}, + {TAS571X_PWM_MUX_REG, 0x01021345}, + {TAS5717_CH1_RIGHT_CH_MIX_REG, 0x00}, + {TAS5717_CH1_LEFT_CH_MIX_REG, 0x800000}, + {TAS5717_CH2_LEFT_CH_MIX_REG, 0x00}, + {TAS5717_CH2_RIGHT_CH_MIX_REG, 0x800000}, +}; + +static const struct regmap_config tas5733_regmap_config = { + .reg_bits = 8, + .val_bits = 32, + .max_register = 0xff, + .reg_read = tas571x_reg_read, + .reg_write = tas571x_reg_write, + .reg_defaults = tas5733_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(tas5733_reg_defaults), + .cache_type = REGCACHE_RBTREE, + .wr_table = &tas571x_write_regs, + .volatile_table = &tas571x_volatile_regs, +}; + +static const struct tas571x_chip tas5733_chip = { + .supply_names = tas5733_supply_names, + .num_supply_names = ARRAY_SIZE(tas5733_supply_names), + .controls = tas5717_controls, + .num_controls = ARRAY_SIZE(tas5717_controls), + .regmap_config = &tas5733_regmap_config, + .vol_reg_size = 2, +}; static const struct tas571x_chip tas5721_chip = { .supply_names = tas5721_supply_names, @@ -897,6 +954,7 @@ static const struct of_device_id tas571x_of_match[] __maybe_unused = { { .compatible = "ti,tas5717", .data = &tas5717_chip, }, { .compatible = "ti,tas5719", .data = &tas5717_chip, }, { .compatible = "ti,tas5721", .data = &tas5721_chip, }, + { .compatible = "ti,tas5733", .data = &tas5733_chip, }, { } }; MODULE_DEVICE_TABLE(of, tas571x_of_match); @@ -907,6 +965,7 @@ static const struct i2c_device_id tas571x_i2c_id[] = { { "tas5717", (kernel_ulong_t) &tas5717_chip }, { "tas5719", (kernel_ulong_t) &tas5717_chip }, { "tas5721", (kernel_ulong_t) &tas5721_chip }, + { "tas5733", (kernel_ulong_t) &tas5733_chip }, { } }; MODULE_DEVICE_TABLE(i2c, tas571x_i2c_id); From f8c760e8fc414bb02373c5ede62fdac53ca8ccb2 Mon Sep 17 00:00:00 2001 From: Herve Codina Date: Fri, 17 Feb 2023 15:56:36 +0100 Subject: [PATCH 090/778] dt-bindings: soc: fsl: cpm_qe: Add TSA controller Add support for the time slot assigner (TSA) available in some PowerQUICC SoC such as MPC885 or MPC866. Signed-off-by: Herve Codina Reviewed-by: Christophe Leroy Link: https://lore.kernel.org/r/20230217145645.1768659-2-herve.codina@bootlin.com Signed-off-by: Mark Brown --- .../bindings/soc/fsl/cpm_qe/fsl,cpm1-tsa.yaml | 215 ++++++++++++++++++ include/dt-bindings/soc/cpm1-fsl,tsa.h | 13 ++ 2 files changed, 228 insertions(+) create mode 100644 Documentation/devicetree/bindings/soc/fsl/cpm_qe/fsl,cpm1-tsa.yaml create mode 100644 include/dt-bindings/soc/cpm1-fsl,tsa.h diff --git a/Documentation/devicetree/bindings/soc/fsl/cpm_qe/fsl,cpm1-tsa.yaml b/Documentation/devicetree/bindings/soc/fsl/cpm_qe/fsl,cpm1-tsa.yaml new file mode 100644 index 000000000000..332e902bcc21 --- /dev/null +++ b/Documentation/devicetree/bindings/soc/fsl/cpm_qe/fsl,cpm1-tsa.yaml @@ -0,0 +1,215 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/soc/fsl/cpm_qe/fsl,cpm1-tsa.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: PowerQUICC CPM Time-slot assigner (TSA) controller + +maintainers: + - Herve Codina + +description: + The TSA is the time-slot assigner that can be found on some PowerQUICC SoC. + Its purpose is to route some TDM time-slots to other internal serial + controllers. + +properties: + compatible: + items: + - enum: + - fsl,mpc885-tsa + - fsl,mpc866-tsa + - const: fsl,cpm1-tsa + + reg: + items: + - description: SI (Serial Interface) register base + - description: SI RAM base + + reg-names: + items: + - const: si_regs + - const: si_ram + + '#address-cells': + const: 1 + + '#size-cells': + const: 0 + + '#fsl,serial-cells': + $ref: /schemas/types.yaml#/definitions/uint32 + const: 1 + description: + TSA consumers that use a phandle to TSA need to pass the serial identifier + with this phandle (defined in dt-bindings/soc/fsl,tsa.h). + For instance "fsl,tsa-serial = <&tsa FSL_CPM_TSA_SCC4>;". + +patternProperties: + '^tdm@[0-1]$': + description: + The TDM managed by this controller + type: object + + additionalProperties: false + + properties: + reg: + minimum: 0 + maximum: 1 + description: + The TDM number for this TDM, 0 for TDMa and 1 for TDMb + + fsl,common-rxtx-pins: + $ref: /schemas/types.yaml#/definitions/flag + description: + The hardware can use four dedicated pins for Tx clock, Tx sync, Rx + clock and Rx sync or use only two pins, Tx/Rx clock and Tx/Rx sync. + Without the 'fsl,common-rxtx-pins' property, the four pins are used. + With the 'fsl,common-rxtx-pins' property, two pins are used. + + clocks: + minItems: 2 + items: + - description: External clock connected to L1RSYNC pin + - description: External clock connected to L1RCLK pin + - description: External clock connected to L1TSYNC pin + - description: External clock connected to L1TCLK pin + + clock-names: + minItems: 2 + items: + - const: l1rsync + - const: l1rclk + - const: l1tsync + - const: l1tclk + + fsl,rx-frame-sync-delay-bits: + enum: [0, 1, 2, 3] + default: 0 + description: | + Receive frame sync delay in number of bits. + Indicates the delay between the Rx sync and the first bit of the Rx + frame. 0 for no bit delay. 1, 2 or 3 for 1, 2 or 3 bits delay. + + fsl,tx-frame-sync-delay-bits: + enum: [0, 1, 2, 3] + default: 0 + description: | + Transmit frame sync delay in number of bits. + Indicates the delay between the Tx sync and the first bit of the Tx + frame. 0 for no bit delay. 1, 2 or 3 for 1, 2 or 3 bits delay. + + fsl,clock-falling-edge: + $ref: /schemas/types.yaml#/definitions/flag + description: + Data is sent on falling edge of the clock (and received on the rising + edge). If 'clock-falling-edge' is not present, data is sent on the + rising edge (and received on the falling edge). + + fsl,fsync-rising-edge: + $ref: /schemas/types.yaml#/definitions/flag + description: + Frame sync pulses are sampled with the rising edge of the channel + clock. If 'fsync-rising-edge' is not present, pulses are sampled with + the falling edge. + + fsl,double-speed-clock: + $ref: /schemas/types.yaml#/definitions/flag + description: + The channel clock is twice the data rate. + + patternProperties: + '^fsl,[rt]x-ts-routes$': + $ref: /schemas/types.yaml#/definitions/uint32-matrix + description: | + A list of tuple that indicates the Tx or Rx time-slots routes. + items: + items: + - description: + The number of time-slots + minimum: 1 + maximum: 64 + - description: | + The source (Tx) or destination (Rx) serial interface + (dt-bindings/soc/cpm1-fsl,tsa.h defines these values) + - 0: No destination + - 1: SCC2 + - 2: SCC3 + - 3: SCC4 + - 4: SMC1 + - 5: SMC2 + enum: [0, 1, 2, 3, 4, 5] + minItems: 1 + maxItems: 64 + + allOf: + # If fsl,common-rxtx-pins is present, only 2 clocks are needed. + # Else, the 4 clocks must be present. + - if: + required: + - fsl,common-rxtx-pins + then: + properties: + clocks: + maxItems: 2 + clock-names: + maxItems: 2 + else: + properties: + clocks: + minItems: 4 + clock-names: + minItems: 4 + + required: + - reg + - clocks + - clock-names + +required: + - compatible + - reg + - reg-names + - '#address-cells' + - '#size-cells' + - '#fsl,serial-cells' + +additionalProperties: false + +examples: + - | + #include + + tsa@ae0 { + compatible = "fsl,mpc885-tsa", "fsl,cpm1-tsa"; + reg = <0xae0 0x10>, + <0xc00 0x200>; + reg-names = "si_regs", "si_ram"; + + #address-cells = <1>; + #size-cells = <0>; + #fsl,serial-cells = <1>; + + tdm@0 { + /* TDMa */ + reg = <0>; + + clocks = <&clk_l1rsynca>, <&clk_l1rclka>; + clock-names = "l1rsync", "l1rclk"; + + fsl,common-rxtx-pins; + fsl,fsync-rising-edge; + + fsl,tx-ts-routes = <2 0>, /* TS 0..1 */ + <24 FSL_CPM_TSA_SCC4>, /* TS 2..25 */ + <1 0>, /* TS 26 */ + <5 FSL_CPM_TSA_SCC3>; /* TS 27..31 */ + + fsl,rx-ts-routes = <2 0>, /* TS 0..1 */ + <24 FSL_CPM_TSA_SCC4>, /* 2..25 */ + <1 0>, /* TS 26 */ + <5 FSL_CPM_TSA_SCC3>; /* TS 27..31 */ + }; + }; diff --git a/include/dt-bindings/soc/cpm1-fsl,tsa.h b/include/dt-bindings/soc/cpm1-fsl,tsa.h new file mode 100644 index 000000000000..2cc44e867dbe --- /dev/null +++ b/include/dt-bindings/soc/cpm1-fsl,tsa.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause */ + +#ifndef __DT_BINDINGS_SOC_FSL_TSA_H +#define __DT_BINDINGS_SOC_FSL_TSA_H + +#define FSL_CPM_TSA_NU 0 /* Pseuso Cell Id for not used item */ +#define FSL_CPM_TSA_SCC2 1 +#define FSL_CPM_TSA_SCC3 2 +#define FSL_CPM_TSA_SCC4 3 +#define FSL_CPM_TSA_SMC1 4 +#define FSL_CPM_TSA_SMC2 5 + +#endif From 1d4ba0b81c1cf2bfc0c55658f53809846ae9de52 Mon Sep 17 00:00:00 2001 From: Herve Codina Date: Fri, 17 Feb 2023 15:56:37 +0100 Subject: [PATCH 091/778] soc: fsl: cpm1: Add support for TSA The TSA (Time Slot Assigner) purpose is to route some TDM time-slots to other internal serial controllers. It is available in some PowerQUICC SoC such as the MPC885 or MPC866. It is also available on some Quicc Engine SoCs. This current version support CPM1 SoCs only and some enhancement are needed to support Quicc Engine SoCs. Signed-off-by: Herve Codina Acked-by: Li Yang Reviewed-by: Christophe Leroy Link: https://lore.kernel.org/r/20230217145645.1768659-3-herve.codina@bootlin.com Signed-off-by: Mark Brown --- drivers/soc/fsl/qe/Kconfig | 11 + drivers/soc/fsl/qe/Makefile | 1 + drivers/soc/fsl/qe/tsa.c | 846 ++++++++++++++++++++++++++++++++++++ drivers/soc/fsl/qe/tsa.h | 42 ++ 4 files changed, 900 insertions(+) create mode 100644 drivers/soc/fsl/qe/tsa.c create mode 100644 drivers/soc/fsl/qe/tsa.h diff --git a/drivers/soc/fsl/qe/Kconfig b/drivers/soc/fsl/qe/Kconfig index 357c5800b112..b0088495c323 100644 --- a/drivers/soc/fsl/qe/Kconfig +++ b/drivers/soc/fsl/qe/Kconfig @@ -33,6 +33,17 @@ config UCC bool default y if UCC_FAST || UCC_SLOW +config CPM_TSA + tristate "CPM TSA support" + depends on OF && HAS_IOMEM + depends on CPM1 || COMPILE_TEST + help + Freescale CPM Time Slot Assigner (TSA) + controller. + + This option enables support for this + controller + config QE_TDM bool default y if FSL_UCC_HDLC diff --git a/drivers/soc/fsl/qe/Makefile b/drivers/soc/fsl/qe/Makefile index 55a555304f3a..45c961acc81b 100644 --- a/drivers/soc/fsl/qe/Makefile +++ b/drivers/soc/fsl/qe/Makefile @@ -4,6 +4,7 @@ # obj-$(CONFIG_QUICC_ENGINE)+= qe.o qe_common.o qe_ic.o qe_io.o obj-$(CONFIG_CPM) += qe_common.o +obj-$(CONFIG_CPM_TSA) += tsa.o obj-$(CONFIG_UCC) += ucc.o obj-$(CONFIG_UCC_SLOW) += ucc_slow.o obj-$(CONFIG_UCC_FAST) += ucc_fast.o diff --git a/drivers/soc/fsl/qe/tsa.c b/drivers/soc/fsl/qe/tsa.c new file mode 100644 index 000000000000..3646153117b3 --- /dev/null +++ b/drivers/soc/fsl/qe/tsa.c @@ -0,0 +1,846 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * TSA driver + * + * Copyright 2022 CS GROUP France + * + * Author: Herve Codina + */ + +#include "tsa.h" +#include +#include +#include +#include +#include +#include +#include +#include + + +/* TSA SI RAM routing tables entry */ +#define TSA_SIRAM_ENTRY_LAST (1 << 16) +#define TSA_SIRAM_ENTRY_BYTE (1 << 17) +#define TSA_SIRAM_ENTRY_CNT(x) (((x) & 0x0f) << 18) +#define TSA_SIRAM_ENTRY_CSEL_MASK (0x7 << 22) +#define TSA_SIRAM_ENTRY_CSEL_NU (0x0 << 22) +#define TSA_SIRAM_ENTRY_CSEL_SCC2 (0x2 << 22) +#define TSA_SIRAM_ENTRY_CSEL_SCC3 (0x3 << 22) +#define TSA_SIRAM_ENTRY_CSEL_SCC4 (0x4 << 22) +#define TSA_SIRAM_ENTRY_CSEL_SMC1 (0x5 << 22) +#define TSA_SIRAM_ENTRY_CSEL_SMC2 (0x6 << 22) + +/* SI mode register (32 bits) */ +#define TSA_SIMODE 0x00 +#define TSA_SIMODE_SMC2 0x80000000 +#define TSA_SIMODE_SMC1 0x00008000 +#define TSA_SIMODE_TDMA(x) ((x) << 0) +#define TSA_SIMODE_TDMB(x) ((x) << 16) +#define TSA_SIMODE_TDM_MASK 0x0fff +#define TSA_SIMODE_TDM_SDM_MASK 0x0c00 +#define TSA_SIMODE_TDM_SDM_NORM 0x0000 +#define TSA_SIMODE_TDM_SDM_ECHO 0x0400 +#define TSA_SIMODE_TDM_SDM_INTL_LOOP 0x0800 +#define TSA_SIMODE_TDM_SDM_LOOP_CTRL 0x0c00 +#define TSA_SIMODE_TDM_RFSD(x) ((x) << 8) +#define TSA_SIMODE_TDM_DSC 0x0080 +#define TSA_SIMODE_TDM_CRT 0x0040 +#define TSA_SIMODE_TDM_STZ 0x0020 +#define TSA_SIMODE_TDM_CE 0x0010 +#define TSA_SIMODE_TDM_FE 0x0008 +#define TSA_SIMODE_TDM_GM 0x0004 +#define TSA_SIMODE_TDM_TFSD(x) ((x) << 0) + +/* SI global mode register (8 bits) */ +#define TSA_SIGMR 0x04 +#define TSA_SIGMR_ENB (1<<3) +#define TSA_SIGMR_ENA (1<<2) +#define TSA_SIGMR_RDM_MASK 0x03 +#define TSA_SIGMR_RDM_STATIC_TDMA 0x00 +#define TSA_SIGMR_RDM_DYN_TDMA 0x01 +#define TSA_SIGMR_RDM_STATIC_TDMAB 0x02 +#define TSA_SIGMR_RDM_DYN_TDMAB 0x03 + +/* SI status register (8 bits) */ +#define TSA_SISTR 0x06 + +/* SI command register (8 bits) */ +#define TSA_SICMR 0x07 + +/* SI clock route register (32 bits) */ +#define TSA_SICR 0x0C +#define TSA_SICR_SCC2(x) ((x) << 8) +#define TSA_SICR_SCC3(x) ((x) << 16) +#define TSA_SICR_SCC4(x) ((x) << 24) +#define TSA_SICR_SCC_MASK 0x0ff +#define TSA_SICR_SCC_GRX (1 << 7) +#define TSA_SICR_SCC_SCX_TSA (1 << 6) +#define TSA_SICR_SCC_RXCS_MASK (0x7 << 3) +#define TSA_SICR_SCC_RXCS_BRG1 (0x0 << 3) +#define TSA_SICR_SCC_RXCS_BRG2 (0x1 << 3) +#define TSA_SICR_SCC_RXCS_BRG3 (0x2 << 3) +#define TSA_SICR_SCC_RXCS_BRG4 (0x3 << 3) +#define TSA_SICR_SCC_RXCS_CLK15 (0x4 << 3) +#define TSA_SICR_SCC_RXCS_CLK26 (0x5 << 3) +#define TSA_SICR_SCC_RXCS_CLK37 (0x6 << 3) +#define TSA_SICR_SCC_RXCS_CLK48 (0x7 << 3) +#define TSA_SICR_SCC_TXCS_MASK (0x7 << 0) +#define TSA_SICR_SCC_TXCS_BRG1 (0x0 << 0) +#define TSA_SICR_SCC_TXCS_BRG2 (0x1 << 0) +#define TSA_SICR_SCC_TXCS_BRG3 (0x2 << 0) +#define TSA_SICR_SCC_TXCS_BRG4 (0x3 << 0) +#define TSA_SICR_SCC_TXCS_CLK15 (0x4 << 0) +#define TSA_SICR_SCC_TXCS_CLK26 (0x5 << 0) +#define TSA_SICR_SCC_TXCS_CLK37 (0x6 << 0) +#define TSA_SICR_SCC_TXCS_CLK48 (0x7 << 0) + +/* Serial interface RAM pointer register (32 bits) */ +#define TSA_SIRP 0x10 + +struct tsa_entries_area { + void *__iomem entries_start; + void *__iomem entries_next; + void *__iomem last_entry; +}; + +struct tsa_tdm { + bool is_enable; + struct clk *l1rclk_clk; + struct clk *l1rsync_clk; + struct clk *l1tclk_clk; + struct clk *l1tsync_clk; + u32 simode_tdm; +}; + +#define TSA_TDMA 0 +#define TSA_TDMB 1 + +struct tsa { + struct device *dev; + void *__iomem si_regs; + void *__iomem si_ram; + resource_size_t si_ram_sz; + spinlock_t lock; + int tdms; /* TSA_TDMx ORed */ + struct tsa_tdm tdm[2]; /* TDMa and TDMb */ + struct tsa_serial { + unsigned int id; + struct tsa_serial_info info; + } serials[6]; +}; + +static inline struct tsa *tsa_serial_get_tsa(struct tsa_serial *tsa_serial) +{ + /* The serials table is indexed by the serial id */ + return container_of(tsa_serial, struct tsa, serials[tsa_serial->id]); +} + +static inline void tsa_write32(void *__iomem addr, u32 val) +{ + iowrite32be(val, addr); +} + +static inline void tsa_write8(void *__iomem addr, u32 val) +{ + iowrite8(val, addr); +} + +static inline u32 tsa_read32(void *__iomem addr) +{ + return ioread32be(addr); +} + +static inline void tsa_clrbits32(void *__iomem addr, u32 clr) +{ + tsa_write32(addr, tsa_read32(addr) & ~clr); +} + +static inline void tsa_clrsetbits32(void *__iomem addr, u32 clr, u32 set) +{ + tsa_write32(addr, (tsa_read32(addr) & ~clr) | set); +} + +int tsa_serial_connect(struct tsa_serial *tsa_serial) +{ + struct tsa *tsa = tsa_serial_get_tsa(tsa_serial); + unsigned long flags; + u32 clear; + u32 set; + + switch (tsa_serial->id) { + case FSL_CPM_TSA_SCC2: + clear = TSA_SICR_SCC2(TSA_SICR_SCC_MASK); + set = TSA_SICR_SCC2(TSA_SICR_SCC_SCX_TSA); + break; + case FSL_CPM_TSA_SCC3: + clear = TSA_SICR_SCC3(TSA_SICR_SCC_MASK); + set = TSA_SICR_SCC3(TSA_SICR_SCC_SCX_TSA); + break; + case FSL_CPM_TSA_SCC4: + clear = TSA_SICR_SCC4(TSA_SICR_SCC_MASK); + set = TSA_SICR_SCC4(TSA_SICR_SCC_SCX_TSA); + break; + default: + dev_err(tsa->dev, "Unsupported serial id %u\n", tsa_serial->id); + return -EINVAL; + } + + spin_lock_irqsave(&tsa->lock, flags); + tsa_clrsetbits32(tsa->si_regs + TSA_SICR, clear, set); + spin_unlock_irqrestore(&tsa->lock, flags); + + return 0; +} +EXPORT_SYMBOL(tsa_serial_connect); + +int tsa_serial_disconnect(struct tsa_serial *tsa_serial) +{ + struct tsa *tsa = tsa_serial_get_tsa(tsa_serial); + unsigned long flags; + u32 clear; + + switch (tsa_serial->id) { + case FSL_CPM_TSA_SCC2: + clear = TSA_SICR_SCC2(TSA_SICR_SCC_MASK); + break; + case FSL_CPM_TSA_SCC3: + clear = TSA_SICR_SCC3(TSA_SICR_SCC_MASK); + break; + case FSL_CPM_TSA_SCC4: + clear = TSA_SICR_SCC4(TSA_SICR_SCC_MASK); + break; + default: + dev_err(tsa->dev, "Unsupported serial id %u\n", tsa_serial->id); + return -EINVAL; + } + + spin_lock_irqsave(&tsa->lock, flags); + tsa_clrsetbits32(tsa->si_regs + TSA_SICR, clear, 0); + spin_unlock_irqrestore(&tsa->lock, flags); + + return 0; +} +EXPORT_SYMBOL(tsa_serial_disconnect); + +int tsa_serial_get_info(struct tsa_serial *tsa_serial, struct tsa_serial_info *info) +{ + memcpy(info, &tsa_serial->info, sizeof(*info)); + return 0; +} +EXPORT_SYMBOL(tsa_serial_get_info); + +static void tsa_init_entries_area(struct tsa *tsa, struct tsa_entries_area *area, + u32 tdms, u32 tdm_id, bool is_rx) +{ + resource_size_t quarter; + resource_size_t half; + + quarter = tsa->si_ram_sz/4; + half = tsa->si_ram_sz/2; + + if (tdms == BIT(TSA_TDMA)) { + /* Only TDMA */ + if (is_rx) { + /* First half of si_ram */ + area->entries_start = tsa->si_ram; + area->entries_next = area->entries_start + half; + area->last_entry = NULL; + } else { + /* Second half of si_ram */ + area->entries_start = tsa->si_ram + half; + area->entries_next = area->entries_start + half; + area->last_entry = NULL; + } + } else { + /* Only TDMB or both TDMs */ + if (tdm_id == TSA_TDMA) { + if (is_rx) { + /* First half of first half of si_ram */ + area->entries_start = tsa->si_ram; + area->entries_next = area->entries_start + quarter; + area->last_entry = NULL; + } else { + /* First half of second half of si_ram */ + area->entries_start = tsa->si_ram + (2 * quarter); + area->entries_next = area->entries_start + quarter; + area->last_entry = NULL; + } + } else { + if (is_rx) { + /* Second half of first half of si_ram */ + area->entries_start = tsa->si_ram + quarter; + area->entries_next = area->entries_start + quarter; + area->last_entry = NULL; + } else { + /* Second half of second half of si_ram */ + area->entries_start = tsa->si_ram + (3 * quarter); + area->entries_next = area->entries_start + quarter; + area->last_entry = NULL; + } + } + } +} + +static const char *tsa_serial_id2name(struct tsa *tsa, u32 serial_id) +{ + switch (serial_id) { + case FSL_CPM_TSA_NU: return "Not used"; + case FSL_CPM_TSA_SCC2: return "SCC2"; + case FSL_CPM_TSA_SCC3: return "SCC3"; + case FSL_CPM_TSA_SCC4: return "SCC4"; + case FSL_CPM_TSA_SMC1: return "SMC1"; + case FSL_CPM_TSA_SMC2: return "SMC2"; + default: + break; + } + return NULL; +} + +static u32 tsa_serial_id2csel(struct tsa *tsa, u32 serial_id) +{ + switch (serial_id) { + case FSL_CPM_TSA_SCC2: return TSA_SIRAM_ENTRY_CSEL_SCC2; + case FSL_CPM_TSA_SCC3: return TSA_SIRAM_ENTRY_CSEL_SCC3; + case FSL_CPM_TSA_SCC4: return TSA_SIRAM_ENTRY_CSEL_SCC4; + case FSL_CPM_TSA_SMC1: return TSA_SIRAM_ENTRY_CSEL_SMC1; + case FSL_CPM_TSA_SMC2: return TSA_SIRAM_ENTRY_CSEL_SMC2; + default: + break; + } + return TSA_SIRAM_ENTRY_CSEL_NU; +} + +static int tsa_add_entry(struct tsa *tsa, struct tsa_entries_area *area, + u32 count, u32 serial_id) +{ + void *__iomem addr; + u32 left; + u32 val; + u32 cnt; + u32 nb; + + addr = area->last_entry ? area->last_entry + 4 : area->entries_start; + + nb = DIV_ROUND_UP(count, 8); + if ((addr + (nb * 4)) > area->entries_next) { + dev_err(tsa->dev, "si ram area full\n"); + return -ENOSPC; + } + + if (area->last_entry) { + /* Clear last flag */ + tsa_clrbits32(area->last_entry, TSA_SIRAM_ENTRY_LAST); + } + + left = count; + while (left) { + val = TSA_SIRAM_ENTRY_BYTE | tsa_serial_id2csel(tsa, serial_id); + + if (left > 16) { + cnt = 16; + } else { + cnt = left; + val |= TSA_SIRAM_ENTRY_LAST; + area->last_entry = addr; + } + val |= TSA_SIRAM_ENTRY_CNT(cnt - 1); + + tsa_write32(addr, val); + addr += 4; + left -= cnt; + } + + return 0; +} + +static int tsa_of_parse_tdm_route(struct tsa *tsa, struct device_node *tdm_np, + u32 tdms, u32 tdm_id, bool is_rx) +{ + struct tsa_entries_area area; + const char *route_name; + u32 serial_id; + int len, i; + u32 count; + const char *serial_name; + struct tsa_serial_info *serial_info; + struct tsa_tdm *tdm; + int ret; + u32 ts; + + route_name = is_rx ? "fsl,rx-ts-routes" : "fsl,tx-ts-routes"; + + len = of_property_count_u32_elems(tdm_np, route_name); + if (len < 0) { + dev_err(tsa->dev, "%pOF: failed to read %s\n", tdm_np, route_name); + return len; + } + if (len % 2 != 0) { + dev_err(tsa->dev, "%pOF: wrong %s format\n", tdm_np, route_name); + return -EINVAL; + } + + tsa_init_entries_area(tsa, &area, tdms, tdm_id, is_rx); + ts = 0; + for (i = 0; i < len; i += 2) { + of_property_read_u32_index(tdm_np, route_name, i, &count); + of_property_read_u32_index(tdm_np, route_name, i + 1, &serial_id); + + if (serial_id >= ARRAY_SIZE(tsa->serials)) { + dev_err(tsa->dev, "%pOF: invalid serial id (%u)\n", + tdm_np, serial_id); + return -EINVAL; + } + + serial_name = tsa_serial_id2name(tsa, serial_id); + if (!serial_name) { + dev_err(tsa->dev, "%pOF: unsupported serial id (%u)\n", + tdm_np, serial_id); + return -EINVAL; + } + + dev_dbg(tsa->dev, "tdm_id=%u, %s ts %u..%u -> %s\n", + tdm_id, route_name, ts, ts+count-1, serial_name); + ts += count; + + ret = tsa_add_entry(tsa, &area, count, serial_id); + if (ret) + return ret; + + serial_info = &tsa->serials[serial_id].info; + tdm = &tsa->tdm[tdm_id]; + if (is_rx) { + serial_info->rx_fs_rate = clk_get_rate(tdm->l1rsync_clk); + serial_info->rx_bit_rate = clk_get_rate(tdm->l1rclk_clk); + serial_info->nb_rx_ts += count; + } else { + serial_info->tx_fs_rate = tdm->l1tsync_clk ? + clk_get_rate(tdm->l1tsync_clk) : + clk_get_rate(tdm->l1rsync_clk); + serial_info->tx_bit_rate = tdm->l1tclk_clk ? + clk_get_rate(tdm->l1tclk_clk) : + clk_get_rate(tdm->l1rclk_clk); + serial_info->nb_tx_ts += count; + } + } + return 0; +} + +static inline int tsa_of_parse_tdm_rx_route(struct tsa *tsa, + struct device_node *tdm_np, + u32 tdms, u32 tdm_id) +{ + return tsa_of_parse_tdm_route(tsa, tdm_np, tdms, tdm_id, true); +} + +static inline int tsa_of_parse_tdm_tx_route(struct tsa *tsa, + struct device_node *tdm_np, + u32 tdms, u32 tdm_id) +{ + return tsa_of_parse_tdm_route(tsa, tdm_np, tdms, tdm_id, false); +} + +static int tsa_of_parse_tdms(struct tsa *tsa, struct device_node *np) +{ + struct device_node *tdm_np; + struct tsa_tdm *tdm; + struct clk *clk; + u32 tdm_id, val; + int ret; + int i; + + tsa->tdms = 0; + tsa->tdm[0].is_enable = false; + tsa->tdm[1].is_enable = false; + + for_each_available_child_of_node(np, tdm_np) { + ret = of_property_read_u32(tdm_np, "reg", &tdm_id); + if (ret) { + dev_err(tsa->dev, "%pOF: failed to read reg\n", tdm_np); + of_node_put(tdm_np); + return ret; + } + switch (tdm_id) { + case 0: + tsa->tdms |= BIT(TSA_TDMA); + break; + case 1: + tsa->tdms |= BIT(TSA_TDMB); + break; + default: + dev_err(tsa->dev, "%pOF: Invalid tdm_id (%u)\n", tdm_np, + tdm_id); + of_node_put(tdm_np); + return -EINVAL; + } + } + + for_each_available_child_of_node(np, tdm_np) { + ret = of_property_read_u32(tdm_np, "reg", &tdm_id); + if (ret) { + dev_err(tsa->dev, "%pOF: failed to read reg\n", tdm_np); + of_node_put(tdm_np); + return ret; + } + + tdm = &tsa->tdm[tdm_id]; + tdm->simode_tdm = TSA_SIMODE_TDM_SDM_NORM; + + val = 0; + ret = of_property_read_u32(tdm_np, "fsl,rx-frame-sync-delay-bits", + &val); + if (ret && ret != -EINVAL) { + dev_err(tsa->dev, + "%pOF: failed to read fsl,rx-frame-sync-delay-bits\n", + tdm_np); + of_node_put(tdm_np); + return ret; + } + if (val > 3) { + dev_err(tsa->dev, + "%pOF: Invalid fsl,rx-frame-sync-delay-bits (%u)\n", + tdm_np, val); + of_node_put(tdm_np); + return -EINVAL; + } + tdm->simode_tdm |= TSA_SIMODE_TDM_RFSD(val); + + val = 0; + ret = of_property_read_u32(tdm_np, "fsl,tx-frame-sync-delay-bits", + &val); + if (ret && ret != -EINVAL) { + dev_err(tsa->dev, + "%pOF: failed to read fsl,tx-frame-sync-delay-bits\n", + tdm_np); + of_node_put(tdm_np); + return ret; + } + if (val > 3) { + dev_err(tsa->dev, + "%pOF: Invalid fsl,tx-frame-sync-delay-bits (%u)\n", + tdm_np, val); + of_node_put(tdm_np); + return -EINVAL; + } + tdm->simode_tdm |= TSA_SIMODE_TDM_TFSD(val); + + if (of_property_read_bool(tdm_np, "fsl,common-rxtx-pins")) + tdm->simode_tdm |= TSA_SIMODE_TDM_CRT; + + if (of_property_read_bool(tdm_np, "fsl,clock-falling-edge")) + tdm->simode_tdm |= TSA_SIMODE_TDM_CE; + + if (of_property_read_bool(tdm_np, "fsl,fsync-rising-edge")) + tdm->simode_tdm |= TSA_SIMODE_TDM_FE; + + if (of_property_read_bool(tdm_np, "fsl,double-speed-clock")) + tdm->simode_tdm |= TSA_SIMODE_TDM_DSC; + + clk = of_clk_get_by_name(tdm_np, "l1rsync"); + if (IS_ERR(clk)) { + ret = PTR_ERR(clk); + of_node_put(tdm_np); + goto err; + } + ret = clk_prepare_enable(clk); + if (ret) { + clk_put(clk); + of_node_put(tdm_np); + goto err; + } + tdm->l1rsync_clk = clk; + + clk = of_clk_get_by_name(tdm_np, "l1rclk"); + if (IS_ERR(clk)) { + ret = PTR_ERR(clk); + of_node_put(tdm_np); + goto err; + } + ret = clk_prepare_enable(clk); + if (ret) { + clk_put(clk); + of_node_put(tdm_np); + goto err; + } + tdm->l1rclk_clk = clk; + + if (!(tdm->simode_tdm & TSA_SIMODE_TDM_CRT)) { + clk = of_clk_get_by_name(tdm_np, "l1tsync"); + if (IS_ERR(clk)) { + ret = PTR_ERR(clk); + of_node_put(tdm_np); + goto err; + } + ret = clk_prepare_enable(clk); + if (ret) { + clk_put(clk); + of_node_put(tdm_np); + goto err; + } + tdm->l1tsync_clk = clk; + + clk = of_clk_get_by_name(tdm_np, "l1tclk"); + if (IS_ERR(clk)) { + ret = PTR_ERR(clk); + of_node_put(tdm_np); + goto err; + } + ret = clk_prepare_enable(clk); + if (ret) { + clk_put(clk); + of_node_put(tdm_np); + goto err; + } + tdm->l1tclk_clk = clk; + } + + ret = tsa_of_parse_tdm_rx_route(tsa, tdm_np, tsa->tdms, tdm_id); + if (ret) { + of_node_put(tdm_np); + goto err; + } + + ret = tsa_of_parse_tdm_tx_route(tsa, tdm_np, tsa->tdms, tdm_id); + if (ret) { + of_node_put(tdm_np); + goto err; + } + + tdm->is_enable = true; + } + return 0; + +err: + for (i = 0; i < 2; i++) { + if (tsa->tdm[i].l1rsync_clk) { + clk_disable_unprepare(tsa->tdm[i].l1rsync_clk); + clk_put(tsa->tdm[i].l1rsync_clk); + } + if (tsa->tdm[i].l1rclk_clk) { + clk_disable_unprepare(tsa->tdm[i].l1rclk_clk); + clk_put(tsa->tdm[i].l1rclk_clk); + } + if (tsa->tdm[i].l1tsync_clk) { + clk_disable_unprepare(tsa->tdm[i].l1rsync_clk); + clk_put(tsa->tdm[i].l1rsync_clk); + } + if (tsa->tdm[i].l1tclk_clk) { + clk_disable_unprepare(tsa->tdm[i].l1rclk_clk); + clk_put(tsa->tdm[i].l1rclk_clk); + } + } + return ret; +} + +static void tsa_init_si_ram(struct tsa *tsa) +{ + resource_size_t i; + + /* Fill all entries as the last one */ + for (i = 0; i < tsa->si_ram_sz; i += 4) + tsa_write32(tsa->si_ram + i, TSA_SIRAM_ENTRY_LAST); +} + +static int tsa_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct resource *res; + struct tsa *tsa; + unsigned int i; + u32 val; + int ret; + + tsa = devm_kzalloc(&pdev->dev, sizeof(*tsa), GFP_KERNEL); + if (!tsa) + return -ENOMEM; + + tsa->dev = &pdev->dev; + + for (i = 0; i < ARRAY_SIZE(tsa->serials); i++) + tsa->serials[i].id = i; + + spin_lock_init(&tsa->lock); + + tsa->si_regs = devm_platform_ioremap_resource_byname(pdev, "si_regs"); + if (IS_ERR(tsa->si_regs)) + return PTR_ERR(tsa->si_regs); + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "si_ram"); + if (!res) { + dev_err(tsa->dev, "si_ram resource missing\n"); + return -EINVAL; + } + tsa->si_ram_sz = resource_size(res); + tsa->si_ram = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(tsa->si_ram)) + return PTR_ERR(tsa->si_ram); + + tsa_init_si_ram(tsa); + + ret = tsa_of_parse_tdms(tsa, np); + if (ret) + return ret; + + /* Set SIMODE */ + val = 0; + if (tsa->tdm[0].is_enable) + val |= TSA_SIMODE_TDMA(tsa->tdm[0].simode_tdm); + if (tsa->tdm[1].is_enable) + val |= TSA_SIMODE_TDMB(tsa->tdm[1].simode_tdm); + + tsa_clrsetbits32(tsa->si_regs + TSA_SIMODE, + TSA_SIMODE_TDMA(TSA_SIMODE_TDM_MASK) | + TSA_SIMODE_TDMB(TSA_SIMODE_TDM_MASK), + val); + + /* Set SIGMR */ + val = (tsa->tdms == BIT(TSA_TDMA)) ? + TSA_SIGMR_RDM_STATIC_TDMA : TSA_SIGMR_RDM_STATIC_TDMAB; + if (tsa->tdms & BIT(TSA_TDMA)) + val |= TSA_SIGMR_ENA; + if (tsa->tdms & BIT(TSA_TDMB)) + val |= TSA_SIGMR_ENB; + tsa_write8(tsa->si_regs + TSA_SIGMR, val); + + platform_set_drvdata(pdev, tsa); + + return 0; +} + +static int tsa_remove(struct platform_device *pdev) +{ + struct tsa *tsa = platform_get_drvdata(pdev); + int i; + + for (i = 0; i < 2; i++) { + if (tsa->tdm[i].l1rsync_clk) { + clk_disable_unprepare(tsa->tdm[i].l1rsync_clk); + clk_put(tsa->tdm[i].l1rsync_clk); + } + if (tsa->tdm[i].l1rclk_clk) { + clk_disable_unprepare(tsa->tdm[i].l1rclk_clk); + clk_put(tsa->tdm[i].l1rclk_clk); + } + if (tsa->tdm[i].l1tsync_clk) { + clk_disable_unprepare(tsa->tdm[i].l1rsync_clk); + clk_put(tsa->tdm[i].l1rsync_clk); + } + if (tsa->tdm[i].l1tclk_clk) { + clk_disable_unprepare(tsa->tdm[i].l1rclk_clk); + clk_put(tsa->tdm[i].l1rclk_clk); + } + } + return 0; +} + +static const struct of_device_id tsa_id_table[] = { + { .compatible = "fsl,cpm1-tsa" }, + {} /* sentinel */ +}; +MODULE_DEVICE_TABLE(of, tsa_id_table); + +static struct platform_driver tsa_driver = { + .driver = { + .name = "fsl-tsa", + .of_match_table = of_match_ptr(tsa_id_table), + }, + .probe = tsa_probe, + .remove = tsa_remove, +}; +module_platform_driver(tsa_driver); + +struct tsa_serial *tsa_serial_get_byphandle(struct device_node *np, + const char *phandle_name) +{ + struct of_phandle_args out_args; + struct platform_device *pdev; + struct tsa_serial *tsa_serial; + struct tsa *tsa; + int ret; + + ret = of_parse_phandle_with_fixed_args(np, phandle_name, 1, 0, &out_args); + if (ret < 0) + return ERR_PTR(ret); + + if (!of_match_node(tsa_driver.driver.of_match_table, out_args.np)) { + of_node_put(out_args.np); + return ERR_PTR(-EINVAL); + } + + pdev = of_find_device_by_node(out_args.np); + of_node_put(out_args.np); + if (!pdev) + return ERR_PTR(-ENODEV); + + tsa = platform_get_drvdata(pdev); + if (!tsa) { + platform_device_put(pdev); + return ERR_PTR(-EPROBE_DEFER); + } + + if (out_args.args_count != 1) { + platform_device_put(pdev); + return ERR_PTR(-EINVAL); + } + + if (out_args.args[0] >= ARRAY_SIZE(tsa->serials)) { + platform_device_put(pdev); + return ERR_PTR(-EINVAL); + } + + tsa_serial = &tsa->serials[out_args.args[0]]; + + /* + * Be sure that the serial id matches the phandle arg. + * The tsa_serials table is indexed by serial ids. The serial id is set + * during the probe() call and needs to be coherent. + */ + if (WARN_ON(tsa_serial->id != out_args.args[0])) { + platform_device_put(pdev); + return ERR_PTR(-EINVAL); + } + + return tsa_serial; +} +EXPORT_SYMBOL(tsa_serial_get_byphandle); + +void tsa_serial_put(struct tsa_serial *tsa_serial) +{ + struct tsa *tsa = tsa_serial_get_tsa(tsa_serial); + + put_device(tsa->dev); +} +EXPORT_SYMBOL(tsa_serial_put); + +static void devm_tsa_serial_release(struct device *dev, void *res) +{ + struct tsa_serial **tsa_serial = res; + + tsa_serial_put(*tsa_serial); +} + +struct tsa_serial *devm_tsa_serial_get_byphandle(struct device *dev, + struct device_node *np, + const char *phandle_name) +{ + struct tsa_serial *tsa_serial; + struct tsa_serial **dr; + + dr = devres_alloc(devm_tsa_serial_release, sizeof(*dr), GFP_KERNEL); + if (!dr) + return ERR_PTR(-ENOMEM); + + tsa_serial = tsa_serial_get_byphandle(np, phandle_name); + if (!IS_ERR(tsa_serial)) { + *dr = tsa_serial; + devres_add(dev, dr); + } else { + devres_free(dr); + } + + return tsa_serial; +} +EXPORT_SYMBOL(devm_tsa_serial_get_byphandle); + +MODULE_AUTHOR("Herve Codina "); +MODULE_DESCRIPTION("CPM TSA driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/soc/fsl/qe/tsa.h b/drivers/soc/fsl/qe/tsa.h new file mode 100644 index 000000000000..d9df89b6da3e --- /dev/null +++ b/drivers/soc/fsl/qe/tsa.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * TSA management + * + * Copyright 2022 CS GROUP France + * + * Author: Herve Codina + */ +#ifndef __SOC_FSL_TSA_H__ +#define __SOC_FSL_TSA_H__ + +#include + +struct device_node; +struct device; +struct tsa_serial; + +struct tsa_serial *tsa_serial_get_byphandle(struct device_node *np, + const char *phandle_name); +void tsa_serial_put(struct tsa_serial *tsa_serial); +struct tsa_serial *devm_tsa_serial_get_byphandle(struct device *dev, + struct device_node *np, + const char *phandle_name); + +/* Connect and disconnect the TSA serial */ +int tsa_serial_connect(struct tsa_serial *tsa_serial); +int tsa_serial_disconnect(struct tsa_serial *tsa_serial); + +/* Cell information */ +struct tsa_serial_info { + unsigned long rx_fs_rate; + unsigned long rx_bit_rate; + u8 nb_rx_ts; + unsigned long tx_fs_rate; + unsigned long tx_bit_rate; + u8 nb_tx_ts; +}; + +/* Get information */ +int tsa_serial_get_info(struct tsa_serial *tsa_serial, struct tsa_serial_info *info); + +#endif /* __SOC_FSL_TSA_H__ */ From a2b117414f16b036d2eb5081d5776872e3731c51 Mon Sep 17 00:00:00 2001 From: Herve Codina Date: Fri, 17 Feb 2023 15:56:38 +0100 Subject: [PATCH 092/778] MAINTAINERS: add the Freescale TSA controller entry After contributing the driver, add myself as the maintainer for the Freescale TSA controller. Signed-off-by: Herve Codina Reviewed-by: Christophe Leroy Link: https://lore.kernel.org/r/20230217145645.1768659-4-herve.codina@bootlin.com Signed-off-by: Mark Brown --- MAINTAINERS | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 8d5bc223f305..fea9ee7ade8e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8247,6 +8247,15 @@ S: Maintained F: drivers/soc/fsl/qe/ F: include/soc/fsl/qe/ +FREESCALE QUICC ENGINE TSA DRIVER +M: Herve Codina +L: linuxppc-dev@lists.ozlabs.org +S: Maintained +F: Documentation/devicetree/bindings/soc/fsl/cpm_qe/fsl,cpm1-tsa.yaml +F: drivers/soc/fsl/qe/tsa.c +F: drivers/soc/fsl/qe/tsa.h +F: include/dt-bindings/soc/cpm1-fsl,tsa.h + FREESCALE QUICC ENGINE UCC ETHERNET DRIVER M: Li Yang L: netdev@vger.kernel.org From b38736ac01e34491f339e12f9883dc4a8cc3d358 Mon Sep 17 00:00:00 2001 From: Herve Codina Date: Fri, 17 Feb 2023 15:56:39 +0100 Subject: [PATCH 093/778] powerpc/8xx: Use a larger CPM1 command check mask The CPM1 command mask is defined for use with the standard CPM1 command register as described in the user's manual: 0 |1 3|4 7|8 11|12 14| 15| RST| - |OPCODE|CH_NUM| - |FLG| In the QMC extension the CPM1 command register is redefined (QMC supplement user's manuel) with the following mapping: 0 |1 3|4 7|8 13|14| 15| RST|QMC OPCODE| 1110|CHANNEL_NUMBER| -|FLG| Extend the check command mask in order to support both the standard CH_NUM field and the QMC extension CHANNEL_NUMBER field. Signed-off-by: Herve Codina Acked-by: Christophe Leroy Acked-by: Michael Ellerman Link: https://lore.kernel.org/r/20230217145645.1768659-5-herve.codina@bootlin.com Signed-off-by: Mark Brown --- arch/powerpc/platforms/8xx/cpm1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/platforms/8xx/cpm1.c b/arch/powerpc/platforms/8xx/cpm1.c index bb38c8d8f8de..c57fcda7a4bb 100644 --- a/arch/powerpc/platforms/8xx/cpm1.c +++ b/arch/powerpc/platforms/8xx/cpm1.c @@ -94,7 +94,7 @@ int cpm_command(u32 command, u8 opcode) int i, ret; unsigned long flags; - if (command & 0xffffff0f) + if (command & 0xffffff03) return -EINVAL; spin_lock_irqsave(&cmd_lock, flags); From a9b121327c939624e3e2c244283883501846fa97 Mon Sep 17 00:00:00 2001 From: Herve Codina Date: Fri, 17 Feb 2023 15:56:40 +0100 Subject: [PATCH 094/778] dt-bindings: soc: fsl: cpm_qe: Add QMC controller Add support for the QMC (QUICC Multichannel Controller) available in some PowerQUICC SoC such as MPC885 or MPC866. Signed-off-by: Herve Codina Reviewed-by: Krzysztof Kozlowski Reviewed-by: Christophe Leroy Link: https://lore.kernel.org/r/20230217145645.1768659-6-herve.codina@bootlin.com Signed-off-by: Mark Brown --- .../soc/fsl/cpm_qe/fsl,cpm1-scc-qmc.yaml | 172 ++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100644 Documentation/devicetree/bindings/soc/fsl/cpm_qe/fsl,cpm1-scc-qmc.yaml diff --git a/Documentation/devicetree/bindings/soc/fsl/cpm_qe/fsl,cpm1-scc-qmc.yaml b/Documentation/devicetree/bindings/soc/fsl/cpm_qe/fsl,cpm1-scc-qmc.yaml new file mode 100644 index 000000000000..4ebbc7d52981 --- /dev/null +++ b/Documentation/devicetree/bindings/soc/fsl/cpm_qe/fsl,cpm1-scc-qmc.yaml @@ -0,0 +1,172 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/soc/fsl/cpm_qe/fsl,cpm1-scc-qmc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: PowerQUICC CPM QUICC Multichannel Controller (QMC) + +maintainers: + - Herve Codina + +description: + The QMC (QUICC Multichannel Controller) emulates up to 64 channels within one + serial controller using the same TDM physical interface routed from TSA. + +properties: + compatible: + items: + - enum: + - fsl,mpc885-scc-qmc + - fsl,mpc866-scc-qmc + - const: fsl,cpm1-scc-qmc + + reg: + items: + - description: SCC (Serial communication controller) register base + - description: SCC parameter ram base + - description: Dual port ram base + + reg-names: + items: + - const: scc_regs + - const: scc_pram + - const: dpram + + interrupts: + maxItems: 1 + description: SCC interrupt line in the CPM interrupt controller + + fsl,tsa-serial: + $ref: /schemas/types.yaml#/definitions/phandle-array + items: + - items: + - description: phandle to TSA node + - enum: [1, 2, 3] + description: | + TSA serial interface (dt-bindings/soc/cpm1-fsl,tsa.h defines these + values) + - 1: SCC2 + - 2: SCC3 + - 3: SCC4 + description: + Should be a phandle/number pair. The phandle to TSA node and the TSA + serial interface to use. + + '#address-cells': + const: 1 + + '#size-cells': + const: 0 + + '#fsl,chan-cells': + $ref: /schemas/types.yaml#/definitions/uint32 + const: 1 + description: + QMC consumers that use a phandle to QMC need to pass the channel number + with this phandle. + For instance "fsl,qmc-chan = <&qmc 16>;". + +patternProperties: + '^channel@([0-9]|[1-5][0-9]|6[0-3])$': + description: + A channel managed by this controller + type: object + + properties: + reg: + minimum: 0 + maximum: 63 + description: + The channel number + + fsl,operational-mode: + $ref: /schemas/types.yaml#/definitions/string + enum: [transparent, hdlc] + default: transparent + description: | + The channel operational mode + - hdlc: The channel handles HDLC frames + - transparent: The channel handles raw data without any processing + + fsl,reverse-data: + $ref: /schemas/types.yaml#/definitions/flag + description: + The bit order as seen on the channels is reversed, + transmitting/receiving the MSB of each octet first. + This flag is used only in 'transparent' mode. + + fsl,tx-ts-mask: + $ref: /schemas/types.yaml#/definitions/uint64 + description: + Channel assigned Tx time-slots within the Tx time-slots routed by the + TSA to this cell. + + fsl,rx-ts-mask: + $ref: /schemas/types.yaml#/definitions/uint64 + description: + Channel assigned Rx time-slots within the Rx time-slots routed by the + TSA to this cell. + + required: + - reg + - fsl,tx-ts-mask + - fsl,rx-ts-mask + +required: + - compatible + - reg + - reg-names + - interrupts + - fsl,tsa-serial + - '#address-cells' + - '#size-cells' + - '#fsl,chan-cells' + +additionalProperties: false + +examples: + - | + #include + + qmc@a60 { + compatible = "fsl,mpc885-scc-qmc", "fsl,cpm1-scc-qmc"; + reg = <0xa60 0x20>, + <0x3f00 0xc0>, + <0x2000 0x1000>; + reg-names = "scc_regs", "scc_pram", "dpram"; + interrupts = <27>; + interrupt-parent = <&CPM_PIC>; + + #address-cells = <1>; + #size-cells = <0>; + #fsl,chan-cells = <1>; + + fsl,tsa-serial = <&tsa FSL_CPM_TSA_SCC4>; + + channel@16 { + /* Ch16 : First 4 even TS from all routed from TSA */ + reg = <16>; + fsl,mode = "transparent"; + fsl,reverse-data; + fsl,tx-ts-mask = <0x00000000 0x000000aa>; + fsl,rx-ts-mask = <0x00000000 0x000000aa>; + }; + + channel@17 { + /* Ch17 : First 4 odd TS from all routed from TSA */ + reg = <17>; + fsl,mode = "transparent"; + fsl,reverse-data; + fsl,tx-ts-mask = <0x00000000 0x00000055>; + fsl,rx-ts-mask = <0x00000000 0x00000055>; + }; + + channel@19 { + /* Ch19 : 8 TS (TS 8..15) from all routed from TSA */ + reg = <19>; + fsl,mode = "hdlc"; + fsl,tx-ts-mask = <0x00000000 0x0000ff00>; + fsl,rx-ts-mask = <0x00000000 0x0000ff00>; + }; + }; From 3178d58e0b9772d690456c0bdf8c9f5e191d45f1 Mon Sep 17 00:00:00 2001 From: Herve Codina Date: Fri, 17 Feb 2023 15:56:41 +0100 Subject: [PATCH 095/778] soc: fsl: cpm1: Add support for QMC The QMC (QUICC Multichannel Controller) emulates up to 64 channels within one serial controller using the same TDM physical interface routed from the TSA. It is available in some PowerQUICC SoC such as the MPC885 or MPC866. It is also available on some Quicc Engine SoCs. This current version support CPM1 SoCs only and some enhancement are needed to support Quicc Engine SoCs. Signed-off-by: Herve Codina Acked-by: Li Yang Reviewed-by: Christophe Leroy Link: https://lore.kernel.org/r/20230217145645.1768659-7-herve.codina@bootlin.com Signed-off-by: Mark Brown --- drivers/soc/fsl/qe/Kconfig | 12 + drivers/soc/fsl/qe/Makefile | 1 + drivers/soc/fsl/qe/qmc.c | 1533 +++++++++++++++++++++++++++++++++++ include/soc/fsl/qe/qmc.h | 71 ++ 4 files changed, 1617 insertions(+) create mode 100644 drivers/soc/fsl/qe/qmc.c create mode 100644 include/soc/fsl/qe/qmc.h diff --git a/drivers/soc/fsl/qe/Kconfig b/drivers/soc/fsl/qe/Kconfig index b0088495c323..f90cfdf0c763 100644 --- a/drivers/soc/fsl/qe/Kconfig +++ b/drivers/soc/fsl/qe/Kconfig @@ -44,6 +44,18 @@ config CPM_TSA This option enables support for this controller +config CPM_QMC + tristate "CPM QMC support" + depends on OF && HAS_IOMEM + depends on CPM1 || (SOC_FSL && COMPILE_TEST) + depends on CPM_TSA + help + Freescale CPM QUICC Multichannel Controller + (QMC) + + This option enables support for this + controller + config QE_TDM bool default y if FSL_UCC_HDLC diff --git a/drivers/soc/fsl/qe/Makefile b/drivers/soc/fsl/qe/Makefile index 45c961acc81b..ec8506e13113 100644 --- a/drivers/soc/fsl/qe/Makefile +++ b/drivers/soc/fsl/qe/Makefile @@ -5,6 +5,7 @@ obj-$(CONFIG_QUICC_ENGINE)+= qe.o qe_common.o qe_ic.o qe_io.o obj-$(CONFIG_CPM) += qe_common.o obj-$(CONFIG_CPM_TSA) += tsa.o +obj-$(CONFIG_CPM_QMC) += qmc.o obj-$(CONFIG_UCC) += ucc.o obj-$(CONFIG_UCC_SLOW) += ucc_slow.o obj-$(CONFIG_UCC_FAST) += ucc_fast.o diff --git a/drivers/soc/fsl/qe/qmc.c b/drivers/soc/fsl/qe/qmc.c new file mode 100644 index 000000000000..cfa7207353e0 --- /dev/null +++ b/drivers/soc/fsl/qe/qmc.c @@ -0,0 +1,1533 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * QMC driver + * + * Copyright 2022 CS GROUP France + * + * Author: Herve Codina + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "tsa.h" + +/* SCC general mode register high (32 bits) */ +#define SCC_GSMRL 0x00 +#define SCC_GSMRL_ENR (1 << 5) +#define SCC_GSMRL_ENT (1 << 4) +#define SCC_GSMRL_MODE_QMC (0x0A << 0) + +/* SCC general mode register low (32 bits) */ +#define SCC_GSMRH 0x04 +#define SCC_GSMRH_CTSS (1 << 7) +#define SCC_GSMRH_CDS (1 << 8) +#define SCC_GSMRH_CTSP (1 << 9) +#define SCC_GSMRH_CDP (1 << 10) + +/* SCC event register (16 bits) */ +#define SCC_SCCE 0x10 +#define SCC_SCCE_IQOV (1 << 3) +#define SCC_SCCE_GINT (1 << 2) +#define SCC_SCCE_GUN (1 << 1) +#define SCC_SCCE_GOV (1 << 0) + +/* SCC mask register (16 bits) */ +#define SCC_SCCM 0x14 +/* Multichannel base pointer (32 bits) */ +#define QMC_GBL_MCBASE 0x00 +/* Multichannel controller state (16 bits) */ +#define QMC_GBL_QMCSTATE 0x04 +/* Maximum receive buffer length (16 bits) */ +#define QMC_GBL_MRBLR 0x06 +/* Tx time-slot assignment table pointer (16 bits) */ +#define QMC_GBL_TX_S_PTR 0x08 +/* Rx pointer (16 bits) */ +#define QMC_GBL_RXPTR 0x0A +/* Global receive frame threshold (16 bits) */ +#define QMC_GBL_GRFTHR 0x0C +/* Global receive frame count (16 bits) */ +#define QMC_GBL_GRFCNT 0x0E +/* Multichannel interrupt base address (32 bits) */ +#define QMC_GBL_INTBASE 0x10 +/* Multichannel interrupt pointer (32 bits) */ +#define QMC_GBL_INTPTR 0x14 +/* Rx time-slot assignment table pointer (16 bits) */ +#define QMC_GBL_RX_S_PTR 0x18 +/* Tx pointer (16 bits) */ +#define QMC_GBL_TXPTR 0x1A +/* CRC constant (32 bits) */ +#define QMC_GBL_C_MASK32 0x1C +/* Time slot assignment table Rx (32 x 16 bits) */ +#define QMC_GBL_TSATRX 0x20 +/* Time slot assignment table Tx (32 x 16 bits) */ +#define QMC_GBL_TSATTX 0x60 +/* CRC constant (16 bits) */ +#define QMC_GBL_C_MASK16 0xA0 + +/* TSA entry (16bit entry in TSATRX and TSATTX) */ +#define QMC_TSA_VALID (1 << 15) +#define QMC_TSA_WRAP (1 << 14) +#define QMC_TSA_MASK (0x303F) +#define QMC_TSA_CHANNEL(x) ((x) << 6) + +/* Tx buffer descriptor base address (16 bits, offset from MCBASE) */ +#define QMC_SPE_TBASE 0x00 + +/* Channel mode register (16 bits) */ +#define QMC_SPE_CHAMR 0x02 +#define QMC_SPE_CHAMR_MODE_HDLC (1 << 15) +#define QMC_SPE_CHAMR_MODE_TRANSP ((0 << 15) | (1 << 13)) +#define QMC_SPE_CHAMR_ENT (1 << 12) +#define QMC_SPE_CHAMR_POL (1 << 8) +#define QMC_SPE_CHAMR_HDLC_IDLM (1 << 13) +#define QMC_SPE_CHAMR_HDLC_CRC (1 << 7) +#define QMC_SPE_CHAMR_HDLC_NOF (0x0f << 0) +#define QMC_SPE_CHAMR_TRANSP_RD (1 << 14) +#define QMC_SPE_CHAMR_TRANSP_SYNC (1 << 10) + +/* Tx internal state (32 bits) */ +#define QMC_SPE_TSTATE 0x04 +/* Tx buffer descriptor pointer (16 bits) */ +#define QMC_SPE_TBPTR 0x0C +/* Zero-insertion state (32 bits) */ +#define QMC_SPE_ZISTATE 0x14 +/* Channel’s interrupt mask flags (16 bits) */ +#define QMC_SPE_INTMSK 0x1C +/* Rx buffer descriptor base address (16 bits, offset from MCBASE) */ +#define QMC_SPE_RBASE 0x20 +/* HDLC: Maximum frame length register (16 bits) */ +#define QMC_SPE_MFLR 0x22 +/* TRANSPARENT: Transparent maximum receive length (16 bits) */ +#define QMC_SPE_TMRBLR 0x22 +/* Rx internal state (32 bits) */ +#define QMC_SPE_RSTATE 0x24 +/* Rx buffer descriptor pointer (16 bits) */ +#define QMC_SPE_RBPTR 0x2C +/* Packs 4 bytes to 1 long word before writing to buffer (32 bits) */ +#define QMC_SPE_RPACK 0x30 +/* Zero deletion state (32 bits) */ +#define QMC_SPE_ZDSTATE 0x34 + +/* Transparent synchronization (16 bits) */ +#define QMC_SPE_TRNSYNC 0x3C +#define QMC_SPE_TRNSYNC_RX(x) ((x) << 8) +#define QMC_SPE_TRNSYNC_TX(x) ((x) << 0) + +/* Interrupt related registers bits */ +#define QMC_INT_V (1 << 15) +#define QMC_INT_W (1 << 14) +#define QMC_INT_NID (1 << 13) +#define QMC_INT_IDL (1 << 12) +#define QMC_INT_GET_CHANNEL(x) (((x) & 0x0FC0) >> 6) +#define QMC_INT_MRF (1 << 5) +#define QMC_INT_UN (1 << 4) +#define QMC_INT_RXF (1 << 3) +#define QMC_INT_BSY (1 << 2) +#define QMC_INT_TXB (1 << 1) +#define QMC_INT_RXB (1 << 0) + +/* BD related registers bits */ +#define QMC_BD_RX_E (1 << 15) +#define QMC_BD_RX_W (1 << 13) +#define QMC_BD_RX_I (1 << 12) +#define QMC_BD_RX_L (1 << 11) +#define QMC_BD_RX_F (1 << 10) +#define QMC_BD_RX_CM (1 << 9) +#define QMC_BD_RX_UB (1 << 7) +#define QMC_BD_RX_LG (1 << 5) +#define QMC_BD_RX_NO (1 << 4) +#define QMC_BD_RX_AB (1 << 3) +#define QMC_BD_RX_CR (1 << 2) + +#define QMC_BD_TX_R (1 << 15) +#define QMC_BD_TX_W (1 << 13) +#define QMC_BD_TX_I (1 << 12) +#define QMC_BD_TX_L (1 << 11) +#define QMC_BD_TX_TC (1 << 10) +#define QMC_BD_TX_CM (1 << 9) +#define QMC_BD_TX_UB (1 << 7) +#define QMC_BD_TX_PAD (0x0f << 0) + +/* Numbers of BDs and interrupt items */ +#define QMC_NB_TXBDS 8 +#define QMC_NB_RXBDS 8 +#define QMC_NB_INTS 128 + +struct qmc_xfer_desc { + union { + void (*tx_complete)(void *context); + void (*rx_complete)(void *context, size_t length); + }; + void *context; +}; + +struct qmc_chan { + struct list_head list; + unsigned int id; + struct qmc *qmc; + void *__iomem s_param; + enum qmc_mode mode; + u64 tx_ts_mask; + u64 rx_ts_mask; + bool is_reverse_data; + + spinlock_t tx_lock; + cbd_t __iomem *txbds; + cbd_t __iomem *txbd_free; + cbd_t __iomem *txbd_done; + struct qmc_xfer_desc tx_desc[QMC_NB_TXBDS]; + u64 nb_tx_underrun; + bool is_tx_stopped; + + spinlock_t rx_lock; + cbd_t __iomem *rxbds; + cbd_t __iomem *rxbd_free; + cbd_t __iomem *rxbd_done; + struct qmc_xfer_desc rx_desc[QMC_NB_RXBDS]; + u64 nb_rx_busy; + int rx_pending; + bool is_rx_halted; + bool is_rx_stopped; +}; + +struct qmc { + struct device *dev; + struct tsa_serial *tsa_serial; + void *__iomem scc_regs; + void *__iomem scc_pram; + void *__iomem dpram; + u16 scc_pram_offset; + cbd_t __iomem *bd_table; + dma_addr_t bd_dma_addr; + size_t bd_size; + u16 __iomem *int_table; + u16 __iomem *int_curr; + dma_addr_t int_dma_addr; + size_t int_size; + struct list_head chan_head; + struct qmc_chan *chans[64]; +}; + +static inline void qmc_write16(void *__iomem addr, u16 val) +{ + iowrite16be(val, addr); +} + +static inline u16 qmc_read16(void *__iomem addr) +{ + return ioread16be(addr); +} + +static inline void qmc_setbits16(void *__iomem addr, u16 set) +{ + qmc_write16(addr, qmc_read16(addr) | set); +} + +static inline void qmc_clrbits16(void *__iomem addr, u16 clr) +{ + qmc_write16(addr, qmc_read16(addr) & ~clr); +} + +static inline void qmc_write32(void *__iomem addr, u32 val) +{ + iowrite32be(val, addr); +} + +static inline u32 qmc_read32(void *__iomem addr) +{ + return ioread32be(addr); +} + +static inline void qmc_setbits32(void *__iomem addr, u32 set) +{ + qmc_write32(addr, qmc_read32(addr) | set); +} + + +int qmc_chan_get_info(struct qmc_chan *chan, struct qmc_chan_info *info) +{ + struct tsa_serial_info tsa_info; + int ret; + + /* Retrieve info from the TSA related serial */ + ret = tsa_serial_get_info(chan->qmc->tsa_serial, &tsa_info); + if (ret) + return ret; + + info->mode = chan->mode; + info->rx_fs_rate = tsa_info.rx_fs_rate; + info->rx_bit_rate = tsa_info.rx_bit_rate; + info->nb_tx_ts = hweight64(chan->tx_ts_mask); + info->tx_fs_rate = tsa_info.tx_fs_rate; + info->tx_bit_rate = tsa_info.tx_bit_rate; + info->nb_rx_ts = hweight64(chan->rx_ts_mask); + + return 0; +} +EXPORT_SYMBOL(qmc_chan_get_info); + +int qmc_chan_set_param(struct qmc_chan *chan, const struct qmc_chan_param *param) +{ + if (param->mode != chan->mode) + return -EINVAL; + + switch (param->mode) { + case QMC_HDLC: + if ((param->hdlc.max_rx_buf_size % 4) || + (param->hdlc.max_rx_buf_size < 8)) + return -EINVAL; + + qmc_write16(chan->qmc->scc_pram + QMC_GBL_MRBLR, + param->hdlc.max_rx_buf_size - 8); + qmc_write16(chan->s_param + QMC_SPE_MFLR, + param->hdlc.max_rx_frame_size); + if (param->hdlc.is_crc32) { + qmc_setbits16(chan->s_param + QMC_SPE_CHAMR, + QMC_SPE_CHAMR_HDLC_CRC); + } else { + qmc_clrbits16(chan->s_param + QMC_SPE_CHAMR, + QMC_SPE_CHAMR_HDLC_CRC); + } + break; + + case QMC_TRANSPARENT: + qmc_write16(chan->s_param + QMC_SPE_TMRBLR, + param->transp.max_rx_buf_size); + break; + + default: + return -EINVAL; + } + + return 0; +} +EXPORT_SYMBOL(qmc_chan_set_param); + +int qmc_chan_write_submit(struct qmc_chan *chan, dma_addr_t addr, size_t length, + void (*complete)(void *context), void *context) +{ + struct qmc_xfer_desc *xfer_desc; + unsigned long flags; + cbd_t *__iomem bd; + u16 ctrl; + int ret; + + /* + * R bit UB bit + * 0 0 : The BD is free + * 1 1 : The BD is in used, waiting for transfer + * 0 1 : The BD is in used, waiting for completion + * 1 0 : Should not append + */ + + spin_lock_irqsave(&chan->tx_lock, flags); + bd = chan->txbd_free; + + ctrl = qmc_read16(&bd->cbd_sc); + if (ctrl & (QMC_BD_TX_R | QMC_BD_TX_UB)) { + /* We are full ... */ + ret = -EBUSY; + goto end; + } + + qmc_write16(&bd->cbd_datlen, length); + qmc_write32(&bd->cbd_bufaddr, addr); + + xfer_desc = &chan->tx_desc[bd - chan->txbds]; + xfer_desc->tx_complete = complete; + xfer_desc->context = context; + + /* Activate the descriptor */ + ctrl |= (QMC_BD_TX_R | QMC_BD_TX_UB); + wmb(); /* Be sure to flush the descriptor before control update */ + qmc_write16(&bd->cbd_sc, ctrl); + + if (!chan->is_tx_stopped) + qmc_setbits16(chan->s_param + QMC_SPE_CHAMR, QMC_SPE_CHAMR_POL); + + if (ctrl & QMC_BD_TX_W) + chan->txbd_free = chan->txbds; + else + chan->txbd_free++; + + ret = 0; + +end: + spin_unlock_irqrestore(&chan->tx_lock, flags); + return ret; +} +EXPORT_SYMBOL(qmc_chan_write_submit); + +static void qmc_chan_write_done(struct qmc_chan *chan) +{ + struct qmc_xfer_desc *xfer_desc; + void (*complete)(void *context); + unsigned long flags; + void *context; + cbd_t *__iomem bd; + u16 ctrl; + + /* + * R bit UB bit + * 0 0 : The BD is free + * 1 1 : The BD is in used, waiting for transfer + * 0 1 : The BD is in used, waiting for completion + * 1 0 : Should not append + */ + + spin_lock_irqsave(&chan->tx_lock, flags); + bd = chan->txbd_done; + + ctrl = qmc_read16(&bd->cbd_sc); + while (!(ctrl & QMC_BD_TX_R)) { + if (!(ctrl & QMC_BD_TX_UB)) + goto end; + + xfer_desc = &chan->tx_desc[bd - chan->txbds]; + complete = xfer_desc->tx_complete; + context = xfer_desc->context; + xfer_desc->tx_complete = NULL; + xfer_desc->context = NULL; + + qmc_write16(&bd->cbd_sc, ctrl & ~QMC_BD_TX_UB); + + if (ctrl & QMC_BD_TX_W) + chan->txbd_done = chan->txbds; + else + chan->txbd_done++; + + if (complete) { + spin_unlock_irqrestore(&chan->tx_lock, flags); + complete(context); + spin_lock_irqsave(&chan->tx_lock, flags); + } + + bd = chan->txbd_done; + ctrl = qmc_read16(&bd->cbd_sc); + } + +end: + spin_unlock_irqrestore(&chan->tx_lock, flags); +} + +int qmc_chan_read_submit(struct qmc_chan *chan, dma_addr_t addr, size_t length, + void (*complete)(void *context, size_t length), void *context) +{ + struct qmc_xfer_desc *xfer_desc; + unsigned long flags; + cbd_t *__iomem bd; + u16 ctrl; + int ret; + + /* + * E bit UB bit + * 0 0 : The BD is free + * 1 1 : The BD is in used, waiting for transfer + * 0 1 : The BD is in used, waiting for completion + * 1 0 : Should not append + */ + + spin_lock_irqsave(&chan->rx_lock, flags); + bd = chan->rxbd_free; + + ctrl = qmc_read16(&bd->cbd_sc); + if (ctrl & (QMC_BD_RX_E | QMC_BD_RX_UB)) { + /* We are full ... */ + ret = -EBUSY; + goto end; + } + + qmc_write16(&bd->cbd_datlen, 0); /* data length is updated by the QMC */ + qmc_write32(&bd->cbd_bufaddr, addr); + + xfer_desc = &chan->rx_desc[bd - chan->rxbds]; + xfer_desc->rx_complete = complete; + xfer_desc->context = context; + + /* Activate the descriptor */ + ctrl |= (QMC_BD_RX_E | QMC_BD_RX_UB); + wmb(); /* Be sure to flush data before descriptor activation */ + qmc_write16(&bd->cbd_sc, ctrl); + + /* Restart receiver if needed */ + if (chan->is_rx_halted && !chan->is_rx_stopped) { + /* Restart receiver */ + if (chan->mode == QMC_TRANSPARENT) + qmc_write32(chan->s_param + QMC_SPE_ZDSTATE, 0x18000080); + else + qmc_write32(chan->s_param + QMC_SPE_ZDSTATE, 0x00000080); + qmc_write32(chan->s_param + QMC_SPE_RSTATE, 0x31000000); + chan->is_rx_halted = false; + } + chan->rx_pending++; + + if (ctrl & QMC_BD_RX_W) + chan->rxbd_free = chan->rxbds; + else + chan->rxbd_free++; + + ret = 0; +end: + spin_unlock_irqrestore(&chan->rx_lock, flags); + return ret; +} +EXPORT_SYMBOL(qmc_chan_read_submit); + +static void qmc_chan_read_done(struct qmc_chan *chan) +{ + void (*complete)(void *context, size_t size); + struct qmc_xfer_desc *xfer_desc; + unsigned long flags; + cbd_t *__iomem bd; + void *context; + u16 datalen; + u16 ctrl; + + /* + * E bit UB bit + * 0 0 : The BD is free + * 1 1 : The BD is in used, waiting for transfer + * 0 1 : The BD is in used, waiting for completion + * 1 0 : Should not append + */ + + spin_lock_irqsave(&chan->rx_lock, flags); + bd = chan->rxbd_done; + + ctrl = qmc_read16(&bd->cbd_sc); + while (!(ctrl & QMC_BD_RX_E)) { + if (!(ctrl & QMC_BD_RX_UB)) + goto end; + + xfer_desc = &chan->rx_desc[bd - chan->rxbds]; + complete = xfer_desc->rx_complete; + context = xfer_desc->context; + xfer_desc->rx_complete = NULL; + xfer_desc->context = NULL; + + datalen = qmc_read16(&bd->cbd_datlen); + qmc_write16(&bd->cbd_sc, ctrl & ~QMC_BD_RX_UB); + + if (ctrl & QMC_BD_RX_W) + chan->rxbd_done = chan->rxbds; + else + chan->rxbd_done++; + + chan->rx_pending--; + + if (complete) { + spin_unlock_irqrestore(&chan->rx_lock, flags); + complete(context, datalen); + spin_lock_irqsave(&chan->rx_lock, flags); + } + + bd = chan->rxbd_done; + ctrl = qmc_read16(&bd->cbd_sc); + } + +end: + spin_unlock_irqrestore(&chan->rx_lock, flags); +} + +static int qmc_chan_command(struct qmc_chan *chan, u8 qmc_opcode) +{ + return cpm_command(chan->id << 2, (qmc_opcode << 4) | 0x0E); +} + +static int qmc_chan_stop_rx(struct qmc_chan *chan) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(&chan->rx_lock, flags); + + /* Send STOP RECEIVE command */ + ret = qmc_chan_command(chan, 0x0); + if (ret) { + dev_err(chan->qmc->dev, "chan %u: Send STOP RECEIVE failed (%d)\n", + chan->id, ret); + goto end; + } + + chan->is_rx_stopped = true; + +end: + spin_unlock_irqrestore(&chan->rx_lock, flags); + return ret; +} + +static int qmc_chan_stop_tx(struct qmc_chan *chan) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(&chan->tx_lock, flags); + + /* Send STOP TRANSMIT command */ + ret = qmc_chan_command(chan, 0x1); + if (ret) { + dev_err(chan->qmc->dev, "chan %u: Send STOP TRANSMIT failed (%d)\n", + chan->id, ret); + goto end; + } + + chan->is_tx_stopped = true; + +end: + spin_unlock_irqrestore(&chan->tx_lock, flags); + return ret; +} + +int qmc_chan_stop(struct qmc_chan *chan, int direction) +{ + int ret; + + if (direction & QMC_CHAN_READ) { + ret = qmc_chan_stop_rx(chan); + if (ret) + return ret; + } + + if (direction & QMC_CHAN_WRITE) { + ret = qmc_chan_stop_tx(chan); + if (ret) + return ret; + } + + return 0; +} +EXPORT_SYMBOL(qmc_chan_stop); + +static void qmc_chan_start_rx(struct qmc_chan *chan) +{ + unsigned long flags; + + spin_lock_irqsave(&chan->rx_lock, flags); + + /* Restart the receiver */ + if (chan->mode == QMC_TRANSPARENT) + qmc_write32(chan->s_param + QMC_SPE_ZDSTATE, 0x18000080); + else + qmc_write32(chan->s_param + QMC_SPE_ZDSTATE, 0x00000080); + qmc_write32(chan->s_param + QMC_SPE_RSTATE, 0x31000000); + chan->is_rx_halted = false; + + chan->is_rx_stopped = false; + + spin_unlock_irqrestore(&chan->rx_lock, flags); +} + +static void qmc_chan_start_tx(struct qmc_chan *chan) +{ + unsigned long flags; + + spin_lock_irqsave(&chan->tx_lock, flags); + + /* + * Enable channel transmitter as it could be disabled if + * qmc_chan_reset() was called. + */ + qmc_setbits16(chan->s_param + QMC_SPE_CHAMR, QMC_SPE_CHAMR_ENT); + + /* Set the POL bit in the channel mode register */ + qmc_setbits16(chan->s_param + QMC_SPE_CHAMR, QMC_SPE_CHAMR_POL); + + chan->is_tx_stopped = false; + + spin_unlock_irqrestore(&chan->tx_lock, flags); +} + +int qmc_chan_start(struct qmc_chan *chan, int direction) +{ + if (direction & QMC_CHAN_READ) + qmc_chan_start_rx(chan); + + if (direction & QMC_CHAN_WRITE) + qmc_chan_start_tx(chan); + + return 0; +} +EXPORT_SYMBOL(qmc_chan_start); + +static void qmc_chan_reset_rx(struct qmc_chan *chan) +{ + struct qmc_xfer_desc *xfer_desc; + unsigned long flags; + cbd_t *__iomem bd; + u16 ctrl; + + spin_lock_irqsave(&chan->rx_lock, flags); + bd = chan->rxbds; + do { + ctrl = qmc_read16(&bd->cbd_sc); + qmc_write16(&bd->cbd_sc, ctrl & ~(QMC_BD_RX_UB | QMC_BD_RX_E)); + + xfer_desc = &chan->rx_desc[bd - chan->rxbds]; + xfer_desc->rx_complete = NULL; + xfer_desc->context = NULL; + + bd++; + } while (!(ctrl & QMC_BD_RX_W)); + + chan->rxbd_free = chan->rxbds; + chan->rxbd_done = chan->rxbds; + qmc_write16(chan->s_param + QMC_SPE_RBPTR, + qmc_read16(chan->s_param + QMC_SPE_RBASE)); + + chan->rx_pending = 0; + chan->is_rx_stopped = false; + + spin_unlock_irqrestore(&chan->rx_lock, flags); +} + +static void qmc_chan_reset_tx(struct qmc_chan *chan) +{ + struct qmc_xfer_desc *xfer_desc; + unsigned long flags; + cbd_t *__iomem bd; + u16 ctrl; + + spin_lock_irqsave(&chan->tx_lock, flags); + + /* Disable transmitter. It will be re-enable on qmc_chan_start() */ + qmc_clrbits16(chan->s_param + QMC_SPE_CHAMR, QMC_SPE_CHAMR_ENT); + + bd = chan->txbds; + do { + ctrl = qmc_read16(&bd->cbd_sc); + qmc_write16(&bd->cbd_sc, ctrl & ~(QMC_BD_TX_UB | QMC_BD_TX_R)); + + xfer_desc = &chan->tx_desc[bd - chan->txbds]; + xfer_desc->tx_complete = NULL; + xfer_desc->context = NULL; + + bd++; + } while (!(ctrl & QMC_BD_TX_W)); + + chan->txbd_free = chan->txbds; + chan->txbd_done = chan->txbds; + qmc_write16(chan->s_param + QMC_SPE_TBPTR, + qmc_read16(chan->s_param + QMC_SPE_TBASE)); + + /* Reset TSTATE and ZISTATE to their initial value */ + qmc_write32(chan->s_param + QMC_SPE_TSTATE, 0x30000000); + qmc_write32(chan->s_param + QMC_SPE_ZISTATE, 0x00000100); + + spin_unlock_irqrestore(&chan->tx_lock, flags); +} + +int qmc_chan_reset(struct qmc_chan *chan, int direction) +{ + if (direction & QMC_CHAN_READ) + qmc_chan_reset_rx(chan); + + if (direction & QMC_CHAN_WRITE) + qmc_chan_reset_tx(chan); + + return 0; +} +EXPORT_SYMBOL(qmc_chan_reset); + +static int qmc_check_chans(struct qmc *qmc) +{ + struct tsa_serial_info info; + bool is_one_table = false; + struct qmc_chan *chan; + u64 tx_ts_mask = 0; + u64 rx_ts_mask = 0; + u64 tx_ts_assigned_mask; + u64 rx_ts_assigned_mask; + int ret; + + /* Retrieve info from the TSA related serial */ + ret = tsa_serial_get_info(qmc->tsa_serial, &info); + if (ret) + return ret; + + /* + * If more than 32 TS are assigned to this serial, one common table is + * used for Tx and Rx and so masks must be equal for all channels. + */ + if ((info.nb_tx_ts > 32) || (info.nb_rx_ts > 32)) { + if (info.nb_tx_ts != info.nb_rx_ts) { + dev_err(qmc->dev, "Number of TSA Tx/Rx TS assigned are not equal\n"); + return -EINVAL; + } + is_one_table = true; + } + + + tx_ts_assigned_mask = (((u64)1) << info.nb_tx_ts) - 1; + rx_ts_assigned_mask = (((u64)1) << info.nb_rx_ts) - 1; + + list_for_each_entry(chan, &qmc->chan_head, list) { + if (chan->tx_ts_mask > tx_ts_assigned_mask) { + dev_err(qmc->dev, "chan %u uses TSA unassigned Tx TS\n", chan->id); + return -EINVAL; + } + if (tx_ts_mask & chan->tx_ts_mask) { + dev_err(qmc->dev, "chan %u uses an already used Tx TS\n", chan->id); + return -EINVAL; + } + + if (chan->rx_ts_mask > rx_ts_assigned_mask) { + dev_err(qmc->dev, "chan %u uses TSA unassigned Rx TS\n", chan->id); + return -EINVAL; + } + if (rx_ts_mask & chan->rx_ts_mask) { + dev_err(qmc->dev, "chan %u uses an already used Rx TS\n", chan->id); + return -EINVAL; + } + + if (is_one_table && (chan->tx_ts_mask != chan->rx_ts_mask)) { + dev_err(qmc->dev, "chan %u uses different Rx and Tx TS\n", chan->id); + return -EINVAL; + } + + tx_ts_mask |= chan->tx_ts_mask; + rx_ts_mask |= chan->rx_ts_mask; + } + + return 0; +} + +static unsigned int qmc_nb_chans(struct qmc *qmc) +{ + unsigned int count = 0; + struct qmc_chan *chan; + + list_for_each_entry(chan, &qmc->chan_head, list) + count++; + + return count; +} + +static int qmc_of_parse_chans(struct qmc *qmc, struct device_node *np) +{ + struct device_node *chan_np; + struct qmc_chan *chan; + const char *mode; + u32 chan_id; + u64 ts_mask; + int ret; + + for_each_available_child_of_node(np, chan_np) { + ret = of_property_read_u32(chan_np, "reg", &chan_id); + if (ret) { + dev_err(qmc->dev, "%pOF: failed to read reg\n", chan_np); + of_node_put(chan_np); + return ret; + } + if (chan_id > 63) { + dev_err(qmc->dev, "%pOF: Invalid chan_id\n", chan_np); + of_node_put(chan_np); + return -EINVAL; + } + + chan = devm_kzalloc(qmc->dev, sizeof(*chan), GFP_KERNEL); + if (!chan) { + of_node_put(chan_np); + return -ENOMEM; + } + + chan->id = chan_id; + spin_lock_init(&chan->rx_lock); + spin_lock_init(&chan->tx_lock); + + ret = of_property_read_u64(chan_np, "fsl,tx-ts-mask", &ts_mask); + if (ret) { + dev_err(qmc->dev, "%pOF: failed to read fsl,tx-ts-mask\n", + chan_np); + of_node_put(chan_np); + return ret; + } + chan->tx_ts_mask = ts_mask; + + ret = of_property_read_u64(chan_np, "fsl,rx-ts-mask", &ts_mask); + if (ret) { + dev_err(qmc->dev, "%pOF: failed to read fsl,rx-ts-mask\n", + chan_np); + of_node_put(chan_np); + return ret; + } + chan->rx_ts_mask = ts_mask; + + mode = "transparent"; + ret = of_property_read_string(chan_np, "fsl,operational-mode", &mode); + if (ret && ret != -EINVAL) { + dev_err(qmc->dev, "%pOF: failed to read fsl,operational-mode\n", + chan_np); + of_node_put(chan_np); + return ret; + } + if (!strcmp(mode, "transparent")) { + chan->mode = QMC_TRANSPARENT; + } else if (!strcmp(mode, "hdlc")) { + chan->mode = QMC_HDLC; + } else { + dev_err(qmc->dev, "%pOF: Invalid fsl,operational-mode (%s)\n", + chan_np, mode); + of_node_put(chan_np); + return -EINVAL; + } + + chan->is_reverse_data = of_property_read_bool(chan_np, + "fsl,reverse-data"); + + list_add_tail(&chan->list, &qmc->chan_head); + qmc->chans[chan->id] = chan; + } + + return qmc_check_chans(qmc); +} + +static int qmc_setup_tsa_64rxtx(struct qmc *qmc, const struct tsa_serial_info *info) +{ + struct qmc_chan *chan; + unsigned int i; + u16 val; + + /* + * Use a common Tx/Rx 64 entries table. + * Everything was previously checked, Tx and Rx related stuffs are + * identical -> Used Rx related stuff to build the table + */ + + /* Invalidate all entries */ + for (i = 0; i < 64; i++) + qmc_write16(qmc->scc_pram + QMC_GBL_TSATRX + (i * 2), 0x0000); + + /* Set entries based on Rx stuff*/ + list_for_each_entry(chan, &qmc->chan_head, list) { + for (i = 0; i < info->nb_rx_ts; i++) { + if (!(chan->rx_ts_mask & (((u64)1) << i))) + continue; + + val = QMC_TSA_VALID | QMC_TSA_MASK | + QMC_TSA_CHANNEL(chan->id); + qmc_write16(qmc->scc_pram + QMC_GBL_TSATRX + (i * 2), val); + } + } + + /* Set Wrap bit on last entry */ + qmc_setbits16(qmc->scc_pram + QMC_GBL_TSATRX + ((info->nb_rx_ts - 1) * 2), + QMC_TSA_WRAP); + + /* Init pointers to the table */ + val = qmc->scc_pram_offset + QMC_GBL_TSATRX; + qmc_write16(qmc->scc_pram + QMC_GBL_RX_S_PTR, val); + qmc_write16(qmc->scc_pram + QMC_GBL_RXPTR, val); + qmc_write16(qmc->scc_pram + QMC_GBL_TX_S_PTR, val); + qmc_write16(qmc->scc_pram + QMC_GBL_TXPTR, val); + + return 0; +} + +static int qmc_setup_tsa_32rx_32tx(struct qmc *qmc, const struct tsa_serial_info *info) +{ + struct qmc_chan *chan; + unsigned int i; + u16 val; + + /* + * Use a Tx 32 entries table and a Rx 32 entries table. + * Everything was previously checked. + */ + + /* Invalidate all entries */ + for (i = 0; i < 32; i++) { + qmc_write16(qmc->scc_pram + QMC_GBL_TSATRX + (i * 2), 0x0000); + qmc_write16(qmc->scc_pram + QMC_GBL_TSATTX + (i * 2), 0x0000); + } + + /* Set entries based on Rx and Tx stuff*/ + list_for_each_entry(chan, &qmc->chan_head, list) { + /* Rx part */ + for (i = 0; i < info->nb_rx_ts; i++) { + if (!(chan->rx_ts_mask & (((u64)1) << i))) + continue; + + val = QMC_TSA_VALID | QMC_TSA_MASK | + QMC_TSA_CHANNEL(chan->id); + qmc_write16(qmc->scc_pram + QMC_GBL_TSATRX + (i * 2), val); + } + /* Tx part */ + for (i = 0; i < info->nb_tx_ts; i++) { + if (!(chan->tx_ts_mask & (((u64)1) << i))) + continue; + + val = QMC_TSA_VALID | QMC_TSA_MASK | + QMC_TSA_CHANNEL(chan->id); + qmc_write16(qmc->scc_pram + QMC_GBL_TSATTX + (i * 2), val); + } + } + + /* Set Wrap bit on last entries */ + qmc_setbits16(qmc->scc_pram + QMC_GBL_TSATRX + ((info->nb_rx_ts - 1) * 2), + QMC_TSA_WRAP); + qmc_setbits16(qmc->scc_pram + QMC_GBL_TSATTX + ((info->nb_tx_ts - 1) * 2), + QMC_TSA_WRAP); + + /* Init Rx pointers ...*/ + val = qmc->scc_pram_offset + QMC_GBL_TSATRX; + qmc_write16(qmc->scc_pram + QMC_GBL_RX_S_PTR, val); + qmc_write16(qmc->scc_pram + QMC_GBL_RXPTR, val); + + /* ... and Tx pointers */ + val = qmc->scc_pram_offset + QMC_GBL_TSATTX; + qmc_write16(qmc->scc_pram + QMC_GBL_TX_S_PTR, val); + qmc_write16(qmc->scc_pram + QMC_GBL_TXPTR, val); + + return 0; +} + +static int qmc_setup_tsa(struct qmc *qmc) +{ + struct tsa_serial_info info; + int ret; + + /* Retrieve info from the TSA related serial */ + ret = tsa_serial_get_info(qmc->tsa_serial, &info); + if (ret) + return ret; + + /* + * Setup one common 64 entries table or two 32 entries (one for Tx and + * one for Tx) according to assigned TS numbers. + */ + return ((info.nb_tx_ts > 32) || (info.nb_rx_ts > 32)) ? + qmc_setup_tsa_64rxtx(qmc, &info) : + qmc_setup_tsa_32rx_32tx(qmc, &info); +} + +static int qmc_setup_chan_trnsync(struct qmc *qmc, struct qmc_chan *chan) +{ + struct tsa_serial_info info; + u16 first_rx, last_tx; + u16 trnsync; + int ret; + + /* Retrieve info from the TSA related serial */ + ret = tsa_serial_get_info(chan->qmc->tsa_serial, &info); + if (ret) + return ret; + + /* Find the first Rx TS allocated to the channel */ + first_rx = chan->rx_ts_mask ? __ffs64(chan->rx_ts_mask) + 1 : 0; + + /* Find the last Tx TS allocated to the channel */ + last_tx = fls64(chan->tx_ts_mask); + + trnsync = 0; + if (info.nb_rx_ts) + trnsync |= QMC_SPE_TRNSYNC_RX((first_rx % info.nb_rx_ts) * 2); + if (info.nb_tx_ts) + trnsync |= QMC_SPE_TRNSYNC_TX((last_tx % info.nb_tx_ts) * 2); + + qmc_write16(chan->s_param + QMC_SPE_TRNSYNC, trnsync); + + dev_dbg(qmc->dev, "chan %u: trnsync=0x%04x, rx %u/%u 0x%llx, tx %u/%u 0x%llx\n", + chan->id, trnsync, + first_rx, info.nb_rx_ts, chan->rx_ts_mask, + last_tx, info.nb_tx_ts, chan->tx_ts_mask); + + return 0; +} + +static int qmc_setup_chan(struct qmc *qmc, struct qmc_chan *chan) +{ + unsigned int i; + cbd_t __iomem *bd; + int ret; + u16 val; + + chan->qmc = qmc; + + /* Set channel specific parameter base address */ + chan->s_param = qmc->dpram + (chan->id * 64); + /* 16 bd per channel (8 rx and 8 tx) */ + chan->txbds = qmc->bd_table + (chan->id * (QMC_NB_TXBDS + QMC_NB_RXBDS)); + chan->rxbds = qmc->bd_table + (chan->id * (QMC_NB_TXBDS + QMC_NB_RXBDS)) + QMC_NB_TXBDS; + + chan->txbd_free = chan->txbds; + chan->txbd_done = chan->txbds; + chan->rxbd_free = chan->rxbds; + chan->rxbd_done = chan->rxbds; + + /* TBASE and TBPTR*/ + val = chan->id * (QMC_NB_TXBDS + QMC_NB_RXBDS) * sizeof(cbd_t); + qmc_write16(chan->s_param + QMC_SPE_TBASE, val); + qmc_write16(chan->s_param + QMC_SPE_TBPTR, val); + + /* RBASE and RBPTR*/ + val = ((chan->id * (QMC_NB_TXBDS + QMC_NB_RXBDS)) + QMC_NB_TXBDS) * sizeof(cbd_t); + qmc_write16(chan->s_param + QMC_SPE_RBASE, val); + qmc_write16(chan->s_param + QMC_SPE_RBPTR, val); + qmc_write32(chan->s_param + QMC_SPE_TSTATE, 0x30000000); + qmc_write32(chan->s_param + QMC_SPE_RSTATE, 0x31000000); + qmc_write32(chan->s_param + QMC_SPE_ZISTATE, 0x00000100); + if (chan->mode == QMC_TRANSPARENT) { + qmc_write32(chan->s_param + QMC_SPE_ZDSTATE, 0x18000080); + qmc_write16(chan->s_param + QMC_SPE_TMRBLR, 60); + val = QMC_SPE_CHAMR_MODE_TRANSP | QMC_SPE_CHAMR_TRANSP_SYNC; + if (chan->is_reverse_data) + val |= QMC_SPE_CHAMR_TRANSP_RD; + qmc_write16(chan->s_param + QMC_SPE_CHAMR, val); + ret = qmc_setup_chan_trnsync(qmc, chan); + if (ret) + return ret; + } else { + qmc_write32(chan->s_param + QMC_SPE_ZDSTATE, 0x00000080); + qmc_write16(chan->s_param + QMC_SPE_MFLR, 60); + qmc_write16(chan->s_param + QMC_SPE_CHAMR, + QMC_SPE_CHAMR_MODE_HDLC | QMC_SPE_CHAMR_HDLC_IDLM); + } + + /* Do not enable interrupts now. They will be enabled later */ + qmc_write16(chan->s_param + QMC_SPE_INTMSK, 0x0000); + + /* Init Rx BDs and set Wrap bit on last descriptor */ + BUILD_BUG_ON(QMC_NB_RXBDS == 0); + val = QMC_BD_RX_I; + for (i = 0; i < QMC_NB_RXBDS; i++) { + bd = chan->rxbds + i; + qmc_write16(&bd->cbd_sc, val); + } + bd = chan->rxbds + QMC_NB_RXBDS - 1; + qmc_write16(&bd->cbd_sc, val | QMC_BD_RX_W); + + /* Init Tx BDs and set Wrap bit on last descriptor */ + BUILD_BUG_ON(QMC_NB_TXBDS == 0); + val = QMC_BD_TX_I; + if (chan->mode == QMC_HDLC) + val |= QMC_BD_TX_L | QMC_BD_TX_TC; + for (i = 0; i < QMC_NB_TXBDS; i++) { + bd = chan->txbds + i; + qmc_write16(&bd->cbd_sc, val); + } + bd = chan->txbds + QMC_NB_TXBDS - 1; + qmc_write16(&bd->cbd_sc, val | QMC_BD_TX_W); + + return 0; +} + +static int qmc_setup_chans(struct qmc *qmc) +{ + struct qmc_chan *chan; + int ret; + + list_for_each_entry(chan, &qmc->chan_head, list) { + ret = qmc_setup_chan(qmc, chan); + if (ret) + return ret; + } + + return 0; +} + +static int qmc_finalize_chans(struct qmc *qmc) +{ + struct qmc_chan *chan; + int ret; + + list_for_each_entry(chan, &qmc->chan_head, list) { + /* Unmask channel interrupts */ + if (chan->mode == QMC_HDLC) { + qmc_write16(chan->s_param + QMC_SPE_INTMSK, + QMC_INT_NID | QMC_INT_IDL | QMC_INT_MRF | + QMC_INT_UN | QMC_INT_RXF | QMC_INT_BSY | + QMC_INT_TXB | QMC_INT_RXB); + } else { + qmc_write16(chan->s_param + QMC_SPE_INTMSK, + QMC_INT_UN | QMC_INT_BSY | + QMC_INT_TXB | QMC_INT_RXB); + } + + /* Forced stop the channel */ + ret = qmc_chan_stop(chan, QMC_CHAN_ALL); + if (ret) + return ret; + } + + return 0; +} + +static int qmc_setup_ints(struct qmc *qmc) +{ + unsigned int i; + u16 __iomem *last; + + /* Raz all entries */ + for (i = 0; i < (qmc->int_size / sizeof(u16)); i++) + qmc_write16(qmc->int_table + i, 0x0000); + + /* Set Wrap bit on last entry */ + if (qmc->int_size >= sizeof(u16)) { + last = qmc->int_table + (qmc->int_size / sizeof(u16)) - 1; + qmc_write16(last, QMC_INT_W); + } + + return 0; +} + +static void qmc_irq_gint(struct qmc *qmc) +{ + struct qmc_chan *chan; + unsigned int chan_id; + unsigned long flags; + u16 int_entry; + + int_entry = qmc_read16(qmc->int_curr); + while (int_entry & QMC_INT_V) { + /* Clear all but the Wrap bit */ + qmc_write16(qmc->int_curr, int_entry & QMC_INT_W); + + chan_id = QMC_INT_GET_CHANNEL(int_entry); + chan = qmc->chans[chan_id]; + if (!chan) { + dev_err(qmc->dev, "interrupt on invalid chan %u\n", chan_id); + goto int_next; + } + + if (int_entry & QMC_INT_TXB) + qmc_chan_write_done(chan); + + if (int_entry & QMC_INT_UN) { + dev_info(qmc->dev, "intr chan %u, 0x%04x (UN)\n", chan_id, + int_entry); + chan->nb_tx_underrun++; + } + + if (int_entry & QMC_INT_BSY) { + dev_info(qmc->dev, "intr chan %u, 0x%04x (BSY)\n", chan_id, + int_entry); + chan->nb_rx_busy++; + /* Restart the receiver if needed */ + spin_lock_irqsave(&chan->rx_lock, flags); + if (chan->rx_pending && !chan->is_rx_stopped) { + if (chan->mode == QMC_TRANSPARENT) + qmc_write32(chan->s_param + QMC_SPE_ZDSTATE, 0x18000080); + else + qmc_write32(chan->s_param + QMC_SPE_ZDSTATE, 0x00000080); + qmc_write32(chan->s_param + QMC_SPE_RSTATE, 0x31000000); + chan->is_rx_halted = false; + } else { + chan->is_rx_halted = true; + } + spin_unlock_irqrestore(&chan->rx_lock, flags); + } + + if (int_entry & QMC_INT_RXB) + qmc_chan_read_done(chan); + +int_next: + if (int_entry & QMC_INT_W) + qmc->int_curr = qmc->int_table; + else + qmc->int_curr++; + int_entry = qmc_read16(qmc->int_curr); + } +} + +static irqreturn_t qmc_irq_handler(int irq, void *priv) +{ + struct qmc *qmc = (struct qmc *)priv; + u16 scce; + + scce = qmc_read16(qmc->scc_regs + SCC_SCCE); + qmc_write16(qmc->scc_regs + SCC_SCCE, scce); + + if (unlikely(scce & SCC_SCCE_IQOV)) + dev_info(qmc->dev, "IRQ queue overflow\n"); + + if (unlikely(scce & SCC_SCCE_GUN)) + dev_err(qmc->dev, "Global transmitter underrun\n"); + + if (unlikely(scce & SCC_SCCE_GOV)) + dev_err(qmc->dev, "Global receiver overrun\n"); + + /* normal interrupt */ + if (likely(scce & SCC_SCCE_GINT)) + qmc_irq_gint(qmc); + + return IRQ_HANDLED; +} + +static int qmc_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + unsigned int nb_chans; + struct resource *res; + struct qmc *qmc; + int irq; + int ret; + + qmc = devm_kzalloc(&pdev->dev, sizeof(*qmc), GFP_KERNEL); + if (!qmc) + return -ENOMEM; + + qmc->dev = &pdev->dev; + INIT_LIST_HEAD(&qmc->chan_head); + + qmc->scc_regs = devm_platform_ioremap_resource_byname(pdev, "scc_regs"); + if (IS_ERR(qmc->scc_regs)) + return PTR_ERR(qmc->scc_regs); + + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "scc_pram"); + if (!res) + return -EINVAL; + qmc->scc_pram_offset = res->start - get_immrbase(); + qmc->scc_pram = devm_ioremap_resource(qmc->dev, res); + if (IS_ERR(qmc->scc_pram)) + return PTR_ERR(qmc->scc_pram); + + qmc->dpram = devm_platform_ioremap_resource_byname(pdev, "dpram"); + if (IS_ERR(qmc->dpram)) + return PTR_ERR(qmc->dpram); + + qmc->tsa_serial = devm_tsa_serial_get_byphandle(qmc->dev, np, "fsl,tsa-serial"); + if (IS_ERR(qmc->tsa_serial)) { + return dev_err_probe(qmc->dev, PTR_ERR(qmc->tsa_serial), + "Failed to get TSA serial\n"); + } + + /* Connect the serial (SCC) to TSA */ + ret = tsa_serial_connect(qmc->tsa_serial); + if (ret) { + dev_err(qmc->dev, "Failed to connect TSA serial\n"); + return ret; + } + + /* Parse channels informationss */ + ret = qmc_of_parse_chans(qmc, np); + if (ret) + goto err_tsa_serial_disconnect; + + nb_chans = qmc_nb_chans(qmc); + + /* Init GMSR_H and GMSR_L registers */ + qmc_write32(qmc->scc_regs + SCC_GSMRH, + SCC_GSMRH_CDS | SCC_GSMRH_CTSS | SCC_GSMRH_CDP | SCC_GSMRH_CTSP); + + /* enable QMC mode */ + qmc_write32(qmc->scc_regs + SCC_GSMRL, SCC_GSMRL_MODE_QMC); + + /* + * Allocate the buffer descriptor table + * 8 rx and 8 tx descriptors per channel + */ + qmc->bd_size = (nb_chans * (QMC_NB_TXBDS + QMC_NB_RXBDS)) * sizeof(cbd_t); + qmc->bd_table = dmam_alloc_coherent(qmc->dev, qmc->bd_size, + &qmc->bd_dma_addr, GFP_KERNEL); + if (!qmc->bd_table) { + dev_err(qmc->dev, "Failed to allocate bd table\n"); + ret = -ENOMEM; + goto err_tsa_serial_disconnect; + } + memset(qmc->bd_table, 0, qmc->bd_size); + + qmc_write32(qmc->scc_pram + QMC_GBL_MCBASE, qmc->bd_dma_addr); + + /* Allocate the interrupt table */ + qmc->int_size = QMC_NB_INTS * sizeof(u16); + qmc->int_table = dmam_alloc_coherent(qmc->dev, qmc->int_size, + &qmc->int_dma_addr, GFP_KERNEL); + if (!qmc->int_table) { + dev_err(qmc->dev, "Failed to allocate interrupt table\n"); + ret = -ENOMEM; + goto err_tsa_serial_disconnect; + } + memset(qmc->int_table, 0, qmc->int_size); + + qmc->int_curr = qmc->int_table; + qmc_write32(qmc->scc_pram + QMC_GBL_INTBASE, qmc->int_dma_addr); + qmc_write32(qmc->scc_pram + QMC_GBL_INTPTR, qmc->int_dma_addr); + + /* Set MRBLR (valid for HDLC only) max MRU + max CRC */ + qmc_write16(qmc->scc_pram + QMC_GBL_MRBLR, HDLC_MAX_MRU + 4); + + qmc_write16(qmc->scc_pram + QMC_GBL_GRFTHR, 1); + qmc_write16(qmc->scc_pram + QMC_GBL_GRFCNT, 1); + + qmc_write32(qmc->scc_pram + QMC_GBL_C_MASK32, 0xDEBB20E3); + qmc_write16(qmc->scc_pram + QMC_GBL_C_MASK16, 0xF0B8); + + ret = qmc_setup_tsa(qmc); + if (ret) + goto err_tsa_serial_disconnect; + + qmc_write16(qmc->scc_pram + QMC_GBL_QMCSTATE, 0x8000); + + ret = qmc_setup_chans(qmc); + if (ret) + goto err_tsa_serial_disconnect; + + /* Init interrupts table */ + ret = qmc_setup_ints(qmc); + if (ret) + goto err_tsa_serial_disconnect; + + /* Disable and clear interrupts, set the irq handler */ + qmc_write16(qmc->scc_regs + SCC_SCCM, 0x0000); + qmc_write16(qmc->scc_regs + SCC_SCCE, 0x000F); + irq = platform_get_irq(pdev, 0); + if (irq < 0) + goto err_tsa_serial_disconnect; + ret = devm_request_irq(qmc->dev, irq, qmc_irq_handler, 0, "qmc", qmc); + if (ret < 0) + goto err_tsa_serial_disconnect; + + /* Enable interrupts */ + qmc_write16(qmc->scc_regs + SCC_SCCM, + SCC_SCCE_IQOV | SCC_SCCE_GINT | SCC_SCCE_GUN | SCC_SCCE_GOV); + + ret = qmc_finalize_chans(qmc); + if (ret < 0) + goto err_disable_intr; + + /* Enable transmiter and receiver */ + qmc_setbits32(qmc->scc_regs + SCC_GSMRL, SCC_GSMRL_ENR | SCC_GSMRL_ENT); + + platform_set_drvdata(pdev, qmc); + + return 0; + +err_disable_intr: + qmc_write16(qmc->scc_regs + SCC_SCCM, 0); + +err_tsa_serial_disconnect: + tsa_serial_disconnect(qmc->tsa_serial); + return ret; +} + +static int qmc_remove(struct platform_device *pdev) +{ + struct qmc *qmc = platform_get_drvdata(pdev); + + /* Disable transmiter and receiver */ + qmc_setbits32(qmc->scc_regs + SCC_GSMRL, 0); + + /* Disable interrupts */ + qmc_write16(qmc->scc_regs + SCC_SCCM, 0); + + /* Disconnect the serial from TSA */ + tsa_serial_disconnect(qmc->tsa_serial); + + return 0; +} + +static const struct of_device_id qmc_id_table[] = { + { .compatible = "fsl,cpm1-scc-qmc" }, + {} /* sentinel */ +}; +MODULE_DEVICE_TABLE(of, qmc_id_table); + +static struct platform_driver qmc_driver = { + .driver = { + .name = "fsl-qmc", + .of_match_table = of_match_ptr(qmc_id_table), + }, + .probe = qmc_probe, + .remove = qmc_remove, +}; +module_platform_driver(qmc_driver); + +struct qmc_chan *qmc_chan_get_byphandle(struct device_node *np, const char *phandle_name) +{ + struct of_phandle_args out_args; + struct platform_device *pdev; + struct qmc_chan *qmc_chan; + struct qmc *qmc; + int ret; + + ret = of_parse_phandle_with_fixed_args(np, phandle_name, 1, 0, + &out_args); + if (ret < 0) + return ERR_PTR(ret); + + if (!of_match_node(qmc_driver.driver.of_match_table, out_args.np)) { + of_node_put(out_args.np); + return ERR_PTR(-EINVAL); + } + + pdev = of_find_device_by_node(out_args.np); + of_node_put(out_args.np); + if (!pdev) + return ERR_PTR(-ENODEV); + + qmc = platform_get_drvdata(pdev); + if (!qmc) { + platform_device_put(pdev); + return ERR_PTR(-EPROBE_DEFER); + } + + if (out_args.args_count != 1) { + platform_device_put(pdev); + return ERR_PTR(-EINVAL); + } + + if (out_args.args[0] >= ARRAY_SIZE(qmc->chans)) { + platform_device_put(pdev); + return ERR_PTR(-EINVAL); + } + + qmc_chan = qmc->chans[out_args.args[0]]; + if (!qmc_chan) { + platform_device_put(pdev); + return ERR_PTR(-ENOENT); + } + + return qmc_chan; +} +EXPORT_SYMBOL(qmc_chan_get_byphandle); + +void qmc_chan_put(struct qmc_chan *chan) +{ + put_device(chan->qmc->dev); +} +EXPORT_SYMBOL(qmc_chan_put); + +static void devm_qmc_chan_release(struct device *dev, void *res) +{ + struct qmc_chan **qmc_chan = res; + + qmc_chan_put(*qmc_chan); +} + +struct qmc_chan *devm_qmc_chan_get_byphandle(struct device *dev, + struct device_node *np, + const char *phandle_name) +{ + struct qmc_chan *qmc_chan; + struct qmc_chan **dr; + + dr = devres_alloc(devm_qmc_chan_release, sizeof(*dr), GFP_KERNEL); + if (!dr) + return ERR_PTR(-ENOMEM); + + qmc_chan = qmc_chan_get_byphandle(np, phandle_name); + if (!IS_ERR(qmc_chan)) { + *dr = qmc_chan; + devres_add(dev, dr); + } else { + devres_free(dr); + } + + return qmc_chan; +} +EXPORT_SYMBOL(devm_qmc_chan_get_byphandle); + +MODULE_AUTHOR("Herve Codina "); +MODULE_DESCRIPTION("CPM QMC driver"); +MODULE_LICENSE("GPL"); diff --git a/include/soc/fsl/qe/qmc.h b/include/soc/fsl/qe/qmc.h new file mode 100644 index 000000000000..3c61a50d2ae2 --- /dev/null +++ b/include/soc/fsl/qe/qmc.h @@ -0,0 +1,71 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * QMC management + * + * Copyright 2022 CS GROUP France + * + * Author: Herve Codina + */ +#ifndef __SOC_FSL_QMC_H__ +#define __SOC_FSL_QMC_H__ + +#include + +struct device_node; +struct device; +struct qmc_chan; + +struct qmc_chan *qmc_chan_get_byphandle(struct device_node *np, const char *phandle_name); +void qmc_chan_put(struct qmc_chan *chan); +struct qmc_chan *devm_qmc_chan_get_byphandle(struct device *dev, struct device_node *np, + const char *phandle_name); + +enum qmc_mode { + QMC_TRANSPARENT, + QMC_HDLC, +}; + +struct qmc_chan_info { + enum qmc_mode mode; + unsigned long rx_fs_rate; + unsigned long rx_bit_rate; + u8 nb_rx_ts; + unsigned long tx_fs_rate; + unsigned long tx_bit_rate; + u8 nb_tx_ts; +}; + +int qmc_chan_get_info(struct qmc_chan *chan, struct qmc_chan_info *info); + +struct qmc_chan_param { + enum qmc_mode mode; + union { + struct { + u16 max_rx_buf_size; + u16 max_rx_frame_size; + bool is_crc32; + } hdlc; + struct { + u16 max_rx_buf_size; + } transp; + }; +}; + +int qmc_chan_set_param(struct qmc_chan *chan, const struct qmc_chan_param *param); + +int qmc_chan_write_submit(struct qmc_chan *chan, dma_addr_t addr, size_t length, + void (*complete)(void *context), void *context); + +int qmc_chan_read_submit(struct qmc_chan *chan, dma_addr_t addr, size_t length, + void (*complete)(void *context, size_t length), + void *context); + +#define QMC_CHAN_READ (1<<0) +#define QMC_CHAN_WRITE (1<<1) +#define QMC_CHAN_ALL (QMC_CHAN_READ | QMC_CHAN_WRITE) + +int qmc_chan_start(struct qmc_chan *chan, int direction); +int qmc_chan_stop(struct qmc_chan *chan, int direction); +int qmc_chan_reset(struct qmc_chan *chan, int direction); + +#endif /* __SOC_FSL_QMC_H__ */ From db12f7bbbb22d06ba9f65dc607d230f636e4a22a Mon Sep 17 00:00:00 2001 From: Herve Codina Date: Fri, 17 Feb 2023 15:56:42 +0100 Subject: [PATCH 096/778] MAINTAINERS: add the Freescale QMC controller entry After contributing the driver, add myself as the maintainer for the Freescale QMC controller. Signed-off-by: Herve Codina Reviewed-by: Christophe Leroy Link: https://lore.kernel.org/r/20230217145645.1768659-8-herve.codina@bootlin.com Signed-off-by: Mark Brown --- MAINTAINERS | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index fea9ee7ade8e..5597d402fbd8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8247,6 +8247,14 @@ S: Maintained F: drivers/soc/fsl/qe/ F: include/soc/fsl/qe/ +FREESCALE QUICC ENGINE QMC DRIVER +M: Herve Codina +L: linuxppc-dev@lists.ozlabs.org +S: Maintained +F: Documentation/devicetree/bindings/soc/fsl/cpm_qe/fsl,cpm1-scc-qmc.yaml +F: drivers/soc/fsl/qe/qmc.c +F: include/soc/fsl/qe/qmc.h + FREESCALE QUICC ENGINE TSA DRIVER M: Herve Codina L: linuxppc-dev@lists.ozlabs.org From f72ebecd8008e1ccf2e85da9791339e572cc9333 Mon Sep 17 00:00:00 2001 From: Herve Codina Date: Fri, 17 Feb 2023 15:56:43 +0100 Subject: [PATCH 097/778] dt-bindings: sound: Add support for QMC audio The QMC (QUICC mutichannel controller) is a controller present in some PowerQUICC SoC such as MPC885. The QMC audio is an ASoC component that uses the QMC controller to transfer the audio data. Signed-off-by: Herve Codina Reviewed-by: Krzysztof Kozlowski Reviewed-by: Christophe Leroy Link: https://lore.kernel.org/r/20230217145645.1768659-9-herve.codina@bootlin.com Signed-off-by: Mark Brown --- .../bindings/sound/fsl,qmc-audio.yaml | 117 ++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/fsl,qmc-audio.yaml diff --git a/Documentation/devicetree/bindings/sound/fsl,qmc-audio.yaml b/Documentation/devicetree/bindings/sound/fsl,qmc-audio.yaml new file mode 100644 index 000000000000..ff5cd9241941 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/fsl,qmc-audio.yaml @@ -0,0 +1,117 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/fsl,qmc-audio.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: QMC audio + +maintainers: + - Herve Codina + +description: | + The QMC audio is an ASoC component which uses QMC (QUICC Multichannel + Controller) channels to transfer the audio data. + It provides as many DAI as the number of QMC channel used. + +allOf: + - $ref: dai-common.yaml# + +properties: + compatible: + const: fsl,qmc-audio + + '#address-cells': + const: 1 + '#size-cells': + const: 0 + '#sound-dai-cells': + const: 1 + +patternProperties: + '^dai@([0-9]|[1-5][0-9]|6[0-3])$': + description: + A DAI managed by this controller + type: object + + properties: + reg: + minimum: 0 + maximum: 63 + description: + The DAI number + + fsl,qmc-chan: + $ref: /schemas/types.yaml#/definitions/phandle-array + items: + - items: + - description: phandle to QMC node + - description: Channel number + description: + Should be a phandle/number pair. The phandle to QMC node and the QMC + channel to use for this DAI. + + required: + - reg + - fsl,qmc-chan + +required: + - compatible + - '#address-cells' + - '#size-cells' + - '#sound-dai-cells' + +additionalProperties: false + +examples: + - | + audio_controller: audio-controller { + compatible = "fsl,qmc-audio"; + #address-cells = <1>; + #size-cells = <0>; + #sound-dai-cells = <1>; + dai@16 { + reg = <16>; + fsl,qmc-chan = <&qmc 16>; + }; + dai@17 { + reg = <17>; + fsl,qmc-chan = <&qmc 17>; + }; + }; + + sound { + compatible = "simple-audio-card"; + #address-cells = <1>; + #size-cells = <0>; + simple-audio-card,dai-link@0 { + reg = <0>; + format = "dsp_b"; + cpu { + sound-dai = <&audio_controller 16>; + }; + codec { + sound-dai = <&codec1>; + dai-tdm-slot-num = <4>; + dai-tdm-slot-width = <8>; + /* TS 3, 5, 7, 9 */ + dai-tdm-slot-tx-mask = <0 0 0 1 0 1 0 1 0 1>; + dai-tdm-slot-rx-mask = <0 0 0 1 0 1 0 1 0 1>; + }; + }; + simple-audio-card,dai-link@1 { + reg = <1>; + format = "dsp_b"; + cpu { + sound-dai = <&audio_controller 17>; + }; + codec { + sound-dai = <&codec2>; + dai-tdm-slot-num = <4>; + dai-tdm-slot-width = <8>; + /* TS 2, 4, 6, 8 */ + dai-tdm-slot-tx-mask = <0 0 1 0 1 0 1 0 1>; + dai-tdm-slot-rx-mask = <0 0 1 0 1 0 1 0 1>; + }; + }; + }; From 075c7125b11c72e7933401d73000d6d151196072 Mon Sep 17 00:00:00 2001 From: Herve Codina Date: Fri, 17 Feb 2023 15:56:44 +0100 Subject: [PATCH 098/778] ASoC: fsl: Add support for QMC audio The QMC audio is an ASoC component which provides DAIs that use the QMC (QUICC Multichannel Controller) to transfer the audio data. It provides as many DAIs as the number of QMC channels it references. Signed-off-by: Herve Codina Reviewed-by: Christophe Leroy Tested-by: Christophe Leroy Link: https://lore.kernel.org/r/20230217145645.1768659-10-herve.codina@bootlin.com Signed-off-by: Mark Brown --- sound/soc/fsl/Kconfig | 9 + sound/soc/fsl/Makefile | 2 + sound/soc/fsl/fsl_qmc_audio.c | 735 ++++++++++++++++++++++++++++++++++ 3 files changed, 746 insertions(+) create mode 100644 sound/soc/fsl/fsl_qmc_audio.c diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 614eceda6b9e..17db29c25d96 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -172,6 +172,15 @@ config SND_MPC52xx_DMA config SND_SOC_POWERPC_DMA tristate +config SND_SOC_POWERPC_QMC_AUDIO + tristate "QMC ALSA SoC support" + depends on CPM_QMC + help + ALSA SoC Audio support using the Freescale QUICC Multichannel + Controller (QMC). + Say Y or M if you want to add support for SoC audio using Freescale + QMC. + comment "SoC Audio support for Freescale PPC boards:" config SND_SOC_MPC8610_HPCD diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile index b54beb1a66fa..8db7e97d0bd5 100644 --- a/sound/soc/fsl/Makefile +++ b/sound/soc/fsl/Makefile @@ -28,6 +28,7 @@ snd-soc-fsl-easrc-objs := fsl_easrc.o snd-soc-fsl-xcvr-objs := fsl_xcvr.o snd-soc-fsl-aud2htx-objs := fsl_aud2htx.o snd-soc-fsl-rpmsg-objs := fsl_rpmsg.o +snd-soc-fsl-qmc-audio-objs := fsl_qmc_audio.o obj-$(CONFIG_SND_SOC_FSL_AUDMIX) += snd-soc-fsl-audmix.o obj-$(CONFIG_SND_SOC_FSL_ASOC_CARD) += snd-soc-fsl-asoc-card.o @@ -44,6 +45,7 @@ obj-$(CONFIG_SND_SOC_POWERPC_DMA) += snd-soc-fsl-dma.o obj-$(CONFIG_SND_SOC_FSL_XCVR) += snd-soc-fsl-xcvr.o obj-$(CONFIG_SND_SOC_FSL_AUD2HTX) += snd-soc-fsl-aud2htx.o obj-$(CONFIG_SND_SOC_FSL_RPMSG) += snd-soc-fsl-rpmsg.o +obj-$(CONFIG_SND_SOC_POWERPC_QMC_AUDIO) += snd-soc-fsl-qmc-audio.o # MPC5200 Platform Support obj-$(CONFIG_SND_MPC52xx_DMA) += mpc5200_dma.o diff --git a/sound/soc/fsl/fsl_qmc_audio.c b/sound/soc/fsl/fsl_qmc_audio.c new file mode 100644 index 000000000000..7cbb8e4758cc --- /dev/null +++ b/sound/soc/fsl/fsl_qmc_audio.c @@ -0,0 +1,735 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ALSA SoC using the QUICC Multichannel Controller (QMC) + * + * Copyright 2022 CS GROUP France + * + * Author: Herve Codina + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct qmc_dai { + char *name; + int id; + struct device *dev; + struct qmc_chan *qmc_chan; + unsigned int nb_tx_ts; + unsigned int nb_rx_ts; +}; + +struct qmc_audio { + struct device *dev; + unsigned int num_dais; + struct qmc_dai *dais; + struct snd_soc_dai_driver *dai_drivers; +}; + +struct qmc_dai_prtd { + struct qmc_dai *qmc_dai; + dma_addr_t dma_buffer_start; + dma_addr_t period_ptr_submitted; + dma_addr_t period_ptr_ended; + dma_addr_t dma_buffer_end; + size_t period_size; + struct snd_pcm_substream *substream; +}; + +static int qmc_audio_pcm_construct(struct snd_soc_component *component, + struct snd_soc_pcm_runtime *rtd) +{ + struct snd_card *card = rtd->card->snd_card; + int ret; + + ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32)); + if (ret) + return ret; + + snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, card->dev, + 64*1024, 64*1024); + return 0; +} + +static int qmc_audio_pcm_hw_params(struct snd_soc_component *component, + struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct qmc_dai_prtd *prtd = substream->runtime->private_data; + + prtd->dma_buffer_start = runtime->dma_addr; + prtd->dma_buffer_end = runtime->dma_addr + params_buffer_bytes(params); + prtd->period_size = params_period_bytes(params); + prtd->period_ptr_submitted = prtd->dma_buffer_start; + prtd->period_ptr_ended = prtd->dma_buffer_start; + prtd->substream = substream; + + return 0; +} + +static void qmc_audio_pcm_write_complete(void *context) +{ + struct qmc_dai_prtd *prtd = context; + int ret; + + prtd->period_ptr_ended += prtd->period_size; + if (prtd->period_ptr_ended >= prtd->dma_buffer_end) + prtd->period_ptr_ended = prtd->dma_buffer_start; + + prtd->period_ptr_submitted += prtd->period_size; + if (prtd->period_ptr_submitted >= prtd->dma_buffer_end) + prtd->period_ptr_submitted = prtd->dma_buffer_start; + + ret = qmc_chan_write_submit(prtd->qmc_dai->qmc_chan, + prtd->period_ptr_submitted, prtd->period_size, + qmc_audio_pcm_write_complete, prtd); + if (ret) { + dev_err(prtd->qmc_dai->dev, "write_submit failed %d\n", + ret); + } + + snd_pcm_period_elapsed(prtd->substream); +} + +static void qmc_audio_pcm_read_complete(void *context, size_t length) +{ + struct qmc_dai_prtd *prtd = context; + int ret; + + if (length != prtd->period_size) { + dev_err(prtd->qmc_dai->dev, "read complete length = %zu, exp %zu\n", + length, prtd->period_size); + } + + prtd->period_ptr_ended += prtd->period_size; + if (prtd->period_ptr_ended >= prtd->dma_buffer_end) + prtd->period_ptr_ended = prtd->dma_buffer_start; + + prtd->period_ptr_submitted += prtd->period_size; + if (prtd->period_ptr_submitted >= prtd->dma_buffer_end) + prtd->period_ptr_submitted = prtd->dma_buffer_start; + + ret = qmc_chan_read_submit(prtd->qmc_dai->qmc_chan, + prtd->period_ptr_submitted, prtd->period_size, + qmc_audio_pcm_read_complete, prtd); + if (ret) { + dev_err(prtd->qmc_dai->dev, "read_submit failed %d\n", + ret); + } + + snd_pcm_period_elapsed(prtd->substream); +} + +static int qmc_audio_pcm_trigger(struct snd_soc_component *component, + struct snd_pcm_substream *substream, int cmd) +{ + struct qmc_dai_prtd *prtd = substream->runtime->private_data; + int ret; + + if (!prtd->qmc_dai) { + dev_err(component->dev, "qmc_dai is not set\n"); + return -EINVAL; + } + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + /* Submit first chunk ... */ + ret = qmc_chan_write_submit(prtd->qmc_dai->qmc_chan, + prtd->period_ptr_submitted, prtd->period_size, + qmc_audio_pcm_write_complete, prtd); + if (ret) { + dev_err(component->dev, "write_submit failed %d\n", + ret); + return ret; + } + + /* ... prepare next one ... */ + prtd->period_ptr_submitted += prtd->period_size; + if (prtd->period_ptr_submitted >= prtd->dma_buffer_end) + prtd->period_ptr_submitted = prtd->dma_buffer_start; + + /* ... and send it */ + ret = qmc_chan_write_submit(prtd->qmc_dai->qmc_chan, + prtd->period_ptr_submitted, prtd->period_size, + qmc_audio_pcm_write_complete, prtd); + if (ret) { + dev_err(component->dev, "write_submit failed %d\n", + ret); + return ret; + } + } else { + /* Submit first chunk ... */ + ret = qmc_chan_read_submit(prtd->qmc_dai->qmc_chan, + prtd->period_ptr_submitted, prtd->period_size, + qmc_audio_pcm_read_complete, prtd); + if (ret) { + dev_err(component->dev, "read_submit failed %d\n", + ret); + return ret; + } + + /* ... prepare next one ... */ + prtd->period_ptr_submitted += prtd->period_size; + if (prtd->period_ptr_submitted >= prtd->dma_buffer_end) + prtd->period_ptr_submitted = prtd->dma_buffer_start; + + /* ... and send it */ + ret = qmc_chan_read_submit(prtd->qmc_dai->qmc_chan, + prtd->period_ptr_submitted, prtd->period_size, + qmc_audio_pcm_read_complete, prtd); + if (ret) { + dev_err(component->dev, "write_submit failed %d\n", + ret); + return ret; + } + } + break; + + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + break; + + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + break; + + default: + return -EINVAL; + } + + return 0; +} + +static snd_pcm_uframes_t qmc_audio_pcm_pointer(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct qmc_dai_prtd *prtd = substream->runtime->private_data; + + return bytes_to_frames(substream->runtime, + prtd->period_ptr_ended - prtd->dma_buffer_start); +} + +static int qmc_audio_of_xlate_dai_name(struct snd_soc_component *component, + const struct of_phandle_args *args, + const char **dai_name) +{ + struct qmc_audio *qmc_audio = dev_get_drvdata(component->dev); + struct snd_soc_dai_driver *dai_driver; + int id = args->args[0]; + int i; + + for (i = 0; i < qmc_audio->num_dais; i++) { + dai_driver = qmc_audio->dai_drivers + i; + if (dai_driver->id == id) { + *dai_name = dai_driver->name; + return 0; + } + } + + return -EINVAL; +} + +static const struct snd_pcm_hardware qmc_audio_pcm_hardware = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_PAUSE, + .period_bytes_min = 32, + .period_bytes_max = 64*1024, + .periods_min = 2, + .periods_max = 2*1024, + .buffer_bytes_max = 64*1024, +}; + +static int qmc_audio_pcm_open(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct qmc_dai_prtd *prtd; + int ret; + + snd_soc_set_runtime_hwparams(substream, &qmc_audio_pcm_hardware); + + /* ensure that buffer size is a multiple of period size */ + ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); + if (ret < 0) + return ret; + + prtd = kzalloc(sizeof(*prtd), GFP_KERNEL); + if (prtd == NULL) + return -ENOMEM; + + runtime->private_data = prtd; + + return 0; +} + +static int qmc_audio_pcm_close(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct qmc_dai_prtd *prtd = substream->runtime->private_data; + + kfree(prtd); + return 0; +} + +static const struct snd_soc_component_driver qmc_audio_soc_platform = { + .open = qmc_audio_pcm_open, + .close = qmc_audio_pcm_close, + .hw_params = qmc_audio_pcm_hw_params, + .trigger = qmc_audio_pcm_trigger, + .pointer = qmc_audio_pcm_pointer, + .pcm_construct = qmc_audio_pcm_construct, + .of_xlate_dai_name = qmc_audio_of_xlate_dai_name, +}; + +static unsigned int qmc_dai_get_index(struct snd_soc_dai *dai) +{ + struct qmc_audio *qmc_audio = snd_soc_dai_get_drvdata(dai); + + return dai->driver - qmc_audio->dai_drivers; +} + +static struct qmc_dai *qmc_dai_get_data(struct snd_soc_dai *dai) +{ + struct qmc_audio *qmc_audio = snd_soc_dai_get_drvdata(dai); + unsigned int index; + + index = qmc_dai_get_index(dai); + if (index > qmc_audio->num_dais) + return NULL; + + return qmc_audio->dais + index; +} + +/* + * The constraints for format/channel is to match with the number of 8bit + * time-slots available. + */ +static int qmc_dai_hw_rule_channels_by_format(struct qmc_dai *qmc_dai, + struct snd_pcm_hw_params *params, + unsigned int nb_ts) +{ + struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); + snd_pcm_format_t format = params_format(params); + struct snd_interval ch = {0}; + + switch (snd_pcm_format_physical_width(format)) { + case 8: + ch.max = nb_ts; + break; + case 16: + ch.max = nb_ts/2; + break; + case 32: + ch.max = nb_ts/4; + break; + case 64: + ch.max = nb_ts/8; + break; + default: + dev_err(qmc_dai->dev, "format physical width %u not supported\n", + snd_pcm_format_physical_width(format)); + return -EINVAL; + } + + ch.min = ch.max ? 1 : 0; + + return snd_interval_refine(c, &ch); +} + +static int qmc_dai_hw_rule_playback_channels_by_format(struct snd_pcm_hw_params *params, + struct snd_pcm_hw_rule *rule) +{ + struct qmc_dai *qmc_dai = rule->private; + + return qmc_dai_hw_rule_channels_by_format(qmc_dai, params, qmc_dai->nb_tx_ts); +} + +static int qmc_dai_hw_rule_capture_channels_by_format( + struct snd_pcm_hw_params *params, + struct snd_pcm_hw_rule *rule) +{ + struct qmc_dai *qmc_dai = rule->private; + + return qmc_dai_hw_rule_channels_by_format(qmc_dai, params, qmc_dai->nb_rx_ts); +} + +static int qmc_dai_hw_rule_format_by_channels(struct qmc_dai *qmc_dai, + struct snd_pcm_hw_params *params, + unsigned int nb_ts) +{ + struct snd_mask *f_old = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); + unsigned int channels = params_channels(params); + unsigned int slot_width; + struct snd_mask f_new; + unsigned int i; + + if (!channels || channels > nb_ts) { + dev_err(qmc_dai->dev, "channels %u not supported\n", + nb_ts); + return -EINVAL; + } + + slot_width = (nb_ts / channels) * 8; + + snd_mask_none(&f_new); + for (i = 0; i <= SNDRV_PCM_FORMAT_LAST; i++) { + if (snd_mask_test(f_old, i)) { + if (snd_pcm_format_physical_width(i) <= slot_width) + snd_mask_set(&f_new, i); + } + } + + return snd_mask_refine(f_old, &f_new); +} + +static int qmc_dai_hw_rule_playback_format_by_channels( + struct snd_pcm_hw_params *params, + struct snd_pcm_hw_rule *rule) +{ + struct qmc_dai *qmc_dai = rule->private; + + return qmc_dai_hw_rule_format_by_channels(qmc_dai, params, qmc_dai->nb_tx_ts); +} + +static int qmc_dai_hw_rule_capture_format_by_channels( + struct snd_pcm_hw_params *params, + struct snd_pcm_hw_rule *rule) +{ + struct qmc_dai *qmc_dai = rule->private; + + return qmc_dai_hw_rule_format_by_channels(qmc_dai, params, qmc_dai->nb_rx_ts); +} + +static int qmc_dai_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct qmc_dai_prtd *prtd = substream->runtime->private_data; + snd_pcm_hw_rule_func_t hw_rule_channels_by_format; + snd_pcm_hw_rule_func_t hw_rule_format_by_channels; + struct qmc_dai *qmc_dai; + unsigned int frame_bits; + int ret; + + qmc_dai = qmc_dai_get_data(dai); + if (!qmc_dai) { + dev_err(dai->dev, "Invalid dai\n"); + return -EINVAL; + } + + prtd->qmc_dai = qmc_dai; + + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { + hw_rule_channels_by_format = qmc_dai_hw_rule_capture_channels_by_format; + hw_rule_format_by_channels = qmc_dai_hw_rule_capture_format_by_channels; + frame_bits = qmc_dai->nb_rx_ts * 8; + } else { + hw_rule_channels_by_format = qmc_dai_hw_rule_playback_channels_by_format; + hw_rule_format_by_channels = qmc_dai_hw_rule_playback_format_by_channels; + frame_bits = qmc_dai->nb_tx_ts * 8; + } + + ret = snd_pcm_hw_rule_add(substream->runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, + hw_rule_channels_by_format, qmc_dai, + SNDRV_PCM_HW_PARAM_FORMAT, -1); + if (ret) { + dev_err(dai->dev, "Failed to add channels rule (%d)\n", ret); + return ret; + } + + ret = snd_pcm_hw_rule_add(substream->runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT, + hw_rule_format_by_channels, qmc_dai, + SNDRV_PCM_HW_PARAM_CHANNELS, -1); + if (ret) { + dev_err(dai->dev, "Failed to add format rule (%d)\n", ret); + return ret; + } + + ret = snd_pcm_hw_constraint_single(substream->runtime, + SNDRV_PCM_HW_PARAM_FRAME_BITS, + frame_bits); + if (ret < 0) { + dev_err(dai->dev, "Failed to add frame_bits constraint (%d)\n", ret); + return ret; + } + + return 0; +} + +static int qmc_dai_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct qmc_chan_param chan_param = {0}; + struct qmc_dai *qmc_dai; + int ret; + + qmc_dai = qmc_dai_get_data(dai); + if (!qmc_dai) { + dev_err(dai->dev, "Invalid dai\n"); + return -EINVAL; + } + + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { + chan_param.mode = QMC_TRANSPARENT; + chan_param.transp.max_rx_buf_size = params_period_bytes(params); + ret = qmc_chan_set_param(qmc_dai->qmc_chan, &chan_param); + if (ret) { + dev_err(dai->dev, "set param failed %d\n", + ret); + return ret; + } + } + + return 0; +} + +static int qmc_dai_trigger(struct snd_pcm_substream *substream, int cmd, + struct snd_soc_dai *dai) +{ + struct qmc_dai *qmc_dai; + int direction; + int ret; + + qmc_dai = qmc_dai_get_data(dai); + if (!qmc_dai) { + dev_err(dai->dev, "Invalid dai\n"); + return -EINVAL; + } + + direction = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? + QMC_CHAN_WRITE : QMC_CHAN_READ; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + ret = qmc_chan_start(qmc_dai->qmc_chan, direction); + if (ret) + return ret; + break; + + case SNDRV_PCM_TRIGGER_STOP: + ret = qmc_chan_stop(qmc_dai->qmc_chan, direction); + if (ret) + return ret; + ret = qmc_chan_reset(qmc_dai->qmc_chan, direction); + if (ret) + return ret; + break; + + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + ret = qmc_chan_stop(qmc_dai->qmc_chan, direction); + if (ret) + return ret; + break; + + default: + return -EINVAL; + } + + return 0; +} + +static const struct snd_soc_dai_ops qmc_dai_ops = { + .startup = qmc_dai_startup, + .trigger = qmc_dai_trigger, + .hw_params = qmc_dai_hw_params, +}; + +static u64 qmc_audio_formats(u8 nb_ts) +{ + u64 formats; + unsigned int chan_width; + unsigned int format_width; + int i; + + if (!nb_ts) + return 0; + + formats = 0; + chan_width = nb_ts * 8; + for (i = 0; i <= SNDRV_PCM_FORMAT_LAST; i++) { + /* + * Support format other than little-endian (ie big-endian or + * without endianness such as 8bit formats) + */ + if (snd_pcm_format_little_endian(i) == 1) + continue; + + /* Support physical width multiple of 8bit */ + format_width = snd_pcm_format_physical_width(i); + if (format_width == 0 || format_width % 8) + continue; + + /* + * And support physical width that can fit N times in the + * channel + */ + if (format_width > chan_width || chan_width % format_width) + continue; + + formats |= (1ULL << i); + } + return formats; +} + +static int qmc_audio_dai_parse(struct qmc_audio *qmc_audio, struct device_node *np, + struct qmc_dai *qmc_dai, struct snd_soc_dai_driver *qmc_soc_dai_driver) +{ + struct qmc_chan_info info; + u32 val; + int ret; + + qmc_dai->dev = qmc_audio->dev; + + ret = of_property_read_u32(np, "reg", &val); + if (ret) { + dev_err(qmc_audio->dev, "%pOF: failed to read reg\n", np); + return ret; + } + qmc_dai->id = val; + + qmc_dai->name = devm_kasprintf(qmc_audio->dev, GFP_KERNEL, "%s.%d", + np->parent->name, qmc_dai->id); + + qmc_dai->qmc_chan = devm_qmc_chan_get_byphandle(qmc_audio->dev, np, + "fsl,qmc-chan"); + if (IS_ERR(qmc_dai->qmc_chan)) { + ret = PTR_ERR(qmc_dai->qmc_chan); + return dev_err_probe(qmc_audio->dev, ret, + "dai %d get QMC channel failed\n", qmc_dai->id); + } + + qmc_soc_dai_driver->id = qmc_dai->id; + qmc_soc_dai_driver->name = qmc_dai->name; + + ret = qmc_chan_get_info(qmc_dai->qmc_chan, &info); + if (ret) { + dev_err(qmc_audio->dev, "dai %d get QMC channel info failed %d\n", + qmc_dai->id, ret); + return ret; + } + dev_info(qmc_audio->dev, "dai %d QMC channel mode %d, nb_tx_ts %u, nb_rx_ts %u\n", + qmc_dai->id, info.mode, info.nb_tx_ts, info.nb_rx_ts); + + if (info.mode != QMC_TRANSPARENT) { + dev_err(qmc_audio->dev, "dai %d QMC chan mode %d is not QMC_TRANSPARENT\n", + qmc_dai->id, info.mode); + return -EINVAL; + } + qmc_dai->nb_tx_ts = info.nb_tx_ts; + qmc_dai->nb_rx_ts = info.nb_rx_ts; + + qmc_soc_dai_driver->playback.channels_min = 0; + qmc_soc_dai_driver->playback.channels_max = 0; + if (qmc_dai->nb_tx_ts) { + qmc_soc_dai_driver->playback.channels_min = 1; + qmc_soc_dai_driver->playback.channels_max = qmc_dai->nb_tx_ts; + } + qmc_soc_dai_driver->playback.formats = qmc_audio_formats(qmc_dai->nb_tx_ts); + + qmc_soc_dai_driver->capture.channels_min = 0; + qmc_soc_dai_driver->capture.channels_max = 0; + if (qmc_dai->nb_rx_ts) { + qmc_soc_dai_driver->capture.channels_min = 1; + qmc_soc_dai_driver->capture.channels_max = qmc_dai->nb_rx_ts; + } + qmc_soc_dai_driver->capture.formats = qmc_audio_formats(qmc_dai->nb_rx_ts); + + qmc_soc_dai_driver->playback.rates = snd_pcm_rate_to_rate_bit(info.tx_fs_rate); + qmc_soc_dai_driver->playback.rate_min = info.tx_fs_rate; + qmc_soc_dai_driver->playback.rate_max = info.tx_fs_rate; + qmc_soc_dai_driver->capture.rates = snd_pcm_rate_to_rate_bit(info.rx_fs_rate); + qmc_soc_dai_driver->capture.rate_min = info.rx_fs_rate; + qmc_soc_dai_driver->capture.rate_max = info.rx_fs_rate; + + qmc_soc_dai_driver->ops = &qmc_dai_ops; + + return 0; +} + +static int qmc_audio_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct qmc_audio *qmc_audio; + struct device_node *child; + unsigned int i; + int ret; + + qmc_audio = devm_kzalloc(&pdev->dev, sizeof(*qmc_audio), GFP_KERNEL); + if (!qmc_audio) + return -ENOMEM; + + qmc_audio->dev = &pdev->dev; + + qmc_audio->num_dais = of_get_available_child_count(np); + if (qmc_audio->num_dais) { + qmc_audio->dais = devm_kcalloc(&pdev->dev, qmc_audio->num_dais, + sizeof(*qmc_audio->dais), + GFP_KERNEL); + if (!qmc_audio->dais) + return -ENOMEM; + + qmc_audio->dai_drivers = devm_kcalloc(&pdev->dev, qmc_audio->num_dais, + sizeof(*qmc_audio->dai_drivers), + GFP_KERNEL); + if (!qmc_audio->dai_drivers) + return -ENOMEM; + } + + i = 0; + for_each_available_child_of_node(np, child) { + ret = qmc_audio_dai_parse(qmc_audio, child, + qmc_audio->dais + i, + qmc_audio->dai_drivers + i); + if (ret) { + of_node_put(child); + return ret; + } + i++; + } + + + platform_set_drvdata(pdev, qmc_audio); + + ret = devm_snd_soc_register_component(qmc_audio->dev, + &qmc_audio_soc_platform, + qmc_audio->dai_drivers, + qmc_audio->num_dais); + if (ret) + return ret; + + return 0; +} + +static const struct of_device_id qmc_audio_id_table[] = { + { .compatible = "fsl,qmc-audio" }, + {} /* sentinel */ +}; +MODULE_DEVICE_TABLE(of, qmc_audio_id_table); + +static struct platform_driver qmc_audio_driver = { + .driver = { + .name = "fsl-qmc-audio", + .of_match_table = of_match_ptr(qmc_audio_id_table), + }, + .probe = qmc_audio_probe, +}; +module_platform_driver(qmc_audio_driver); + +MODULE_AUTHOR("Herve Codina "); +MODULE_DESCRIPTION("CPM/QE QMC audio driver"); +MODULE_LICENSE("GPL"); From eb7ff1cbe7494e7f67e33afdab37361081882ca2 Mon Sep 17 00:00:00 2001 From: Herve Codina Date: Fri, 17 Feb 2023 15:56:45 +0100 Subject: [PATCH 099/778] MAINTAINERS: add the Freescale QMC audio entry After contributing the component, add myself as the maintainer for the Freescale QMC audio ASoC component. Signed-off-by: Herve Codina Reviewed-by: Christophe Leroy Link: https://lore.kernel.org/r/20230217145645.1768659-11-herve.codina@bootlin.com Signed-off-by: Mark Brown --- MAINTAINERS | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 5597d402fbd8..a6e6b70cf8bd 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8315,6 +8315,14 @@ F: sound/soc/fsl/fsl* F: sound/soc/fsl/imx* F: sound/soc/fsl/mpc8610_hpcd.c +FREESCALE SOC SOUND QMC DRIVER +M: Herve Codina +L: alsa-devel@alsa-project.org (moderated for non-subscribers) +L: linuxppc-dev@lists.ozlabs.org +S: Maintained +F: Documentation/devicetree/bindings/sound/fsl,qmc-audio.yaml +F: sound/soc/fsl/fsl_qmc_audio.c + FREESCALE USB PERIPHERAL DRIVERS M: Li Yang L: linux-usb@vger.kernel.org From 00d612909e12827f77891a0bd7802855fae330da Mon Sep 17 00:00:00 2001 From: Lucas Tanure Date: Fri, 17 Feb 2023 11:08:42 +0000 Subject: [PATCH 100/778] ASoC: amd: vangogh: Remove unnecessary init function Remove empty acp5x_cs35l41_init function Signed-off-by: Lucas Tanure Link: https://lore.kernel.org/r/20230217110850.1045250-2-lucas.tanure@collabora.com Signed-off-by: Mark Brown --- sound/soc/amd/vangogh/acp5x-mach.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/sound/soc/amd/vangogh/acp5x-mach.c b/sound/soc/amd/vangogh/acp5x-mach.c index eebf2650ad27..5bd9418919a0 100644 --- a/sound/soc/amd/vangogh/acp5x-mach.c +++ b/sound/soc/amd/vangogh/acp5x-mach.c @@ -73,11 +73,6 @@ static int acp5x_8821_init(struct snd_soc_pcm_runtime *rtd) return ret; } -static int acp5x_cs35l41_init(struct snd_soc_pcm_runtime *rtd) -{ - return 0; -} - static const unsigned int rates[] = { 48000, }; @@ -258,7 +253,6 @@ static struct snd_soc_dai_link acp5x_dai[] = { .dpcm_playback = 1, .playback_only = 1, .ops = &acp5x_cs35l41_play_ops, - .init = acp5x_cs35l41_init, SND_SOC_DAILINK_REG(acp5x_bt, cs35l41, platform), }, }; From ddd42a12a33eb4d6e9f90a75c50e5044c83b99cf Mon Sep 17 00:00:00 2001 From: Lucas Tanure Date: Fri, 17 Feb 2023 11:08:43 +0000 Subject: [PATCH 101/778] ASoC: amd: vangogh: Small code refactor Small refactor of the code: - sort includes in alphabetical order - sort variables declarations by line length - remove unnecessary "struct snd_soc_card *card" lines - insert blank lines before return - break/unbreak some lines for better read - align defines Signed-off-by: Lucas Tanure Link: https://lore.kernel.org/r/20230217110850.1045250-3-lucas.tanure@collabora.com Signed-off-by: Mark Brown --- sound/soc/amd/vangogh/acp5x-mach.c | 145 +++++++++++++---------------- 1 file changed, 64 insertions(+), 81 deletions(-) diff --git a/sound/soc/amd/vangogh/acp5x-mach.c b/sound/soc/amd/vangogh/acp5x-mach.c index 5bd9418919a0..f914f6327cda 100644 --- a/sound/soc/amd/vangogh/acp5x-mach.c +++ b/sound/soc/amd/vangogh/acp5x-mach.c @@ -5,34 +5,31 @@ * * Copyright 2021 Advanced Micro Devices, Inc. */ - -#include -#include -#include -#include -#include -#include - -#include +#include #include +#include #include #include +#include #include #include -#include -#include +#include +#include +#include +#include +#include +#include #include "../../codecs/nau8821.h" #include "../../codecs/cs35l41.h" - #include "acp5x.h" -#define DRV_NAME "acp5x_mach" -#define DUAL_CHANNEL 2 -#define ACP5X_NUVOTON_CODEC_DAI "nau8821-hifi" -#define VG_JUPITER 1 -#define ACP5X_NUVOTON_BCLK 3072000 -#define ACP5X_NAU8821_FREQ_OUT 12288000 +#define DRV_NAME "acp5x_mach" +#define DUAL_CHANNEL 2 +#define ACP5X_NUVOTON_CODEC_DAI "nau8821-hifi" +#define VG_JUPITER 1 +#define ACP5X_NUVOTON_BCLK 3072000 +#define ACP5X_NAU8821_FREQ_OUT 12288000 static unsigned long acp5x_machine_id; static struct snd_soc_jack vg_headset; @@ -50,16 +47,14 @@ static struct snd_soc_jack_pin acp5x_nau8821_jack_pins[] = { static int acp5x_8821_init(struct snd_soc_pcm_runtime *rtd) { + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component; int ret; - struct snd_soc_card *card = rtd->card; - struct snd_soc_component *component = - asoc_rtd_to_codec(rtd, 0)->component; /* * Headset buttons map to the google Reference headset. * These can be configured by userspace. */ - ret = snd_soc_card_jack_new_pins(card, "Headset Jack", + ret = snd_soc_card_jack_new_pins(rtd->card, "Headset Jack", SND_JACK_HEADSET | SND_JACK_BTN_0, &vg_headset, acp5x_nau8821_jack_pins, ARRAY_SIZE(acp5x_nau8821_jack_pins)); @@ -70,6 +65,7 @@ static int acp5x_8821_init(struct snd_soc_pcm_runtime *rtd) snd_jack_set_key(vg_headset.jack, SND_JACK_BTN_0, KEY_MEDIA); nau8821_enable_jack_detect(component, &vg_headset); + return ret; } @@ -104,8 +100,7 @@ static int acp5x_8821_startup(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); - struct snd_soc_card *card = rtd->card; - struct acp5x_platform_info *machine = snd_soc_card_get_drvdata(card); + struct acp5x_platform_info *machine = snd_soc_card_get_drvdata(rtd->card); machine->play_i2s_instance = I2S_SP_INSTANCE; machine->cap_i2s_instance = I2S_SP_INSTANCE; @@ -118,6 +113,7 @@ static int acp5x_8821_startup(struct snd_pcm_substream *substream) snd_pcm_hw_constraint_list(substream->runtime, 0, SNDRV_PCM_HW_PARAM_SAMPLE_BITS, &constraints_sample_bits); + return 0; } @@ -126,16 +122,13 @@ static int acp5x_nau8821_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; - struct snd_soc_dai *codec_dai = - snd_soc_card_get_codec_dai(card, - ACP5X_NUVOTON_CODEC_DAI); + struct snd_soc_dai *dai = snd_soc_card_get_codec_dai(card, ACP5X_NUVOTON_CODEC_DAI); int ret; - ret = snd_soc_dai_set_sysclk(codec_dai, NAU8821_CLK_FLL_BLK, 0, - SND_SOC_CLOCK_IN); + ret = snd_soc_dai_set_sysclk(dai, NAU8821_CLK_FLL_BLK, 0, SND_SOC_CLOCK_IN); if (ret < 0) dev_err(card->dev, "can't set FS clock %d\n", ret); - ret = snd_soc_dai_set_pll(codec_dai, 0, 0, snd_soc_params_to_bclk(params), + ret = snd_soc_dai_set_pll(dai, 0, 0, snd_soc_params_to_bclk(params), params_rate(params) * 256); if (ret < 0) dev_err(card->dev, "can't set FLL: %d\n", ret); @@ -145,10 +138,9 @@ static int acp5x_nau8821_hw_params(struct snd_pcm_substream *substream, static int acp5x_cs35l41_startup(struct snd_pcm_substream *substream) { - struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); - struct snd_soc_card *card = rtd->card; - struct acp5x_platform_info *machine = snd_soc_card_get_drvdata(card); + struct acp5x_platform_info *machine = snd_soc_card_get_drvdata(rtd->card); + struct snd_pcm_runtime *runtime = substream->runtime; machine->play_i2s_instance = I2S_HS_INSTANCE; @@ -157,6 +149,7 @@ static int acp5x_cs35l41_startup(struct snd_pcm_substream *substream) &constraints_channels); snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); + return 0; } @@ -164,16 +157,16 @@ static int acp5x_cs35l41_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); - struct snd_soc_card *card = rtd->card; - struct snd_soc_dai *codec_dai; - int ret, i; unsigned int num_codecs = rtd->dai_link->num_codecs; + struct snd_soc_card *card = rtd->card; + struct snd_soc_dai *dai; unsigned int bclk_val; + int ret, i; ret = 0; for (i = 0; i < num_codecs; i++) { - codec_dai = asoc_rtd_to_codec(rtd, i); - if (strcmp(codec_dai->name, "cs35l41-pcm") == 0) { + dai = asoc_rtd_to_codec(rtd, i); + if (strcmp(dai->name, "cs35l41-pcm") == 0) { switch (params_rate(params)) { case 48000: bclk_val = 1536000; @@ -183,8 +176,8 @@ static int acp5x_cs35l41_hw_params(struct snd_pcm_substream *substream, params_rate(params)); return -EINVAL; } - ret = snd_soc_component_set_sysclk(codec_dai->component, - 0, 0, bclk_val, SND_SOC_CLOCK_IN); + ret = snd_soc_component_set_sysclk(dai->component, 0, 0, + bclk_val, SND_SOC_CLOCK_IN); if (ret < 0) { dev_err(card->dev, "failed to set sysclk for CS35l41 dai\n"); return ret; @@ -216,28 +209,19 @@ static struct snd_soc_codec_conf cs35l41_conf[] = { }, }; -SND_SOC_DAILINK_DEF(acp5x_i2s, - DAILINK_COMP_ARRAY(COMP_CPU("acp5x_i2s_playcap.0"))); - -SND_SOC_DAILINK_DEF(acp5x_bt, - DAILINK_COMP_ARRAY(COMP_CPU("acp5x_i2s_playcap.1"))); - -SND_SOC_DAILINK_DEF(nau8821, - DAILINK_COMP_ARRAY(COMP_CODEC("i2c-NVTN2020:00", - "nau8821-hifi"))); - -SND_SOC_DAILINK_DEF(cs35l41, - DAILINK_COMP_ARRAY(COMP_CODEC("spi-VLV1776:00", "cs35l41-pcm"), - COMP_CODEC("spi-VLV1776:01", "cs35l41-pcm"))); - -SND_SOC_DAILINK_DEF(platform, - DAILINK_COMP_ARRAY(COMP_PLATFORM("acp5x_i2s_dma.0"))); +SND_SOC_DAILINK_DEF(platform, DAILINK_COMP_ARRAY(COMP_PLATFORM("acp5x_i2s_dma.0"))); +SND_SOC_DAILINK_DEF(acp5x_i2s, DAILINK_COMP_ARRAY(COMP_CPU("acp5x_i2s_playcap.0"))); +SND_SOC_DAILINK_DEF(acp5x_bt, DAILINK_COMP_ARRAY(COMP_CPU("acp5x_i2s_playcap.1"))); +SND_SOC_DAILINK_DEF(nau8821, DAILINK_COMP_ARRAY(COMP_CODEC("i2c-NVTN2020:00", "nau8821-hifi"))); +SND_SOC_DAILINK_DEF(cs35l41, DAILINK_COMP_ARRAY(COMP_CODEC("spi-VLV1776:00", "cs35l41-pcm"), + COMP_CODEC("spi-VLV1776:01", "cs35l41-pcm"))); static struct snd_soc_dai_link acp5x_dai[] = { { .name = "acp5x-8821-play", .stream_name = "Playback/Capture", - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | + .dai_fmt = SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC, .dpcm_playback = 1, .dpcm_capture = 1, @@ -248,7 +232,8 @@ static struct snd_soc_dai_link acp5x_dai[] = { { .name = "acp5x-CS35L41-Stereo", .stream_name = "CS35L41 Stereo Playback", - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | + .dai_fmt = SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC, .dpcm_playback = 1, .playback_only = 1, @@ -258,36 +243,34 @@ static struct snd_soc_dai_link acp5x_dai[] = { }; static int platform_clock_control(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *k, int event) + struct snd_kcontrol *k, int event) { struct snd_soc_dapm_context *dapm = w->dapm; struct snd_soc_card *card = dapm->card; - struct snd_soc_dai *codec_dai; + struct snd_soc_dai *dai; int ret = 0; - codec_dai = snd_soc_card_get_codec_dai(card, ACP5X_NUVOTON_CODEC_DAI); - if (!codec_dai) { + dai = snd_soc_card_get_codec_dai(card, ACP5X_NUVOTON_CODEC_DAI); + if (!dai) { dev_err(card->dev, "Codec dai not found\n"); return -EIO; } if (SND_SOC_DAPM_EVENT_OFF(event)) { - ret = snd_soc_dai_set_sysclk(codec_dai, NAU8821_CLK_INTERNAL, - 0, SND_SOC_CLOCK_IN); + ret = snd_soc_dai_set_sysclk(dai, NAU8821_CLK_INTERNAL, 0, SND_SOC_CLOCK_IN); if (ret < 0) { dev_err(card->dev, "set sysclk err = %d\n", ret); return -EIO; } } else { - ret = snd_soc_dai_set_sysclk(codec_dai, NAU8821_CLK_FLL_BLK, 0, - SND_SOC_CLOCK_IN); + ret = snd_soc_dai_set_sysclk(dai, NAU8821_CLK_FLL_BLK, 0, SND_SOC_CLOCK_IN); if (ret < 0) - dev_err(codec_dai->dev, "can't set BLK clock %d\n", ret); - ret = snd_soc_dai_set_pll(codec_dai, 0, 0, ACP5X_NUVOTON_BCLK, - ACP5X_NAU8821_FREQ_OUT); + dev_err(dai->dev, "can't set BLK clock %d\n", ret); + ret = snd_soc_dai_set_pll(dai, 0, 0, ACP5X_NUVOTON_BCLK, ACP5X_NAU8821_FREQ_OUT); if (ret < 0) - dev_err(codec_dai->dev, "can't set FLL: %d\n", ret); + dev_err(dai->dev, "can't set FLL: %d\n", ret); } + return ret; } @@ -302,7 +285,8 @@ static const struct snd_soc_dapm_widget acp5x_8821_widgets[] = { SND_SOC_DAPM_MIC("Headset Mic", NULL), SND_SOC_DAPM_MIC("Int Mic", NULL), SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, - platform_clock_control, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + platform_clock_control, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), }; static const struct snd_soc_dapm_route acp5x_8821_audio_route[] = { @@ -336,6 +320,7 @@ static struct snd_soc_card acp5x_card = { static int acp5x_vg_quirk_cb(const struct dmi_system_id *id) { acp5x_machine_id = VG_JUPITER; + return 1; } @@ -352,12 +337,12 @@ static const struct dmi_system_id acp5x_vg_quirk_table[] = { static int acp5x_probe(struct platform_device *pdev) { - int ret; struct acp5x_platform_info *machine; + struct device *dev = &pdev->dev; struct snd_soc_card *card; + int ret; - machine = devm_kzalloc(&pdev->dev, sizeof(struct acp5x_platform_info), - GFP_KERNEL); + machine = devm_kzalloc(dev, sizeof(struct acp5x_platform_info), GFP_KERNEL); if (!machine) return -ENOMEM; @@ -365,20 +350,18 @@ static int acp5x_probe(struct platform_device *pdev) switch (acp5x_machine_id) { case VG_JUPITER: card = &acp5x_card; - acp5x_card.dev = &pdev->dev; break; default: return -ENODEV; } + card->dev = dev; platform_set_drvdata(pdev, card); snd_soc_card_set_drvdata(card, machine); - ret = devm_snd_soc_register_card(&pdev->dev, card); - if (ret) { - return dev_err_probe(&pdev->dev, ret, - "snd_soc_register_card(%s) failed\n", - acp5x_card.name); - } + ret = devm_snd_soc_register_card(dev, card); + if (ret) + return dev_err_probe(dev, ret, "Register card (%s) failed\n", card->name); + return 0; } From 50e81116ef576b58384c8829bd767b5decbc2968 Mon Sep 17 00:00:00 2001 From: Lucas Tanure Date: Fri, 17 Feb 2023 11:08:44 +0000 Subject: [PATCH 102/778] ASoC: amd: vangogh: use sizeof of variable instead of struct type Use sizeof(*machine) instead of sizeof(struct acp5x_platform_info) There is a possibility of bug when variable type has changed but corresponding struct passed to the sizeof has not. Signed-off-by: Lucas Tanure Link: https://lore.kernel.org/r/20230217110850.1045250-4-lucas.tanure@collabora.com Signed-off-by: Mark Brown --- sound/soc/amd/vangogh/acp5x-mach.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/amd/vangogh/acp5x-mach.c b/sound/soc/amd/vangogh/acp5x-mach.c index f914f6327cda..43c80103d138 100644 --- a/sound/soc/amd/vangogh/acp5x-mach.c +++ b/sound/soc/amd/vangogh/acp5x-mach.c @@ -342,7 +342,7 @@ static int acp5x_probe(struct platform_device *pdev) struct snd_soc_card *card; int ret; - machine = devm_kzalloc(dev, sizeof(struct acp5x_platform_info), GFP_KERNEL); + machine = devm_kzalloc(dev, sizeof(*machine), GFP_KERNEL); if (!machine) return -ENOMEM; From 88f5870dd360e6604dceff808bf960bf6ddf0377 Mon Sep 17 00:00:00 2001 From: Lucas Tanure Date: Fri, 17 Feb 2023 11:08:45 +0000 Subject: [PATCH 103/778] ASoC: amd: vangogh: remove unnecessarily included headers Remove unused includes and replace by Signed-off-by: Lucas Tanure Link: https://lore.kernel.org/r/20230217110850.1045250-5-lucas.tanure@collabora.com Signed-off-by: Mark Brown --- sound/soc/amd/vangogh/acp5x-mach.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/sound/soc/amd/vangogh/acp5x-mach.c b/sound/soc/amd/vangogh/acp5x-mach.c index 43c80103d138..a1cd52e58574 100644 --- a/sound/soc/amd/vangogh/acp5x-mach.c +++ b/sound/soc/amd/vangogh/acp5x-mach.c @@ -5,23 +5,19 @@ * * Copyright 2021 Advanced Micro Devices, Inc. */ + #include -#include #include -#include #include -#include #include -#include +#include #include #include -#include #include #include #include #include "../../codecs/nau8821.h" -#include "../../codecs/cs35l41.h" #include "acp5x.h" #define DRV_NAME "acp5x_mach" From a719afe679b1c84413a70132a2de69c36b469144 Mon Sep 17 00:00:00 2001 From: Lucas Tanure Date: Fri, 17 Feb 2023 11:08:46 +0000 Subject: [PATCH 104/778] ASoC: amd: vangogh: use for_each_rtd_components instead of for To iterate over components use for_each_rtd_components And compare to component name, so asoc_rtd_to_codec and the dai code can be removed Signed-off-by: Lucas Tanure Link: https://lore.kernel.org/r/20230217110850.1045250-6-lucas.tanure@collabora.com Signed-off-by: Mark Brown --- sound/soc/amd/vangogh/acp5x-mach.c | 42 ++++++++++++++++-------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/sound/soc/amd/vangogh/acp5x-mach.c b/sound/soc/amd/vangogh/acp5x-mach.c index a1cd52e58574..e7183d8ac3a2 100644 --- a/sound/soc/amd/vangogh/acp5x-mach.c +++ b/sound/soc/amd/vangogh/acp5x-mach.c @@ -153,35 +153,37 @@ static int acp5x_cs35l41_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); - unsigned int num_codecs = rtd->dai_link->num_codecs; - struct snd_soc_card *card = rtd->card; - struct snd_soc_dai *dai; - unsigned int bclk_val; + unsigned int bclk, rate = params_rate(params); + struct snd_soc_component *comp; int ret, i; - ret = 0; - for (i = 0; i < num_codecs; i++) { - dai = asoc_rtd_to_codec(rtd, i); - if (strcmp(dai->name, "cs35l41-pcm") == 0) { - switch (params_rate(params)) { - case 48000: - bclk_val = 1536000; - break; - default: - dev_err(card->dev, "Invalid Samplerate:0x%x\n", - params_rate(params)); + switch (rate) { + case 48000: + bclk = 1536000; + break; + default: + bclk = 0; + break; + } + + for_each_rtd_components(rtd, i, comp) { + if (!(strcmp(comp->name, "spi-VLV1776:00")) || + !(strcmp(comp->name, "spi-VLV1776:01"))) { + if (!bclk) { + dev_err(comp->dev, "Invalid sample rate: 0x%x\n", rate); return -EINVAL; } - ret = snd_soc_component_set_sysclk(dai->component, 0, 0, - bclk_val, SND_SOC_CLOCK_IN); - if (ret < 0) { - dev_err(card->dev, "failed to set sysclk for CS35l41 dai\n"); + + ret = snd_soc_component_set_sysclk(comp, 0, 0, bclk, SND_SOC_CLOCK_IN); + if (ret) { + dev_err(comp->dev, "failed to set SYSCLK: %d\n", ret); return ret; } } } - return ret; + return 0; + } static const struct snd_soc_ops acp5x_8821_ops = { From 9490fbb85be830b9f4078775d678426335e36a64 Mon Sep 17 00:00:00 2001 From: Lucas Tanure Date: Fri, 17 Feb 2023 11:08:47 +0000 Subject: [PATCH 105/778] ASoC: amd: vangogh: Check Bit Clock rate before snd_soc_dai_set_pll Check bit clock is valid before setting it with snd_soc_dai_set_pll Signed-off-by: Lucas Tanure Link: https://lore.kernel.org/r/20230217110850.1045250-7-lucas.tanure@collabora.com Signed-off-by: Mark Brown --- sound/soc/amd/vangogh/acp5x-mach.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/sound/soc/amd/vangogh/acp5x-mach.c b/sound/soc/amd/vangogh/acp5x-mach.c index e7183d8ac3a2..c746605b63a1 100644 --- a/sound/soc/amd/vangogh/acp5x-mach.c +++ b/sound/soc/amd/vangogh/acp5x-mach.c @@ -119,13 +119,19 @@ static int acp5x_nau8821_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; struct snd_soc_dai *dai = snd_soc_card_get_codec_dai(card, ACP5X_NUVOTON_CODEC_DAI); - int ret; + int ret, bclk; ret = snd_soc_dai_set_sysclk(dai, NAU8821_CLK_FLL_BLK, 0, SND_SOC_CLOCK_IN); if (ret < 0) dev_err(card->dev, "can't set FS clock %d\n", ret); - ret = snd_soc_dai_set_pll(dai, 0, 0, snd_soc_params_to_bclk(params), - params_rate(params) * 256); + + bclk = snd_soc_params_to_bclk(params); + if (bclk < 0) { + dev_err(dai->dev, "Fail to get BCLK rate: %d\n", bclk); + return bclk; + } + + ret = snd_soc_dai_set_pll(dai, 0, 0, bclk, params_rate(params) * 256); if (ret < 0) dev_err(card->dev, "can't set FLL: %d\n", ret); From ab89aa0d3bdef8cea6002c237c669f980a13b0e4 Mon Sep 17 00:00:00 2001 From: Lucas Tanure Date: Fri, 17 Feb 2023 11:08:48 +0000 Subject: [PATCH 106/778] ASoC: amd: vangogh: Move nau8821 and CPU side code up for future platform Move nau8821 and CPU side code up in the source so future platforms can be added. Signed-off-by: Lucas Tanure Link: https://lore.kernel.org/r/20230217110850.1045250-8-lucas.tanure@collabora.com Signed-off-by: Mark Brown --- sound/soc/amd/vangogh/acp5x-mach.c | 97 +++++++++++++++--------------- 1 file changed, 50 insertions(+), 47 deletions(-) diff --git a/sound/soc/amd/vangogh/acp5x-mach.c b/sound/soc/amd/vangogh/acp5x-mach.c index c746605b63a1..153ce9e84a23 100644 --- a/sound/soc/amd/vangogh/acp5x-mach.c +++ b/sound/soc/amd/vangogh/acp5x-mach.c @@ -30,6 +30,11 @@ static unsigned long acp5x_machine_id; static struct snd_soc_jack vg_headset; +SND_SOC_DAILINK_DEF(platform, DAILINK_COMP_ARRAY(COMP_PLATFORM("acp5x_i2s_dma.0"))); +SND_SOC_DAILINK_DEF(acp5x_i2s, DAILINK_COMP_ARRAY(COMP_CPU("acp5x_i2s_playcap.0"))); +SND_SOC_DAILINK_DEF(acp5x_bt, DAILINK_COMP_ARRAY(COMP_CPU("acp5x_i2s_playcap.1"))); +SND_SOC_DAILINK_DEF(nau8821, DAILINK_COMP_ARRAY(COMP_CODEC("i2c-NVTN2020:00", "nau8821-hifi"))); + static struct snd_soc_jack_pin acp5x_nau8821_jack_pins[] = { { .pin = "Headphone", @@ -41,6 +46,44 @@ static struct snd_soc_jack_pin acp5x_nau8821_jack_pins[] = { }, }; +static const struct snd_kcontrol_new acp5x_8821_controls[] = { + SOC_DAPM_PIN_SWITCH("Headphone"), + SOC_DAPM_PIN_SWITCH("Headset Mic"), + SOC_DAPM_PIN_SWITCH("Int Mic"), +}; + +static int platform_clock_control(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *k, int event) +{ + struct snd_soc_dapm_context *dapm = w->dapm; + struct snd_soc_card *card = dapm->card; + struct snd_soc_dai *dai; + int ret = 0; + + dai = snd_soc_card_get_codec_dai(card, ACP5X_NUVOTON_CODEC_DAI); + if (!dai) { + dev_err(card->dev, "Codec dai not found\n"); + return -EIO; + } + + if (SND_SOC_DAPM_EVENT_OFF(event)) { + ret = snd_soc_dai_set_sysclk(dai, NAU8821_CLK_INTERNAL, 0, SND_SOC_CLOCK_IN); + if (ret < 0) { + dev_err(card->dev, "set sysclk err = %d\n", ret); + return -EIO; + } + } else { + ret = snd_soc_dai_set_sysclk(dai, NAU8821_CLK_FLL_BLK, 0, SND_SOC_CLOCK_IN); + if (ret < 0) + dev_err(dai->dev, "can't set BLK clock %d\n", ret); + ret = snd_soc_dai_set_pll(dai, 0, 0, ACP5X_NUVOTON_BCLK, ACP5X_NAU8821_FREQ_OUT); + if (ret < 0) + dev_err(dai->dev, "can't set FLL: %d\n", ret); + } + + return ret; +} + static int acp5x_8821_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component; @@ -138,6 +181,11 @@ static int acp5x_nau8821_hw_params(struct snd_pcm_substream *substream, return ret; } +static const struct snd_soc_ops acp5x_8821_ops = { + .startup = acp5x_8821_startup, + .hw_params = acp5x_nau8821_hw_params, +}; + static int acp5x_cs35l41_startup(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); @@ -192,11 +240,6 @@ static int acp5x_cs35l41_hw_params(struct snd_pcm_substream *substream, } -static const struct snd_soc_ops acp5x_8821_ops = { - .startup = acp5x_8821_startup, - .hw_params = acp5x_nau8821_hw_params, -}; - static const struct snd_soc_ops acp5x_cs35l41_play_ops = { .startup = acp5x_cs35l41_startup, .hw_params = acp5x_cs35l41_hw_params, @@ -213,12 +256,8 @@ static struct snd_soc_codec_conf cs35l41_conf[] = { }, }; -SND_SOC_DAILINK_DEF(platform, DAILINK_COMP_ARRAY(COMP_PLATFORM("acp5x_i2s_dma.0"))); -SND_SOC_DAILINK_DEF(acp5x_i2s, DAILINK_COMP_ARRAY(COMP_CPU("acp5x_i2s_playcap.0"))); -SND_SOC_DAILINK_DEF(acp5x_bt, DAILINK_COMP_ARRAY(COMP_CPU("acp5x_i2s_playcap.1"))); -SND_SOC_DAILINK_DEF(nau8821, DAILINK_COMP_ARRAY(COMP_CODEC("i2c-NVTN2020:00", "nau8821-hifi"))); -SND_SOC_DAILINK_DEF(cs35l41, DAILINK_COMP_ARRAY(COMP_CODEC("spi-VLV1776:00", "cs35l41-pcm"), - COMP_CODEC("spi-VLV1776:01", "cs35l41-pcm"))); +SND_SOC_DAILINK_DEF(cs35l41, DAILINK_COMP_ARRAY(COMP_CODEC("spi-VLV1776:00", "cs35l41-pcm"), + COMP_CODEC("spi-VLV1776:01", "cs35l41-pcm"))); static struct snd_soc_dai_link acp5x_dai[] = { { @@ -246,43 +285,7 @@ static struct snd_soc_dai_link acp5x_dai[] = { }, }; -static int platform_clock_control(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *k, int event) -{ - struct snd_soc_dapm_context *dapm = w->dapm; - struct snd_soc_card *card = dapm->card; - struct snd_soc_dai *dai; - int ret = 0; - dai = snd_soc_card_get_codec_dai(card, ACP5X_NUVOTON_CODEC_DAI); - if (!dai) { - dev_err(card->dev, "Codec dai not found\n"); - return -EIO; - } - - if (SND_SOC_DAPM_EVENT_OFF(event)) { - ret = snd_soc_dai_set_sysclk(dai, NAU8821_CLK_INTERNAL, 0, SND_SOC_CLOCK_IN); - if (ret < 0) { - dev_err(card->dev, "set sysclk err = %d\n", ret); - return -EIO; - } - } else { - ret = snd_soc_dai_set_sysclk(dai, NAU8821_CLK_FLL_BLK, 0, SND_SOC_CLOCK_IN); - if (ret < 0) - dev_err(dai->dev, "can't set BLK clock %d\n", ret); - ret = snd_soc_dai_set_pll(dai, 0, 0, ACP5X_NUVOTON_BCLK, ACP5X_NAU8821_FREQ_OUT); - if (ret < 0) - dev_err(dai->dev, "can't set FLL: %d\n", ret); - } - - return ret; -} - -static const struct snd_kcontrol_new acp5x_8821_controls[] = { - SOC_DAPM_PIN_SWITCH("Headphone"), - SOC_DAPM_PIN_SWITCH("Headset Mic"), - SOC_DAPM_PIN_SWITCH("Int Mic"), -}; static const struct snd_soc_dapm_widget acp5x_8821_widgets[] = { SND_SOC_DAPM_HP("Headphone", NULL), From c10955e4bf28b058862e4f82c7eb8d6f315d8a52 Mon Sep 17 00:00:00 2001 From: Lucas Tanure Date: Fri, 17 Feb 2023 11:08:49 +0000 Subject: [PATCH 107/778] ASoC: amd: vangogh: Centralize strings definition Replace occurrences of strings by their definition, avoiding bugs where the string changed, but not all places have been modified. While at it rename defines to use NAU8821 codec name instead of NUVOTON and align with the other defines. Signed-off-by: Lucas Tanure Link: https://lore.kernel.org/r/20230217110850.1045250-9-lucas.tanure@collabora.com Signed-off-by: Mark Brown --- sound/soc/amd/vangogh/acp5x-mach.c | 31 ++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/sound/soc/amd/vangogh/acp5x-mach.c b/sound/soc/amd/vangogh/acp5x-mach.c index 153ce9e84a23..367570e5c60f 100644 --- a/sound/soc/amd/vangogh/acp5x-mach.c +++ b/sound/soc/amd/vangogh/acp5x-mach.c @@ -22,10 +22,14 @@ #define DRV_NAME "acp5x_mach" #define DUAL_CHANNEL 2 -#define ACP5X_NUVOTON_CODEC_DAI "nau8821-hifi" #define VG_JUPITER 1 -#define ACP5X_NUVOTON_BCLK 3072000 +#define ACP5X_NAU8821_BCLK 3072000 #define ACP5X_NAU8821_FREQ_OUT 12288000 +#define ACP5X_NAU8821_COMP_NAME "i2c-NVTN2020:00" +#define ACP5X_NAU8821_DAI_NAME "nau8821-hifi" +#define ACP5X_CS35L41_COMP_LNAME "spi-VLV1776:00" +#define ACP5X_CS35L41_COMP_RNAME "spi-VLV1776:01" +#define ACP5X_CS35L41_DAI_NAME "cs35l41-pcm" static unsigned long acp5x_machine_id; static struct snd_soc_jack vg_headset; @@ -33,7 +37,8 @@ static struct snd_soc_jack vg_headset; SND_SOC_DAILINK_DEF(platform, DAILINK_COMP_ARRAY(COMP_PLATFORM("acp5x_i2s_dma.0"))); SND_SOC_DAILINK_DEF(acp5x_i2s, DAILINK_COMP_ARRAY(COMP_CPU("acp5x_i2s_playcap.0"))); SND_SOC_DAILINK_DEF(acp5x_bt, DAILINK_COMP_ARRAY(COMP_CPU("acp5x_i2s_playcap.1"))); -SND_SOC_DAILINK_DEF(nau8821, DAILINK_COMP_ARRAY(COMP_CODEC("i2c-NVTN2020:00", "nau8821-hifi"))); +SND_SOC_DAILINK_DEF(nau8821, DAILINK_COMP_ARRAY(COMP_CODEC(ACP5X_NAU8821_COMP_NAME, + ACP5X_NAU8821_DAI_NAME))); static struct snd_soc_jack_pin acp5x_nau8821_jack_pins[] = { { @@ -60,7 +65,7 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w, struct snd_soc_dai *dai; int ret = 0; - dai = snd_soc_card_get_codec_dai(card, ACP5X_NUVOTON_CODEC_DAI); + dai = snd_soc_card_get_codec_dai(card, ACP5X_NAU8821_DAI_NAME); if (!dai) { dev_err(card->dev, "Codec dai not found\n"); return -EIO; @@ -76,7 +81,7 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w, ret = snd_soc_dai_set_sysclk(dai, NAU8821_CLK_FLL_BLK, 0, SND_SOC_CLOCK_IN); if (ret < 0) dev_err(dai->dev, "can't set BLK clock %d\n", ret); - ret = snd_soc_dai_set_pll(dai, 0, 0, ACP5X_NUVOTON_BCLK, ACP5X_NAU8821_FREQ_OUT); + ret = snd_soc_dai_set_pll(dai, 0, 0, ACP5X_NAU8821_BCLK, ACP5X_NAU8821_FREQ_OUT); if (ret < 0) dev_err(dai->dev, "can't set FLL: %d\n", ret); } @@ -161,7 +166,7 @@ static int acp5x_nau8821_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; - struct snd_soc_dai *dai = snd_soc_card_get_codec_dai(card, ACP5X_NUVOTON_CODEC_DAI); + struct snd_soc_dai *dai = snd_soc_card_get_codec_dai(card, ACP5X_NAU8821_DAI_NAME); int ret, bclk; ret = snd_soc_dai_set_sysclk(dai, NAU8821_CLK_FLL_BLK, 0, SND_SOC_CLOCK_IN); @@ -221,8 +226,8 @@ static int acp5x_cs35l41_hw_params(struct snd_pcm_substream *substream, } for_each_rtd_components(rtd, i, comp) { - if (!(strcmp(comp->name, "spi-VLV1776:00")) || - !(strcmp(comp->name, "spi-VLV1776:01"))) { + if (!(strcmp(comp->name, ACP5X_CS35L41_COMP_LNAME)) || + !(strcmp(comp->name, ACP5X_CS35L41_COMP_RNAME))) { if (!bclk) { dev_err(comp->dev, "Invalid sample rate: 0x%x\n", rate); return -EINVAL; @@ -247,17 +252,19 @@ static const struct snd_soc_ops acp5x_cs35l41_play_ops = { static struct snd_soc_codec_conf cs35l41_conf[] = { { - .dlc = COMP_CODEC_CONF("spi-VLV1776:00"), + .dlc = COMP_CODEC_CONF(ACP5X_CS35L41_COMP_LNAME), .name_prefix = "Left", }, { - .dlc = COMP_CODEC_CONF("spi-VLV1776:01"), + .dlc = COMP_CODEC_CONF(ACP5X_CS35L41_COMP_RNAME), .name_prefix = "Right", }, }; -SND_SOC_DAILINK_DEF(cs35l41, DAILINK_COMP_ARRAY(COMP_CODEC("spi-VLV1776:00", "cs35l41-pcm"), - COMP_CODEC("spi-VLV1776:01", "cs35l41-pcm"))); +SND_SOC_DAILINK_DEF(cs35l41, DAILINK_COMP_ARRAY(COMP_CODEC(ACP5X_CS35L41_COMP_LNAME, + ACP5X_CS35L41_DAI_NAME), + COMP_CODEC(ACP5X_CS35L41_COMP_RNAME, + ACP5X_CS35L41_DAI_NAME))); static struct snd_soc_dai_link acp5x_dai[] = { { From e902324826ec276e50140a462c991c37b04cd392 Mon Sep 17 00:00:00 2001 From: Lucas Tanure Date: Fri, 17 Feb 2023 11:08:50 +0000 Subject: [PATCH 108/778] ASoC: amd: vangogh: Add components prefix in structs and function names Add prefixes 8821/35l41 in structs and function names so future platforms can be added and reference the correct sound card. Also include acp5x prefix to cs35l41_conf. Signed-off-by: Lucas Tanure Link: https://lore.kernel.org/r/20230217110850.1045250-10-lucas.tanure@collabora.com Signed-off-by: Mark Brown --- sound/soc/amd/vangogh/acp5x-mach.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/sound/soc/amd/vangogh/acp5x-mach.c b/sound/soc/amd/vangogh/acp5x-mach.c index 367570e5c60f..e5bcd1e6eb73 100644 --- a/sound/soc/amd/vangogh/acp5x-mach.c +++ b/sound/soc/amd/vangogh/acp5x-mach.c @@ -250,7 +250,7 @@ static const struct snd_soc_ops acp5x_cs35l41_play_ops = { .hw_params = acp5x_cs35l41_hw_params, }; -static struct snd_soc_codec_conf cs35l41_conf[] = { +static struct snd_soc_codec_conf acp5x_cs35l41_conf[] = { { .dlc = COMP_CODEC_CONF(ACP5X_CS35L41_COMP_LNAME), .name_prefix = "Left", @@ -266,7 +266,7 @@ SND_SOC_DAILINK_DEF(cs35l41, DAILINK_COMP_ARRAY(COMP_CODEC(ACP5X_CS35L41_COMP_LN COMP_CODEC(ACP5X_CS35L41_COMP_RNAME, ACP5X_CS35L41_DAI_NAME))); -static struct snd_soc_dai_link acp5x_dai[] = { +static struct snd_soc_dai_link acp5x_8821_35l41_dai[] = { { .name = "acp5x-8821-play", .stream_name = "Playback/Capture", @@ -294,7 +294,7 @@ static struct snd_soc_dai_link acp5x_dai[] = { -static const struct snd_soc_dapm_widget acp5x_8821_widgets[] = { +static const struct snd_soc_dapm_widget acp5x_8821_35l41_widgets[] = { SND_SOC_DAPM_HP("Headphone", NULL), SND_SOC_DAPM_MIC("Headset Mic", NULL), SND_SOC_DAPM_MIC("Int Mic", NULL), @@ -303,7 +303,7 @@ static const struct snd_soc_dapm_widget acp5x_8821_widgets[] = { SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), }; -static const struct snd_soc_dapm_route acp5x_8821_audio_route[] = { +static const struct snd_soc_dapm_route acp5x_8821_35l41_audio_route[] = { /* HP jack connectors - unknown if we have jack detection */ { "Headphone", NULL, "HPOL" }, { "Headphone", NULL, "HPOR" }, @@ -316,17 +316,17 @@ static const struct snd_soc_dapm_route acp5x_8821_audio_route[] = { { "Int Mic", NULL, "Platform Clock" }, }; -static struct snd_soc_card acp5x_card = { +static struct snd_soc_card acp5x_8821_35l41_card = { .name = "acp5x", .owner = THIS_MODULE, - .dai_link = acp5x_dai, - .num_links = ARRAY_SIZE(acp5x_dai), - .dapm_widgets = acp5x_8821_widgets, - .num_dapm_widgets = ARRAY_SIZE(acp5x_8821_widgets), - .dapm_routes = acp5x_8821_audio_route, - .num_dapm_routes = ARRAY_SIZE(acp5x_8821_audio_route), - .codec_conf = cs35l41_conf, - .num_configs = ARRAY_SIZE(cs35l41_conf), + .dai_link = acp5x_8821_35l41_dai, + .num_links = ARRAY_SIZE(acp5x_8821_35l41_dai), + .dapm_widgets = acp5x_8821_35l41_widgets, + .num_dapm_widgets = ARRAY_SIZE(acp5x_8821_35l41_widgets), + .dapm_routes = acp5x_8821_35l41_audio_route, + .num_dapm_routes = ARRAY_SIZE(acp5x_8821_35l41_audio_route), + .codec_conf = acp5x_cs35l41_conf, + .num_configs = ARRAY_SIZE(acp5x_cs35l41_conf), .controls = acp5x_8821_controls, .num_controls = ARRAY_SIZE(acp5x_8821_controls), }; @@ -363,7 +363,7 @@ static int acp5x_probe(struct platform_device *pdev) dmi_check_system(acp5x_vg_quirk_table); switch (acp5x_machine_id) { case VG_JUPITER: - card = &acp5x_card; + card = &acp5x_8821_35l41_card; break; default: return -ENODEV; From ae9db908517717888c4d618fdb90c02ec3fa1b3d Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Mon, 20 Feb 2023 09:58:02 +0200 Subject: [PATCH 109/778] ASoC: SOF: Intel: hda: Do not re-enable L1 if disabled before suspend We have a workaround in place to address a known issue with host DMA running into xruns when capture streams are running. But when resuming from Sx, we unconditionally re-enable DMI L1 without taking the workaround into account and this could lead to xruns when a suspended capture stream is restarted. To fix this rename the flag l1_support_enabled to l1_disabled in struct sof_intel_hda_dev to save the L1 disabled status which can be set/cleared when we get/put a stream and use the flag to determine if DMI L1 should enabled or not during the post_fw_run op. Signed-off-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Rander Wang Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230220075804.4829-2-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-ctrl.c | 8 +++++--- sound/soc/sof/intel/hda-dsp.c | 10 ++++------ sound/soc/sof/intel/hda-stream.c | 10 ++++++++-- sound/soc/sof/intel/hda.h | 2 +- 4 files changed, 18 insertions(+), 12 deletions(-) diff --git a/sound/soc/sof/intel/hda-ctrl.c b/sound/soc/sof/intel/hda-ctrl.c index 3aea36c077c9..a1037512da1f 100644 --- a/sound/soc/sof/intel/hda-ctrl.c +++ b/sound/soc/sof/intel/hda-ctrl.c @@ -158,16 +158,18 @@ void hda_dsp_ctrl_misc_clock_gating(struct snd_sof_dev *sdev, bool enable) */ int hda_dsp_ctrl_clock_power_gating(struct snd_sof_dev *sdev, bool enable) { + struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; u32 val; /* enable/disable audio dsp clock gating */ val = enable ? PCI_CGCTL_ADSPDCGE : 0; snd_sof_pci_update_bits(sdev, PCI_CGCTL, PCI_CGCTL_ADSPDCGE, val); - /* enable/disable DMI Link L1 support */ + /* disable the DMI link when requested. But enable only if it wasn't disabled previously */ val = enable ? HDA_VS_INTEL_EM2_L1SEN : 0; - snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, HDA_VS_INTEL_EM2, - HDA_VS_INTEL_EM2_L1SEN, val); + if (!enable || !hda->l1_disabled) + snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, HDA_VS_INTEL_EM2, + HDA_VS_INTEL_EM2_L1SEN, val); /* enable/disable audio dsp power gating */ val = enable ? 0 : PCI_PGCTL_ADSPPGD; diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index 68eb06f13a1f..e3b69dbc1308 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -776,7 +776,7 @@ int hda_dsp_resume(struct snd_sof_dev *sdev) } /* restore L1SEN bit */ - if (hda->l1_support_changed) + if (hda->l1_disabled) snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, HDA_VS_INTEL_EM2, HDA_VS_INTEL_EM2_L1SEN, 0); @@ -868,11 +868,9 @@ int hda_dsp_suspend(struct snd_sof_dev *sdev, u32 target_state) } /* enable L1SEN to make sure the system can enter S0Ix */ - hda->l1_support_changed = - snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, - HDA_VS_INTEL_EM2, - HDA_VS_INTEL_EM2_L1SEN, - HDA_VS_INTEL_EM2_L1SEN); + if (hda->l1_disabled) + snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, HDA_VS_INTEL_EM2, + HDA_VS_INTEL_EM2_L1SEN, HDA_VS_INTEL_EM2_L1SEN); /* stop the CORB/RIRB DMA if it is On */ hda_codec_suspend_cmd_io(sdev); diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index 7f0fd05a96e6..d96d9cd9e62f 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -182,6 +182,7 @@ int hda_dsp_stream_spib_config(struct snd_sof_dev *sdev, struct hdac_ext_stream * hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction, u32 flags) { + struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; struct hdac_bus *bus = sof_to_bus(sdev); struct sof_intel_hda_stream *hda_stream; struct hdac_ext_stream *hext_stream = NULL; @@ -222,10 +223,12 @@ hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction, u32 flags) * Workaround to address a known issue with host DMA that results * in xruns during pause/release in capture scenarios. */ - if (!(flags & SOF_HDA_STREAM_DMI_L1_COMPATIBLE)) + if (!(flags & SOF_HDA_STREAM_DMI_L1_COMPATIBLE)) { snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, HDA_VS_INTEL_EM2, HDA_VS_INTEL_EM2_L1SEN, 0); + hda->l1_disabled = true; + } return hext_stream; } @@ -233,6 +236,7 @@ hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction, u32 flags) /* free a stream */ int hda_dsp_stream_put(struct snd_sof_dev *sdev, int direction, int stream_tag) { + struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; struct hdac_bus *bus = sof_to_bus(sdev); struct sof_intel_hda_stream *hda_stream; struct hdac_ext_stream *hext_stream; @@ -264,9 +268,11 @@ int hda_dsp_stream_put(struct snd_sof_dev *sdev, int direction, int stream_tag) spin_unlock_irq(&bus->reg_lock); /* Enable DMI L1 if permitted */ - if (dmi_l1_enable) + if (dmi_l1_enable) { snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, HDA_VS_INTEL_EM2, HDA_VS_INTEL_EM2_L1SEN, HDA_VS_INTEL_EM2_L1SEN); + hda->l1_disabled = false; + } if (!found) { dev_err(sdev->dev, "%s: stream_tag %d not opened!\n", diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 45f9d4248f14..0679bebe4ad7 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -502,7 +502,7 @@ struct sof_intel_hda_dev { u32 stream_max; /* PM related */ - bool l1_support_changed;/* during suspend, is L1SEN changed or not */ + bool l1_disabled;/* is DMI link L1 disabled? */ /* DMIC device */ struct platform_device *dmic_dev; From 1133a9aaf36510ffbb83573b8982239b5a2dbee0 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Mon, 20 Feb 2023 09:58:03 +0200 Subject: [PATCH 110/778] ASoC: SOF: Intel: hda: Restrict DMI L1 disable workaround The workaround to disable DMI L1 should be restricted to only the CAVS IP's. Signed-off-by: Ranjani Sridharan Reviewed-by: Rander Wang Reviewed-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230220075804.4829-3-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-stream.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index d96d9cd9e62f..c37ef581637f 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -182,6 +182,7 @@ int hda_dsp_stream_spib_config(struct snd_sof_dev *sdev, struct hdac_ext_stream * hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction, u32 flags) { + const struct sof_intel_dsp_desc *chip_info = get_chip_info(sdev->pdata); struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; struct hdac_bus *bus = sof_to_bus(sdev); struct sof_intel_hda_stream *hda_stream; @@ -221,9 +222,10 @@ hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction, u32 flags) /* * Prevent DMI Link L1 entry for streams that don't support it. * Workaround to address a known issue with host DMA that results - * in xruns during pause/release in capture scenarios. + * in xruns during pause/release in capture scenarios. This is not needed for the ACE IP. */ - if (!(flags & SOF_HDA_STREAM_DMI_L1_COMPATIBLE)) { + if (chip_info->hw_ip_version < SOF_INTEL_ACE_1_0 && + !(flags & SOF_HDA_STREAM_DMI_L1_COMPATIBLE)) { snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, HDA_VS_INTEL_EM2, HDA_VS_INTEL_EM2_L1SEN, 0); @@ -236,6 +238,7 @@ hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction, u32 flags) /* free a stream */ int hda_dsp_stream_put(struct snd_sof_dev *sdev, int direction, int stream_tag) { + const struct sof_intel_dsp_desc *chip_info = get_chip_info(sdev->pdata); struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; struct hdac_bus *bus = sof_to_bus(sdev); struct sof_intel_hda_stream *hda_stream; @@ -268,7 +271,7 @@ int hda_dsp_stream_put(struct snd_sof_dev *sdev, int direction, int stream_tag) spin_unlock_irq(&bus->reg_lock); /* Enable DMI L1 if permitted */ - if (dmi_l1_enable) { + if (chip_info->hw_ip_version < SOF_INTEL_ACE_1_0 && dmi_l1_enable) { snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, HDA_VS_INTEL_EM2, HDA_VS_INTEL_EM2_L1SEN, HDA_VS_INTEL_EM2_L1SEN); hda->l1_disabled = false; From 2b5a30cafb2eff4e6a34bc80b1d16ed6ca5c2c71 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Mon, 20 Feb 2023 09:58:04 +0200 Subject: [PATCH 111/778] ASoC: SOF: Intel: MTL: Enable DMI L1 DMI L1 should be enabled unconditionally after FW boot is complete. Signed-off-by: Ranjani Sridharan Reviewed-by: Rander Wang Reviewed-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230220075804.4829-4-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/mtl.c | 3 +++ sound/soc/sof/intel/mtl.h | 2 ++ 2 files changed, 5 insertions(+) diff --git a/sound/soc/sof/intel/mtl.c b/sound/soc/sof/intel/mtl.c index 307faad2ecf4..216fd07a3a93 100644 --- a/sound/soc/sof/intel/mtl.c +++ b/sound/soc/sof/intel/mtl.c @@ -280,6 +280,9 @@ static int mtl_dsp_post_fw_run(struct snd_sof_dev *sdev) } hda_sdw_int_enable(sdev, true); + + /* enable DMI L1 */ + snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, MTL_EM2, MTL_EM2_L1SEN, MTL_EM2_L1SEN); return 0; } diff --git a/sound/soc/sof/intel/mtl.h b/sound/soc/sof/intel/mtl.h index 26418fb08807..ddc05304a9d5 100644 --- a/sound/soc/sof/intel/mtl.h +++ b/sound/soc/sof/intel/mtl.h @@ -28,6 +28,8 @@ #define MTL_HFINTIPPTR_PTR_MASK GENMASK(20, 0) #define MTL_HDA_VS_D0I3C 0x1D4A +#define MTL_EM2 0x1c44 +#define MTL_EM2_L1SEN BIT(13) #define MTL_DSP2CXCAP_PRIMARY_CORE 0x178D00 #define MTL_DSP2CXCTL_PRIMARY_CORE 0x178D04 From 6668f70abeea30f4674b2fdbc4232d5c3611b272 Mon Sep 17 00:00:00 2001 From: Richard Leitner Date: Fri, 3 Mar 2023 11:04:01 +0100 Subject: [PATCH 112/778] ASoC: dt-bindings: maxim,max9867: convert txt bindings to yaml Convert from max9867.txt to maxim,max9867.yaml and add missing '#sound-dai-cells' property. Signed-off-by: Richard Leitner Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230302-max9867-v2-1-fd2036d5e825@skidata.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/max9867.txt | 17 ------ .../bindings/sound/maxim,max9867.yaml | 55 +++++++++++++++++++ 2 files changed, 55 insertions(+), 17 deletions(-) delete mode 100644 Documentation/devicetree/bindings/sound/max9867.txt create mode 100644 Documentation/devicetree/bindings/sound/maxim,max9867.yaml diff --git a/Documentation/devicetree/bindings/sound/max9867.txt b/Documentation/devicetree/bindings/sound/max9867.txt deleted file mode 100644 index b8bd914ee697..000000000000 --- a/Documentation/devicetree/bindings/sound/max9867.txt +++ /dev/null @@ -1,17 +0,0 @@ -max9867 codec - -This device supports I2C mode only. - -Required properties: - -- compatible : "maxim,max9867" -- reg : The chip select number on the I2C bus - -Example: - -&i2c { - max9867: max9867@18 { - compatible = "maxim,max9867"; - reg = <0x18>; - }; -}; diff --git a/Documentation/devicetree/bindings/sound/maxim,max9867.yaml b/Documentation/devicetree/bindings/sound/maxim,max9867.yaml new file mode 100644 index 000000000000..74cd163546ec --- /dev/null +++ b/Documentation/devicetree/bindings/sound/maxim,max9867.yaml @@ -0,0 +1,55 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/maxim,max9867.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Maxim Integrated MAX9867 CODEC + +description: | + This device supports I2C only. + Pins on the device (for linking into audio routes): + * LOUT + * ROUT + * LINL + * LINR + * MICL + * MICR + * DMICL + * DMICR + +maintainers: + - Ladislav Michl + +allOf: + - $ref: dai-common.yaml# + +properties: + compatible: + enum: + - maxim,max9867 + + '#sound-dai-cells': + const: 0 + + reg: + maxItems: 1 + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + codec@18 { + compatible = "maxim,max9867"; + #sound-dai-cells = <0>; + reg = <0x18>; + }; + }; +... From d63e55b3e8ec90da69107f32038f3059d7317cc5 Mon Sep 17 00:00:00 2001 From: Richard Leitner Date: Fri, 3 Mar 2023 11:04:02 +0100 Subject: [PATCH 113/778] ASoC: dt-bindings: maxim,max9867: add clocks property Add clocks property to require a "mclk" definition for the maxim,max9867 codec. Signed-off-by: Richard Leitner Link: https://lore.kernel.org/r/20230302-max9867-v2-2-fd2036d5e825@skidata.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/maxim,max9867.yaml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/maxim,max9867.yaml b/Documentation/devicetree/bindings/sound/maxim,max9867.yaml index 74cd163546ec..6f27029b137d 100644 --- a/Documentation/devicetree/bindings/sound/maxim,max9867.yaml +++ b/Documentation/devicetree/bindings/sound/maxim,max9867.yaml @@ -35,9 +35,13 @@ properties: reg: maxItems: 1 + clocks: + maxItems: 1 + required: - compatible - reg + - clocks additionalProperties: false @@ -50,6 +54,13 @@ examples: compatible = "maxim,max9867"; #sound-dai-cells = <0>; reg = <0x18>; + clocks = <&codec_clk>; }; }; + + codec_clk: clock { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <12288000>; + }; ... From 448b06ba107d925d59d02781acdd2e4ad12dda0b Mon Sep 17 00:00:00 2001 From: Benjamin Bara Date: Fri, 3 Mar 2023 11:04:03 +0100 Subject: [PATCH 114/778] ASoC: maxim,max9867: add "mclk" support Add basic support for the codecs' mclk. Enable it on SND_SOC_BIAS_ON, disable it on SND_SOC_BIAS_OFF. Signed-off-by: Benjamin Bara Signed-off-by: Richard Leitner Link: https://lore.kernel.org/r/20230302-max9867-v2-3-fd2036d5e825@skidata.com Signed-off-by: Mark Brown --- sound/soc/codecs/max9867.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/max9867.c b/sound/soc/codecs/max9867.c index e161ab037bf7..ae552d72beec 100644 --- a/sound/soc/codecs/max9867.c +++ b/sound/soc/codecs/max9867.c @@ -6,6 +6,7 @@ // Copyright 2018 Ladislav Michl // +#include #include #include #include @@ -16,6 +17,7 @@ #include "max9867.h" struct max9867_priv { + struct clk *mclk; struct regmap *regmap; const struct snd_pcm_hw_constraint_list *constraints; unsigned int sysclk, pclk; @@ -577,6 +579,11 @@ static int max9867_set_bias_level(struct snd_soc_component *component, struct max9867_priv *max9867 = snd_soc_component_get_drvdata(component); switch (level) { + case SND_SOC_BIAS_ON: + err = clk_prepare_enable(max9867->mclk); + if (err) + return err; + break; case SND_SOC_BIAS_STANDBY: if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) { err = regcache_sync(max9867->regmap); @@ -595,6 +602,7 @@ static int max9867_set_bias_level(struct snd_soc_component *component, return err; regcache_mark_dirty(max9867->regmap); + clk_disable_unprepare(max9867->mclk); break; default: break; @@ -663,9 +671,16 @@ static int max9867_i2c_probe(struct i2c_client *i2c) dev_info(&i2c->dev, "device revision: %x\n", reg); ret = devm_snd_soc_register_component(&i2c->dev, &max9867_component, max9867_dai, ARRAY_SIZE(max9867_dai)); - if (ret < 0) + if (ret < 0) { dev_err(&i2c->dev, "Failed to register component: %d\n", ret); - return ret; + return ret; + } + + max9867->mclk = devm_clk_get(&i2c->dev, NULL); + if (IS_ERR(max9867->mclk)) + return PTR_ERR(max9867->mclk); + + return 0; } static const struct i2c_device_id max9867_i2c_id[] = { From 28ce5698456ab53540093836c6fee15119cf1821 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Wed, 1 Mar 2023 13:38:00 +0200 Subject: [PATCH 115/778] ASoC: mchp-spdiftx: use FIELD_PREP() where possible Use directly FIELD_PREP() marco where possible. There is no need for the extra wrappers. Signed-off-by: Claudiu Beznea Link: https://lore.kernel.org/r/20230301113807.24036-2-claudiu.beznea@microchip.com Signed-off-by: Mark Brown --- sound/soc/atmel/mchp-spdiftx.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/sound/soc/atmel/mchp-spdiftx.c b/sound/soc/atmel/mchp-spdiftx.c index 20d135c718b0..bf4252412f9f 100644 --- a/sound/soc/atmel/mchp-spdiftx.c +++ b/sound/soc/atmel/mchp-spdiftx.c @@ -72,11 +72,9 @@ /* Valid Bits per Sample */ #define SPDIFTX_MR_VBPS_MASK GENMASK(13, 8) -#define SPDIFTX_MR_VBPS(bps) FIELD_PREP(SPDIFTX_MR_VBPS_MASK, bps) /* Chunk Size */ #define SPDIFTX_MR_CHUNK_MASK GENMASK(19, 16) -#define SPDIFTX_MR_CHUNK(size) FIELD_PREP(SPDIFTX_MR_CHUNK_MASK, size) /* Validity Bits for Channels 1 and 2 */ #define SPDIFTX_MR_VALID1 BIT(24) @@ -89,7 +87,6 @@ /* Bytes per Sample */ #define SPDIFTX_MR_BPS_MASK GENMASK(29, 28) -#define SPDIFTX_MR_BPS(bytes) FIELD_PREP(SPDIFTX_MR_BPS_MASK, (bytes - 1)) /* * ---- Interrupt Enable/Disable/Mask/Status Register (Write/Read-only) ---- @@ -402,47 +399,47 @@ static int mchp_spdiftx_hw_params(struct snd_pcm_substream *substream, params_channels(params)); return -EINVAL; } - mr |= SPDIFTX_MR_CHUNK(dev->playback.maxburst); + mr |= FIELD_PREP(SPDIFTX_MR_CHUNK_MASK, dev->playback.maxburst); switch (params_format(params)) { case SNDRV_PCM_FORMAT_S8: - mr |= SPDIFTX_MR_VBPS(8); + mr |= FIELD_PREP(SPDIFTX_MR_VBPS_MASK, 8); break; case SNDRV_PCM_FORMAT_S16_BE: mr |= SPDIFTX_MR_ENDIAN_BIG; fallthrough; case SNDRV_PCM_FORMAT_S16_LE: - mr |= SPDIFTX_MR_VBPS(16); + mr |= FIELD_PREP(SPDIFTX_MR_VBPS_MASK, 16); break; case SNDRV_PCM_FORMAT_S18_3BE: mr |= SPDIFTX_MR_ENDIAN_BIG; fallthrough; case SNDRV_PCM_FORMAT_S18_3LE: - mr |= SPDIFTX_MR_VBPS(18); + mr |= FIELD_PREP(SPDIFTX_MR_VBPS_MASK, 18); break; case SNDRV_PCM_FORMAT_S20_3BE: mr |= SPDIFTX_MR_ENDIAN_BIG; fallthrough; case SNDRV_PCM_FORMAT_S20_3LE: - mr |= SPDIFTX_MR_VBPS(20); + mr |= FIELD_PREP(SPDIFTX_MR_VBPS_MASK, 20); break; case SNDRV_PCM_FORMAT_S24_3BE: mr |= SPDIFTX_MR_ENDIAN_BIG; fallthrough; case SNDRV_PCM_FORMAT_S24_3LE: - mr |= SPDIFTX_MR_VBPS(24); + mr |= FIELD_PREP(SPDIFTX_MR_VBPS_MASK, 24); break; case SNDRV_PCM_FORMAT_S24_BE: mr |= SPDIFTX_MR_ENDIAN_BIG; fallthrough; case SNDRV_PCM_FORMAT_S24_LE: - mr |= SPDIFTX_MR_VBPS(24); + mr |= FIELD_PREP(SPDIFTX_MR_VBPS_MASK, 24); break; case SNDRV_PCM_FORMAT_S32_BE: mr |= SPDIFTX_MR_ENDIAN_BIG; fallthrough; case SNDRV_PCM_FORMAT_S32_LE: - mr |= SPDIFTX_MR_VBPS(32); + mr |= FIELD_PREP(SPDIFTX_MR_VBPS_MASK, 32); break; default: dev_err(dev->dev, "unsupported PCM format: %d\n", @@ -450,7 +447,7 @@ static int mchp_spdiftx_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } - mr |= SPDIFTX_MR_BPS(bps); + mr |= FIELD_PREP(SPDIFTX_MR_BPS_MASK, bps - 1); switch (params_rate(params)) { case 22050: From 0ab4bd5bf277349262065e88eb2feaaabf53584c Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Wed, 1 Mar 2023 13:38:01 +0200 Subject: [PATCH 116/778] ASoC: mchp-spdiftx: use regmap_update_bits() Use regmap_update_bits() instead of regmap_read(), running variable, regmap_write(). There is no need for extra variables and checks around it as regmap_update_bits() already does this. With this code becomes simpler. Signed-off-by: Claudiu Beznea Link: https://lore.kernel.org/r/20230301113807.24036-3-claudiu.beznea@microchip.com Signed-off-by: Mark Brown --- sound/soc/atmel/mchp-spdiftx.c | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/sound/soc/atmel/mchp-spdiftx.c b/sound/soc/atmel/mchp-spdiftx.c index bf4252412f9f..e7241d819748 100644 --- a/sound/soc/atmel/mchp-spdiftx.c +++ b/sound/soc/atmel/mchp-spdiftx.c @@ -306,15 +306,10 @@ static int mchp_spdiftx_trigger(struct snd_pcm_substream *substream, int cmd, { struct mchp_spdiftx_dev *dev = snd_soc_dai_get_drvdata(dai); struct mchp_spdiftx_mixer_control *ctrl = &dev->control; - u32 mr; - int running; int ret; /* do not start/stop while channel status or user data is updated */ spin_lock(&ctrl->lock); - regmap_read(dev->regmap, SPDIFTX_MR, &mr); - running = !!(mr & SPDIFTX_MR_TXEN_ENABLE); - switch (cmd) { case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_START: @@ -323,10 +318,8 @@ static int mchp_spdiftx_trigger(struct snd_pcm_substream *substream, int cmd, dev->suspend_irq = 0; fallthrough; case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - if (!running) { - mr &= ~SPDIFTX_MR_TXEN_MASK; - mr |= SPDIFTX_MR_TXEN_ENABLE; - } + ret = regmap_update_bits(dev->regmap, SPDIFTX_MR, SPDIFTX_MR_TXEN_MASK, + SPDIFTX_MR_TXEN_ENABLE); break; case SNDRV_PCM_TRIGGER_SUSPEND: regmap_read(dev->regmap, SPDIFTX_IMR, &dev->suspend_irq); @@ -336,17 +329,12 @@ static int mchp_spdiftx_trigger(struct snd_pcm_substream *substream, int cmd, SPDIFTX_IR_TXUDR | SPDIFTX_IR_TXOVR); fallthrough; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - if (running) { - mr &= ~SPDIFTX_MR_TXEN_MASK; - mr |= SPDIFTX_MR_TXEN_DISABLE; - } + ret = regmap_update_bits(dev->regmap, SPDIFTX_MR, SPDIFTX_MR_TXEN_MASK, + SPDIFTX_MR_TXEN_DISABLE); break; default: - spin_unlock(&ctrl->lock); - return -EINVAL; + ret = -EINVAL; } - - ret = regmap_write(dev->regmap, SPDIFTX_MR, mr); spin_unlock(&ctrl->lock); if (ret) dev_err(dev->dev, "unable to disable TX: %d\n", ret); From 2d8dad4dc4d4a12afa3c31e72b60727d4c133b99 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Wed, 1 Mar 2023 13:38:02 +0200 Subject: [PATCH 117/778] ASoC: mchp-spdiftx: update debug message Previous debug message states that there was a failure and tx was not disabled. Which is not true as the TX in this function could also be enabled. Thus improve a bit the debug message by s/disable/start\/stop/. Signed-off-by: Claudiu Beznea Link: https://lore.kernel.org/r/20230301113807.24036-4-claudiu.beznea@microchip.com Signed-off-by: Mark Brown --- sound/soc/atmel/mchp-spdiftx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/atmel/mchp-spdiftx.c b/sound/soc/atmel/mchp-spdiftx.c index e7241d819748..02a2fa7a42dd 100644 --- a/sound/soc/atmel/mchp-spdiftx.c +++ b/sound/soc/atmel/mchp-spdiftx.c @@ -337,7 +337,7 @@ static int mchp_spdiftx_trigger(struct snd_pcm_substream *substream, int cmd, } spin_unlock(&ctrl->lock); if (ret) - dev_err(dev->dev, "unable to disable TX: %d\n", ret); + dev_err(dev->dev, "unable to start/stop TX: %d\n", ret); return ret; } From 129742576dd1b972ea1e671595a085e29012f7f3 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Wed, 1 Mar 2023 13:38:03 +0200 Subject: [PATCH 118/778] ASoC: mchp-pdmc: use FIELD_PREP() where possible Use FIELD_PREP() macro where possible instead of driver local defined macros. Signed-off-by: Claudiu Beznea Link: https://lore.kernel.org/r/20230301113807.24036-5-claudiu.beznea@microchip.com Signed-off-by: Mark Brown --- sound/soc/atmel/mchp-pdmc.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/sound/soc/atmel/mchp-pdmc.c b/sound/soc/atmel/mchp-pdmc.c index 1aed3baa9369..6ec5324fd65e 100644 --- a/sound/soc/atmel/mchp-pdmc.c +++ b/sound/soc/atmel/mchp-pdmc.c @@ -8,6 +8,7 @@ #include +#include #include #include #include @@ -49,8 +50,6 @@ #define MCHP_PDMC_MR_OSR256 (3 << 16) #define MCHP_PDMC_MR_SINCORDER_MASK GENMASK(23, 20) -#define MCHP_PDMC_MR_SINCORDER(order) (((order) << 20) & \ - MCHP_PDMC_MR_SINCORDER_MASK) #define MCHP_PDMC_MR_SINC_OSR_MASK GENMASK(27, 24) #define MCHP_PDMC_MR_SINC_OSR_DIS (0 << 24) @@ -62,8 +61,6 @@ #define MCHP_PDMC_MR_SINC_OSR_256 (6 << 24) #define MCHP_PDMC_MR_CHUNK_MASK GENMASK(31, 28) -#define MCHP_PDMC_MR_CHUNK(chunk) (((chunk) << 28) & \ - MCHP_PDMC_MR_CHUNK_MASK) /* * ---- Configuration Register (Read/Write) ---- @@ -617,10 +614,10 @@ static int mchp_pdmc_hw_params(struct snd_pcm_substream *substream, mr_val |= mchp_pdmc_mr_set_osr(dd->audio_filter_en, osr); - mr_val |= MCHP_PDMC_MR_SINCORDER(dd->sinc_order); + mr_val |= FIELD_PREP(MCHP_PDMC_MR_SINCORDER_MASK, dd->sinc_order); dd->addr.maxburst = mchp_pdmc_period_to_maxburst(snd_pcm_lib_period_bytes(substream)); - mr_val |= MCHP_PDMC_MR_CHUNK(dd->addr.maxburst); + mr_val |= FIELD_PREP(MCHP_PDMC_MR_CHUNK_MASK, dd->addr.maxburst); dev_dbg(comp->dev, "maxburst set to %d\n", dd->addr.maxburst); snd_soc_component_update_bits(comp, MCHP_PDMC_MR, From 51124a30308e6db8658575e5d9ec1ea3cb3ba3c3 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Wed, 1 Mar 2023 13:38:04 +0200 Subject: [PATCH 119/778] ASoC: mchp-pdmc: return directly ret Return directly ret instead of having different branches for error and OK paths. Signed-off-by: Claudiu Beznea Link: https://lore.kernel.org/r/20230301113807.24036-6-claudiu.beznea@microchip.com Signed-off-by: Mark Brown --- sound/soc/atmel/mchp-pdmc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/atmel/mchp-pdmc.c b/sound/soc/atmel/mchp-pdmc.c index 6ec5324fd65e..853a7adfd654 100644 --- a/sound/soc/atmel/mchp-pdmc.c +++ b/sound/soc/atmel/mchp-pdmc.c @@ -759,12 +759,10 @@ static int mchp_pdmc_pcm_new(struct snd_soc_pcm_runtime *rtd, int ret; ret = mchp_pdmc_add_chmap_ctls(rtd->pcm, dd); - if (ret < 0) { + if (ret < 0) dev_err(dd->dev, "failed to add channel map controls: %d\n", ret); - return ret; - } - return 0; + return ret; } static struct snd_soc_dai_driver mchp_pdmc_dai = { From cb72b29cd5cfac20894a040e411dec70bb75097c Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Wed, 1 Mar 2023 13:38:05 +0200 Subject: [PATCH 120/778] ASoC: mchp-pdmc: avoid casting to/from void pointer Do not cast to and from void pointer. There is no need for this. Signed-off-by: Claudiu Beznea Link: https://lore.kernel.org/r/20230301113807.24036-7-claudiu.beznea@microchip.com Signed-off-by: Mark Brown --- sound/soc/atmel/mchp-pdmc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/atmel/mchp-pdmc.c b/sound/soc/atmel/mchp-pdmc.c index 853a7adfd654..81bfa98fd516 100644 --- a/sound/soc/atmel/mchp-pdmc.c +++ b/sound/soc/atmel/mchp-pdmc.c @@ -783,7 +783,7 @@ static struct snd_soc_dai_driver mchp_pdmc_dai = { /* PDMC interrupt handler */ static irqreturn_t mchp_pdmc_interrupt(int irq, void *dev_id) { - struct mchp_pdmc *dd = (struct mchp_pdmc *)dev_id; + struct mchp_pdmc *dd = dev_id; u32 isr, msr, pending; irqreturn_t ret = IRQ_NONE; @@ -1077,7 +1077,7 @@ static int mchp_pdmc_probe(struct platform_device *pdev) } ret = devm_request_irq(dev, irq, mchp_pdmc_interrupt, 0, - dev_name(&pdev->dev), (void *)dd); + dev_name(&pdev->dev), dd); if (ret < 0) { dev_err(dev, "can't register ISR for IRQ %u (ret=%i)\n", irq, ret); From 8f943f00d7a844daa9acafd304c2178f30ecc255 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Wed, 1 Mar 2023 13:38:06 +0200 Subject: [PATCH 121/778] MAINTAINERS: add myself as maintainer for Microchip AT91 sound drivers Codrin is not with Microchip anymore. As I worked lately with Microchip AT91 sound drivers add myself as maintainer for these. Signed-off-by: Claudiu Beznea Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230301113807.24036-8-claudiu.beznea@microchip.com Signed-off-by: Mark Brown --- MAINTAINERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 8d5bc223f305..2fb66b564224 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -13593,7 +13593,7 @@ F: Documentation/devicetree/bindings/serial/atmel,at91-usart.yaml F: drivers/spi/spi-at91-usart.c MICROCHIP AUDIO ASOC DRIVERS -M: Codrin Ciubotariu +M: Claudiu Beznea L: alsa-devel@alsa-project.org (moderated for non-subscribers) S: Supported F: sound/soc/atmel @@ -13768,7 +13768,7 @@ S: Supported F: drivers/spi/spi-atmel.* MICROCHIP SSC DRIVER -M: Codrin Ciubotariu +M: Claudiu Beznea L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Supported F: drivers/misc/atmel-ssc.c From 15dbfc04e6865bae1aa275216baa1a7eb55cd2cf Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Wed, 1 Mar 2023 13:38:07 +0200 Subject: [PATCH 122/778] MAINTAINERS: update Microchip AT91 sound entries with documentation files Add documentation files to Microchip AT91 sound entries. Signed-off-by: Claudiu Beznea Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230301113807.24036-9-claudiu.beznea@microchip.com Signed-off-by: Mark Brown --- MAINTAINERS | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 2fb66b564224..6b730e8be8c1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -13596,6 +13596,10 @@ MICROCHIP AUDIO ASOC DRIVERS M: Claudiu Beznea L: alsa-devel@alsa-project.org (moderated for non-subscribers) S: Supported +F: Documentation/devicetree/bindings/sound/atmel* +F: Documentation/devicetree/bindings/sound/axentia,tse850-pcm5142.txt +F: Documentation/devicetree/bindings/sound/microchip,sama7g5-* +F: Documentation/devicetree/bindings/sound/mikroe,mikroe-proto.txt F: sound/soc/atmel MICROCHIP CSI2DC DRIVER @@ -13771,6 +13775,7 @@ MICROCHIP SSC DRIVER M: Claudiu Beznea L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Supported +F: Documentation/devicetree/bindings/misc/atmel-ssc.txt F: drivers/misc/atmel-ssc.c F: include/linux/atmel-ssc.h From c9ef0fee3bdf8197538aadc728e475fceba113bb Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Fri, 3 Mar 2023 10:04:57 -0800 Subject: [PATCH 123/778] ASoC: Intel: avs: Use struct_size for struct avs_modcfg_ext size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The struct avs_modcfg_ext structure has a flexible array member for the pin_fmts array, and the size should be calculated using struct_size to prevent the potential for overflow with the allocation. Reviewed-by: Cezary Rojewski Reviewed-by: "Amadeusz Sławiński" Signed-off-by: Jacob Keller Link: https://lore.kernel.org/r/20230303180457.2457069-1-jacob.e.keller@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/path.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/avs/path.c b/sound/soc/intel/avs/path.c index 05302ab705ae..adbe23a47847 100644 --- a/sound/soc/intel/avs/path.c +++ b/sound/soc/intel/avs/path.c @@ -478,7 +478,7 @@ static int avs_modext_create(struct avs_dev *adev, struct avs_path_module *mod) int ret, i; num_pins = tcfg->generic.num_input_pins + tcfg->generic.num_output_pins; - cfg_size = sizeof(*cfg) + sizeof(*cfg->pin_fmts) * num_pins; + cfg_size = struct_size(cfg, pin_fmts, num_pins); cfg = kzalloc(cfg_size, GFP_KERNEL); if (!cfg) From af5932fc58d351d3908d0a732ccabaef088311a0 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 17 Feb 2023 16:06:25 +0100 Subject: [PATCH 124/778] ASoC: dt-bindings: wlf,wm8960: Convert to dtschema Convert the Wolfson WM8960 audio codecs bindings to DT schema. Changes against original binding: 1. Document clocks and clock-names - already present in DTS and used by Linux driver. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Rob Herring Acked-by: Charles Keepax Link: https://lore.kernel.org/r/20230217150627.779764-1-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/wlf,wm8960.yaml | 88 +++++++++++++++++++ .../devicetree/bindings/sound/wm8960.txt | 42 --------- 2 files changed, 88 insertions(+), 42 deletions(-) create mode 100644 Documentation/devicetree/bindings/sound/wlf,wm8960.yaml delete mode 100644 Documentation/devicetree/bindings/sound/wm8960.txt diff --git a/Documentation/devicetree/bindings/sound/wlf,wm8960.yaml b/Documentation/devicetree/bindings/sound/wlf,wm8960.yaml new file mode 100644 index 000000000000..ee8eba7f0104 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/wlf,wm8960.yaml @@ -0,0 +1,88 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/wlf,wm8960.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Wolfson WM8960 audio codec + +maintainers: + - patches@opensource.cirrus.com + +properties: + compatible: + const: wlf,wm8960 + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-names: + items: + - const: mclk + + '#sound-dai-cells': + const: 0 + + wlf,capless: + type: boolean + description: + If present, OUT3 pin will be enabled and disabled together with HP_L and + HP_R pins in response to jack detect events. + + wlf,gpio-cfg: + $ref: /schemas/types.yaml#/definitions/uint32-array + maxItems: 2 + description: | + A list of GPIO configuration register values. + - gpio-cfg[0]: ALRCGPIO of R9 (Audio interface) + - gpio-cfg[1]: {GPIOPOL:GPIOSEL[2:0]} of R48 (Additional Control 4). + + wlf,hp-cfg: + $ref: /schemas/types.yaml#/definitions/uint32-array + maxItems: 3 + description: | + A list of headphone jack detect configuration register values: + - hp-cfg[0]: HPSEL[1:0] of R48 (Additional Control 4). + - hp-cfg[1]: {HPSWEN:HPSWPOL} of R24 (Additional Control 2). + - hp-cfg[2]: {TOCLKSEL:TOEN} of R23 (Additional Control 1). + + wlf,shared-lrclk: + type: boolean + description: + If present, the LRCM bit of R24 (Additional control 2) gets set, + indicating that ADCLRC and DACLRC pins will be disabled only when ADC + (Left and Right) and DAC (Left and Right) are disabled. + When WM8960 works on synchronize mode and DACLRC pin is used to supply + frame clock, it will no frame clock for captrue unless enable DAC to + enable DACLRC pin. If shared-lrclk is present, no need to enable DAC for + captrue. + +required: + - compatible + - reg + +allOf: + - $ref: dai-common.yaml# + +unevaluatedProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + + audio-codec@1a { + compatible = "wlf,wm8960"; + reg = <0x1a>; + clocks = <&clks 0>; + clock-names = "mclk"; + #sound-dai-cells = <0>; + wlf,hp-cfg = <3 2 3>; + wlf,gpio-cfg = <1 3>; + wlf,shared-lrclk; + }; + }; diff --git a/Documentation/devicetree/bindings/sound/wm8960.txt b/Documentation/devicetree/bindings/sound/wm8960.txt deleted file mode 100644 index 85d3b287108c..000000000000 --- a/Documentation/devicetree/bindings/sound/wm8960.txt +++ /dev/null @@ -1,42 +0,0 @@ -WM8960 audio CODEC - -This device supports I2C only. - -Required properties: - - - compatible : "wlf,wm8960" - - - reg : the I2C address of the device. - -Optional properties: - - wlf,shared-lrclk: This is a boolean property. If present, the LRCM bit of - R24 (Additional control 2) gets set, indicating that ADCLRC and DACLRC pins - will be disabled only when ADC (Left and Right) and DAC (Left and Right) - are disabled. - When wm8960 works on synchronize mode and DACLRC pin is used to supply - frame clock, it will no frame clock for captrue unless enable DAC to enable - DACLRC pin. If shared-lrclk is present, no need to enable DAC for captrue. - - - wlf,capless: This is a boolean property. If present, OUT3 pin will be - enabled and disabled together with HP_L and HP_R pins in response to jack - detect events. - - - wlf,hp-cfg: A list of headphone jack detect configuration register values. - The list must be 3 entries long. - hp-cfg[0]: HPSEL[1:0] of R48 (Additional Control 4). - hp-cfg[1]: {HPSWEN:HPSWPOL} of R24 (Additional Control 2). - hp-cfg[2]: {TOCLKSEL:TOEN} of R23 (Additional Control 1). - - - wlf,gpio-cfg: A list of GPIO configuration register values. - The list must be 2 entries long. - gpio-cfg[0]: ALRCGPIO of R9 (Audio interface) - gpio-cfg[1]: {GPIOPOL:GPIOSEL[2:0]} of R48 (Additional Control 4). - -Example: - -wm8960: codec@1a { - compatible = "wlf,wm8960"; - reg = <0x1a>; - - wlf,shared-lrclk; -}; From 5ddcf9768f7a15da997259038c16a9e00c06aa87 Mon Sep 17 00:00:00 2001 From: Chancel Liu Date: Mon, 27 Feb 2023 17:19:37 +0800 Subject: [PATCH 125/778] ASoC: dt-bindings: wlf,wm8524: Convert to json-schema Convert the Wolfson WM8524 24-bit 192KHz Stereo DAC device tree binding documentation to json-schema. Signed-off-by: Chancel Liu Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230227091938.1671416-1-chancel.liu@nxp.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/wlf,wm8524.yaml | 40 +++++++++++++++++++ .../devicetree/bindings/sound/wm8524.txt | 16 -------- 2 files changed, 40 insertions(+), 16 deletions(-) create mode 100644 Documentation/devicetree/bindings/sound/wlf,wm8524.yaml delete mode 100644 Documentation/devicetree/bindings/sound/wm8524.txt diff --git a/Documentation/devicetree/bindings/sound/wlf,wm8524.yaml b/Documentation/devicetree/bindings/sound/wlf,wm8524.yaml new file mode 100644 index 000000000000..4d951ece394e --- /dev/null +++ b/Documentation/devicetree/bindings/sound/wlf,wm8524.yaml @@ -0,0 +1,40 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/wlf,wm8524.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Wolfson WM8524 24-bit 192KHz Stereo DAC + +maintainers: + - patches@opensource.cirrus.com + +allOf: + - $ref: dai-common.yaml# + +properties: + compatible: + const: wlf,wm8524 + + "#sound-dai-cells": + const: 0 + + wlf,mute-gpios: + maxItems: 1 + description: + a GPIO spec for the MUTE pin. + +required: + - compatible + - wlf,mute-gpios + +unevaluatedProperties: false + +examples: + - | + #include + + wm8524: codec { + compatible = "wlf,wm8524"; + wlf,mute-gpios = <&gpio1 8 GPIO_ACTIVE_LOW>; + }; diff --git a/Documentation/devicetree/bindings/sound/wm8524.txt b/Documentation/devicetree/bindings/sound/wm8524.txt deleted file mode 100644 index f6c0c263b135..000000000000 --- a/Documentation/devicetree/bindings/sound/wm8524.txt +++ /dev/null @@ -1,16 +0,0 @@ -WM8524 audio CODEC - -This device does not use I2C or SPI but a simple Hardware Control Interface. - -Required properties: - - - compatible : "wlf,wm8524" - - - wlf,mute-gpios: a GPIO spec for the MUTE pin. - -Example: - -wm8524: codec { - compatible = "wlf,wm8524"; - wlf,mute-gpios = <&gpio1 8 GPIO_ACTIVE_LOW>; -}; From 4c2c935a278e53bf9a1713bb0a01ce299a994e9b Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Thu, 2 Mar 2023 10:46:16 +0000 Subject: [PATCH 126/778] ASoC: qcom: common: add kcontrol to jack pins Add Kcontrol to jack pins so that device switch in ucm can be done correctly. Signed-off-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20230302104616.26318-1-srinivas.kandagatla@linaro.org Signed-off-by: Mark Brown --- sound/soc/qcom/common.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/sound/soc/qcom/common.c b/sound/soc/qcom/common.c index 96fe80241fb4..c1f24af17506 100644 --- a/sound/soc/qcom/common.c +++ b/sound/soc/qcom/common.c @@ -180,6 +180,18 @@ err_put_np: } EXPORT_SYMBOL_GPL(qcom_snd_parse_of); +static struct snd_soc_jack_pin qcom_headset_jack_pins[] = { + /* Headset */ + { + .pin = "Mic Jack", + .mask = SND_JACK_MICROPHONE, + }, + { + .pin = "Headphone Jack", + .mask = SND_JACK_HEADPHONE, + }, +}; + int qcom_snd_wcd_jack_setup(struct snd_soc_pcm_runtime *rtd, struct snd_soc_jack *jack, bool *jack_setup) { @@ -189,13 +201,14 @@ int qcom_snd_wcd_jack_setup(struct snd_soc_pcm_runtime *rtd, int rval, i; if (!*jack_setup) { - rval = snd_soc_card_jack_new(card, "Headset Jack", + rval = snd_soc_card_jack_new_pins(card, "Headset Jack", SND_JACK_HEADSET | SND_JACK_LINEOUT | SND_JACK_MECHANICAL | SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2 | SND_JACK_BTN_3 | SND_JACK_BTN_4 | SND_JACK_BTN_5, - jack); + jack, qcom_headset_jack_pins, + ARRAY_SIZE(qcom_headset_jack_pins)); if (rval < 0) { dev_err(card->dev, "Unable to add Headphone Jack\n"); From cd01b5f090434e7b2661aee208745539c552f5d2 Mon Sep 17 00:00:00 2001 From: Seven Lee Date: Fri, 17 Feb 2023 17:25:23 +0800 Subject: [PATCH 127/778] ASoC: nau8821: Implement DRC controls This patch is support dynamic range compression controls. Signed-off-by: Seven Lee Signed-off-by: Seven Lee Link: https://lore.kernel.org/r/20230217092523.357142-1-wtli@nuvoton.com Signed-off-by: Mark Brown --- sound/soc/codecs/nau8821.c | 96 ++++++++++++++++++++++++++++++++++++++ sound/soc/codecs/nau8821.h | 23 +++++++++ 2 files changed, 119 insertions(+) diff --git a/sound/soc/codecs/nau8821.c b/sound/soc/codecs/nau8821.c index 4a72b94e8410..fee970427a24 100644 --- a/sound/soc/codecs/nau8821.c +++ b/sound/soc/codecs/nau8821.c @@ -322,12 +322,92 @@ static const struct soc_enum nau8821_dac_oversampl_enum = SOC_ENUM_SINGLE(NAU8821_R2C_DAC_CTRL1, NAU8821_DAC_OVERSAMPLE_SFT, ARRAY_SIZE(nau8821_dac_oversampl), nau8821_dac_oversampl); +static const char * const nau8821_adc_drc_noise_gate[] = { + "1:1", "2:1", "4:1", "8:1" }; + +static const struct soc_enum nau8821_adc_drc_noise_gate_enum = + SOC_ENUM_SINGLE(NAU8821_R38_ADC_DRC_SLOPES, NAU8821_DRC_NG_SLP_ADC_SFT, + ARRAY_SIZE(nau8821_adc_drc_noise_gate), + nau8821_adc_drc_noise_gate); + +static const char * const nau8821_adc_drc_expansion_slope[] = { + "1:1", "2:1", "4:1" }; + +static const struct soc_enum nau8821_adc_drc_expansion_slope_enum = + SOC_ENUM_SINGLE(NAU8821_R38_ADC_DRC_SLOPES, NAU8821_DRC_EXP_SLP_ADC_SFT, + ARRAY_SIZE(nau8821_adc_drc_expansion_slope), + nau8821_adc_drc_expansion_slope); + +static const char * const nau8821_adc_drc_lower_region[] = { + "0", "1:2", "1:4", "1:8", "1:16", "", "", "1:1" }; + +static const struct soc_enum nau8821_adc_drc_lower_region_enum = + SOC_ENUM_SINGLE(NAU8821_R38_ADC_DRC_SLOPES, + NAU8821_DRC_CMP2_SLP_ADC_SFT, + ARRAY_SIZE(nau8821_adc_drc_lower_region), + nau8821_adc_drc_lower_region); + +static const char * const nau8821_higher_region[] = { + "0", "1:2", "1:4", "1:8", "1:16", "", "", "1:1" }; + +static const struct soc_enum nau8821_higher_region_enum = + SOC_ENUM_SINGLE(NAU8821_R38_ADC_DRC_SLOPES, + NAU8821_DRC_CMP1_SLP_ADC_SFT, + ARRAY_SIZE(nau8821_higher_region), + nau8821_higher_region); + +static const char * const nau8821_limiter_slope[] = { + "0", "1:2", "1:4", "1:8", "1:16", "1:32", "1:64", "1:1" }; + +static const struct soc_enum nau8821_limiter_slope_enum = + SOC_ENUM_SINGLE(NAU8821_R38_ADC_DRC_SLOPES, + NAU8821_DRC_LMT_SLP_ADC_SFT, ARRAY_SIZE(nau8821_limiter_slope), + nau8821_limiter_slope); + +static const char * const nau8821_detection_attack_time[] = { + "Ts", "3Ts", "7Ts", "15Ts", "31Ts", "63Ts", "127Ts", "255Ts", + "", "511Ts" }; + +static const struct soc_enum nau8821_detection_attack_time_enum = + SOC_ENUM_SINGLE(NAU8821_R39_ADC_DRC_ATKDCY, + NAU8821_DRC_PK_COEF1_ADC_SFT, + ARRAY_SIZE(nau8821_detection_attack_time), + nau8821_detection_attack_time); + +static const char * const nau8821_detection_release_time[] = { + "63Ts", "127Ts", "255Ts", "511Ts", "1023Ts", "2047Ts", "4095Ts", + "8191Ts", "", "16383Ts" }; + +static const struct soc_enum nau8821_detection_release_time_enum = + SOC_ENUM_SINGLE(NAU8821_R39_ADC_DRC_ATKDCY, + NAU8821_DRC_PK_COEF2_ADC_SFT, + ARRAY_SIZE(nau8821_detection_release_time), + nau8821_detection_release_time); + +static const char * const nau8821_attack_time[] = { + "Ts", "3Ts", "7Ts", "15Ts", "31Ts", "63Ts", "127Ts", "255Ts", + "511Ts", "1023Ts", "2047Ts", "4095Ts", "8191Ts" }; + +static const struct soc_enum nau8821_attack_time_enum = + SOC_ENUM_SINGLE(NAU8821_R39_ADC_DRC_ATKDCY, NAU8821_DRC_ATK_ADC_SFT, + ARRAY_SIZE(nau8821_attack_time), nau8821_attack_time); + +static const char * const nau8821_decay_time[] = { + "63Ts", "127Ts", "255Ts", "511Ts", "1023Ts", "2047Ts", "4095Ts", + "8191Ts", "16383Ts", "32757Ts", "65535Ts" }; + +static const struct soc_enum nau8821_decay_time_enum = + SOC_ENUM_SINGLE(NAU8821_R39_ADC_DRC_ATKDCY, NAU8821_DRC_DCY_ADC_SFT, + ARRAY_SIZE(nau8821_decay_time), nau8821_decay_time); + static const DECLARE_TLV_DB_MINMAX_MUTE(adc_vol_tlv, -6600, 2400); static const DECLARE_TLV_DB_MINMAX_MUTE(sidetone_vol_tlv, -4200, 0); static const DECLARE_TLV_DB_MINMAX(hp_vol_tlv, -900, 0); static const DECLARE_TLV_DB_SCALE(playback_vol_tlv, -6600, 50, 1); static const DECLARE_TLV_DB_MINMAX(fepga_gain_tlv, -100, 3600); static const DECLARE_TLV_DB_MINMAX_MUTE(crosstalk_vol_tlv, -7000, 2400); +static const DECLARE_TLV_DB_MINMAX(drc_knee4_tlv, -9800, -3500); +static const DECLARE_TLV_DB_MINMAX(drc_knee3_tlv, -8100, -1800); static const struct snd_kcontrol_new nau8821_controls[] = { SOC_DOUBLE_TLV("Mic Volume", NAU8821_R35_ADC_DGAIN_CTRL1, @@ -346,6 +426,22 @@ static const struct snd_kcontrol_new nau8821_controls[] = { SOC_DOUBLE_TLV("Headphone Crosstalk Volume", NAU8821_R2F_DAC_DGAIN_CTRL, 0, 8, 0xff, 0, crosstalk_vol_tlv), + SOC_SINGLE_TLV("ADC DRC KNEE4", NAU8821_R37_ADC_DRC_KNEE_IP34, + NAU8821_DRC_KNEE4_IP_ADC_SFT, 0x3f, 1, drc_knee4_tlv), + SOC_SINGLE_TLV("ADC DRC KNEE3", NAU8821_R37_ADC_DRC_KNEE_IP34, + NAU8821_DRC_KNEE3_IP_ADC_SFT, 0x3f, 1, drc_knee3_tlv), + + SOC_ENUM("ADC DRC Noise Gate", nau8821_adc_drc_noise_gate_enum), + SOC_ENUM("ADC DRC Expansion Slope", nau8821_adc_drc_expansion_slope_enum), + SOC_ENUM("ADC DRC Lower Region", nau8821_adc_drc_lower_region_enum), + SOC_ENUM("ADC DRC Higher Region", nau8821_higher_region_enum), + SOC_ENUM("ADC DRC Limiter Slope", nau8821_limiter_slope_enum), + SOC_ENUM("ADC DRC Peak Detection Attack Time", nau8821_detection_attack_time_enum), + SOC_ENUM("ADC DRC Peak Detection Release Time", nau8821_detection_release_time_enum), + SOC_ENUM("ADC DRC Attack Time", nau8821_attack_time_enum), + SOC_ENUM("ADC DRC Decay Time", nau8821_decay_time_enum), + SOC_SINGLE("DRC Enable Switch", NAU8821_R36_ADC_DRC_KNEE_IP12, + NAU8821_DRC_ENA_ADC_SFT, 1, 0), SOC_ENUM("ADC Decimation Rate", nau8821_adc_decimation_enum), SOC_ENUM("DAC Oversampling Rate", nau8821_dac_oversampl_enum), diff --git a/sound/soc/codecs/nau8821.h b/sound/soc/codecs/nau8821.h index c44251f54d48..d962293c218e 100644 --- a/sound/soc/codecs/nau8821.h +++ b/sound/soc/codecs/nau8821.h @@ -350,6 +350,29 @@ #define NAU8821_ADCL_CH_VOL_SFT 0 #define NAU8821_ADCL_CH_VOL_MASK 0xff +/* ADC_DRC_KNEE_IP12 (0x36) */ +#define NAU8821_DRC_ENA_ADC_SFT 15 +#define NAU8821_DRC_ENA_ADC_EN (0x1 << NAU8821_DRC_ENA_ADC_SFT) + +/* ADC_DRC_KNEE_IP34 (0x37) */ +#define NAU8821_DRC_KNEE4_IP_ADC_SFT 8 +#define NAU8821_DRC_KNEE4_IP_ADC_MASK (0xff << NAU8821_DRC_KNEE4_IP_ADC_SFT) +#define NAU8821_DRC_KNEE3_IP_ADC_SFT 0 +#define NAU8821_DRC_KNEE3_IP_ADC_MASK 0xff + +/* ADC_DRC_SLOPES (0x38) */ +#define NAU8821_DRC_NG_SLP_ADC_SFT 12 +#define NAU8821_DRC_EXP_SLP_ADC_SFT 9 +#define NAU8821_DRC_CMP2_SLP_ADC_SFT 6 +#define NAU8821_DRC_CMP1_SLP_ADC_SFT 3 +#define NAU8821_DRC_LMT_SLP_ADC_SFT 0 + +/* ADC_DRC_ATKDCY (0x39) */ +#define NAU8821_DRC_PK_COEF1_ADC_SFT 12 +#define NAU8821_DRC_PK_COEF2_ADC_SFT 8 +#define NAU8821_DRC_ATK_ADC_SFT 4 +#define NAU8821_DRC_DCY_ADC_SFT 0 + /* BIQ1_COF10 (0x4a) */ #define NAU8821_BIQ1_DAC_EN_SFT 3 #define NAU8821_BIQ1_DAC_EN_EN (0x1 << NAU8821_BIQ1_DAC_EN_SFT) From 587cbe99152fd735605f3502f42f640bb54f6048 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 23 Feb 2023 21:42:26 -0600 Subject: [PATCH 128/778] ASoC: SOF: ipc4-topology: Replace fake flexible arrays with flexible-array member MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Zero-length arrays as fake flexible arrays are deprecated and we are moving towards adopting C99 flexible-array members, instead. Use the DECLARE_FLEX_ARRAY() helper macro to transform zero-length arrays in unions with flexible-array members. Address the following warnings found with GCC-13 and -fstrict-flex-arrays=3 enabled: sound/soc/sof/ipc4-control.c:176:77: warning: array subscript i is outside array bounds of ‘struct sof_ipc4_ctrl_value_chan[0]’ [-Warray-bounds=] sound/soc/sof/ipc4-control.c:78:29: warning: array subscript 0 is outside array bounds of ‘struct sof_ipc4_ctrl_value_chan[0]’ [-Warray-bounds=] sound/soc/sof/ipc4-control.c:80:33: warning: array subscript i is outside array bounds of ‘struct sof_ipc4_ctrl_value_chan[0]’ [-Warray-bounds=] sound/soc/sof/ipc4-control.c:95:53: warning: array subscript i is outside array bounds of ‘struct sof_ipc4_ctrl_value_chan[0]’ [-Warray-bounds=] sound/soc/sof/ipc4-control.c:96:53: warning: array subscript i is outside array bounds of ‘struct sof_ipc4_ctrl_value_chan[0]’ [-Warray-bounds=] sound/soc/sof/ipc4-control.c:93:53: warning: array subscript 0 is outside array bounds of ‘struct sof_ipc4_ctrl_value_chan[0]’ [-Warray-bounds=] sound/soc/sof/ipc4-control.c:140:58: warning: array subscript i is outside array bounds of ‘struct sof_ipc4_ctrl_value_chan[0]’ [-Warray-bounds=] sound/soc/sof/ipc4-control.c:141:29: warning: array subscript i is outside array bounds of ‘struct sof_ipc4_ctrl_value_chan[0]’ [-Warray-bounds=] sound/soc/sof/ipc4-control.c:142:29: warning: array subscript i is outside array bounds of ‘struct sof_ipc4_ctrl_value_chan[0]’ [-Warray-bounds=] sound/soc/sof/ipc4-topology.c:1475:36: warning: array subscript i is outside array bounds of ‘struct sof_ipc4_ctrl_value_chan[0]’ [-Warray-bounds=] sound/soc/sof/ipc4-topology.c:1476:36: warning: array subscript i is outside array bounds of ‘struct sof_ipc4_ctrl_value_chan[0]’ [-Warray-bounds=] This helps with the ongoing efforts to tighten the FORTIFY_SOURCE routines on memcpy() and help us make progress towards globally enabling -fstrict-flex-arrays=3 [1]. Link: https://github.com/KSPP/linux/issues/21 Link: https://github.com/KSPP/linux/issues/193 Link: https://github.com/KSPP/linux/issues/258 Link: https://gcc.gnu.org/pipermail/gcc-patches/2022-October/602902.html [1] Signed-off-by: Gustavo A. R. Silva Acked-by: Peter Ujfalusi Link: https://lore.kernel.org/r/Y/gyIg1qZduhigPi@work Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/ipc4-topology.h b/sound/soc/sof/ipc4-topology.h index 72529179ac22..8507171a6e4d 100644 --- a/sound/soc/sof/ipc4-topology.h +++ b/sound/soc/sof/ipc4-topology.h @@ -266,8 +266,8 @@ struct sof_ipc4_control_data { int index; union { - struct sof_ipc4_ctrl_value_chan chanv[0]; - struct sof_abi_hdr data[0]; + DECLARE_FLEX_ARRAY(struct sof_ipc4_ctrl_value_chan, chanv); + DECLARE_FLEX_ARRAY(struct sof_abi_hdr, data); }; }; From 7f8b5b24bbb463614dd6b797e6b2ee92b3e2a6a1 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 13 Feb 2023 02:13:06 +0000 Subject: [PATCH 129/778] ASoC: dt-bindings: renesas,rsnd.yaml: add R-Car Gen4 support There are no compatible for "reg/reg-names" and "clock-name" between previous R-Car series and R-Car Gen4. "reg/reg-names" needs 3 categorize (for Gen1, for Gen2/Gen3, for Gen4), therefore, use 3 if-then to avoid nested if-then-else. Move "clock-name" detail properties to under allOf to use if-then-else for Gen4 or others. Link: https://lore.kernel.org/all/87zg9vk0ex.wl-kuninori.morimoto.gx@renesas.com/#r Link: https://lore.kernel.org/all/87r0v2uvm7.wl-kuninori.morimoto.gx@renesas.com/#r Link: https://lore.kernel.org/all/87r0v1t02h.wl-kuninori.morimoto.gx@renesas.com/#r Link: https://lore.kernel.org/all/87y1p7bpma.wl-kuninori.morimoto.gx@renesas.com/#r Reported-by: Geert Uytterhoeven Signed-off-by: Kuninori Morimoto Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/87sffa8g99.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- .../bindings/sound/renesas,rsnd.yaml | 76 ++++++++++++++++--- 1 file changed, 64 insertions(+), 12 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/renesas,rsnd.yaml b/Documentation/devicetree/bindings/sound/renesas,rsnd.yaml index 12ccf29338d9..55e5213b90a1 100644 --- a/Documentation/devicetree/bindings/sound/renesas,rsnd.yaml +++ b/Documentation/devicetree/bindings/sound/renesas,rsnd.yaml @@ -101,17 +101,7 @@ properties: clock-names: description: List of necessary clock names. - minItems: 1 - maxItems: 31 - items: - oneOf: - - const: ssi-all - - pattern: '^ssi\.[0-9]$' - - pattern: '^src\.[0-9]$' - - pattern: '^mix\.[0-1]$' - - pattern: '^ctu\.[0-1]$' - - pattern: '^dvc\.[0-1]$' - - pattern: '^clk_(a|b|c|i)$' + # details are defined below ports: $ref: audio-graph-port.yaml#/definitions/port-base @@ -288,6 +278,11 @@ required: allOf: - $ref: dai-common.yaml# + + #-------------------- + # reg/reg-names + #-------------------- + # for Gen1 - if: properties: compatible: @@ -303,7 +298,15 @@ allOf: - scu - ssi - adg - else: + # for Gen2/Gen3 + - if: + properties: + compatible: + contains: + enum: + - renesas,rcar_sound-gen2 + - renesas,rcar_sound-gen3 + then: properties: reg: minItems: 5 @@ -315,6 +318,55 @@ allOf: - ssiu - ssi - audmapp + # for Gen4 + - if: + properties: + compatible: + contains: + const: renesas,rcar_sound-gen4 + then: + properties: + reg: + maxItems: 4 + reg-names: + items: + enum: + - adg + - ssiu + - ssi + - sdmc + + #-------------------- + # clock-names + #-------------------- + - if: + properties: + compatible: + contains: + const: renesas,rcar_sound-gen4 + then: + properties: + clock-names: + maxItems: 3 + items: + enum: + - ssi.0 + - ssiu.0 + - clkin + else: + properties: + clock-names: + minItems: 1 + maxItems: 31 + items: + oneOf: + - const: ssi-all + - pattern: '^ssi\.[0-9]$' + - pattern: '^src\.[0-9]$' + - pattern: '^mix\.[0-1]$' + - pattern: '^ctu\.[0-1]$' + - pattern: '^dvc\.[0-1]$' + - pattern: '^clk_(a|b|c|i)$' unevaluatedProperties: false From a2d4051b0bd6dffcd736888ae89a550d6f60b060 Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Tue, 21 Feb 2023 20:32:03 +0200 Subject: [PATCH 130/778] ASoC: jack: allow multiple interrupt per gpio This feature is required for coupled hp-mic quirk used by some Nvidia Tegra 3 based devices work properly. Signed-off-by: Svyatoslav Ryhel Link: https://lore.kernel.org/r/20230221183211.21964-3-clamor95@gmail.com Signed-off-by: Mark Brown --- sound/soc/soc-jack.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c index fcece5ca38c6..f951acb2ce36 100644 --- a/sound/soc/soc-jack.c +++ b/sound/soc/soc-jack.c @@ -367,6 +367,7 @@ got_gpio: ret = request_any_context_irq(gpiod_to_irq(gpios[i].desc), gpio_handler, + IRQF_SHARED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, gpios[i].name, From 0106ba2476e1cce06da738a2076a98428a7da2a2 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 20 Feb 2023 10:56:42 +0100 Subject: [PATCH 131/778] ASoC: dt-bindings: qcom,wcd934x: Reference dai-common Reference common DAI properties to get sound-dai-cells description and allow name-prefix. Signed-off-by: Krzysztof Kozlowski Acked-by: Rob Herring Link: https://lore.kernel.org/r/20230220095643.64898-1-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/qcom,wcd934x.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/sound/qcom,wcd934x.yaml b/Documentation/devicetree/bindings/sound/qcom,wcd934x.yaml index ea09590bfa30..ae8346b9d332 100644 --- a/Documentation/devicetree/bindings/sound/qcom,wcd934x.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,wcd934x.yaml @@ -151,6 +151,7 @@ required: - reg allOf: + - $ref: dai-common.yaml# - if: required: - slim-ifc-dev From 631b8a8bb448e90764b8d4b6c0f8cdcc97b1e3e4 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 20 Feb 2023 10:56:43 +0100 Subject: [PATCH 132/778] ASoC: dt-bindings: qcom,wcd9335: Convert to dtschema Convert the Qualcomm WCD9335 audio codec binding to DT schema. Changes against original binding: 1. Drop "mclk2" from clocks as neither Linux driver nor DTS uses it. 2. Do not require vdd-micbias-supply as several DTS do not provide it. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20230220095643.64898-2-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- .../bindings/sound/qcom,wcd9335.txt | 123 -------------- .../bindings/sound/qcom,wcd9335.yaml | 156 ++++++++++++++++++ 2 files changed, 156 insertions(+), 123 deletions(-) delete mode 100644 Documentation/devicetree/bindings/sound/qcom,wcd9335.txt create mode 100644 Documentation/devicetree/bindings/sound/qcom,wcd9335.yaml diff --git a/Documentation/devicetree/bindings/sound/qcom,wcd9335.txt b/Documentation/devicetree/bindings/sound/qcom,wcd9335.txt deleted file mode 100644 index 1f75feec3dec..000000000000 --- a/Documentation/devicetree/bindings/sound/qcom,wcd9335.txt +++ /dev/null @@ -1,123 +0,0 @@ -QCOM WCD9335 Codec - -Qualcomm WCD9335 Codec is a standalone Hi-Fi audio codec IC, supports -Qualcomm Technologies, Inc. (QTI) multimedia solutions, including -the MSM8996, MSM8976, and MSM8956 chipsets. It has in-built -Soundwire controller, interrupt mux. It supports both I2S/I2C and -SLIMbus audio interfaces. - -Required properties with SLIMbus Interface: - -- compatible: - Usage: required - Value type: - Definition: For SLIMbus interface it should be "slimMID,PID", - textual representation of Manufacturer ID, Product Code, - shall be in lower case hexadecimal with leading zeroes - suppressed. Refer to slimbus/bus.txt for details. - Should be: - "slim217,1a0" for MSM8996 and APQ8096 SoCs with SLIMbus. - -- reg - Usage: required - Value type: - Definition: Should be ('Device index', 'Instance ID') - -- interrupts - Usage: required - Value type: - Definition: Interrupts via WCD INTR1 and INTR2 pins - -- interrupt-names: - Usage: required - Value type: - Definition: Interrupt names of WCD INTR1 and INTR2 - Should be: "intr1", "intr2" - -- reset-gpios: - Usage: required - Value type: - Definition: Reset gpio line - -- slim-ifc-dev: - Usage: required - Value type: - Definition: SLIM interface device - -- clocks: - Usage: required - Value type: - Definition: See clock-bindings.txt section "consumers". List of - three clock specifiers for mclk, mclk2 and slimbus clock. - -- clock-names: - Usage: required - Value type: - Definition: Must contain "mclk", "mclk2" and "slimbus" strings. - -- vdd-buck-supply: - Usage: required - Value type: - Definition: Should contain a reference to the 1.8V buck supply - -- vdd-buck-sido-supply: - Usage: required - Value type: - Definition: Should contain a reference to the 1.8V SIDO buck supply - -- vdd-rx-supply: - Usage: required - Value type: - Definition: Should contain a reference to the 1.8V rx supply - -- vdd-tx-supply: - Usage: required - Value type: - Definition: Should contain a reference to the 1.8V tx supply - -- vdd-vbat-supply: - Usage: Optional - Value type: - Definition: Should contain a reference to the vbat supply - -- vdd-micbias-supply: - Usage: required - Value type: - Definition: Should contain a reference to the micbias supply - -- vdd-io-supply: - Usage: required - Value type: - Definition: Should contain a reference to the 1.8V io supply - -- interrupt-controller: - Usage: required - Definition: Indicating that this is a interrupt controller - -- #interrupt-cells: - Usage: required - Value type: - Definition: should be 1 - -#sound-dai-cells - Usage: required - Value type: - Definition: Must be 1 - -audio-codec@1{ - compatible = "slim217,1a0"; - reg = <1 0>; - interrupts = <&msmgpio 54 IRQ_TYPE_LEVEL_HIGH>; - interrupt-names = "intr2" - reset-gpios = <&msmgpio 64 GPIO_ACTIVE_LOW>; - slim-ifc-dev = <&wc9335_ifd>; - clock-names = "mclk", "native"; - clocks = <&rpmcc RPM_SMD_DIV_CLK1>, - <&rpmcc RPM_SMD_BB_CLK1>; - vdd-buck-supply = <&pm8994_s4>; - vdd-rx-supply = <&pm8994_s4>; - vdd-buck-sido-supply = <&pm8994_s4>; - vdd-tx-supply = <&pm8994_s4>; - vdd-io-supply = <&pm8994_s4>; - #sound-dai-cells = <1>; -} diff --git a/Documentation/devicetree/bindings/sound/qcom,wcd9335.yaml b/Documentation/devicetree/bindings/sound/qcom,wcd9335.yaml new file mode 100644 index 000000000000..34f8fe4da9d4 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/qcom,wcd9335.yaml @@ -0,0 +1,156 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/qcom,wcd9335.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm WCD9335 Audio Codec + +maintainers: + - Srinivas Kandagatla + +description: + Qualcomm WCD9335 Codec is a standalone Hi-Fi audio codec IC with in-built + Soundwire controller and interrupt mux. It supports both I2S/I2C and SLIMbus + audio interfaces. + +properties: + compatible: + const: slim217,1a0 + + reg: + maxItems: 1 + + clocks: + maxItems: 2 + + clock-names: + items: + - const: mclk + - const: slimbus + + interrupts: + maxItems: 2 + + interrupt-names: + items: + - const: intr1 + - const: intr2 + + interrupt-controller: true + + '#interrupt-cells': + const: 1 + + reset-gpios: + maxItems: 1 + + slim-ifc-dev: + description: SLIM IFC device interface + $ref: /schemas/types.yaml#/definitions/phandle + + '#sound-dai-cells': + const: 1 + + vdd-buck-supply: + description: 1.8V buck supply + + vdd-buck-sido-supply: + description: 1.8V SIDO buck supply + + vdd-io-supply: + description: 1.8V I/O supply + + vdd-micbias-supply: + description: micbias supply + + vdd-rx-supply: + description: 1.8V rx supply + + vdd-tx-supply: + description: 1.8V tx supply + + vdd-vbat-supply: + description: vbat supply + +required: + - compatible + - reg + +allOf: + - $ref: dai-common.yaml# + - if: + required: + - slim-ifc-dev + then: + required: + - clocks + - clock-names + - interrupts + - interrupt-names + - interrupt-controller + - '#interrupt-cells' + - reset-gpios + - slim-ifc-dev + - '#sound-dai-cells' + - vdd-buck-supply + - vdd-buck-sido-supply + - vdd-io-supply + - vdd-rx-supply + - vdd-tx-supply + else: + properties: + clocks: false + clock-names: false + interrupts: false + interrupt-names: false + interrupt-controller: false + '#interrupt-cells': false + reset-gpios: false + slim-ifc-dev: false + '#sound-dai-cells': false + vdd-buck-supply: false + vdd-buck-sido-supply: false + vdd-io-supply: false + vdd-micbias-supply: false + vdd-rx-supply: false + vdd-tx-supply: false + vdd-vbat-supply: false + +additionalProperties: false + +examples: + - | + #include + #include + #include + + tasha_ifd: codec@0,0 { + compatible = "slim217,1a0"; + reg = <0 0>; + }; + + codec@1,0 { + compatible = "slim217,1a0"; + reg = <1 0>; + + clock-names = "mclk", "slimbus"; + clocks = <&div1_mclk>, <&rpmcc RPM_SMD_BB_CLK1>; + + interrupt-parent = <&tlmm>; + interrupts = <54 IRQ_TYPE_LEVEL_HIGH>, + <53 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "intr1", "intr2"; + interrupt-controller; + #interrupt-cells = <1>; + + reset-gpios = <&tlmm 64 GPIO_ACTIVE_LOW>; + slim-ifc-dev = <&tasha_ifd>; + #sound-dai-cells = <1>; + + vdd-buck-supply = <&vreg_s4a_1p8>; + vdd-buck-sido-supply = <&vreg_s4a_1p8>; + vdd-tx-supply = <&vreg_s4a_1p8>; + vdd-rx-supply = <&vreg_s4a_1p8>; + vdd-io-supply = <&vreg_s4a_1p8>; + }; From a9334b702a03b693f54ebd3b98f67bf722b74870 Mon Sep 17 00:00:00 2001 From: Rongguang Wei Date: Thu, 2 Mar 2023 14:21:43 +0800 Subject: [PATCH 133/778] net: stmmac: add to set device wake up flag when stmmac init phy When MAC is not support PMT, driver will check PHY's WoL capability and set device wakeup capability in stmmac_init_phy(). We can enable the WoL through ethtool, the driver would enable the device wake up flag. Now the device_may_wakeup() return true. But if there is a way which enable the PHY's WoL capability derectly, like in BIOS. The driver would not know the enable thing and would not set the device wake up flag. The phy_suspend may failed like this: [ 32.409063] PM: dpm_run_callback(): mdio_bus_phy_suspend+0x0/0x50 returns -16 [ 32.409065] PM: Device stmmac-1:00 failed to suspend: error -16 [ 32.409067] PM: Some devices failed to suspend, or early wake event detected Add to set the device wakeup enable flag according to the get_wol function result in PHY can fix the error in this scene. v2: add a Fixes tag. Fixes: 1d8e5b0f3f2c ("net: stmmac: Support WOL with phy") Signed-off-by: Rongguang Wei Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index e4902a7bb61e..8f543c3ab5c5 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1170,6 +1170,7 @@ static int stmmac_init_phy(struct net_device *dev) phylink_ethtool_get_wol(priv->phylink, &wol); device_set_wakeup_capable(priv->device, !!wol.supported); + device_set_wakeup_enable(priv->device, !!wol.wolopts); } return ret; From f4b47a2e9463950df3e7c8b70e017877c1d4eb11 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Fri, 3 Mar 2023 16:37:54 +0000 Subject: [PATCH 134/778] net: phylib: get rid of unnecessary locking The locking in phy_probe() and phy_remove() does very little to prevent any races with e.g. phy_attach_direct(), but instead causes lockdep ABBA warnings. Remove it. ====================================================== WARNING: possible circular locking dependency detected 6.2.0-dirty #1108 Tainted: G W E ------------------------------------------------------ ip/415 is trying to acquire lock: ffff5c268f81ef50 (&dev->lock){+.+.}-{3:3}, at: phy_attach_direct+0x17c/0x3a0 [libphy] but task is already holding lock: ffffaef6496cb518 (rtnl_mutex){+.+.}-{3:3}, at: rtnetlink_rcv_msg+0x154/0x560 which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #1 (rtnl_mutex){+.+.}-{3:3}: __lock_acquire+0x35c/0x6c0 lock_acquire.part.0+0xcc/0x220 lock_acquire+0x68/0x84 __mutex_lock+0x8c/0x414 mutex_lock_nested+0x34/0x40 rtnl_lock+0x24/0x30 sfp_bus_add_upstream+0x34/0x150 phy_sfp_probe+0x4c/0x94 [libphy] mv3310_probe+0x148/0x184 [marvell10g] phy_probe+0x8c/0x200 [libphy] call_driver_probe+0xbc/0x15c really_probe+0xc0/0x320 __driver_probe_device+0x84/0x120 driver_probe_device+0x44/0x120 __device_attach_driver+0xc4/0x160 bus_for_each_drv+0x80/0xe0 __device_attach+0xb0/0x1f0 device_initial_probe+0x1c/0x2c bus_probe_device+0xa4/0xb0 device_add+0x360/0x53c phy_device_register+0x60/0xa4 [libphy] fwnode_mdiobus_phy_device_register+0xc0/0x190 [fwnode_mdio] fwnode_mdiobus_register_phy+0x160/0xd80 [fwnode_mdio] of_mdiobus_register+0x140/0x340 [of_mdio] orion_mdio_probe+0x298/0x3c0 [mvmdio] platform_probe+0x70/0xe0 call_driver_probe+0x34/0x15c really_probe+0xc0/0x320 __driver_probe_device+0x84/0x120 driver_probe_device+0x44/0x120 __driver_attach+0x104/0x210 bus_for_each_dev+0x78/0xdc driver_attach+0x2c/0x3c bus_add_driver+0x184/0x240 driver_register+0x80/0x13c __platform_driver_register+0x30/0x3c xt_compat_calc_jump+0x28/0xa4 [x_tables] do_one_initcall+0x50/0x1b0 do_init_module+0x50/0x1fc load_module+0x684/0x744 __do_sys_finit_module+0xc4/0x140 __arm64_sys_finit_module+0x28/0x34 invoke_syscall+0x50/0x120 el0_svc_common.constprop.0+0x6c/0x1b0 do_el0_svc+0x34/0x44 el0_svc+0x48/0xf0 el0t_64_sync_handler+0xb8/0xc0 el0t_64_sync+0x1a0/0x1a4 -> #0 (&dev->lock){+.+.}-{3:3}: check_prev_add+0xb4/0xc80 validate_chain+0x414/0x47c __lock_acquire+0x35c/0x6c0 lock_acquire.part.0+0xcc/0x220 lock_acquire+0x68/0x84 __mutex_lock+0x8c/0x414 mutex_lock_nested+0x34/0x40 phy_attach_direct+0x17c/0x3a0 [libphy] phylink_fwnode_phy_connect.part.0+0x70/0xe4 [phylink] phylink_fwnode_phy_connect+0x48/0x60 [phylink] mvpp2_open+0xec/0x2e0 [mvpp2] __dev_open+0x104/0x214 __dev_change_flags+0x1d4/0x254 dev_change_flags+0x2c/0x7c do_setlink+0x254/0xa50 __rtnl_newlink+0x430/0x514 rtnl_newlink+0x58/0x8c rtnetlink_rcv_msg+0x17c/0x560 netlink_rcv_skb+0x64/0x150 rtnetlink_rcv+0x20/0x30 netlink_unicast+0x1d4/0x2b4 netlink_sendmsg+0x1a4/0x400 ____sys_sendmsg+0x228/0x290 ___sys_sendmsg+0x88/0xec __sys_sendmsg+0x70/0xd0 __arm64_sys_sendmsg+0x2c/0x40 invoke_syscall+0x50/0x120 el0_svc_common.constprop.0+0x6c/0x1b0 do_el0_svc+0x34/0x44 el0_svc+0x48/0xf0 el0t_64_sync_handler+0xb8/0xc0 el0t_64_sync+0x1a0/0x1a4 other info that might help us debug this: Possible unsafe locking scenario: CPU0 CPU1 ---- ---- lock(rtnl_mutex); lock(&dev->lock); lock(rtnl_mutex); lock(&dev->lock); *** DEADLOCK *** Fixes: 298e54fa810e ("net: phy: add core phylib sfp support") Reported-by: Marc Zyngier Signed-off-by: Russell King (Oracle) Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/phy/phy_device.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 9e9fd8ff00f6..1785f1cead97 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -3098,8 +3098,6 @@ static int phy_probe(struct device *dev) if (phydrv->flags & PHY_IS_INTERNAL) phydev->is_internal = true; - mutex_lock(&phydev->lock); - /* Deassert the reset signal */ phy_device_reset(phydev, 0); @@ -3188,12 +3186,10 @@ static int phy_probe(struct device *dev) phydev->state = PHY_READY; out: - /* Assert the reset signal */ + /* Re-assert the reset signal on error */ if (err) phy_device_reset(phydev, 1); - mutex_unlock(&phydev->lock); - return err; } @@ -3203,9 +3199,7 @@ static int phy_remove(struct device *dev) cancel_delayed_work_sync(&phydev->state_queue); - mutex_lock(&phydev->lock); phydev->state = PHY_DOWN; - mutex_unlock(&phydev->lock); sfp_bus_del_upstream(phydev->sfp_bus); phydev->sfp_bus = NULL; From accd7e23693aaaa9aa0d3e9eca0ae77d1be80ab3 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Fri, 3 Mar 2023 18:43:57 -0800 Subject: [PATCH 135/778] bnxt_en: Avoid order-5 memory allocation for TPA data The driver needs to keep track of all the possible concurrent TPA (GRO/LRO) completions on the aggregation ring. On P5 chips, the maximum number of concurrent TPA is 256 and the amount of memory we allocate is order-5 on systems using 4K pages. Memory allocation failure has been reported: NetworkManager: page allocation failure: order:5, mode:0x40dc0(GFP_KERNEL|__GFP_COMP|__GFP_ZERO), nodemask=(null),cpuset=/,mems_allowed=0-1 CPU: 15 PID: 2995 Comm: NetworkManager Kdump: loaded Not tainted 5.10.156 #1 Hardware name: Dell Inc. PowerEdge R660/0M1CC5, BIOS 0.2.25 08/12/2022 Call Trace: dump_stack+0x57/0x6e warn_alloc.cold.120+0x7b/0xdd ? _cond_resched+0x15/0x30 ? __alloc_pages_direct_compact+0x15f/0x170 __alloc_pages_slowpath.constprop.108+0xc58/0xc70 __alloc_pages_nodemask+0x2d0/0x300 kmalloc_order+0x24/0xe0 kmalloc_order_trace+0x19/0x80 bnxt_alloc_mem+0x1150/0x15c0 [bnxt_en] ? bnxt_get_func_stat_ctxs+0x13/0x60 [bnxt_en] __bnxt_open_nic+0x12e/0x780 [bnxt_en] bnxt_open+0x10b/0x240 [bnxt_en] __dev_open+0xe9/0x180 __dev_change_flags+0x1af/0x220 dev_change_flags+0x21/0x60 do_setlink+0x35c/0x1100 Instead of allocating this big chunk of memory and dividing it up for the concurrent TPA instances, allocate each small chunk separately for each TPA instance. This will reduce it to order-0 allocations. Fixes: 79632e9ba386 ("bnxt_en: Expand bnxt_tpa_info struct to support 57500 chips.") Reviewed-by: Somnath Kotur Reviewed-by: Damodharam Ammepalli Reviewed-by: Pavan Chebbi Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 5d4b1f2ebeac..f96d539b469c 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -3145,7 +3145,7 @@ static int bnxt_alloc_ring(struct bnxt *bp, struct bnxt_ring_mem_info *rmem) static void bnxt_free_tpa_info(struct bnxt *bp) { - int i; + int i, j; for (i = 0; i < bp->rx_nr_rings; i++) { struct bnxt_rx_ring_info *rxr = &bp->rx_ring[i]; @@ -3153,8 +3153,10 @@ static void bnxt_free_tpa_info(struct bnxt *bp) kfree(rxr->rx_tpa_idx_map); rxr->rx_tpa_idx_map = NULL; if (rxr->rx_tpa) { - kfree(rxr->rx_tpa[0].agg_arr); - rxr->rx_tpa[0].agg_arr = NULL; + for (j = 0; j < bp->max_tpa; j++) { + kfree(rxr->rx_tpa[j].agg_arr); + rxr->rx_tpa[j].agg_arr = NULL; + } } kfree(rxr->rx_tpa); rxr->rx_tpa = NULL; @@ -3163,14 +3165,13 @@ static void bnxt_free_tpa_info(struct bnxt *bp) static int bnxt_alloc_tpa_info(struct bnxt *bp) { - int i, j, total_aggs = 0; + int i, j; bp->max_tpa = MAX_TPA; if (bp->flags & BNXT_FLAG_CHIP_P5) { if (!bp->max_tpa_v2) return 0; bp->max_tpa = max_t(u16, bp->max_tpa_v2, MAX_TPA_P5); - total_aggs = bp->max_tpa * MAX_SKB_FRAGS; } for (i = 0; i < bp->rx_nr_rings; i++) { @@ -3184,12 +3185,12 @@ static int bnxt_alloc_tpa_info(struct bnxt *bp) if (!(bp->flags & BNXT_FLAG_CHIP_P5)) continue; - agg = kcalloc(total_aggs, sizeof(*agg), GFP_KERNEL); - rxr->rx_tpa[0].agg_arr = agg; - if (!agg) - return -ENOMEM; - for (j = 1; j < bp->max_tpa; j++) - rxr->rx_tpa[j].agg_arr = agg + j * MAX_SKB_FRAGS; + for (j = 0; j < bp->max_tpa; j++) { + agg = kcalloc(MAX_SKB_FRAGS, sizeof(*agg), GFP_KERNEL); + if (!agg) + return -ENOMEM; + rxr->rx_tpa[j].agg_arr = agg; + } rxr->rx_tpa_idx_map = kzalloc(sizeof(*rxr->rx_tpa_idx_map), GFP_KERNEL); if (!rxr->rx_tpa_idx_map) From 89b59a84cb166f1ab5b6de9830e61324937c661e Mon Sep 17 00:00:00 2001 From: Selvin Xavier Date: Fri, 3 Mar 2023 18:43:58 -0800 Subject: [PATCH 136/778] bnxt_en: Fix the double free during device removal Following warning reported by KASAN during driver unload ================================================================== BUG: KASAN: double-free in bnxt_remove_one+0x103/0x200 [bnxt_en] Free of addr ffff88814e8dd4c0 by task rmmod/17469 CPU: 47 PID: 17469 Comm: rmmod Kdump: loaded Tainted: G S 6.2.0-rc7+ #2 Hardware name: Dell Inc. PowerEdge R740/01YM03, BIOS 2.3.10 08/15/2019 Call Trace: dump_stack_lvl+0x33/0x46 print_report+0x17b/0x4b3 ? __call_rcu_common.constprop.79+0x27e/0x8c0 ? __pfx_free_object_rcu+0x10/0x10 ? __virt_addr_valid+0xe3/0x160 ? bnxt_remove_one+0x103/0x200 [bnxt_en] kasan_report_invalid_free+0x64/0xd0 ? bnxt_remove_one+0x103/0x200 [bnxt_en] ? bnxt_remove_one+0x103/0x200 [bnxt_en] __kasan_slab_free+0x179/0x1c0 ? bnxt_remove_one+0x103/0x200 [bnxt_en] __kmem_cache_free+0x194/0x350 bnxt_remove_one+0x103/0x200 [bnxt_en] pci_device_remove+0x62/0x110 device_release_driver_internal+0xf6/0x1c0 driver_detach+0x76/0xe0 bus_remove_driver+0x89/0x160 pci_unregister_driver+0x26/0x110 ? strncpy_from_user+0x188/0x1c0 bnxt_exit+0xc/0x24 [bnxt_en] __x64_sys_delete_module+0x21f/0x390 ? __pfx___x64_sys_delete_module+0x10/0x10 ? __pfx_mem_cgroup_handle_over_high+0x10/0x10 ? _raw_spin_lock+0x87/0xe0 ? __pfx__raw_spin_lock+0x10/0x10 ? __audit_syscall_entry+0x185/0x210 ? ktime_get_coarse_real_ts64+0x51/0x80 ? syscall_trace_enter.isra.18+0x126/0x1a0 do_syscall_64+0x37/0x90 entry_SYSCALL_64_after_hwframe+0x72/0xdc RIP: 0033:0x7effcb6fd71b Code: 73 01 c3 48 8b 0d 6d 17 2c 00 f7 d8 64 89 01 48 83 c8 ff c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa b8 b0 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 3d 17 2c 00 f7 d8 64 89 01 48 RSP: 002b:00007ffeada270b8 EFLAGS: 00000206 ORIG_RAX: 00000000000000b0 RAX: ffffffffffffffda RBX: 00005623660e0750 RCX: 00007effcb6fd71b RDX: 000000000000000a RSI: 0000000000000800 RDI: 00005623660e07b8 RBP: 0000000000000000 R08: 00007ffeada26031 R09: 0000000000000000 R10: 00007effcb771280 R11: 0000000000000206 R12: 00007ffeada272e0 R13: 00007ffeada28bc4 R14: 00005623660e02a0 R15: 00005623660e0750 Auxiliary device structures are freed in bnxt_aux_dev_release. So avoid calling kfree from bnxt_remove_one. Also, set bp->edev to NULL before freeing the auxilary private structure. Fixes: d80d88b0dfff ("bnxt_en: Add auxiliary driver support") Reviewed-by: Ajit Khaparde Reviewed-by: Andy Gospodarek Signed-off-by: Selvin Xavier Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 2 -- drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index f96d539b469c..808236dc898b 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -13205,8 +13205,6 @@ static void bnxt_remove_one(struct pci_dev *pdev) bnxt_free_hwrm_resources(bp); bnxt_ethtool_free(bp); bnxt_dcb_free(bp); - kfree(bp->edev); - bp->edev = NULL; kfree(bp->ptp_cfg); bp->ptp_cfg = NULL; kfree(bp->fw_health); diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c index d4cc9c371e7b..e7b5e28ee29f 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c @@ -317,9 +317,11 @@ static void bnxt_aux_dev_release(struct device *dev) { struct bnxt_aux_priv *aux_priv = container_of(dev, struct bnxt_aux_priv, aux_dev.dev); + struct bnxt *bp = netdev_priv(aux_priv->edev->net); ida_free(&bnxt_aux_dev_ids, aux_priv->id); kfree(aux_priv->edev->ulp_tbl); + bp->edev = NULL; kfree(aux_priv->edev); kfree(aux_priv); } From 9f7dd42f0db1dc6915a52d4a8a96ca18dd8cc34e Mon Sep 17 00:00:00 2001 From: Ivan Delalande Date: Thu, 2 Mar 2023 17:48:31 -0800 Subject: [PATCH 137/778] netfilter: ctnetlink: revert to dumping mark regardless of event type It seems that change was unintentional, we have userspace code that needs the mark while listening for events like REPLY, DESTROY, etc. Also include 0-marks in requested dumps, as they were before that fix. Fixes: 1feeae071507 ("netfilter: ctnetlink: fix compilation warning after data race fixes in ct mark") Signed-off-by: Ivan Delalande Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_conntrack_netlink.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index c11dff91d52d..bfc3aaa2c872 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -328,11 +328,12 @@ nla_put_failure: } #ifdef CONFIG_NF_CONNTRACK_MARK -static int ctnetlink_dump_mark(struct sk_buff *skb, const struct nf_conn *ct) +static int ctnetlink_dump_mark(struct sk_buff *skb, const struct nf_conn *ct, + bool dump) { u32 mark = READ_ONCE(ct->mark); - if (!mark) + if (!mark && !dump) return 0; if (nla_put_be32(skb, CTA_MARK, htonl(mark))) @@ -343,7 +344,7 @@ nla_put_failure: return -1; } #else -#define ctnetlink_dump_mark(a, b) (0) +#define ctnetlink_dump_mark(a, b, c) (0) #endif #ifdef CONFIG_NF_CONNTRACK_SECMARK @@ -548,7 +549,7 @@ static int ctnetlink_dump_extinfo(struct sk_buff *skb, static int ctnetlink_dump_info(struct sk_buff *skb, struct nf_conn *ct) { if (ctnetlink_dump_status(skb, ct) < 0 || - ctnetlink_dump_mark(skb, ct) < 0 || + ctnetlink_dump_mark(skb, ct, true) < 0 || ctnetlink_dump_secctx(skb, ct) < 0 || ctnetlink_dump_id(skb, ct) < 0 || ctnetlink_dump_use(skb, ct) < 0 || @@ -831,8 +832,7 @@ ctnetlink_conntrack_event(unsigned int events, const struct nf_ct_event *item) } #ifdef CONFIG_NF_CONNTRACK_MARK - if (events & (1 << IPCT_MARK) && - ctnetlink_dump_mark(skb, ct) < 0) + if (ctnetlink_dump_mark(skb, ct, events & (1 << IPCT_MARK))) goto nla_put_failure; #endif nlmsg_end(skb, nlh); @@ -2735,7 +2735,7 @@ static int __ctnetlink_glue_build(struct sk_buff *skb, struct nf_conn *ct) goto nla_put_failure; #ifdef CONFIG_NF_CONNTRACK_MARK - if (ctnetlink_dump_mark(skb, ct) < 0) + if (ctnetlink_dump_mark(skb, ct, true) < 0) goto nla_put_failure; #endif if (ctnetlink_dump_labels(skb, ct) < 0) From 4a02426787bf024dafdb79b362285ee325de3f5e Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Fri, 3 Mar 2023 10:58:56 +0100 Subject: [PATCH 138/778] netfilter: tproxy: fix deadlock due to missing BH disable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The xtables packet traverser performs an unconditional local_bh_disable(), but the nf_tables evaluation loop does not. Functions that are called from either xtables or nftables must assume that they can be called in process context. inet_twsk_deschedule_put() assumes that no softirq interrupt can occur. If tproxy is used from nf_tables its possible that we'll deadlock trying to aquire a lock already held in process context. Add a small helper that takes care of this and use it. Link: https://lore.kernel.org/netfilter-devel/401bd6ed-314a-a196-1cdc-e13c720cc8f2@balasys.hu/ Fixes: 4ed8eb6570a4 ("netfilter: nf_tables: Add native tproxy support") Reported-and-tested-by: Major Dávid Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- include/net/netfilter/nf_tproxy.h | 7 +++++++ net/ipv4/netfilter/nf_tproxy_ipv4.c | 2 +- net/ipv6/netfilter/nf_tproxy_ipv6.c | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/include/net/netfilter/nf_tproxy.h b/include/net/netfilter/nf_tproxy.h index 82d0e41b76f2..faa108b1ba67 100644 --- a/include/net/netfilter/nf_tproxy.h +++ b/include/net/netfilter/nf_tproxy.h @@ -17,6 +17,13 @@ static inline bool nf_tproxy_sk_is_transparent(struct sock *sk) return false; } +static inline void nf_tproxy_twsk_deschedule_put(struct inet_timewait_sock *tw) +{ + local_bh_disable(); + inet_twsk_deschedule_put(tw); + local_bh_enable(); +} + /* assign a socket to the skb -- consumes sk */ static inline void nf_tproxy_assign_sock(struct sk_buff *skb, struct sock *sk) { diff --git a/net/ipv4/netfilter/nf_tproxy_ipv4.c b/net/ipv4/netfilter/nf_tproxy_ipv4.c index b22b2c745c76..69e331799604 100644 --- a/net/ipv4/netfilter/nf_tproxy_ipv4.c +++ b/net/ipv4/netfilter/nf_tproxy_ipv4.c @@ -38,7 +38,7 @@ nf_tproxy_handle_time_wait4(struct net *net, struct sk_buff *skb, hp->source, lport ? lport : hp->dest, skb->dev, NF_TPROXY_LOOKUP_LISTENER); if (sk2) { - inet_twsk_deschedule_put(inet_twsk(sk)); + nf_tproxy_twsk_deschedule_put(inet_twsk(sk)); sk = sk2; } } diff --git a/net/ipv6/netfilter/nf_tproxy_ipv6.c b/net/ipv6/netfilter/nf_tproxy_ipv6.c index 929502e51203..52f828bb5a83 100644 --- a/net/ipv6/netfilter/nf_tproxy_ipv6.c +++ b/net/ipv6/netfilter/nf_tproxy_ipv6.c @@ -63,7 +63,7 @@ nf_tproxy_handle_time_wait6(struct sk_buff *skb, int tproto, int thoff, lport ? lport : hp->dest, skb->dev, NF_TPROXY_LOOKUP_LISTENER); if (sk2) { - inet_twsk_deschedule_put(inet_twsk(sk)); + nf_tproxy_twsk_deschedule_put(inet_twsk(sk)); sk = sk2; } } From 14e998ed42208f60d5f848f5e025fa2c2e9667b0 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 6 Mar 2023 09:26:35 -0300 Subject: [PATCH 139/778] tools include UAPI: Sync linux/vhost.h with the kernel sources To get the changes in: 3b688d7a086d0438 ("vhost-vdpa: uAPI to resume the device") To pick up these changes and support them: $ tools/perf/trace/beauty/vhost_virtio_ioctl.sh > before $ cp ../linux/include/uapi/linux/vhost.h tools/include/uapi/linux/vhost.h $ tools/perf/trace/beauty/vhost_virtio_ioctl.sh > after $ diff -u before after --- before 2023-03-06 09:26:14.889251817 -0300 +++ after 2023-03-06 09:26:20.594406270 -0300 @@ -30,6 +30,7 @@ [0x77] = "VDPA_SET_CONFIG_CALL", [0x7C] = "VDPA_SET_GROUP_ASID", [0x7D] = "VDPA_SUSPEND", + [0x7E] = "VDPA_RESUME", }; static const char *vhost_virtio_ioctl_read_cmds[] = { [0x00] = "GET_FEATURES", $ For instance, see how those 'cmd' ioctl arguments get translated, now VDPA_RESUME will be as well: # perf trace -a -e ioctl --max-events=10 0.000 ( 0.011 ms): pipewire/2261 ioctl(fd: 60, cmd: SNDRV_PCM_HWSYNC, arg: 0x1) = 0 21.353 ( 0.014 ms): pipewire/2261 ioctl(fd: 60, cmd: SNDRV_PCM_HWSYNC, arg: 0x1) = 0 25.766 ( 0.014 ms): gnome-shell/2196 ioctl(fd: 14, cmd: DRM_I915_IRQ_WAIT, arg: 0x7ffe4a22c740) = 0 25.845 ( 0.034 ms): gnome-shel:cs0/2212 ioctl(fd: 14, cmd: DRM_I915_IRQ_EMIT, arg: 0x7fd43915dc70) = 0 25.916 ( 0.011 ms): gnome-shell/2196 ioctl(fd: 9, cmd: DRM_MODE_ADDFB2, arg: 0x7ffe4a22c8a0) = 0 25.941 ( 0.025 ms): gnome-shell/2196 ioctl(fd: 9, cmd: DRM_MODE_ATOMIC, arg: 0x7ffe4a22c840) = 0 32.915 ( 0.009 ms): gnome-shell/2196 ioctl(fd: 9, cmd: DRM_MODE_RMFB, arg: 0x7ffe4a22cf9c) = 0 42.522 ( 0.013 ms): gnome-shell/2196 ioctl(fd: 14, cmd: DRM_I915_IRQ_WAIT, arg: 0x7ffe4a22c740) = 0 42.579 ( 0.031 ms): gnome-shel:cs0/2212 ioctl(fd: 14, cmd: DRM_I915_IRQ_EMIT, arg: 0x7fd43915dc70) = 0 42.644 ( 0.010 ms): gnome-shell/2196 ioctl(fd: 9, cmd: DRM_MODE_ADDFB2, arg: 0x7ffe4a22c8a0) = 0 # Cc: Adrian Hunter Cc: Ian Rogers Cc: Jiri Olsa Cc: Michael S. Tsirkin Cc: Namhyung Kim Cc: Sebastien Boeuf Link: https://lore.kernel.org/lkml/ZAXdCTecxSNwAoeK@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/include/uapi/linux/vhost.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tools/include/uapi/linux/vhost.h b/tools/include/uapi/linux/vhost.h index f9f115a7c75b..92e1b700b51c 100644 --- a/tools/include/uapi/linux/vhost.h +++ b/tools/include/uapi/linux/vhost.h @@ -180,4 +180,12 @@ */ #define VHOST_VDPA_SUSPEND _IO(VHOST_VIRTIO, 0x7D) +/* Resume a device so it can resume processing virtqueue requests + * + * After the return of this ioctl the device will have restored all the + * necessary states and it is fully operational to continue processing the + * virtqueue descriptors. + */ +#define VHOST_VDPA_RESUME _IO(VHOST_VIRTIO, 0x7E) + #endif From 0d9fad91abfd723ea5070a46d98a9f4496c93ba9 Mon Sep 17 00:00:00 2001 From: Kars de Jong Date: Thu, 23 Feb 2023 12:23:49 +0100 Subject: [PATCH 140/778] m68k: mm: Fix systems with memory at end of 32-bit address space The calculation of end addresses of memory chunks overflowed to 0 when a memory chunk is located at the end of 32-bit address space. This is the case for the HP300 architecture. Link: https://lore.kernel.org/linux-m68k/CACz-3rhUo5pgNwdWHaPWmz+30Qo9xCg70wNxdf7o5x-6tXq8QQ@mail.gmail.com/ Signed-off-by: Kars de Jong Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20230223112349.26675-1-jongk@linux-m68k.org Signed-off-by: Geert Uytterhoeven --- arch/m68k/mm/motorola.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/m68k/mm/motorola.c b/arch/m68k/mm/motorola.c index 2a375637e007..911301224078 100644 --- a/arch/m68k/mm/motorola.c +++ b/arch/m68k/mm/motorola.c @@ -437,7 +437,7 @@ void __init paging_init(void) } min_addr = m68k_memory[0].addr; - max_addr = min_addr + m68k_memory[0].size; + max_addr = min_addr + m68k_memory[0].size - 1; memblock_add_node(m68k_memory[0].addr, m68k_memory[0].size, 0, MEMBLOCK_NONE); for (i = 1; i < m68k_num_memory;) { @@ -452,21 +452,21 @@ void __init paging_init(void) } memblock_add_node(m68k_memory[i].addr, m68k_memory[i].size, i, MEMBLOCK_NONE); - addr = m68k_memory[i].addr + m68k_memory[i].size; + addr = m68k_memory[i].addr + m68k_memory[i].size - 1; if (addr > max_addr) max_addr = addr; i++; } m68k_memoffset = min_addr - PAGE_OFFSET; - m68k_virt_to_node_shift = fls(max_addr - min_addr - 1) - 6; + m68k_virt_to_node_shift = fls(max_addr - min_addr) - 6; module_fixup(NULL, __start_fixup, __stop_fixup); flush_icache(); - high_memory = phys_to_virt(max_addr); + high_memory = phys_to_virt(max_addr) + 1; min_low_pfn = availmem >> PAGE_SHIFT; - max_pfn = max_low_pfn = max_addr >> PAGE_SHIFT; + max_pfn = max_low_pfn = (max_addr >> PAGE_SHIFT) + 1; /* Reserve kernel text/data/bss and the memory allocated in head.S */ memblock_reserve(m68k_memory[0].addr, availmem - m68k_memory[0].addr); From d4b97925e87eb133e400fe4a482d750c74ce392f Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 27 Feb 2023 21:14:13 +0100 Subject: [PATCH 141/778] m68k: mm: Move initrd phys_to_virt handling after paging_init() When booting with an initial ramdisk on platforms where physical memory does not start at address zero (e.g. on Amiga): initrd: 0ef0602c - 0f800000 Zone ranges: DMA [mem 0x0000000008000000-0x000000f7ffffffff] Normal empty Movable zone start for each node Early memory node ranges node 0: [mem 0x0000000008000000-0x000000000f7fffff] Initmem setup node 0 [mem 0x0000000008000000-0x000000000f7fffff] Unable to handle kernel access at virtual address (ptrval) Oops: 00000000 Modules linked in: PC: [<00201d3c>] memcmp+0x28/0x56 As phys_to_virt() relies on m68k_memoffset and module_fixup(), it must not be called before paging_init(). Hence postpone the phys_to_virt handling for the initial ramdisk until after calling paging_init(). While at it, reduce #ifdef clutter by using IS_ENABLED() instead. Fixes: 376e3fdecb0dcae2 ("m68k: Enable memtest functionality") Reported-by: Stephen Walsh Link: https://lists.debian.org/debian-68k/2022/09/msg00007.html Reported-by: John Paul Adrian Glaubitz Link: https://lore.kernel.org/r/4f45f05f377bf3f5baf88dbd5c3c8aeac59d94f0.camel@physik.fu-berlin.de Signed-off-by: Geert Uytterhoeven Acked-by: Finn Thain Link: https://lore.kernel.org/r/dff216da09ab7a60217c3fc2147e671ae07d636f.1677528627.git.geert@linux-m68k.org --- arch/m68k/kernel/setup_mm.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/m68k/kernel/setup_mm.c b/arch/m68k/kernel/setup_mm.c index 3a2bb2e8fdad..fbff1cea62ca 100644 --- a/arch/m68k/kernel/setup_mm.c +++ b/arch/m68k/kernel/setup_mm.c @@ -326,16 +326,16 @@ void __init setup_arch(char **cmdline_p) panic("No configuration setup"); } -#ifdef CONFIG_BLK_DEV_INITRD - if (m68k_ramdisk.size) { + if (IS_ENABLED(CONFIG_BLK_DEV_INITRD) && m68k_ramdisk.size) memblock_reserve(m68k_ramdisk.addr, m68k_ramdisk.size); + + paging_init(); + + if (IS_ENABLED(CONFIG_BLK_DEV_INITRD) && m68k_ramdisk.size) { initrd_start = (unsigned long)phys_to_virt(m68k_ramdisk.addr); initrd_end = initrd_start + m68k_ramdisk.size; pr_info("initrd: %08lx - %08lx\n", initrd_start, initrd_end); } -#endif - - paging_init(); #ifdef CONFIG_NATFEAT nf_init(); From e36a82bebbf7da814530d5a179bef9df5934b717 Mon Sep 17 00:00:00 2001 From: Michael Schmitz Date: Wed, 1 Mar 2023 15:11:07 +1300 Subject: [PATCH 142/778] m68k: Only force 030 bus error if PC not in exception table __get_kernel_nofault() does copy data in supervisor mode when forcing a task backtrace log through /proc/sysrq_trigger. This is expected cause a bus error exception on e.g. NULL pointer dereferencing when logging a kernel task has no workqueue associated. This bus error ought to be ignored. Our 030 bus error handler is ill equipped to deal with this: Whenever ssw indicates a kernel mode access on a data fault, we don't even attempt to handle the fault and instead always send a SEGV signal (or panic). As a result, the check for exception handling at the fault PC (buried in send_sig_fault() which gets called from do_page_fault() eventually) is never used. In contrast, both 040 and 060 access error handlers do not care whether a fault happened on supervisor mode access, and will call do_page_fault() on those, ultimately honoring the exception table. Add a check in bus_error030 to call do_page_fault() in case we do have an entry for the fault PC in our exception table. I had attempted a fix for this earlier in 2019 that did rely on testing pagefault_disabled() (see link below) to achieve the same thing, but this patch should be more generic. Tested on 030 Atari Falcon. Reported-by: Eero Tamminen Link: https://lore.kernel.org/r/alpine.LNX.2.21.1904091023540.25@nippy.intranet Link: https://lore.kernel.org/r/63130691-1984-c423-c1f2-73bfd8d3dcd3@gmail.com Signed-off-by: Michael Schmitz Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20230301021107.26307-1-schmitzmic@gmail.com Signed-off-by: Geert Uytterhoeven --- arch/m68k/kernel/traps.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c index 5c8cba0efc63..a700807c9b6d 100644 --- a/arch/m68k/kernel/traps.c +++ b/arch/m68k/kernel/traps.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -545,7 +546,8 @@ static inline void bus_error030 (struct frame *fp) errorcode |= 2; if (mmusr & (MMU_I | MMU_WP)) { - if (ssw & 4) { + /* We might have an exception table for this PC */ + if (ssw & 4 && !search_exception_tables(fp->ptregs.pc)) { pr_err("Data %s fault at %#010lx in %s (pc=%#lx)\n", ssw & RW ? "read" : "write", fp->un.fmtb.daddr, From 6a534cfcfdbbd69eaac6656eb8c28a8fa27bb12e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 6 Mar 2023 01:44:13 +0000 Subject: [PATCH 143/778] ASoC: soc-core.c: remove useless dev_dbg() soc-core.c is using dev_dbg(), but some of them are useless. It indicates many dev_dbg() at snd_soc_runtime_get_dai_fmt(), but all of them are just noise, almost no meanings. dev_dbg() on soc_probe_link_dais() indicates dai link and its loop order, but it is just noise, no information. dev_dbg() on snd_soc_register_dai() is duplicated. This patch cleanup these. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87ttyy64cy.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 71b022f7edfd..2faa0d8d0d8e 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1033,7 +1033,6 @@ static void snd_soc_runtime_get_dai_fmt(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_dai_link *dai_link = rtd->dai_link; struct snd_soc_dai *dai, *not_used; - struct device *dev = rtd->dev; u64 pos, possible_fmt; unsigned int mask = 0, dai_fmt = 0; int i, j, priority, pri, until; @@ -1075,8 +1074,6 @@ static void snd_soc_runtime_get_dai_fmt(struct snd_soc_pcm_runtime *rtd) */ until = snd_soc_dai_get_fmt_max_priority(rtd); for (priority = 1; priority <= until; priority++) { - - dev_dbg(dev, "priority = %d\n", priority); for_each_rtd_dais(rtd, j, not_used) { possible_fmt = ULLONG_MAX; @@ -1085,7 +1082,6 @@ static void snd_soc_runtime_get_dai_fmt(struct snd_soc_pcm_runtime *rtd) pri = (j >= i) ? priority : priority - 1; fmt = snd_soc_dai_get_fmt(dai, pri); - dev_dbg(dev, "%s: (pri, fmt) = (%d, %016llX)\n", dai->name, pri, fmt); possible_fmt &= fmt; } if (possible_fmt) @@ -1095,8 +1091,6 @@ static void snd_soc_runtime_get_dai_fmt(struct snd_soc_pcm_runtime *rtd) /* Not Found */ return; found: - dev_dbg(dev, "found auto selected format: %016llX\n", possible_fmt); - /* * convert POSSIBLE_DAIFMT to DAIFMT * @@ -1457,11 +1451,6 @@ static int soc_probe_link_dais(struct snd_soc_card *card) for_each_comp_order(order) { for_each_card_rtds(card, rtd) { - - dev_dbg(card->dev, - "ASoC: probe %s dai link %d late %d\n", - card->name, rtd->num, order); - /* probe all rtd connected DAIs in good order */ ret = snd_soc_pcm_dai_probe(rtd, order); if (ret) @@ -2421,8 +2410,6 @@ struct snd_soc_dai *snd_soc_register_dai(struct snd_soc_component *component, struct device *dev = component->dev; struct snd_soc_dai *dai; - dev_dbg(dev, "ASoC: dynamically register DAI %s\n", dev_name(dev)); - lockdep_assert_held(&client_mutex); dai = devm_kzalloc(dev, sizeof(*dai), GFP_KERNEL); From 49854d3ccc55efd7e6873e0c39f360bdbe251c51 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 27 Feb 2023 19:32:19 +0100 Subject: [PATCH 144/778] udf: Fix lost writes in udf_adinicb_writepage() The patch converting udf_adinicb_writepage() to avoid manually kmapping the page used memcpy_to_page() however that copies in the wrong direction (effectively overwriting file data with the old contents). What we should be using is memcpy_from_page() to copy data from the page into the inode and then mark inode dirty to store the data. Fixes: 5cfc45321a6d ("udf: Convert udf_adinicb_writepage() to memcpy_to_page()") Signed-off-by: Jan Kara --- fs/udf/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/udf/inode.c b/fs/udf/inode.c index f7a9607c2b95..facaf3a20625 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -193,7 +193,7 @@ static int udf_adinicb_writepage(struct folio *folio, struct udf_inode_info *iinfo = UDF_I(inode); BUG_ON(!PageLocked(page)); - memcpy_to_page(page, 0, iinfo->i_data + iinfo->i_lenEAttr, + memcpy_from_page(iinfo->i_data + iinfo->i_lenEAttr, page, 0, i_size_read(inode)); unlock_page(page); mark_inode_dirty(inode); From cecb1f06541e12ec68805dbddb2013ee720dfe3d Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 28 Feb 2023 12:00:25 +0100 Subject: [PATCH 145/778] udf: Fix reading of in-ICB files After merging address space operations of normal and in-ICB files, readahead could get called for in-ICB files which resulted in udf_get_block() being called for these files. udf_get_block() is not prepared to be called for in-ICB files and ends up returning garbage results as it interprets file data as extent list. Fix the problem by skipping readahead for in-ICB files. Fixes: 37a8a39f7ad3 ("udf: Switch to single address_space_operations") Signed-off-by: Jan Kara --- fs/udf/inode.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/fs/udf/inode.c b/fs/udf/inode.c index facaf3a20625..0cb7d8fba2c8 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -241,6 +241,15 @@ static int udf_read_folio(struct file *file, struct folio *folio) static void udf_readahead(struct readahead_control *rac) { + struct udf_inode_info *iinfo = UDF_I(rac->mapping->host); + + /* + * No readahead needed for in-ICB files and udf_get_block() would get + * confused for such file anyway. + */ + if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) + return; + mpage_readahead(rac, udf_get_block); } From 63bceed808c5cafbac4e20b5a40012a0ec6c6529 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 28 Feb 2023 12:11:38 +0100 Subject: [PATCH 146/778] udf: Warn if block mapping is done for in-ICB files Now that address space operations are merge dfor in-ICB and normal files, it is more likely some code mistakenly tries to map blocks for in-ICB files. WARN and return error instead of silently returning garbage. Signed-off-by: Jan Kara --- fs/udf/inode.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/udf/inode.c b/fs/udf/inode.c index 0cb7d8fba2c8..2210e5eb1ea0 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -416,6 +416,9 @@ static int udf_map_block(struct inode *inode, struct udf_map_rq *map) int err; struct udf_inode_info *iinfo = UDF_I(inode); + if (WARN_ON_ONCE(iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)) + return -EFSCORRUPTED; + map->oflags = 0; if (!(map->iflags & UDF_MAP_CREATE)) { struct kernel_lb_addr eloc; From 32db18d606c9a6eac7ac8bb12b4bf0e2eb1d5d14 Mon Sep 17 00:00:00 2001 From: Bagas Sanjaya Date: Tue, 28 Feb 2023 14:45:22 +0700 Subject: [PATCH 147/778] bpf, doc: Do not link to docs.kernel.org for kselftest link The question on how to run BPF selftests have a reference link to kernel selftest documentation (Documentation/dev-tools/kselftest.rst). However, it uses external link to the documentation at kernel.org/docs (aka docs.kernel.org) instead, which requires Internet access. Fix this and replace the link with internal linking, by using :doc: directive while keeping the anchor text. Fixes: b7a27c3aafa252 ("bpf, doc: howto use/run the BPF selftests") Signed-off-by: Bagas Sanjaya Signed-off-by: Daniel Borkmann Link: https://lore.kernel.org/bpf/20230228074523.11493-2-bagasdotme@gmail.com --- Documentation/bpf/bpf_devel_QA.rst | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Documentation/bpf/bpf_devel_QA.rst b/Documentation/bpf/bpf_devel_QA.rst index 715f7321020f..eb087c599ffa 100644 --- a/Documentation/bpf/bpf_devel_QA.rst +++ b/Documentation/bpf/bpf_devel_QA.rst @@ -461,8 +461,8 @@ needed:: $ sudo make run_tests -See the kernels selftest `Documentation/dev-tools/kselftest.rst`_ -document for further documentation. +See :doc:`kernel selftest documentation ` +for details. To maximize the number of tests passing, the .config of the kernel under test should match the config file fragment in @@ -688,7 +688,5 @@ when: .. _netdev-FAQ: Documentation/process/maintainer-netdev.rst .. _selftests: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/tools/testing/selftests/bpf/ -.. _Documentation/dev-tools/kselftest.rst: - https://www.kernel.org/doc/html/latest/dev-tools/kselftest.html Happy BPF hacking! From b7abcd9c656b982a99e18f795bb1cf81f84b656d Mon Sep 17 00:00:00 2001 From: Bagas Sanjaya Date: Tue, 28 Feb 2023 14:45:23 +0700 Subject: [PATCH 148/778] bpf, doc: Link to submitting-patches.rst for general patch submission info The link for patch submission information in general refers to index page for "Working with the kernel development community" section of kernel docs, whereas the link should have been Documentation/process/submitting-patches.rst instead. Fix it by replacing the index target with the appropriate doc. Fixes: 542228384888f5 ("bpf, doc: convert bpf_devel_QA.rst to use RST formatting") Signed-off-by: Bagas Sanjaya Signed-off-by: Daniel Borkmann Link: https://lore.kernel.org/bpf/20230228074523.11493-3-bagasdotme@gmail.com --- Documentation/bpf/bpf_devel_QA.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Documentation/bpf/bpf_devel_QA.rst b/Documentation/bpf/bpf_devel_QA.rst index eb087c599ffa..b421d94dc9f2 100644 --- a/Documentation/bpf/bpf_devel_QA.rst +++ b/Documentation/bpf/bpf_devel_QA.rst @@ -7,8 +7,8 @@ workflows related to reporting bugs, submitting patches, and queueing patches for stable kernels. For general information about submitting patches, please refer to -`Documentation/process/`_. This document only describes additional specifics -related to BPF. +Documentation/process/submitting-patches.rst. This document only describes +additional specifics related to BPF. .. contents:: :local: @@ -684,7 +684,6 @@ when: .. Links -.. _Documentation/process/: https://www.kernel.org/doc/html/latest/process/ .. _netdev-FAQ: Documentation/process/maintainer-netdev.rst .. _selftests: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/tools/testing/selftests/bpf/ From 7d0930647c020f75592adde8712d2cb002b29387 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 6 Mar 2023 14:25:21 -0300 Subject: [PATCH 149/778] tools headers x86 cpufeatures: Sync with the kernel sources To pick the changes from: 8415a74852d7c247 ("x86/cpu, kvm: Add support for CPUID_80000021_EAX") This only causes these perf files to be rebuilt: CC /tmp/build/perf/bench/mem-memcpy-x86-64-asm.o CC /tmp/build/perf/bench/mem-memset-x86-64-asm.o And addresses these perf build warnings: Warning: Kernel ABI header at 'tools/arch/x86/include/asm/disabled-features.h' differs from latest version at 'arch/x86/include/asm/disabled-features.h' diff -u tools/arch/x86/include/asm/disabled-features.h arch/x86/include/asm/disabled-features.h Warning: Kernel ABI header at 'tools/arch/x86/include/asm/required-features.h' differs from latest version at 'arch/x86/include/asm/required-features.h' diff -u tools/arch/x86/include/asm/required-features.h arch/x86/include/asm/required-features.h Cc: Adrian Hunter Cc: Borislav Petkov (AMD) Cc: Ian Rogers Cc: Jiri Olsa Cc: Kim Phillips Cc: Namhyung Kim Link: https://lore.kernel.org/lkml/ZAYlS2XTJ5hRtss7@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/arch/x86/include/asm/cpufeatures.h | 2 +- tools/arch/x86/include/asm/disabled-features.h | 3 ++- tools/arch/x86/include/asm/required-features.h | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/tools/arch/x86/include/asm/cpufeatures.h b/tools/arch/x86/include/asm/cpufeatures.h index 61012476d66e..d53e13048d2e 100644 --- a/tools/arch/x86/include/asm/cpufeatures.h +++ b/tools/arch/x86/include/asm/cpufeatures.h @@ -13,7 +13,7 @@ /* * Defines x86 CPU feature bits */ -#define NCAPINTS 20 /* N 32-bit words worth of info */ +#define NCAPINTS 21 /* N 32-bit words worth of info */ #define NBUGINTS 1 /* N 32-bit bug flags */ /* diff --git a/tools/arch/x86/include/asm/disabled-features.h b/tools/arch/x86/include/asm/disabled-features.h index c44b56f7ffba..5dfa4fb76f4b 100644 --- a/tools/arch/x86/include/asm/disabled-features.h +++ b/tools/arch/x86/include/asm/disabled-features.h @@ -124,6 +124,7 @@ #define DISABLED_MASK17 0 #define DISABLED_MASK18 0 #define DISABLED_MASK19 0 -#define DISABLED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 20) +#define DISABLED_MASK20 0 +#define DISABLED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 21) #endif /* _ASM_X86_DISABLED_FEATURES_H */ diff --git a/tools/arch/x86/include/asm/required-features.h b/tools/arch/x86/include/asm/required-features.h index aff774775c67..7ba1726b71c7 100644 --- a/tools/arch/x86/include/asm/required-features.h +++ b/tools/arch/x86/include/asm/required-features.h @@ -98,6 +98,7 @@ #define REQUIRED_MASK17 0 #define REQUIRED_MASK18 0 #define REQUIRED_MASK19 0 -#define REQUIRED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 20) +#define REQUIRED_MASK20 0 +#define REQUIRED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 21) #endif /* _ASM_X86_REQUIRED_FEATURES_H */ From 12148367d7235a015c7a3ab20bc189a34f63688e Mon Sep 17 00:00:00 2001 From: Boris Burkov Date: Wed, 15 Feb 2023 12:59:50 -0800 Subject: [PATCH 150/778] btrfs: fix potential dead lock in size class loading logic As reported by Filipe, there's a potential deadlock caused by using btrfs_search_forward on commit_root. The locking there is unconditional, even if ->skip_locking and ->search_commit_root is set. It's not meant to be used for commit roots, so it always needs to do locking. So if another task is COWing a child node of the same root node and then needs to wait for block group caching to complete when trying to allocate a metadata extent, it deadlocks. For example: [539604.239315] sysrq: Show Blocked State [539604.240133] task:kworker/u16:6 state:D stack:0 pid:2119594 ppid:2 flags:0x00004000 [539604.241613] Workqueue: btrfs-cache btrfs_work_helper [btrfs] [539604.242673] Call Trace: [539604.243129] [539604.243925] __schedule+0x41d/0xee0 [539604.244797] ? rcu_read_lock_sched_held+0x12/0x70 [539604.245399] ? rwsem_down_read_slowpath+0x185/0x490 [539604.246111] schedule+0x5d/0xf0 [539604.246593] rwsem_down_read_slowpath+0x2da/0x490 [539604.247290] ? rcu_barrier_tasks_trace+0x10/0x20 [539604.248090] __down_read_common+0x3d/0x150 [539604.248702] down_read_nested+0xc3/0x140 [539604.249280] __btrfs_tree_read_lock+0x24/0x100 [btrfs] [539604.250097] btrfs_read_lock_root_node+0x48/0x60 [btrfs] [539604.250915] btrfs_search_forward+0x59/0x460 [btrfs] [539604.251781] ? btrfs_global_root+0x50/0x70 [btrfs] [539604.252476] caching_thread+0x1be/0x920 [btrfs] [539604.253167] btrfs_work_helper+0xf6/0x400 [btrfs] [539604.253848] process_one_work+0x24f/0x5a0 [539604.254476] worker_thread+0x52/0x3b0 [539604.255166] ? __pfx_worker_thread+0x10/0x10 [539604.256047] kthread+0xf0/0x120 [539604.256591] ? __pfx_kthread+0x10/0x10 [539604.257212] ret_from_fork+0x29/0x50 [539604.257822] [539604.258233] task:btrfs-transacti state:D stack:0 pid:2236474 ppid:2 flags:0x00004000 [539604.259802] Call Trace: [539604.260243] [539604.260615] __schedule+0x41d/0xee0 [539604.261205] ? rcu_read_lock_sched_held+0x12/0x70 [539604.262000] ? rwsem_down_read_slowpath+0x185/0x490 [539604.262822] schedule+0x5d/0xf0 [539604.263374] rwsem_down_read_slowpath+0x2da/0x490 [539604.266228] ? lock_acquire+0x160/0x310 [539604.266917] ? rcu_read_lock_sched_held+0x12/0x70 [539604.267996] ? lock_contended+0x19e/0x500 [539604.268720] __down_read_common+0x3d/0x150 [539604.269400] down_read_nested+0xc3/0x140 [539604.270057] __btrfs_tree_read_lock+0x24/0x100 [btrfs] [539604.271129] btrfs_read_lock_root_node+0x48/0x60 [btrfs] [539604.272372] btrfs_search_slot+0x143/0xf70 [btrfs] [539604.273295] update_block_group_item+0x9e/0x190 [btrfs] [539604.274282] btrfs_start_dirty_block_groups+0x1c4/0x4f0 [btrfs] [539604.275381] ? __mutex_unlock_slowpath+0x45/0x280 [539604.276390] btrfs_commit_transaction+0xee/0xed0 [btrfs] [539604.277391] ? lock_acquire+0x1a4/0x310 [539604.278080] ? start_transaction+0xcb/0x6c0 [btrfs] [539604.279099] transaction_kthread+0x142/0x1c0 [btrfs] [539604.279996] ? __pfx_transaction_kthread+0x10/0x10 [btrfs] [539604.280673] kthread+0xf0/0x120 [539604.281050] ? __pfx_kthread+0x10/0x10 [539604.281496] ret_from_fork+0x29/0x50 [539604.281966] [539604.282255] task:fsstress state:D stack:0 pid:2236483 ppid:1 flags:0x00004006 [539604.283897] Call Trace: [539604.284700] [539604.285088] __schedule+0x41d/0xee0 [539604.285660] schedule+0x5d/0xf0 [539604.286175] btrfs_wait_block_group_cache_progress+0xf2/0x170 [btrfs] [539604.287342] ? __pfx_autoremove_wake_function+0x10/0x10 [539604.288450] find_free_extent+0xd93/0x1750 [btrfs] [539604.289256] ? _raw_spin_unlock+0x29/0x50 [539604.289911] ? btrfs_get_alloc_profile+0x127/0x2a0 [btrfs] [539604.290843] btrfs_reserve_extent+0x147/0x290 [btrfs] [539604.291943] btrfs_alloc_tree_block+0xcb/0x3e0 [btrfs] [539604.292903] __btrfs_cow_block+0x138/0x580 [btrfs] [539604.293773] btrfs_cow_block+0x10e/0x240 [btrfs] [539604.294595] btrfs_search_slot+0x7f3/0xf70 [btrfs] [539604.295585] btrfs_update_device+0x71/0x1b0 [btrfs] [539604.296459] btrfs_chunk_alloc_add_chunk_item+0xe0/0x340 [btrfs] [539604.297489] btrfs_chunk_alloc+0x1bf/0x490 [btrfs] [539604.298335] find_free_extent+0x6fa/0x1750 [btrfs] [539604.299174] ? _raw_spin_unlock+0x29/0x50 [539604.299950] ? btrfs_get_alloc_profile+0x127/0x2a0 [btrfs] [539604.300918] btrfs_reserve_extent+0x147/0x290 [btrfs] [539604.301797] btrfs_alloc_tree_block+0xcb/0x3e0 [btrfs] [539604.303017] ? lock_release+0x224/0x4a0 [539604.303855] __btrfs_cow_block+0x138/0x580 [btrfs] [539604.304789] btrfs_cow_block+0x10e/0x240 [btrfs] [539604.305611] btrfs_search_slot+0x7f3/0xf70 [btrfs] [539604.306682] ? btrfs_global_root+0x50/0x70 [btrfs] [539604.308198] lookup_inline_extent_backref+0x17b/0x7a0 [btrfs] [539604.309254] lookup_extent_backref+0x43/0xd0 [btrfs] [539604.310122] __btrfs_free_extent+0xf8/0x810 [btrfs] [539604.310874] ? lock_release+0x224/0x4a0 [539604.311724] ? btrfs_merge_delayed_refs+0x17b/0x1d0 [btrfs] [539604.313023] __btrfs_run_delayed_refs+0x2ba/0x1260 [btrfs] [539604.314271] btrfs_run_delayed_refs+0x8f/0x1c0 [btrfs] [539604.315445] ? rcu_read_lock_sched_held+0x12/0x70 [539604.316706] btrfs_commit_transaction+0xa2/0xed0 [btrfs] [539604.317855] ? do_raw_spin_unlock+0x4b/0xa0 [539604.318544] ? _raw_spin_unlock+0x29/0x50 [539604.319240] create_subvol+0x53d/0x6e0 [btrfs] [539604.320283] btrfs_mksubvol+0x4f5/0x590 [btrfs] [539604.321220] __btrfs_ioctl_snap_create+0x11b/0x180 [btrfs] [539604.322307] btrfs_ioctl_snap_create_v2+0xc6/0x150 [btrfs] [539604.323295] btrfs_ioctl+0x9f7/0x33e0 [btrfs] [539604.324331] ? rcu_read_lock_sched_held+0x12/0x70 [539604.325137] ? lock_release+0x224/0x4a0 [539604.325808] ? __x64_sys_ioctl+0x87/0xc0 [539604.326467] __x64_sys_ioctl+0x87/0xc0 [539604.327109] do_syscall_64+0x38/0x90 [539604.327875] entry_SYSCALL_64_after_hwframe+0x72/0xdc [539604.328792] RIP: 0033:0x7f05a7babaeb This needs to use regular btrfs_search_slot() with some skip and stop logic. Since we only consider five samples (five search slots), don't bother with the complexity of looking for commit_root_sem contention. If necessary, it can be added to the load function in between samples. Reported-by: Filipe Manana Link: https://lore.kernel.org/linux-btrfs/CAL3q7H7eKMD44Z1+=Kb-1RFMMeZpAm2fwyO59yeBwCcSOU80Pg@mail.gmail.com/ Fixes: c7eec3d9aa95 ("btrfs: load block group size class when caching") Signed-off-by: Boris Burkov Signed-off-by: David Sterba --- fs/btrfs/block-group.c | 42 ++++++++++++++++-------------------------- 1 file changed, 16 insertions(+), 26 deletions(-) diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c index 5b10401d803b..05102a55710c 100644 --- a/fs/btrfs/block-group.c +++ b/fs/btrfs/block-group.c @@ -558,14 +558,15 @@ u64 add_new_free_space(struct btrfs_block_group *block_group, u64 start, u64 end static int sample_block_group_extent_item(struct btrfs_caching_control *caching_ctl, struct btrfs_block_group *block_group, int index, int max_index, - struct btrfs_key *key) + struct btrfs_key *found_key) { struct btrfs_fs_info *fs_info = block_group->fs_info; struct btrfs_root *extent_root; - int ret = 0; u64 search_offset; u64 search_end = block_group->start + block_group->length; struct btrfs_path *path; + struct btrfs_key search_key; + int ret = 0; ASSERT(index >= 0); ASSERT(index <= max_index); @@ -585,37 +586,24 @@ static int sample_block_group_extent_item(struct btrfs_caching_control *caching_ path->reada = READA_FORWARD; search_offset = index * div_u64(block_group->length, max_index); - key->objectid = block_group->start + search_offset; - key->type = BTRFS_EXTENT_ITEM_KEY; - key->offset = 0; + search_key.objectid = block_group->start + search_offset; + search_key.type = BTRFS_EXTENT_ITEM_KEY; + search_key.offset = 0; - while (1) { - ret = btrfs_search_forward(extent_root, key, path, 0); - if (ret != 0) - goto out; + btrfs_for_each_slot(extent_root, &search_key, found_key, path, ret) { /* Success; sampled an extent item in the block group */ - if (key->type == BTRFS_EXTENT_ITEM_KEY && - key->objectid >= block_group->start && - key->objectid + key->offset <= search_end) - goto out; + if (found_key->type == BTRFS_EXTENT_ITEM_KEY && + found_key->objectid >= block_group->start && + found_key->objectid + found_key->offset <= search_end) + break; /* We can't possibly find a valid extent item anymore */ - if (key->objectid >= search_end) { + if (found_key->objectid >= search_end) { ret = 1; break; } - if (key->type < BTRFS_EXTENT_ITEM_KEY) - key->type = BTRFS_EXTENT_ITEM_KEY; - else - key->objectid++; - btrfs_release_path(path); - up_read(&fs_info->commit_root_sem); - mutex_unlock(&caching_ctl->mutex); - cond_resched(); - mutex_lock(&caching_ctl->mutex); - down_read(&fs_info->commit_root_sem); } -out: + lockdep_assert_held(&caching_ctl->mutex); lockdep_assert_held_read(&fs_info->commit_root_sem); btrfs_free_path(path); @@ -659,6 +647,7 @@ out: static int load_block_group_size_class(struct btrfs_caching_control *caching_ctl, struct btrfs_block_group *block_group) { + struct btrfs_fs_info *fs_info = block_group->fs_info; struct btrfs_key key; int i; u64 min_size = block_group->length; @@ -668,6 +657,8 @@ static int load_block_group_size_class(struct btrfs_caching_control *caching_ctl if (!btrfs_block_group_should_use_size_class(block_group)) return 0; + lockdep_assert_held(&caching_ctl->mutex); + lockdep_assert_held_read(&fs_info->commit_root_sem); for (i = 0; i < 5; ++i) { ret = sample_block_group_extent_item(caching_ctl, block_group, i, 5, &key); if (ret < 0) @@ -682,7 +673,6 @@ static int load_block_group_size_class(struct btrfs_caching_control *caching_ctl block_group->size_class = size_class; spin_unlock(&block_group->lock); } - out: return ret; } From 2943868a909f1d526da363dc077fd7b578643f4b Mon Sep 17 00:00:00 2001 From: Qu Wenruo Date: Sat, 11 Feb 2023 19:53:05 +0800 Subject: [PATCH 151/778] btrfs: ioctl: return device fsid from DEV_INFO ioctl Currently user space utilizes dev info ioctl to grab the info of a certain devid, this includes its device uuid. But the returned info is not enough to determine if a device is a seed. Commit a26d60dedf9a ("btrfs: sysfs: add devinfo/fsid to retrieve actual fsid from the device") exports the same value in sysfs so this is for parity with ioctl. Add a new member, fsid, into btrfs_ioctl_dev_info_args, and populate the member with fsid value. This should not cause any compatibility problem, following the combinations: - Old user space, old kernel - Old user space, new kernel User space tool won't even check the new member. - New user space, old kernel The kernel won't touch the new member, and user space tool should zero out its argument, thus the new member is all zero. User space tool can then know the kernel doesn't support this fsid reporting, and falls back to whatever they can. - New user space, new kernel Go as planned. Would find the fsid member is no longer zero, and trust its value. Reviewed-by: Anand Jain Signed-off-by: Qu Wenruo Signed-off-by: David Sterba --- fs/btrfs/ioctl.c | 1 + include/uapi/linux/btrfs.h | 12 +++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 8ea557e22252..439a5bf5ebc6 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -2859,6 +2859,7 @@ static long btrfs_ioctl_dev_info(struct btrfs_fs_info *fs_info, di_args->bytes_used = btrfs_device_get_bytes_used(dev); di_args->total_bytes = btrfs_device_get_total_bytes(dev); memcpy(di_args->uuid, dev->uuid, sizeof(di_args->uuid)); + memcpy(di_args->fsid, dev->fs_devices->fsid, BTRFS_UUID_SIZE); if (dev->name) strscpy(di_args->path, btrfs_dev_name(dev), sizeof(di_args->path)); else diff --git a/include/uapi/linux/btrfs.h b/include/uapi/linux/btrfs.h index b4f0f9531119..ada0a489bf2b 100644 --- a/include/uapi/linux/btrfs.h +++ b/include/uapi/linux/btrfs.h @@ -245,7 +245,17 @@ struct btrfs_ioctl_dev_info_args { __u8 uuid[BTRFS_UUID_SIZE]; /* in/out */ __u64 bytes_used; /* out */ __u64 total_bytes; /* out */ - __u64 unused[379]; /* pad to 4k */ + /* + * Optional, out. + * + * Showing the fsid of the device, allowing user space to check if this + * device is a seeding one. + * + * Introduced in v6.3, thus user space still needs to check if kernel + * changed this value. Older kernel will not touch the values here. + */ + __u8 fsid[BTRFS_UUID_SIZE]; + __u64 unused[377]; /* pad to 4k */ __u8 path[BTRFS_DEVICE_PATH_NAME_MAX]; /* out */ }; From c06016a02a6e316d861f7dddd4b70419a47ded2f Mon Sep 17 00:00:00 2001 From: void0red Date: Sat, 18 Feb 2023 12:36:48 +0800 Subject: [PATCH 152/778] btrfs: handle btrfs_del_item errors in __btrfs_update_delayed_inode Even if the slot is already read out, we may still need to re-balance the tree, thus it can cause error in that btrfs_del_item() call and we need to handle it properly. Reviewed-by: Qu Wenruo Signed-off-by: void0red Signed-off-by: David Sterba --- fs/btrfs/delayed-inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c index 0095c6e4c3d1..6b457b010cbc 100644 --- a/fs/btrfs/delayed-inode.c +++ b/fs/btrfs/delayed-inode.c @@ -1048,7 +1048,7 @@ again: * so there is only one iref. The case that several irefs are * in the same item doesn't exist. */ - btrfs_del_item(trans, root, path); + ret = btrfs_del_item(trans, root, path); out: btrfs_release_delayed_iref(node); btrfs_release_path(path); From 98e8d36a26c2ed22f78316df7d4bf33e554b9f9f Mon Sep 17 00:00:00 2001 From: Naohiro Aota Date: Mon, 13 Feb 2023 14:10:38 +0900 Subject: [PATCH 153/778] btrfs: fix unnecessary increment of read error stat on write error Current btrfs_log_dev_io_error() increases the read error count even if the erroneous IO is a WRITE request. This is because it forget to use "else if", and all the error WRITE requests counts as READ error as there is (of course) no REQ_RAHEAD bit set. Fixes: c3a62baf21ad ("btrfs: use chained bios when cloning") CC: stable@vger.kernel.org # 6.1+ Reviewed-by: Christoph Hellwig Reviewed-by: Johannes Thumshirn Signed-off-by: Naohiro Aota Reviewed-by: David Sterba Signed-off-by: David Sterba --- fs/btrfs/bio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/btrfs/bio.c b/fs/btrfs/bio.c index d8b90f95b157..726592868e9c 100644 --- a/fs/btrfs/bio.c +++ b/fs/btrfs/bio.c @@ -287,7 +287,7 @@ static void btrfs_log_dev_io_error(struct bio *bio, struct btrfs_device *dev) if (btrfs_op(bio) == BTRFS_MAP_WRITE) btrfs_dev_stat_inc_and_print(dev, BTRFS_DEV_STAT_WRITE_ERRS); - if (!(bio->bi_opf & REQ_RAHEAD)) + else if (!(bio->bi_opf & REQ_RAHEAD)) btrfs_dev_stat_inc_and_print(dev, BTRFS_DEV_STAT_READ_ERRS); if (bio->bi_opf & REQ_PREFLUSH) btrfs_dev_stat_inc_and_print(dev, BTRFS_DEV_STAT_FLUSH_ERRS); From 95cd356ca23c3807b5f3503687161e216b1c520d Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Tue, 21 Feb 2023 10:11:24 -0800 Subject: [PATCH 154/778] btrfs: fix percent calculation for bg reclaim message We have a report, that the info message for block-group reclaim is crossing the 100% used mark. This is happening as we were truncating the divisor for the division (the block_group->length) to a 32bit value. Fix this by using div64_u64() to not truncate the divisor. In the worst case, it can lead to a div by zero error and should be possible to trigger on 4 disks RAID0, and each device is large enough: $ mkfs.btrfs -f /dev/test/scratch[1234] -m raid1 -d raid0 btrfs-progs v6.1 [...] Filesystem size: 40.00GiB Block group profiles: Data: RAID0 4.00GiB <<< Metadata: RAID1 256.00MiB System: RAID1 8.00MiB Reported-by: Forza Link: https://lore.kernel.org/linux-btrfs/e99483.c11a58d.1863591ca52@tnonline.net/ Fixes: 5f93e776c673 ("btrfs: zoned: print unusable percentage when reclaiming block groups") CC: stable@vger.kernel.org # 5.15+ Reviewed-by: Anand Jain Reviewed-by: Qu Wenruo Signed-off-by: Johannes Thumshirn Reviewed-by: David Sterba [ add Qu's note ] Signed-off-by: David Sterba --- fs/btrfs/block-group.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c index 05102a55710c..0eec3084fb00 100644 --- a/fs/btrfs/block-group.c +++ b/fs/btrfs/block-group.c @@ -1826,7 +1826,8 @@ void btrfs_reclaim_bgs_work(struct work_struct *work) btrfs_info(fs_info, "reclaiming chunk %llu with %llu%% used %llu%% unusable", - bg->start, div_u64(bg->used * 100, bg->length), + bg->start, + div64_u64(bg->used * 100, bg->length), div64_u64(zone_unusable * 100, bg->length)); trace_btrfs_reclaim_block_group(bg); ret = btrfs_relocate_chunk(fs_info, bg->start); From e4cc1483f35940c9288c332dd275f6fad485f8d2 Mon Sep 17 00:00:00 2001 From: Filipe Manana Date: Mon, 27 Feb 2023 12:53:56 +0000 Subject: [PATCH 155/778] btrfs: fix extent map logging bit not cleared for split maps after dropping range At btrfs_drop_extent_map_range() we are clearing the EXTENT_FLAG_LOGGING bit on a 'flags' variable that was not initialized. This makes static checkers complain about it, so initialize the 'flags' variable before clearing the bit. In practice this has no consequences, because EXTENT_FLAG_LOGGING should not be set when btrfs_drop_extent_map_range() is called, as an fsync locks the inode in exclusive mode, locks the inode's mmap semaphore in exclusive mode too and it always flushes all delalloc. Also add a comment about why we clear EXTENT_FLAG_LOGGING on a copy of the flags of the split extent map. Reported-by: Dan Carpenter Link: https://lore.kernel.org/linux-btrfs/Y%2FyipSVozUDEZKow@kili/ Fixes: db21370bffbc ("btrfs: drop extent map range more efficiently") Signed-off-by: Filipe Manana Signed-off-by: David Sterba --- fs/btrfs/extent_map.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c index be94030e1dfb..138afa955370 100644 --- a/fs/btrfs/extent_map.c +++ b/fs/btrfs/extent_map.c @@ -763,7 +763,13 @@ void btrfs_drop_extent_map_range(struct btrfs_inode *inode, u64 start, u64 end, goto next; } + flags = em->flags; clear_bit(EXTENT_FLAG_PINNED, &em->flags); + /* + * In case we split the extent map, we want to preserve the + * EXTENT_FLAG_LOGGING flag on our extent map, but we don't want + * it on the new extent maps. + */ clear_bit(EXTENT_FLAG_LOGGING, &flags); modified = !list_empty(&em->list); @@ -774,7 +780,6 @@ void btrfs_drop_extent_map_range(struct btrfs_inode *inode, u64 start, u64 end, if (em->start >= start && em_end <= end) goto remove_em; - flags = em->flags; gen = em->generation; compressed = test_bit(EXTENT_FLAG_COMPRESSED, &em->flags); From 80c16b2b121fbc3380dbffa9bab7559acbaaa2ed Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 6 Mar 2023 17:22:04 +0200 Subject: [PATCH 156/778] cpumask: Fix typo nr_cpumask_size --> nr_cpumask_bits The never used nr_cpumask_size is just a typo, hence use existing redefinition that's called nr_cpumask_bits. Signed-off-by: Andy Shevchenko Signed-off-by: Linus Torvalds --- include/linux/cpumask.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h index 8fbe76607965..ce8eb7ef2107 100644 --- a/include/linux/cpumask.h +++ b/include/linux/cpumask.h @@ -66,7 +66,7 @@ static inline void set_nr_cpu_ids(unsigned int nr) * * Finally, some operations just want the exact limit, either because * they set bits or just don't have any faster fixed-sized versions. We - * call this just 'nr_cpumask_size'. + * call this just 'nr_cpumask_bits'. * * Note that these optional constants are always guaranteed to be at * least as big as 'nr_cpu_ids' itself is, and all our cpumask From 294635a8165a31408a8b3a24f9c74849ca3d8701 Mon Sep 17 00:00:00 2001 From: Alexander Lobakin Date: Fri, 24 Feb 2023 17:36:07 +0100 Subject: [PATCH 157/778] bpf, test_run: fix &xdp_frame misplacement for LIVE_FRAMES MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit &xdp_buff and &xdp_frame are bound in a way that xdp_buff->data_hard_start == xdp_frame It's always the case and e.g. xdp_convert_buff_to_frame() relies on this. IOW, the following: for (u32 i = 0; i < 0xdead; i++) { xdpf = xdp_convert_buff_to_frame(&xdp); xdp_convert_frame_to_buff(xdpf, &xdp); } shouldn't ever modify @xdpf's contents or the pointer itself. However, "live packet" code wrongly treats &xdp_frame as part of its context placed *before* the data_hard_start. With such flow, data_hard_start is sizeof(*xdpf) off to the right and no longer points to the XDP frame. Instead of replacing `sizeof(ctx)` with `offsetof(ctx, xdpf)` in several places and praying that there are no more miscalcs left somewhere in the code, unionize ::frm with ::data in a flex array, so that both starts pointing to the actual data_hard_start and the XDP frame actually starts being a part of it, i.e. a part of the headroom, not the context. A nice side effect is that the maximum frame size for this mode gets increased by 40 bytes, as xdp_buff::frame_sz includes everything from data_hard_start (-> includes xdpf already) to the end of XDP/skb shared info. Also update %MAX_PKT_SIZE accordingly in the selftests code. Leave it hardcoded for 64 bit && 4k pages, it can be made more flexible later on. Minor: align `&head->data` with how `head->frm` is assigned for consistency. Minor #2: rename 'frm' to 'frame' in &xdp_page_head while at it for clarity. (was found while testing XDP traffic generator on ice, which calls xdp_convert_frame_to_buff() for each XDP frame) Fixes: b530e9e1063e ("bpf: Add "live packet" mode for XDP in BPF_PROG_RUN") Acked-by: Toke Høiland-Jørgensen Signed-off-by: Alexander Lobakin Link: https://lore.kernel.org/r/20230224163607.2994755-1-aleksander.lobakin@intel.com Signed-off-by: Martin KaFai Lau --- net/bpf/test_run.c | 19 +++++++++++++------ .../bpf/prog_tests/xdp_do_redirect.c | 7 ++++--- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/net/bpf/test_run.c b/net/bpf/test_run.c index 6f3d654b3339..f81b24320a36 100644 --- a/net/bpf/test_run.c +++ b/net/bpf/test_run.c @@ -97,8 +97,11 @@ reset: struct xdp_page_head { struct xdp_buff orig_ctx; struct xdp_buff ctx; - struct xdp_frame frm; - u8 data[]; + union { + /* ::data_hard_start starts here */ + DECLARE_FLEX_ARRAY(struct xdp_frame, frame); + DECLARE_FLEX_ARRAY(u8, data); + }; }; struct xdp_test_data { @@ -113,6 +116,10 @@ struct xdp_test_data { u32 frame_cnt; }; +/* tools/testing/selftests/bpf/prog_tests/xdp_do_redirect.c:%MAX_PKT_SIZE + * must be updated accordingly this gets changed, otherwise BPF selftests + * will fail. + */ #define TEST_XDP_FRAME_SIZE (PAGE_SIZE - sizeof(struct xdp_page_head)) #define TEST_XDP_MAX_BATCH 256 @@ -132,8 +139,8 @@ static void xdp_test_run_init_page(struct page *page, void *arg) headroom -= meta_len; new_ctx = &head->ctx; - frm = &head->frm; - data = &head->data; + frm = head->frame; + data = head->data; memcpy(data + headroom, orig_ctx->data_meta, frm_len); xdp_init_buff(new_ctx, TEST_XDP_FRAME_SIZE, &xdp->rxq); @@ -223,7 +230,7 @@ static void reset_ctx(struct xdp_page_head *head) head->ctx.data = head->orig_ctx.data; head->ctx.data_meta = head->orig_ctx.data_meta; head->ctx.data_end = head->orig_ctx.data_end; - xdp_update_frame_from_buff(&head->ctx, &head->frm); + xdp_update_frame_from_buff(&head->ctx, head->frame); } static int xdp_recv_frames(struct xdp_frame **frames, int nframes, @@ -285,7 +292,7 @@ static int xdp_test_run_batch(struct xdp_test_data *xdp, struct bpf_prog *prog, head = phys_to_virt(page_to_phys(page)); reset_ctx(head); ctx = &head->ctx; - frm = &head->frm; + frm = head->frame; xdp->frame_cnt++; act = bpf_prog_run_xdp(prog, ctx); diff --git a/tools/testing/selftests/bpf/prog_tests/xdp_do_redirect.c b/tools/testing/selftests/bpf/prog_tests/xdp_do_redirect.c index 2666c84dbd01..7271a18ab3e2 100644 --- a/tools/testing/selftests/bpf/prog_tests/xdp_do_redirect.c +++ b/tools/testing/selftests/bpf/prog_tests/xdp_do_redirect.c @@ -65,12 +65,13 @@ static int attach_tc_prog(struct bpf_tc_hook *hook, int fd) } /* The maximum permissible size is: PAGE_SIZE - sizeof(struct xdp_page_head) - - * sizeof(struct skb_shared_info) - XDP_PACKET_HEADROOM = 3368 bytes + * SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) - XDP_PACKET_HEADROOM = + * 3408 bytes for 64-byte cacheline and 3216 for 256-byte one. */ #if defined(__s390x__) -#define MAX_PKT_SIZE 3176 +#define MAX_PKT_SIZE 3216 #else -#define MAX_PKT_SIZE 3368 +#define MAX_PKT_SIZE 3408 #endif static void test_max_pkt_size(int fd) { From 9b459804ff9973e173fabafba2a1319f771e85fa Mon Sep 17 00:00:00 2001 From: Lorenz Bauer Date: Mon, 6 Mar 2023 11:21:37 +0000 Subject: [PATCH 158/778] btf: fix resolving BTF_KIND_VAR after ARRAY, STRUCT, UNION, PTR btf_datasec_resolve contains a bug that causes the following BTF to fail loading: [1] DATASEC a size=2 vlen=2 type_id=4 offset=0 size=1 type_id=7 offset=1 size=1 [2] INT (anon) size=1 bits_offset=0 nr_bits=8 encoding=(none) [3] PTR (anon) type_id=2 [4] VAR a type_id=3 linkage=0 [5] INT (anon) size=1 bits_offset=0 nr_bits=8 encoding=(none) [6] TYPEDEF td type_id=5 [7] VAR b type_id=6 linkage=0 This error message is printed during btf_check_all_types: [1] DATASEC a size=2 vlen=2 type_id=7 offset=1 size=1 Invalid type By tracing btf_*_resolve we can pinpoint the problem: btf_datasec_resolve(depth: 1, type_id: 1, mode: RESOLVE_TBD) = 0 btf_var_resolve(depth: 2, type_id: 4, mode: RESOLVE_TBD) = 0 btf_ptr_resolve(depth: 3, type_id: 3, mode: RESOLVE_PTR) = 0 btf_var_resolve(depth: 2, type_id: 4, mode: RESOLVE_PTR) = 0 btf_datasec_resolve(depth: 1, type_id: 1, mode: RESOLVE_PTR) = -22 The last invocation of btf_datasec_resolve should invoke btf_var_resolve by means of env_stack_push, instead it returns EINVAL. The reason is that env_stack_push is never executed for the second VAR. if (!env_type_is_resolve_sink(env, var_type) && !env_type_is_resolved(env, var_type_id)) { env_stack_set_next_member(env, i + 1); return env_stack_push(env, var_type, var_type_id); } env_type_is_resolve_sink() changes its behaviour based on resolve_mode. For RESOLVE_PTR, we can simplify the if condition to the following: (btf_type_is_modifier() || btf_type_is_ptr) && !env_type_is_resolved() Since we're dealing with a VAR the clause evaluates to false. This is not sufficient to trigger the bug however. The log output and EINVAL are only generated if btf_type_id_size() fails. if (!btf_type_id_size(btf, &type_id, &type_size)) { btf_verifier_log_vsi(env, v->t, vsi, "Invalid type"); return -EINVAL; } Most types are sized, so for example a VAR referring to an INT is not a problem. The bug is only triggered if a VAR points at a modifier. Since we skipped btf_var_resolve that modifier was also never resolved, which means that btf_resolved_type_id returns 0 aka VOID for the modifier. This in turn causes btf_type_id_size to return NULL, triggering EINVAL. To summarise, the following conditions are necessary: - VAR pointing at PTR, STRUCT, UNION or ARRAY - Followed by a VAR pointing at TYPEDEF, VOLATILE, CONST, RESTRICT or TYPE_TAG The fix is to reset resolve_mode to RESOLVE_TBD before attempting to resolve a VAR from a DATASEC. Fixes: 1dc92851849c ("bpf: kernel side support for BTF Var and DataSec") Signed-off-by: Lorenz Bauer Link: https://lore.kernel.org/r/20230306112138.155352-2-lmb@isovalent.com Signed-off-by: Martin KaFai Lau --- kernel/bpf/btf.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c index fa22ec79ac0e..73780748404c 100644 --- a/kernel/bpf/btf.c +++ b/kernel/bpf/btf.c @@ -4569,6 +4569,7 @@ static int btf_datasec_resolve(struct btf_verifier_env *env, struct btf *btf = env->btf; u16 i; + env->resolve_mode = RESOLVE_TBD; for_each_vsi_from(i, v->next_member, v->t, vsi) { u32 var_type_id = vsi->type, type_id, type_size = 0; const struct btf_type *var_type = btf_type_by_id(env->btf, From dfdd608c3b365f0fd49d7e13911ebcde06b9865b Mon Sep 17 00:00:00 2001 From: Lorenz Bauer Date: Mon, 6 Mar 2023 11:21:38 +0000 Subject: [PATCH 159/778] selftests/bpf: check that modifier resolves after pointer Add a regression test that ensures that a VAR pointing at a modifier which follows a PTR (or STRUCT or ARRAY) is resolved correctly by the datasec validator. Signed-off-by: Lorenz Bauer Link: https://lore.kernel.org/r/20230306112138.155352-3-lmb@isovalent.com Signed-off-by: Martin KaFai Lau --- tools/testing/selftests/bpf/prog_tests/btf.c | 28 ++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/tools/testing/selftests/bpf/prog_tests/btf.c b/tools/testing/selftests/bpf/prog_tests/btf.c index cbb600be943d..210d643fda6c 100644 --- a/tools/testing/selftests/bpf/prog_tests/btf.c +++ b/tools/testing/selftests/bpf/prog_tests/btf.c @@ -879,6 +879,34 @@ static struct btf_raw_test raw_tests[] = { .btf_load_err = true, .err_str = "Invalid elem", }, +{ + .descr = "var after datasec, ptr followed by modifier", + .raw_types = { + /* .bss section */ /* [1] */ + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_DATASEC, 0, 2), + sizeof(void*)+4), + BTF_VAR_SECINFO_ENC(4, 0, sizeof(void*)), + BTF_VAR_SECINFO_ENC(6, sizeof(void*), 4), + /* int */ /* [2] */ + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), + /* int* */ /* [3] */ + BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 2), + BTF_VAR_ENC(NAME_TBD, 3, 0), /* [4] */ + /* const int */ /* [5] */ + BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 2), + BTF_VAR_ENC(NAME_TBD, 5, 0), /* [6] */ + BTF_END_RAW, + }, + .str_sec = "\0a\0b\0c\0", + .str_sec_size = sizeof("\0a\0b\0c\0"), + .map_type = BPF_MAP_TYPE_ARRAY, + .map_name = ".bss", + .key_size = sizeof(int), + .value_size = sizeof(void*)+4, + .key_type_id = 0, + .value_type_id = 1, + .max_entries = 1, +}, /* Test member exceeds the size of struct. * * struct A { From 8ca09d5fa3549d142c2080a72a4c70ce389163cd Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 6 Mar 2023 12:15:13 -0800 Subject: [PATCH 160/778] cpumask: fix incorrect cpumask scanning result checks It turns out that commit 596ff4a09b89 ("cpumask: re-introduce constant-sized cpumask optimizations") exposed a number of cases of drivers not checking the result of "cpumask_next()" and friends correctly. The documented correct check for "no more cpus in the cpumask" is to check for the result being equal or larger than the number of possible CPU ids, exactly _because_ we've always done those constant-sized cpumask scans using a widened type before. So the return value of a cpumask scan should be checked with if (cpu >= nr_cpu_ids) ... because the cpumask scan did not necessarily stop exactly *at* that maximum CPU id. But a few cases ended up instead using checks like if (cpu == nr_cpumask_bits) ... which used that internal "widened" number of bits. And that used to work pretty much by accident (ok, in this case "by accident" is simply because it matched the historical internal implementation of the cpumask scanning, so it was more of a "intentionally using implementation details rather than an accident"). But the extended constant-sized optimizations then did that internal implementation differently, and now that code that did things wrong but matched the old implementation no longer worked at all. Which then causes subsequent odd problems due to using what ends up being an invalid CPU ID. Most of these cases require either unusual hardware or special uses to hit, but the random.c one triggers quite easily. All you really need is to have a sufficiently small CONFIG_NR_CPUS value for the bit scanning optimization to be triggered, but not enough CPUs to then actually fill that widened cpumask. At that point, the cpumask scanning will return the NR_CPUS constant, which is _not_ the same as nr_cpumask_bits. This just does the mindless fix with sed -i 's/== nr_cpumask_bits/>= nr_cpu_ids/' to fix the incorrect uses. The ones in the SCSI lpfc driver in particular could probably be fixed more cleanly by just removing that repeated pattern entirely, but I am not emptionally invested enough in that driver to care. Reported-and-tested-by: Guenter Roeck Link: https://lore.kernel.org/lkml/481b19b5-83a0-4793-b4fd-194ad7b978c3@roeck-us.net/ Reported-and-tested-by: Geert Uytterhoeven Link: https://lore.kernel.org/lkml/CAMuHMdUKo_Sf7TjKzcNDa8Ve+6QrK+P8nSQrSQ=6LTRmcBKNww@mail.gmail.com/ Reported-by: Vernon Yang Link: https://lore.kernel.org/lkml/20230306160651.2016767-1-vernon2gm@gmail.com/ Cc: Yury Norov Cc: Jason A. Donenfeld Signed-off-by: Linus Torvalds --- arch/powerpc/xmon/xmon.c | 2 +- drivers/char/random.c | 2 +- drivers/net/wireguard/queueing.h | 2 +- drivers/scsi/lpfc/lpfc_init.c | 14 +++++++------- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index 73c620c2a3a1..e753a6bd4888 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c @@ -1275,7 +1275,7 @@ static int xmon_batch_next_cpu(void) while (!cpumask_empty(&xmon_batch_cpus)) { cpu = cpumask_next_wrap(smp_processor_id(), &xmon_batch_cpus, xmon_batch_start_cpu, true); - if (cpu == nr_cpumask_bits) + if (cpu >= nr_cpu_ids) break; if (xmon_batch_start_cpu == -1) xmon_batch_start_cpu = cpu; diff --git a/drivers/char/random.c b/drivers/char/random.c index ce3ccd172cc8..253f2ddb8913 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -1311,7 +1311,7 @@ static void __cold try_to_generate_entropy(void) /* Basic CPU round-robin, which avoids the current CPU. */ do { cpu = cpumask_next(cpu, &timer_cpus); - if (cpu == nr_cpumask_bits) + if (cpu >= nr_cpu_ids) cpu = cpumask_first(&timer_cpus); } while (cpu == smp_processor_id() && num_cpus > 1); diff --git a/drivers/net/wireguard/queueing.h b/drivers/net/wireguard/queueing.h index 583adb37ee1e..125284b346a7 100644 --- a/drivers/net/wireguard/queueing.h +++ b/drivers/net/wireguard/queueing.h @@ -106,7 +106,7 @@ static inline int wg_cpumask_choose_online(int *stored_cpu, unsigned int id) { unsigned int cpu = *stored_cpu, cpu_index, i; - if (unlikely(cpu == nr_cpumask_bits || + if (unlikely(cpu >= nr_cpu_ids || !cpumask_test_cpu(cpu, cpu_online_mask))) { cpu_index = id % cpumask_weight(cpu_online_mask); cpu = cpumask_first(cpu_online_mask); diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 61958a24a43d..73b544bfbb2e 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -12563,7 +12563,7 @@ lpfc_cpu_affinity_check(struct lpfc_hba *phba, int vectors) goto found_same; new_cpu = cpumask_next( new_cpu, cpu_present_mask); - if (new_cpu == nr_cpumask_bits) + if (new_cpu >= nr_cpu_ids) new_cpu = first_cpu; } /* At this point, we leave the CPU as unassigned */ @@ -12577,7 +12577,7 @@ found_same: * selecting the same IRQ. */ start_cpu = cpumask_next(new_cpu, cpu_present_mask); - if (start_cpu == nr_cpumask_bits) + if (start_cpu >= nr_cpu_ids) start_cpu = first_cpu; lpfc_printf_log(phba, KERN_INFO, LOG_INIT, @@ -12613,7 +12613,7 @@ found_same: goto found_any; new_cpu = cpumask_next( new_cpu, cpu_present_mask); - if (new_cpu == nr_cpumask_bits) + if (new_cpu >= nr_cpu_ids) new_cpu = first_cpu; } /* We should never leave an entry unassigned */ @@ -12631,7 +12631,7 @@ found_any: * selecting the same IRQ. */ start_cpu = cpumask_next(new_cpu, cpu_present_mask); - if (start_cpu == nr_cpumask_bits) + if (start_cpu >= nr_cpu_ids) start_cpu = first_cpu; lpfc_printf_log(phba, KERN_INFO, LOG_INIT, @@ -12704,7 +12704,7 @@ found_any: goto found_hdwq; } new_cpu = cpumask_next(new_cpu, cpu_present_mask); - if (new_cpu == nr_cpumask_bits) + if (new_cpu >= nr_cpu_ids) new_cpu = first_cpu; } @@ -12719,7 +12719,7 @@ found_any: goto found_hdwq; new_cpu = cpumask_next(new_cpu, cpu_present_mask); - if (new_cpu == nr_cpumask_bits) + if (new_cpu >= nr_cpu_ids) new_cpu = first_cpu; } @@ -12730,7 +12730,7 @@ found_any: found_hdwq: /* We found an available entry, copy the IRQ info */ start_cpu = cpumask_next(new_cpu, cpu_present_mask); - if (start_cpu == nr_cpumask_bits) + if (start_cpu >= nr_cpu_ids) start_cpu = first_cpu; cpup->hdwq = new_cpup->hdwq; logit: From 06a1574b94ee5272789eaea05a5bdddedea7cc0d Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 6 Mar 2023 14:44:11 -0300 Subject: [PATCH 161/778] tools headers UAPI: Sync linux/perf_event.h with the kernel sources To pick up the changes in: 09519ec3b19e4144 ("perf: Add perf_event_attr::config3") The patches for the tooling side will come later. This addresses this perf build warning: Warning: Kernel ABI header at 'tools/include/uapi/linux/perf_event.h' differs from latest version at 'include/uapi/linux/perf_event.h' diff -u tools/include/uapi/linux/perf_event.h include/uapi/linux/perf_event.h Cc: Adrian Hunter Cc: Ian Rogers Cc: Jiri Olsa Cc: Namhyung Kim Cc: Rob Herring Cc: Will Deacon Link: https://lore.kernel.org/lkml/ZAZLYmDjWjSItWOq@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/include/uapi/linux/perf_event.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/include/uapi/linux/perf_event.h b/tools/include/uapi/linux/perf_event.h index ccb7f5dad59b..37675437b768 100644 --- a/tools/include/uapi/linux/perf_event.h +++ b/tools/include/uapi/linux/perf_event.h @@ -374,6 +374,7 @@ enum perf_event_read_format { #define PERF_ATTR_SIZE_VER5 112 /* add: aux_watermark */ #define PERF_ATTR_SIZE_VER6 120 /* add: aux_sample_size */ #define PERF_ATTR_SIZE_VER7 128 /* add: sig_data */ +#define PERF_ATTR_SIZE_VER8 136 /* add: config3 */ /* * Hardware event_id to monitor via a performance monitoring event: @@ -515,6 +516,8 @@ struct perf_event_attr { * truncated accordingly on 32 bit architectures. */ __u64 sig_data; + + __u64 config3; /* extension of config2 */ }; /* From 5b201a82cd9d0945d70562974ea6ad8e3b1861b5 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 6 Mar 2023 14:50:45 -0300 Subject: [PATCH 162/778] perf tools: Add Adrian Hunter to MAINTAINERS as a reviewer Adrian is the main author of the Intel PT codebase and has been reviewing perf tooling patches consistently for a long time, so lets reflect that in the MAINTAINERS file so that contributors add him to the CC list in patch submissions. Acked-by: Adrian Hunter Acked-by: Ian Rogers Acked-by: Jiri Olsa Acked-by: Namhyung Kim Cc: Alexander Shishkin Cc: Ingo Molnar Cc: Mark Rutland Cc: Peter Zijlstra Link: https://lore.kernel.org/lkml/ZAYosCjlzO9plAYO@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 66b5d5a51d5b..8e46fa10a631 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -16425,6 +16425,7 @@ R: Alexander Shishkin R: Jiri Olsa R: Namhyung Kim R: Ian Rogers +R: Adrian Hunter L: linux-perf-users@vger.kernel.org L: linux-kernel@vger.kernel.org S: Supported From 58aac3a2ef414fea6d7fdf823ea177744a087d13 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sat, 4 Mar 2023 11:52:44 +0100 Subject: [PATCH 163/778] net: phy: smsc: fix link up detection in forced irq mode Currently link up can't be detected in forced mode if polling isn't used. Only link up interrupt source we have is aneg complete which isn't applicable in forced mode. Therefore we have to use energy-on as link up indicator. Fixes: 7365494550f6 ("net: phy: smsc: skip ENERGYON interrupt if disabled") Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/phy/smsc.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c index ac7481ce2fc1..00d9eff91dcf 100644 --- a/drivers/net/phy/smsc.c +++ b/drivers/net/phy/smsc.c @@ -44,7 +44,6 @@ static struct smsc_hw_stat smsc_hw_stats[] = { }; struct smsc_phy_priv { - u16 intmask; bool energy_enable; }; @@ -57,7 +56,6 @@ static int smsc_phy_ack_interrupt(struct phy_device *phydev) static int smsc_phy_config_intr(struct phy_device *phydev) { - struct smsc_phy_priv *priv = phydev->priv; int rc; if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { @@ -65,14 +63,9 @@ static int smsc_phy_config_intr(struct phy_device *phydev) if (rc) return rc; - priv->intmask = MII_LAN83C185_ISF_INT4 | MII_LAN83C185_ISF_INT6; - if (priv->energy_enable) - priv->intmask |= MII_LAN83C185_ISF_INT7; - - rc = phy_write(phydev, MII_LAN83C185_IM, priv->intmask); + rc = phy_write(phydev, MII_LAN83C185_IM, + MII_LAN83C185_ISF_INT_PHYLIB_EVENTS); } else { - priv->intmask = 0; - rc = phy_write(phydev, MII_LAN83C185_IM, 0); if (rc) return rc; @@ -85,7 +78,6 @@ static int smsc_phy_config_intr(struct phy_device *phydev) static irqreturn_t smsc_phy_handle_interrupt(struct phy_device *phydev) { - struct smsc_phy_priv *priv = phydev->priv; int irq_status; irq_status = phy_read(phydev, MII_LAN83C185_ISF); @@ -96,7 +88,7 @@ static irqreturn_t smsc_phy_handle_interrupt(struct phy_device *phydev) return IRQ_NONE; } - if (!(irq_status & priv->intmask)) + if (!(irq_status & MII_LAN83C185_ISF_INT_PHYLIB_EVENTS)) return IRQ_NONE; phy_trigger_machine(phydev); From 193250ace270fecd586dd2d0dfbd9cbd2ade977f Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Sat, 4 Mar 2023 13:43:20 +0000 Subject: [PATCH 164/778] net: ethernet: mtk_eth_soc: fix RX data corruption issue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix data corruption issue with SerDes connected PHYs operating at 1.25 Gbps speed where we could previously observe about 30% packet loss while the bad packet counter was increasing. As almost all boards with MediaTek MT7622 or MT7986 use either the MT7531 switch IC operating at 3.125Gbps SerDes rate or single-port PHYs using rate-adaptation to 2500Base-X mode, this issue only got exposed now when we started trying to use SFP modules operating with 1.25 Gbps with the BananaPi R3 board. The fix is to set bit 12 which disables the RX FIFO clear function when setting up MAC MCR, MediaTek SDK did the same change stating: "If without this patch, kernel might receive invalid packets that are corrupted by GMAC."[1] [1]: https://git01.mediatek.com/plugins/gitiles/openwrt/feeds/mtk-openwrt-feeds/+/d8a2975939a12686c4a95c40db21efdc3f821f63 Fixes: 42c03844e93d ("net-next: mediatek: add support for MediaTek MT7622 SoC") Tested-by: Bjørn Mork Signed-off-by: Daniel Golle Reviewed-by: Vladimir Oltean Reviewed-by: Florian Fainelli Link: https://lore.kernel.org/r/138da2735f92c8b6f8578ec2e5a794ee515b665f.1677937317.git.daniel@makrotopia.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 3 ++- drivers/net/ethernet/mediatek/mtk_eth_soc.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index 14be6ea51b88..3cb43623d3db 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -616,7 +616,8 @@ static int mtk_mac_finish(struct phylink_config *config, unsigned int mode, mcr_cur = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id)); mcr_new = mcr_cur; mcr_new |= MAC_MCR_IPG_CFG | MAC_MCR_FORCE_MODE | - MAC_MCR_BACKOFF_EN | MAC_MCR_BACKPR_EN | MAC_MCR_FORCE_LINK; + MAC_MCR_BACKOFF_EN | MAC_MCR_BACKPR_EN | MAC_MCR_FORCE_LINK | + MAC_MCR_RX_FIFO_CLR_DIS; /* Only update control register when needed! */ if (mcr_new != mcr_cur) diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h index afc9d52e79bf..b65de174c3d9 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h @@ -397,6 +397,7 @@ #define MAC_MCR_FORCE_MODE BIT(15) #define MAC_MCR_TX_EN BIT(14) #define MAC_MCR_RX_EN BIT(13) +#define MAC_MCR_RX_FIFO_CLR_DIS BIT(12) #define MAC_MCR_BACKOFF_EN BIT(9) #define MAC_MCR_BACKPR_EN BIT(8) #define MAC_MCR_FORCE_RX_FC BIT(5) From e539a105f947b9db470fec39fe91d85fe737a432 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Sat, 4 Mar 2023 11:26:10 -0800 Subject: [PATCH 165/778] net: tls: fix device-offloaded sendpage straddling records Adrien reports that incorrect data is transmitted when a single page straddles multiple records. We would transmit the same data in all iterations of the loop. Reported-by: Adrien Moulin Link: https://lore.kernel.org/all/61481278.42813558.1677845235112.JavaMail.zimbra@corp.free.fr Fixes: c1318b39c7d3 ("tls: Add opt-in zerocopy mode of sendfile()") Tested-by: Adrien Moulin Reviewed-by: Tariq Toukan Acked-by: Maxim Mikityanskiy Link: https://lore.kernel.org/r/20230304192610.3818098-1-kuba@kernel.org Signed-off-by: Jakub Kicinski --- net/tls/tls_device.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/tls/tls_device.c b/net/tls/tls_device.c index 6c593788dc25..a7cc4f9faac2 100644 --- a/net/tls/tls_device.c +++ b/net/tls/tls_device.c @@ -508,6 +508,8 @@ handle_error: zc_pfrag.offset = iter_offset.offset; zc_pfrag.size = copy; tls_append_frag(record, &zc_pfrag, copy); + + iter_offset.offset += copy; } else if (copy) { copy = min_t(size_t, copy, pfrag->size - pfrag->offset); From 6cc55c969b7ce8d85e09a636693d4126c3676c11 Mon Sep 17 00:00:00 2001 From: Maurizio Lombardi Date: Tue, 14 Feb 2023 15:15:56 +0100 Subject: [PATCH 166/778] scsi: target: iscsi: Fix an error message in iscsi_check_key() The first half of the error message is printed by pr_err(), the second half is printed by pr_debug(). The user will therefore see only the first part of the message and will miss some useful information. Link: https://lore.kernel.org/r/20230214141556.762047-1-mlombard@redhat.com Signed-off-by: Maurizio Lombardi Reviewed-by: Mike Christie Signed-off-by: Martin K. Petersen --- drivers/target/iscsi/iscsi_target_parameters.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/target/iscsi/iscsi_target_parameters.c b/drivers/target/iscsi/iscsi_target_parameters.c index 2317fb077db0..557516c642c3 100644 --- a/drivers/target/iscsi/iscsi_target_parameters.c +++ b/drivers/target/iscsi/iscsi_target_parameters.c @@ -1262,18 +1262,20 @@ static struct iscsi_param *iscsi_check_key( return param; if (!(param->phase & phase)) { - pr_err("Key \"%s\" may not be negotiated during ", - param->name); + char *phase_name; + switch (phase) { case PHASE_SECURITY: - pr_debug("Security phase.\n"); + phase_name = "Security"; break; case PHASE_OPERATIONAL: - pr_debug("Operational phase.\n"); + phase_name = "Operational"; break; default: - pr_debug("Unknown phase.\n"); + phase_name = "Unknown"; } + pr_err("Key \"%s\" may not be negotiated during %s phase.\n", + param->name, phase_name); return NULL; } From 877b03795fcf29ff2e2351f7e574ecc9b9c51732 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Wed, 8 Feb 2023 16:20:14 +0100 Subject: [PATCH 167/778] scsi: qla2xxx: Add option to disable FC2 Target support Commit 44c57f205876 ("scsi: qla2xxx: Changes to support FCP2 Target") added support for FC2 Targets. Unfortunately, there are older setups which break with this new feature enabled. Allow to disable it via module option. Link: https://lore.kernel.org/r/20230208152014.109214-1-dwagner@suse.de Signed-off-by: Daniel Wagner Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_gbl.h | 1 + drivers/scsi/qla2xxx/qla_init.c | 3 ++- drivers/scsi/qla2xxx/qla_os.c | 10 +++++++++- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 9142df876c73..9aba07c7bde4 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -192,6 +192,7 @@ extern int ql2xsecenable; extern int ql2xenforce_iocb_limit; extern int ql2xabts_wait_nvme; extern u32 ql2xnvme_queues; +extern int ql2xfc2target; extern int qla2x00_loop_reset(scsi_qla_host_t *); extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int); diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 1dbc1496ebed..ec0423ec6681 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -1840,7 +1840,8 @@ void qla2x00_handle_rscn(scsi_qla_host_t *vha, struct event_arg *ea) case RSCN_PORT_ADDR: fcport = qla2x00_find_fcport_by_nportid(vha, &ea->id, 1); if (fcport) { - if (fcport->flags & FCF_FCP2_DEVICE && + if (ql2xfc2target && + fcport->flags & FCF_FCP2_DEVICE && atomic_read(&fcport->state) == FCS_ONLINE) { ql_dbg(ql_dbg_disc, vha, 0x2115, "Delaying session delete for FCP2 portid=%06x %8phC ", diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 545167627e48..80c4ee9df2a4 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -360,6 +360,13 @@ MODULE_PARM_DESC(ql2xnvme_queues, "1 - Minimum number of queues supported\n" "8 - Default value"); +int ql2xfc2target = 1; +module_param(ql2xfc2target, int, 0444); +MODULE_PARM_DESC(qla2xfc2target, + "Enables FC2 Target support. " + "0 - FC2 Target support is disabled. " + "1 - FC2 Target support is enabled (default)."); + static struct scsi_transport_template *qla2xxx_transport_template = NULL; struct scsi_transport_template *qla2xxx_transport_vport_template = NULL; @@ -4085,7 +4092,8 @@ qla2x00_mark_all_devices_lost(scsi_qla_host_t *vha) "Mark all dev lost\n"); list_for_each_entry(fcport, &vha->vp_fcports, list) { - if (fcport->loop_id != FC_NO_LOOP_ID && + if (ql2xfc2target && + fcport->loop_id != FC_NO_LOOP_ID && (fcport->flags & FCF_FCP2_DEVICE) && fcport->port_type == FCT_TARGET && !qla2x00_reset_active(vha)) { From 06d1a90de60208054cca15ef200138cfdbb642a9 Mon Sep 17 00:00:00 2001 From: Kang Chen Date: Mon, 27 Feb 2023 11:10:30 +0800 Subject: [PATCH 168/778] scsi: hisi_sas: Check devm_add_action() return value In case devm_add_action() fails, check it in the caller of interrupt_preinit_v3_hw(). Link: https://lore.kernel.org/r/20230227031030.893324-1-void0red@gmail.com Signed-off-by: Kang Chen Acked-by: Xiang Chen Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index 0c3fcb807806..a63279f55d09 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -2495,8 +2495,7 @@ static int interrupt_preinit_v3_hw(struct hisi_hba *hisi_hba) hisi_hba->cq_nvecs = vectors - BASE_VECTORS_V3_HW; shost->nr_hw_queues = hisi_hba->cq_nvecs; - devm_add_action(&pdev->dev, hisi_sas_v3_free_vectors, pdev); - return 0; + return devm_add_action(&pdev->dev, hisi_sas_v3_free_vectors, pdev); } static int interrupt_init_v3_hw(struct hisi_hba *hisi_hba) From 2ebe16155dc8bd4e602cad5b5f65458d2eaa1a75 Mon Sep 17 00:00:00 2001 From: Adrien Thierry Date: Mon, 20 Feb 2023 09:07:40 -0500 Subject: [PATCH 169/778] scsi: ufs: core: Add soft dependency on governor_simpleondemand The ufshcd driver uses simpleondemand governor for devfreq. Add it to the list of ufshcd softdeps to allow userspace initramfs tools like dracut to automatically pull the governor module into the initramfs together with UFS drivers. Link: https://lore.kernel.org/r/20230220140740.14379-1-athierry@redhat.com Signed-off-by: Adrien Thierry Signed-off-by: Martin K. Petersen --- drivers/ufs/core/ufshcd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c index 172d25fef740..05eac965ee27 100644 --- a/drivers/ufs/core/ufshcd.c +++ b/drivers/ufs/core/ufshcd.c @@ -10512,4 +10512,5 @@ module_exit(ufshcd_core_exit); MODULE_AUTHOR("Santosh Yaragnavi "); MODULE_AUTHOR("Vinayak Holikatti "); MODULE_DESCRIPTION("Generic UFS host controller driver Core"); +MODULE_SOFTDEP("pre: governor_simpleondemand"); MODULE_LICENSE("GPL"); From fa8d32721a07d1349d963832400e97ebb515aa96 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 27 Feb 2023 13:07:26 +0300 Subject: [PATCH 170/778] scsi: ufs: ufs-qcom: Remove impossible check The "dev_req_params" pointer points to inside the middle of a struct so it can't be NULL. Removing this impossible condition is nice because now we don't need to consider the correct error code for that situation. Link: https://lore.kernel.org/r/Y/yA3niWUcGYgBU8@kili Fixes: f06fcc7155dc ("scsi: ufs-qcom: add QUniPro hardware support and power optimizations") Signed-off-by: Dan Carpenter Signed-off-by: Martin K. Petersen --- drivers/ufs/host/ufs-qcom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c index 34fc453f3eb1..797230ad3939 100644 --- a/drivers/ufs/host/ufs-qcom.c +++ b/drivers/ufs/host/ufs-qcom.c @@ -1177,7 +1177,7 @@ static int ufs_qcom_clk_scale_notify(struct ufs_hba *hba, err = ufs_qcom_clk_scale_down_post_change(hba); - if (err || !dev_req_params) { + if (err) { ufshcd_uic_hibern8_exit(hba); return err; } From c8be073bd2bced20f58e65276281fc116758c7cb Mon Sep 17 00:00:00 2001 From: Asutosh Das Date: Wed, 1 Mar 2023 17:41:06 -0800 Subject: [PATCH 171/778] scsi: ufs: mcq: qcom: Fix passing zero to PTR_ERR Fix an error case in ufs_qcom_mcq_config_resource(), where the return value is set to 0 before passing it to PTR_ERR. This led to Smatch warning: drivers/ufs/host/ufs-qcom.c:1455 ufs_qcom_mcq_config_resource() warn: passing zero to 'PTR_ERR' Fixes: c263b4ef737e ("scsi: ufs: core: mcq: Configure resource regions") Reported-by: Dan Carpenter Signed-off-by: Asutosh Das Link: https://lore.kernel.org/r/94ca99b327af634799ce5f25d0112c28cd00970d.1677721072.git.quic_asutoshd@quicinc.com Reviewed-by: Bjorn Andersson Reviewed-by: Manivannan Sadhasivam Signed-off-by: Martin K. Petersen --- drivers/ufs/host/ufs-qcom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c index 797230ad3939..2781739a66e0 100644 --- a/drivers/ufs/host/ufs-qcom.c +++ b/drivers/ufs/host/ufs-qcom.c @@ -1451,8 +1451,8 @@ static int ufs_qcom_mcq_config_resource(struct ufs_hba *hba) if (IS_ERR(res->base)) { dev_err(hba->dev, "Failed to map res %s, err=%d\n", res->name, (int)PTR_ERR(res->base)); - res->base = NULL; ret = PTR_ERR(res->base); + res->base = NULL; return ret; } } From c9507eab9fa7af7ab4c80856eeafd1481ff16f7c Mon Sep 17 00:00:00 2001 From: Asutosh Das Date: Wed, 1 Mar 2023 17:42:56 -0800 Subject: [PATCH 172/778] scsi: ufs: mcq: qcom: Clean the return path of ufs_qcom_mcq_config_resource() Smatch static checker reported: drivers/ufs/host/ufs-qcom.c:1469 ufs_qcom_mcq_config_resource() info: returning a literal zero is cleaner Fix the above warning by returning in place instead of a jump to a label. Also remove the usage of devm_kfree() as it's unnecessary in this function. Fixes: c263b4ef737e ("scsi: ufs: core: mcq: Configure resource regions") Reported-by: Dan Carpenter Signed-off-by: Asutosh Das Link: https://lore.kernel.org/r/3ebd2582af74b81ef7b57149f57c6a3bf0963953.1677721229.git.quic_asutoshd@quicinc.com Reviewed-by: Bjorn Andersson Reviewed-by: Manivannan Sadhasivam Signed-off-by: Martin K. Petersen --- drivers/ufs/host/ufs-qcom.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c index 2781739a66e0..a02cd866e2f8 100644 --- a/drivers/ufs/host/ufs-qcom.c +++ b/drivers/ufs/host/ufs-qcom.c @@ -1466,7 +1466,7 @@ static int ufs_qcom_mcq_config_resource(struct ufs_hba *hba) /* Explicitly allocate MCQ resource from ufs_mem */ res_mcq = devm_kzalloc(hba->dev, sizeof(*res_mcq), GFP_KERNEL); if (!res_mcq) - return ret; + return -ENOMEM; res_mcq->start = res_mem->start + MCQ_SQATTR_OFFSET(hba->mcq_capabilities); @@ -1478,7 +1478,7 @@ static int ufs_qcom_mcq_config_resource(struct ufs_hba *hba) if (ret) { dev_err(hba->dev, "Failed to insert MCQ resource, err=%d\n", ret); - goto insert_res_err; + return ret; } res->base = devm_ioremap_resource(hba->dev, res_mcq); @@ -1495,8 +1495,6 @@ out: ioremap_err: res->base = NULL; remove_resource(res_mcq); -insert_res_err: - devm_kfree(hba->dev, res_mcq); return ret; } From 312320b0e0ec21249a17645683fe5304d796aec1 Mon Sep 17 00:00:00 2001 From: Justin Tee Date: Mon, 27 Feb 2023 20:43:36 -0800 Subject: [PATCH 173/778] scsi: lpfc: Check kzalloc() in lpfc_sli4_cgn_params_read() If kzalloc() fails in lpfc_sli4_cgn_params_read(), then we rely on lpfc_read_object()'s routine to NULL check pdata. Currently, an early return error is thrown from lpfc_read_object() to protect us from NULL ptr dereference, but the errno code is -ENODEV. Change the errno code to a more appropriate -ENOMEM. Reported-by: Kang Chen Link: https://lore.kernel.org/all/20230226102338.3362585-1-void0red@gmail.com Signed-off-by: Justin Tee Link: https://lore.kernel.org/r/20230228044336.5195-1-justintee8345@gmail.com Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_init.c | 2 ++ drivers/scsi/lpfc/lpfc_sli.c | 4 ---- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 61958a24a43d..60e4ac2b8a6b 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -7291,6 +7291,8 @@ lpfc_sli4_cgn_params_read(struct lpfc_hba *phba) /* Find out if the FW has a new set of congestion parameters. */ len = sizeof(struct lpfc_cgn_param); pdata = kzalloc(len, GFP_KERNEL); + if (!pdata) + return -ENOMEM; ret = lpfc_read_object(phba, (char *)LPFC_PORT_CFG_NAME, pdata, len); diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index c5b69f313af3..c5ad46fdde81 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -22109,10 +22109,6 @@ lpfc_read_object(struct lpfc_hba *phba, char *rdobject, uint32_t *datap, struct lpfc_dmabuf *pcmd; u32 rd_object_name[LPFC_MBX_OBJECT_NAME_LEN_DW] = {0}; - /* sanity check on queue memory */ - if (!datap) - return -ENODEV; - mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!mbox) return -ENOMEM; From 2850b23e9f9ae3696e472d2883ea1b43aafa884e Mon Sep 17 00:00:00 2001 From: Jakob Koschel Date: Wed, 1 Mar 2023 18:19:14 +0100 Subject: [PATCH 174/778] scsi: lpfc: Avoid usage of list iterator variable after loop If the &epd_pool->list is empty when executing lpfc_get_io_buf_from_expedite_pool() the function would return an invalid pointer. Even in the case if the list is guaranteed to be populated, the iterator variable should not be used after the loop to be more robust for future changes. Linus proposed to avoid any use of the list iterator variable after the loop, in the attempt to move the list iterator variable declaration into the macro to avoid any potential misuse after the loop [1]. Link: https://lore.kernel.org/all/CAHk-=wgRr_D8CB-D9Kg-c=EHreAsk5SqXPwr9Y7k9sA6cWXJ6w@mail.gmail.com/ [1] Signed-off-by: Jakob Koschel Link: https://lore.kernel.org/r/20230301-scsi-lpfc-avoid-list-iterator-after-loop-v1-1-325578ae7561@gmail.com Reviewed-by: Justin Tee Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_sli.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index c5ad46fdde81..cf630aa6734e 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -21899,20 +21899,20 @@ lpfc_get_io_buf_from_private_pool(struct lpfc_hba *phba, static struct lpfc_io_buf * lpfc_get_io_buf_from_expedite_pool(struct lpfc_hba *phba) { - struct lpfc_io_buf *lpfc_ncmd; + struct lpfc_io_buf *lpfc_ncmd = NULL, *iter; struct lpfc_io_buf *lpfc_ncmd_next; unsigned long iflag; struct lpfc_epd_pool *epd_pool; epd_pool = &phba->epd_pool; - lpfc_ncmd = NULL; spin_lock_irqsave(&epd_pool->lock, iflag); if (epd_pool->count > 0) { - list_for_each_entry_safe(lpfc_ncmd, lpfc_ncmd_next, + list_for_each_entry_safe(iter, lpfc_ncmd_next, &epd_pool->list, list) { - list_del(&lpfc_ncmd->list); + list_del(&iter->list); epd_pool->count--; + lpfc_ncmd = iter; break; } } From 02ca7da2919ada525fb424640205110e24646b50 Mon Sep 17 00:00:00 2001 From: Ranjan Kumar Date: Tue, 28 Feb 2023 06:08:30 -0800 Subject: [PATCH 175/778] scsi: mpi3mr: ioctl timeout when disabling/enabling interrupt As part of Task Management handling, the driver will disable and enable the MSIx index zero which belongs to the Admin reply queue. During this transition the driver loses some interrupts and this leads to Admin request and ioctl timeouts. After enabling the interrupts, poll the Admin reply queue to avoid timeouts. Signed-off-by: Ranjan Kumar Signed-off-by: Sreekanth Reddy Link: https://lore.kernel.org/r/20230228140835.4075-2-ranjan.kumar@broadcom.com Signed-off-by: Martin K. Petersen --- drivers/scsi/mpi3mr/mpi3mr.h | 3 +++ drivers/scsi/mpi3mr/mpi3mr_fw.c | 12 ++++++++++-- drivers/scsi/mpi3mr/mpi3mr_os.c | 1 + 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h index 23de2603e71f..40f238fa80cc 100644 --- a/drivers/scsi/mpi3mr/mpi3mr.h +++ b/drivers/scsi/mpi3mr/mpi3mr.h @@ -902,6 +902,7 @@ struct scmd_priv { * @admin_reply_ephase:Admin reply queue expected phase * @admin_reply_base: Admin reply queue base virtual address * @admin_reply_dma: Admin reply queue base dma address + * @admin_reply_q_in_use: Queue is handled by poll/ISR * @ready_timeout: Controller ready timeout * @intr_info: Interrupt cookie pointer * @intr_info_count: Number of interrupt cookies @@ -1055,6 +1056,7 @@ struct mpi3mr_ioc { u8 admin_reply_ephase; void *admin_reply_base; dma_addr_t admin_reply_dma; + atomic_t admin_reply_q_in_use; u32 ready_timeout; @@ -1390,4 +1392,5 @@ void mpi3mr_add_event_wait_for_device_refresh(struct mpi3mr_ioc *mrioc); void mpi3mr_flush_drv_cmds(struct mpi3mr_ioc *mrioc); void mpi3mr_flush_cmds_for_unrecovered_controller(struct mpi3mr_ioc *mrioc); void mpi3mr_free_enclosure_list(struct mpi3mr_ioc *mrioc); +int mpi3mr_process_admin_reply_q(struct mpi3mr_ioc *mrioc); #endif /*MPI3MR_H_INCLUDED*/ diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c index 758f7ca9e0ee..4254e46a20f1 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_fw.c +++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c @@ -415,7 +415,7 @@ out: le64_to_cpu(scsi_reply->sense_data_buffer_address)); } -static int mpi3mr_process_admin_reply_q(struct mpi3mr_ioc *mrioc) +int mpi3mr_process_admin_reply_q(struct mpi3mr_ioc *mrioc) { u32 exp_phase = mrioc->admin_reply_ephase; u32 admin_reply_ci = mrioc->admin_reply_ci; @@ -423,12 +423,17 @@ static int mpi3mr_process_admin_reply_q(struct mpi3mr_ioc *mrioc) u64 reply_dma = 0; struct mpi3_default_reply_descriptor *reply_desc; + if (!atomic_add_unless(&mrioc->admin_reply_q_in_use, 1, 1)) + return 0; + reply_desc = (struct mpi3_default_reply_descriptor *)mrioc->admin_reply_base + admin_reply_ci; if ((le16_to_cpu(reply_desc->reply_flags) & - MPI3_REPLY_DESCRIPT_FLAGS_PHASE_MASK) != exp_phase) + MPI3_REPLY_DESCRIPT_FLAGS_PHASE_MASK) != exp_phase) { + atomic_dec(&mrioc->admin_reply_q_in_use); return 0; + } do { if (mrioc->unrecoverable) @@ -454,6 +459,7 @@ static int mpi3mr_process_admin_reply_q(struct mpi3mr_ioc *mrioc) writel(admin_reply_ci, &mrioc->sysif_regs->admin_reply_queue_ci); mrioc->admin_reply_ci = admin_reply_ci; mrioc->admin_reply_ephase = exp_phase; + atomic_dec(&mrioc->admin_reply_q_in_use); return num_admin_replies; } @@ -2605,6 +2611,7 @@ static int mpi3mr_setup_admin_qpair(struct mpi3mr_ioc *mrioc) mrioc->admin_reply_ci = 0; mrioc->admin_reply_ephase = 1; mrioc->admin_reply_base = NULL; + atomic_set(&mrioc->admin_reply_q_in_use, 0); if (!mrioc->admin_req_base) { mrioc->admin_req_base = dma_alloc_coherent(&mrioc->pdev->dev, @@ -4155,6 +4162,7 @@ void mpi3mr_memset_buffers(struct mpi3mr_ioc *mrioc) memset(mrioc->admin_req_base, 0, mrioc->admin_req_q_sz); if (mrioc->admin_reply_base) memset(mrioc->admin_reply_base, 0, mrioc->admin_reply_q_sz); + atomic_set(&mrioc->admin_reply_q_in_use, 0); if (mrioc->init_cmds.reply) { memset(mrioc->init_cmds.reply, 0, sizeof(*mrioc->init_cmds.reply)); diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c index 6eaeba41072c..a794cc8a1c0b 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_os.c +++ b/drivers/scsi/mpi3mr/mpi3mr_os.c @@ -3720,6 +3720,7 @@ int mpi3mr_issue_tm(struct mpi3mr_ioc *mrioc, u8 tm_type, mpi3mr_poll_pend_io_completions(mrioc); mpi3mr_ioc_enable_intr(mrioc); mpi3mr_poll_pend_io_completions(mrioc); + mpi3mr_process_admin_reply_q(mrioc); } switch (tm_type) { case MPI3_SCSITASKMGMT_TASKTYPE_TARGET_RESET: From 5b06a7169c59ce0c77ef8b9c82aa07c478f82aac Mon Sep 17 00:00:00 2001 From: Ranjan Kumar Date: Tue, 28 Feb 2023 06:08:31 -0800 Subject: [PATCH 176/778] scsi: mpi3mr: Driver unload crashes host when enhanced logging is enabled Prevent driver from trying to dereference a NULL pointer in a debug print while removing a device during driver unload. Signed-off-by: Ranjan Kumar Signed-off-by: Sreekanth Reddy Link: https://lore.kernel.org/r/20230228140835.4075-3-ranjan.kumar@broadcom.com Signed-off-by: Martin K. Petersen --- drivers/scsi/mpi3mr/mpi3mr_transport.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/mpi3mr/mpi3mr_transport.c b/drivers/scsi/mpi3mr/mpi3mr_transport.c index 3b61815979da..b795a325534d 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_transport.c +++ b/drivers/scsi/mpi3mr/mpi3mr_transport.c @@ -1552,7 +1552,8 @@ static void mpi3mr_sas_port_remove(struct mpi3mr_ioc *mrioc, u64 sas_address, list_for_each_entry_safe(mr_sas_phy, next_phy, &mr_sas_port->phy_list, port_siblings) { - if ((mrioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO)) + if ((!mrioc->stop_drv_processing) && + (mrioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO)) dev_info(&mr_sas_port->port->dev, "remove: sas_address(0x%016llx), phy(%d)\n", (unsigned long long) From 0a319f1629495d27879b7ebf6eee62b8cf6e4c37 Mon Sep 17 00:00:00 2001 From: Ranjan Kumar Date: Tue, 28 Feb 2023 06:08:32 -0800 Subject: [PATCH 177/778] scsi: mpi3mr: Wait for diagnostic save during controller init If a controller reset operation is triggered to recover the controller from a fault state, then wait for the snapdump to be saved in the firmware region before proceeding to reset the controller. Signed-off-by: Ranjan Kumar Signed-off-by: Sreekanth Reddy Link: https://lore.kernel.org/r/20230228140835.4075-4-ranjan.kumar@broadcom.com Signed-off-by: Martin K. Petersen --- drivers/scsi/mpi3mr/mpi3mr_fw.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c index 4254e46a20f1..fa903a70baac 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_fw.c +++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c @@ -1198,7 +1198,7 @@ mpi3mr_revalidate_factsdata(struct mpi3mr_ioc *mrioc) */ static int mpi3mr_bring_ioc_ready(struct mpi3mr_ioc *mrioc) { - u32 ioc_config, ioc_status, timeout; + u32 ioc_config, ioc_status, timeout, host_diagnostic; int retval = 0; enum mpi3mr_iocstate ioc_state; u64 base_info; @@ -1252,6 +1252,23 @@ static int mpi3mr_bring_ioc_ready(struct mpi3mr_ioc *mrioc) retval, mpi3mr_iocstate_name(ioc_state)); } if (ioc_state != MRIOC_STATE_RESET) { + if (ioc_state == MRIOC_STATE_FAULT) { + timeout = MPI3_SYSIF_DIAG_SAVE_TIMEOUT * 10; + mpi3mr_print_fault_info(mrioc); + do { + host_diagnostic = + readl(&mrioc->sysif_regs->host_diagnostic); + if (!(host_diagnostic & + MPI3_SYSIF_HOST_DIAG_SAVE_IN_PROGRESS)) + break; + if (!pci_device_is_present(mrioc->pdev)) { + mrioc->unrecoverable = 1; + ioc_err(mrioc, "controller is not present at the bringup\n"); + goto out_device_not_present; + } + msleep(100); + } while (--timeout); + } mpi3mr_print_fault_info(mrioc); ioc_info(mrioc, "issuing soft reset to bring to reset state\n"); retval = mpi3mr_issue_reset(mrioc, From ba8a9ba41fbde250fd8b0ed1e5dad0dc9318df46 Mon Sep 17 00:00:00 2001 From: Ranjan Kumar Date: Tue, 28 Feb 2023 06:08:33 -0800 Subject: [PATCH 178/778] scsi: mpi3mr: Return proper values for failures in firmware init path Return proper non-zero return values for all the cases when the controller initialization and re-initialization fails. Signed-off-by: Ranjan Kumar Signed-off-by: Sreekanth Reddy Link: https://lore.kernel.org/r/20230228140835.4075-5-ranjan.kumar@broadcom.com Signed-off-by: Martin K. Petersen --- drivers/scsi/mpi3mr/mpi3mr_fw.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c index fa903a70baac..29acf6111db3 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_fw.c +++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c @@ -3840,8 +3840,10 @@ retry_init: dprint_init(mrioc, "allocating config page buffers\n"); mrioc->cfg_page = dma_alloc_coherent(&mrioc->pdev->dev, MPI3MR_DEFAULT_CFG_PAGE_SZ, &mrioc->cfg_page_dma, GFP_KERNEL); - if (!mrioc->cfg_page) + if (!mrioc->cfg_page) { + retval = -1; goto out_failed_noretry; + } mrioc->cfg_page_sz = MPI3MR_DEFAULT_CFG_PAGE_SZ; @@ -3903,8 +3905,10 @@ retry_init: dprint_init(mrioc, "allocating memory for throttle groups\n"); sz = sizeof(struct mpi3mr_throttle_group_info); mrioc->throttle_groups = kcalloc(mrioc->num_io_throttle_group, sz, GFP_KERNEL); - if (!mrioc->throttle_groups) + if (!mrioc->throttle_groups) { + retval = -1; goto out_failed_noretry; + } } retval = mpi3mr_enable_events(mrioc); @@ -3924,6 +3928,7 @@ out_failed: mpi3mr_memset_buffers(mrioc); goto retry_init; } + retval = -1; out_failed_noretry: ioc_err(mrioc, "controller initialization failed\n"); mpi3mr_issue_reset(mrioc, MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT, @@ -4036,6 +4041,7 @@ retry_init: ioc_err(mrioc, "cannot create minimum number of operational queues expected:%d created:%d\n", mrioc->shost->nr_hw_queues, mrioc->num_op_reply_q); + retval = -1; goto out_failed_noretry; } @@ -4102,6 +4108,7 @@ out_failed: mpi3mr_memset_buffers(mrioc); goto retry_init; } + retval = -1; out_failed_noretry: ioc_err(mrioc, "controller %s is failed\n", (is_resume)?"resume":"re-initialization"); From 4f297e856a7b5da2f2c66a12e739666e23943560 Mon Sep 17 00:00:00 2001 From: Ranjan Kumar Date: Tue, 28 Feb 2023 06:08:34 -0800 Subject: [PATCH 179/778] scsi: mpi3mr: NVMe command size greater than 8K fails A wrong variable is checked while populating PRP entries in the PRP page and this results in failure. No PRP entries in the PRP page were successfully created and any NVMe Encapsulated commands with PRP of size greater than 8K failed. Signed-off-by: Ranjan Kumar Signed-off-by: Sreekanth Reddy Link: https://lore.kernel.org/r/20230228140835.4075-6-ranjan.kumar@broadcom.com Signed-off-by: Martin K. Petersen --- drivers/scsi/mpi3mr/mpi3mr_app.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/mpi3mr/mpi3mr_app.c b/drivers/scsi/mpi3mr/mpi3mr_app.c index bff637702397..d10c6afb7f9c 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_app.c +++ b/drivers/scsi/mpi3mr/mpi3mr_app.c @@ -886,7 +886,7 @@ static int mpi3mr_build_nvme_prp(struct mpi3mr_ioc *mrioc, * each time through the loop. */ *prp_entry = cpu_to_le64(dma_addr); - if (*prp1_entry & sgemod_mask) { + if (*prp_entry & sgemod_mask) { dprint_bsg_err(mrioc, "%s: PRP address collides with SGE modifier\n", __func__); @@ -895,7 +895,7 @@ static int mpi3mr_build_nvme_prp(struct mpi3mr_ioc *mrioc, *prp_entry &= ~sgemod_mask; *prp_entry |= sgemod_val; prp_entry++; - prp_entry_dma++; + prp_entry_dma += prp_size; } /* From 8e45183978d64699df639e795235433a60f35047 Mon Sep 17 00:00:00 2001 From: Ranjan Kumar Date: Tue, 28 Feb 2023 06:08:35 -0800 Subject: [PATCH 180/778] scsi: mpi3mr: Bad drive in topology results kernel crash When the SAS Transport Layer support is enabled and a device exposed to the OS by the driver fails INQUIRY commands, the driver frees up the memory allocated for an internal HBA port data structure. However, in some places, the reference to the freed memory is not cleared. When the firmware sends the Device Info change event for the same device again, the freed memory is accessed and that leads to memory corruption and OS crash. Signed-off-by: Ranjan Kumar Signed-off-by: Sreekanth Reddy Link: https://lore.kernel.org/r/20230228140835.4075-7-ranjan.kumar@broadcom.com Signed-off-by: Martin K. Petersen --- drivers/scsi/mpi3mr/mpi3mr_transport.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/mpi3mr/mpi3mr_transport.c b/drivers/scsi/mpi3mr/mpi3mr_transport.c index b795a325534d..be25f242fa79 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_transport.c +++ b/drivers/scsi/mpi3mr/mpi3mr_transport.c @@ -2358,15 +2358,16 @@ int mpi3mr_report_tgtdev_to_sas_transport(struct mpi3mr_ioc *mrioc, tgtdev->host_exposed = 1; if (!mpi3mr_sas_port_add(mrioc, tgtdev->dev_handle, sas_address_parent, hba_port)) { - tgtdev->host_exposed = 0; retval = -1; - } else if ((!tgtdev->starget)) { - if (!mrioc->is_driver_loading) + } else if ((!tgtdev->starget) && (!mrioc->is_driver_loading)) { mpi3mr_sas_port_remove(mrioc, sas_address, sas_address_parent, hba_port); - tgtdev->host_exposed = 0; retval = -1; } + if (retval) { + tgtdev->dev_spec.sas_sata_inf.hba_port = NULL; + tgtdev->host_exposed = 0; + } return retval; } @@ -2395,6 +2396,7 @@ void mpi3mr_remove_tgtdev_from_sas_transport(struct mpi3mr_ioc *mrioc, mpi3mr_sas_port_remove(mrioc, sas_address, sas_address_parent, hba_port); tgtdev->host_exposed = 0; + tgtdev->dev_spec.sas_sata_inf.hba_port = NULL; } /** @@ -2451,7 +2453,7 @@ static u8 mpi3mr_get_port_id_by_rphy(struct mpi3mr_ioc *mrioc, struct sas_rphy * tgtdev = __mpi3mr_get_tgtdev_by_addr_and_rphy(mrioc, rphy->identify.sas_address, rphy); - if (tgtdev) { + if (tgtdev && tgtdev->dev_spec.sas_sata_inf.hba_port) { port_id = tgtdev->dev_spec.sas_sata_inf.hba_port->port_id; mpi3mr_tgtdev_put(tgtdev); From bfa659177dcba48cf13f2bd88c1972f12a60bf1c Mon Sep 17 00:00:00 2001 From: Chandrakanth Patil Date: Thu, 2 Mar 2023 16:23:40 +0530 Subject: [PATCH 181/778] scsi: megaraid_sas: Update max supported LD IDs to 240 The firmware only supports Logical Disk IDs up to 240 and LD ID 255 (0xFF) is reserved for deleted LDs. However, in some cases, firmware was assigning LD ID 254 (0xFE) to deleted LDs and this was causing the driver to mark the wrong disk as deleted. This in turn caused the wrong disk device to be taken offline by the SCSI midlayer. To address this issue, limit the LD ID range from 255 to 240. This ensures the deleted LD ID is properly identified and removed by the driver without accidently deleting any valid LDs. Fixes: ae6874ba4b43 ("scsi: megaraid_sas: Early detection of VD deletion through RaidMap update") Reported-by: Martin K. Petersen Signed-off-by: Chandrakanth Patil Signed-off-by: Sumit Saxena Link: https://lore.kernel.org/r/20230302105342.34933-2-chandrakanth.patil@broadcom.com Signed-off-by: Martin K. Petersen --- drivers/scsi/megaraid/megaraid_sas.h | 2 ++ drivers/scsi/megaraid/megaraid_sas_fp.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index 4919ea54b827..2ef9d41fc6f4 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h @@ -1519,6 +1519,8 @@ struct megasas_ctrl_info { #define MEGASAS_MAX_LD_IDS (MEGASAS_MAX_LD_CHANNELS * \ MEGASAS_MAX_DEV_PER_CHANNEL) +#define MEGASAS_MAX_SUPPORTED_LD_IDS 240 + #define MEGASAS_MAX_SECTORS (2*1024) #define MEGASAS_MAX_SECTORS_IEEE (2*128) #define MEGASAS_DBG_LVL 1 diff --git a/drivers/scsi/megaraid/megaraid_sas_fp.c b/drivers/scsi/megaraid/megaraid_sas_fp.c index da1cad1ee123..4463a538102a 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fp.c +++ b/drivers/scsi/megaraid/megaraid_sas_fp.c @@ -358,7 +358,7 @@ u8 MR_ValidateMapInfo(struct megasas_instance *instance, u64 map_id) ld = MR_TargetIdToLdGet(i, drv_map); /* For non existing VDs, iterate to next VD*/ - if (ld >= (MAX_LOGICAL_DRIVES_EXT - 1)) + if (ld >= MEGASAS_MAX_SUPPORTED_LD_IDS) continue; raid = MR_LdRaidGet(ld, drv_map); From 9bcb1d5a3d10f4d15da2174f8eaec942602f681f Mon Sep 17 00:00:00 2001 From: Chandrakanth Patil Date: Thu, 2 Mar 2023 16:23:41 +0530 Subject: [PATCH 182/778] scsi: megaraid_sas: Add crash dump mode capability bit in MFI capabilities In kdump kernel mode, the driver works in reduced functionality mode with some features disabled such as reduced MSI-X count and RDPQ disabled, etc. However, the firmware is not aware of this mode in some cases, which results in undefined behavior. To address this, the driver informs the firmware about the kdump mode through MPI capabilities bit during driver initialization. This allows firmware to adjust its behavior accordingly. Signed-off-by: Chandrakanth Patil Signed-off-by: Sumit Saxena Link: https://lore.kernel.org/r/20230302105342.34933-3-chandrakanth.patil@broadcom.com Signed-off-by: Martin K. Petersen --- drivers/scsi/megaraid/megaraid_sas.h | 6 ++++-- drivers/scsi/megaraid/megaraid_sas_fusion.c | 3 +++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index 2ef9d41fc6f4..c2bace65105b 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h @@ -1760,7 +1760,8 @@ union megasas_sgl_frame { typedef union _MFI_CAPABILITIES { struct { #if defined(__BIG_ENDIAN_BITFIELD) - u32 reserved:16; + u32 reserved:15; + u32 support_memdump:1; u32 support_fw_exposed_dev_list:1; u32 support_nvme_passthru:1; u32 support_64bit_mode:1; @@ -1794,7 +1795,8 @@ typedef union _MFI_CAPABILITIES { u32 support_64bit_mode:1; u32 support_nvme_passthru:1; u32 support_fw_exposed_dev_list:1; - u32 reserved:16; + u32 support_memdump:1; + u32 reserved:15; #endif } mfi_capabilities; __le32 reg; diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c index 6597e118c805..84c9a55a5794 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c @@ -1201,6 +1201,9 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) drv_ops->mfi_capabilities.support_nvme_passthru = 1; drv_ops->mfi_capabilities.support_fw_exposed_dev_list = 1; + if (reset_devices) + drv_ops->mfi_capabilities.support_memdump = 1; + if (instance->consistent_mask_64bit) drv_ops->mfi_capabilities.support_64bit_mode = 1; From a2033f9f9d785972513bca207ed4a48bffc75f8f Mon Sep 17 00:00:00 2001 From: Chandrakanth Patil Date: Thu, 2 Mar 2023 16:23:42 +0530 Subject: [PATCH 183/778] scsi: megaraid_sas: Driver version update to 07.725.01.00-rc1 Update driver version. Signed-off-by: Chandrakanth Patil Link: https://lore.kernel.org/r/20230302105342.34933-4-chandrakanth.patil@broadcom.com Signed-off-by: Martin K. Petersen --- drivers/scsi/megaraid/megaraid_sas.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index c2bace65105b..63bac3684c19 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h @@ -23,8 +23,8 @@ /* * MegaRAID SAS Driver meta data */ -#define MEGASAS_VERSION "07.719.03.00-rc1" -#define MEGASAS_RELDATE "Sep 29, 2021" +#define MEGASAS_VERSION "07.725.01.00-rc1" +#define MEGASAS_RELDATE "Mar 2, 2023" #define MEGASAS_MSIX_NAME_LEN 32 From 11d9874c4204a785f43d899a1ab12f9dc8d9de3e Mon Sep 17 00:00:00 2001 From: Michael Kelley Date: Mon, 27 Feb 2023 08:48:34 -0800 Subject: [PATCH 184/778] scsi: storvsc: Handle BlockSize change in Hyper-V VHD/VHDX file Hyper-V uses a VHD or VHDX file on the host as the underlying storage for a virtual disk. The VHD/VHDX file format is a sparse format where real disk space on the host is assigned in chunks that the VHD/VHDX file format calls the BlockSize. This BlockSize is not to be confused with the 512-byte (or 4096-byte) sector size of the underlying storage device. The default block size for a new VHD/VHDX file is 32 Mbytes. When a guest VM touches any disk space within a 32 Mbyte chunk of the VHD/VHDX file, Hyper-V allocates 32 Mbytes of real disk space for that section of the VHD/VHDX. Similarly, if a discard operation is done that covers an entire 32 Mbyte chunk, Hyper-V will free the real disk space for that portion of the VHD/VHDX. This BlockSize is surfaced in Linux as the "discard_granularity" in /sys/block/sd/queue, which makes sense. Hyper-V also has differencing disks that can overlay a VHD/VHDX file to capture changes to the VHD/VHDX while preserving the original VHD/VHDX. One example of this differencing functionality is for VM snapshots. When a snapshot is created, a differencing disk is created. If the snapshot is rolled back, Hyper-V can just delete the differencing disk, and the VM will see the original disk contents at the time the snapshot was taken. Differencing disks are used in other scenarios as well. The BlockSize for a differencing disk defaults to 2 Mbytes, not 32 Mbytes. The smaller default is used because changes to differencing disks are typically scattered all over, and Hyper-V doesn't want to allocate 32 Mbytes of real disk space for a stray write here or there. The smaller BlockSize provides more efficient use of real disk space. When a differencing disk is added to a VHD/VHDX, Hyper-V reports UNIT_ATTENTION with a sense code indicating "Operating parameters have changed", because the value of discard_granularity should be changed to 2 Mbytes. When the differencing disk is removed, discard_granularity should be changed back to 32 Mbytes. However, current code simply reports a message from scsi_report_sense() and the value of /sys/block/sd/queue/discard_granularity is not updated. The message isn't very actionable by a sysadmin. Fix this by having the storvsc driver check for the sense code indicating that the underly VHD/VHDX block size has changed, and do a rescan of the device to pick up the new discard_granularity. With this change the entire transition to/from differencing disks is handled automatically and transparently, with no confusing messages being output. Link: https://lore.kernel.org/r/1677516514-86060-1-git-send-email-mikelley@microsoft.com Signed-off-by: Michael Kelley Signed-off-by: Martin K. Petersen --- drivers/scsi/storvsc_drv.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 33f568b7f54d..d9ce379c4d2e 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -987,6 +987,22 @@ static void storvsc_handle_error(struct vmscsi_request *vm_srb, goto do_work; } + /* + * Check for "Operating parameters have changed" + * due to Hyper-V changing the VHD/VHDX BlockSize + * when adding/removing a differencing disk. This + * causes discard_granularity to change, so do a + * rescan to pick up the new granularity. We don't + * want scsi_report_sense() to output a message + * that a sysadmin wouldn't know what to do with. + */ + if ((asc == 0x3f) && (ascq != 0x03) && + (ascq != 0x0e)) { + process_err_fn = storvsc_device_scan; + set_host_byte(scmnd, DID_REQUEUE); + goto do_work; + } + /* * Otherwise, let upper layer deal with the * error when sense message is present From 288b3271d920c9ba949c3bab0f749f4cecc70e09 Mon Sep 17 00:00:00 2001 From: Shin'ichiro Kawasaki Date: Mon, 6 Mar 2023 15:30:24 +0900 Subject: [PATCH 185/778] scsi: sd: Fix wrong zone_write_granularity value during revalidate When the sd driver revalidates host-managed SMR disks, it calls disk_set_zoned() which changes the zone_write_granularity attribute value to the logical block size regardless of the device type. After that, the sd driver overwrites the value in sd_zbc_read_zone() with the physical block size, since ZBC/ZAC requires this for host-managed disks. Between the calls to disk_set_zoned() and sd_zbc_read_zone(), there exists a window where the attribute shows the logical block size as the zone_write_granularity value, which is wrong for host-managed disks. The duration of the window is from 20ms to 200ms, depending on report zone command execution time. To avoid the wrong zone_write_granularity value between disk_set_zoned() and sd_zbc_read_zone(), modify the value not in sd_zbc_read_zone() but just after disk_set_zoned() call. Fixes: a805a4fa4fa3 ("block: introduce zone_write_granularity limit") Signed-off-by: Shin'ichiro Kawasaki Link: https://lore.kernel.org/r/20230306063024.3376959-1-shinichiro.kawasaki@wdc.com Reviewed-by: Damien Le Moal Reviewed-by: Johannes Thumshirn Reviewed-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/scsi/sd.c | 7 ++++++- drivers/scsi/sd_zbc.c | 8 -------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 4f28dd617eca..4bb87043e6db 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -2988,8 +2988,13 @@ static void sd_read_block_characteristics(struct scsi_disk *sdkp) } if (sdkp->device->type == TYPE_ZBC) { - /* Host-managed */ + /* + * Host-managed: Per ZBC and ZAC specifications, writes in + * sequential write required zones of host-managed devices must + * be aligned to the device physical block size. + */ disk_set_zoned(sdkp->disk, BLK_ZONED_HM); + blk_queue_zone_write_granularity(q, sdkp->physical_block_size); } else { sdkp->zoned = zoned; if (sdkp->zoned == 1) { diff --git a/drivers/scsi/sd_zbc.c b/drivers/scsi/sd_zbc.c index 6b3a02d4406c..22801c24ea19 100644 --- a/drivers/scsi/sd_zbc.c +++ b/drivers/scsi/sd_zbc.c @@ -965,14 +965,6 @@ int sd_zbc_read_zones(struct scsi_disk *sdkp, u8 buf[SD_BUF_SIZE]) disk_set_max_active_zones(disk, 0); nr_zones = round_up(sdkp->capacity, zone_blocks) >> ilog2(zone_blocks); - /* - * Per ZBC and ZAC specifications, writes in sequential write required - * zones of host-managed devices must be aligned to the device physical - * block size. - */ - if (blk_queue_zoned_model(q) == BLK_ZONED_HM) - blk_queue_zone_write_granularity(q, sdkp->physical_block_size); - sdkp->early_zone_info.nr_zones = nr_zones; sdkp->early_zone_info.zone_blocks = zone_blocks; From e18048da9bc3f87acef4eb67a11b4fc55fe15424 Mon Sep 17 00:00:00 2001 From: Palmer Dabbelt Date: Thu, 23 Feb 2023 14:46:05 -0800 Subject: [PATCH 186/778] RISC-V: Stop emitting attributes The RISC-V ELF attributes don't contain any useful information. New toolchains ignore them, but they frequently trip up various older/mixed toolchains. So just turn them off. Tested-by: Conor Dooley Link: https://lore.kernel.org/r/20230223224605.6995-1-palmer@rivosinc.com Cc: stable@vger.kernel.org Signed-off-by: Palmer Dabbelt --- arch/riscv/Makefile | 7 +++++++ arch/riscv/kernel/compat_vdso/Makefile | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile index 6203c3378922..4de83b9b1772 100644 --- a/arch/riscv/Makefile +++ b/arch/riscv/Makefile @@ -84,6 +84,13 @@ endif # Avoid generating .eh_frame sections. KBUILD_CFLAGS += -fno-asynchronous-unwind-tables -fno-unwind-tables +# The RISC-V attributes frequently cause compatibility issues and provide no +# information, so just turn them off. +KBUILD_CFLAGS += $(call cc-option,-mno-riscv-attribute) +KBUILD_AFLAGS += $(call cc-option,-mno-riscv-attribute) +KBUILD_CFLAGS += $(call as-option,-Wa$(comma)-mno-arch-attr) +KBUILD_AFLAGS += $(call as-option,-Wa$(comma)-mno-arch-attr) + KBUILD_CFLAGS_MODULE += $(call cc-option,-mno-relax) KBUILD_AFLAGS_MODULE += $(call as-option,-Wa$(comma)-mno-relax) diff --git a/arch/riscv/kernel/compat_vdso/Makefile b/arch/riscv/kernel/compat_vdso/Makefile index 260daf3236d3..7f34f3c7c882 100644 --- a/arch/riscv/kernel/compat_vdso/Makefile +++ b/arch/riscv/kernel/compat_vdso/Makefile @@ -14,6 +14,10 @@ COMPAT_LD := $(LD) COMPAT_CC_FLAGS := -march=rv32g -mabi=ilp32 COMPAT_LD_FLAGS := -melf32lriscv +# Disable attributes, as they're useless and break the build. +COMPAT_CC_FLAGS += $(call cc-option,-mno-riscv-attribute) +COMPAT_CC_FLAGS += $(call as-option,-Wa$(comma)-mno-arch-attr) + # Files to link into the compat_vdso obj-compat_vdso = $(patsubst %, %.o, $(compat_vdso-syms)) note.o From c64c67c0748be5afb769a4eedbeb3ce6de36958f Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 6 Mar 2023 19:58:56 -0500 Subject: [PATCH 187/778] alpha: fix lazy-FPU mis(merged/applied/whatnot) Looks like a braino that used to be fixed in e.g. #next.alpha had gotten into alpha.git cherry-picked version of that patch. Sure, alpha has no preempt, but preempt_enable() in place of preempt_disable() is actively confusing the readers... Other than that, the cherry-picked variant matches what I have. Signed-off-by: Al Viro --- arch/alpha/lib/fpreg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/alpha/lib/fpreg.c b/arch/alpha/lib/fpreg.c index 612c5eca71bc..7c08b225261c 100644 --- a/arch/alpha/lib/fpreg.c +++ b/arch/alpha/lib/fpreg.c @@ -23,7 +23,7 @@ alpha_read_fp_reg (unsigned long reg) if (unlikely(reg >= 32)) return 0; - preempt_enable(); + preempt_disable(); if (current_thread_info()->status & TS_SAVED_FP) val = current_thread_info()->fp[reg]; else switch (reg) { @@ -133,7 +133,7 @@ alpha_read_fp_reg_s (unsigned long reg) if (unlikely(reg >= 32)) return 0; - preempt_enable(); + preempt_disable(); if (current_thread_info()->status & TS_SAVED_FP) { LDT(0, current_thread_info()->fp[reg]); STS(0, val); From 849ad04cf562ac63b0371a825eed473d84de9c6d Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 7 Mar 2023 01:50:53 -0500 Subject: [PATCH 188/778] new helper: put_and_unmap_page() kunmap_local() + put_page(), as done by e.g. ext2 directory handling. Signed-off-by: Al Viro --- include/linux/highmem.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/linux/highmem.h b/include/linux/highmem.h index b06254e76d99..8fc10089e19e 100644 --- a/include/linux/highmem.h +++ b/include/linux/highmem.h @@ -481,4 +481,10 @@ static inline void folio_zero_range(struct folio *folio, zero_user_segments(&folio->page, start, start + length, 0, 0); } +static inline void put_and_unmap_page(struct page *page, void *addr) +{ + kunmap_local(addr); + put_page(page); +} + #endif /* _LINUX_HIGHMEM_H */ From c77737b736ceb50fdf150434347dbd81ec76dbb1 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 7 Mar 2023 05:22:54 +0000 Subject: [PATCH 189/778] netfilter: conntrack: adopt safer max chain length Customers using GKE 1.25 and 1.26 are facing conntrack issues root caused to commit c9c3b6811f74 ("netfilter: conntrack: make max chain length random"). Even if we assume Uniform Hashing, a bucket often reachs 8 chained items while the load factor of the hash table is smaller than 0.5 With a limit of 16, we reach load factors of 3. With a limit of 32, we reach load factors of 11. With a limit of 40, we reach load factors of 15. With a limit of 50, we reach load factors of 24. This patch changes MIN_CHAINLEN to 50, to minimize risks. Ideally, we could in the future add a cushion based on expected load factor (2 * nf_conntrack_max / nf_conntrack_buckets), because some setups might expect unusual values. Fixes: c9c3b6811f74 ("netfilter: conntrack: make max chain length random") Signed-off-by: Eric Dumazet Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_conntrack_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 7250082e7de5..c6a6a6099b4e 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -96,8 +96,8 @@ static DEFINE_MUTEX(nf_conntrack_mutex); #define GC_SCAN_MAX_DURATION msecs_to_jiffies(10) #define GC_SCAN_EXPIRED_MAX (64000u / HZ) -#define MIN_CHAINLEN 8u -#define MAX_CHAINLEN (32u - MIN_CHAINLEN) +#define MIN_CHAINLEN 50u +#define MAX_CHAINLEN (80u - MIN_CHAINLEN) static struct conntrack_gc_work conntrack_gc_work; From 24efcdf03d85bb73df0ba99f69c8d238e7ada0e5 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 14 Feb 2023 16:25:07 +0100 Subject: [PATCH 190/778] platform/x86/amd: pmc: remove CONFIG_SUSPEND checks The amd_pmc_write_stb() function was previously hidden in an ifdef to avoid a warning when CONFIG_SUSPEND is disabled, but now there is an additional caller: drivers/platform/x86/amd/pmc.c: In function 'amd_pmc_stb_debugfs_open_v2': drivers/platform/x86/amd/pmc.c:256:8: error: implicit declaration of function 'amd_pmc_write_stb'; did you mean 'amd_pmc_read_stb'? [-Werror=implicit-function-declaration] 256 | ret = amd_pmc_write_stb(dev, AMD_PMC_STB_DUMMY_PC); | ^~~~~~~~~~~~~~~~~ | amd_pmc_read_stb There is now an easier way to handle this using DEFINE_SIMPLE_DEV_PM_OPS() to replace all the #ifdefs, letting gcc drop any of the unused functions silently. Fixes: b0d4bb973539 ("platform/x86/amd: pmc: Write dummy postcode into the STB DRAM") Signed-off-by: Arnd Bergmann Link: https://lore.kernel.org/r/20230214152512.806188-1-arnd@kernel.org Signed-off-by: Hans de Goede Reviewed-by: Hans de Goede --- drivers/platform/x86/amd/pmc.c | 30 +++++++++--------------------- 1 file changed, 9 insertions(+), 21 deletions(-) diff --git a/drivers/platform/x86/amd/pmc.c b/drivers/platform/x86/amd/pmc.c index ab05b9ee6655..2edaae04a691 100644 --- a/drivers/platform/x86/amd/pmc.c +++ b/drivers/platform/x86/amd/pmc.c @@ -171,9 +171,7 @@ MODULE_PARM_DESC(disable_workarounds, "Disable workarounds for platform bugs"); static struct amd_pmc_dev pmc; static int amd_pmc_send_cmd(struct amd_pmc_dev *dev, u32 arg, u32 *data, u8 msg, bool ret); static int amd_pmc_read_stb(struct amd_pmc_dev *dev, u32 *buf); -#ifdef CONFIG_SUSPEND static int amd_pmc_write_stb(struct amd_pmc_dev *dev, u32 data); -#endif static inline u32 amd_pmc_reg_read(struct amd_pmc_dev *dev, int reg_offset) { @@ -386,7 +384,6 @@ static int get_metrics_table(struct amd_pmc_dev *pdev, struct smu_metrics *table return 0; } -#ifdef CONFIG_SUSPEND static void amd_pmc_validate_deepest(struct amd_pmc_dev *pdev) { struct smu_metrics table; @@ -400,7 +397,6 @@ static void amd_pmc_validate_deepest(struct amd_pmc_dev *pdev) dev_dbg(pdev->dev, "Last suspend in deepest state for %lluus\n", table.timein_s0i3_lastcapture); } -#endif static int amd_pmc_get_smu_version(struct amd_pmc_dev *dev) { @@ -673,7 +669,6 @@ out_unlock: return rc; } -#ifdef CONFIG_SUSPEND static int amd_pmc_get_os_hint(struct amd_pmc_dev *dev) { switch (dev->cpu_id) { @@ -861,9 +856,7 @@ static int __maybe_unused amd_pmc_suspend_handler(struct device *dev) return 0; } -static SIMPLE_DEV_PM_OPS(amd_pmc_pm, amd_pmc_suspend_handler, NULL); - -#endif +static DEFINE_SIMPLE_DEV_PM_OPS(amd_pmc_pm, amd_pmc_suspend_handler, NULL); static const struct pci_device_id pmc_pci_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_PS) }, @@ -905,7 +898,6 @@ static int amd_pmc_s2d_init(struct amd_pmc_dev *dev) return 0; } -#ifdef CONFIG_SUSPEND static int amd_pmc_write_stb(struct amd_pmc_dev *dev, u32 data) { int err; @@ -926,7 +918,6 @@ static int amd_pmc_write_stb(struct amd_pmc_dev *dev, u32 data) return 0; } -#endif static int amd_pmc_read_stb(struct amd_pmc_dev *dev, u32 *buf) { @@ -1017,11 +1008,11 @@ static int amd_pmc_probe(struct platform_device *pdev) } platform_set_drvdata(pdev, dev); -#ifdef CONFIG_SUSPEND - err = acpi_register_lps0_dev(&amd_pmc_s2idle_dev_ops); - if (err) - dev_warn(dev->dev, "failed to register LPS0 sleep handler, expect increased power consumption\n"); -#endif + if (IS_ENABLED(CONFIG_SUSPEND)) { + err = acpi_register_lps0_dev(&amd_pmc_s2idle_dev_ops); + if (err) + dev_warn(dev->dev, "failed to register LPS0 sleep handler, expect increased power consumption\n"); + } amd_pmc_dbgfs_register(dev); return 0; @@ -1035,9 +1026,8 @@ static int amd_pmc_remove(struct platform_device *pdev) { struct amd_pmc_dev *dev = platform_get_drvdata(pdev); -#ifdef CONFIG_SUSPEND - acpi_unregister_lps0_dev(&amd_pmc_s2idle_dev_ops); -#endif + if (IS_ENABLED(CONFIG_SUSPEND)) + acpi_unregister_lps0_dev(&amd_pmc_s2idle_dev_ops); amd_pmc_dbgfs_unregister(dev); pci_dev_put(dev->rdev); mutex_destroy(&dev->lock); @@ -1061,9 +1051,7 @@ static struct platform_driver amd_pmc_driver = { .name = "amd_pmc", .acpi_match_table = amd_pmc_acpi_ids, .dev_groups = pmc_groups, -#ifdef CONFIG_SUSPEND - .pm = &amd_pmc_pm, -#endif + .pm = pm_sleep_ptr(&amd_pmc_pm), }, .probe = amd_pmc_probe, .remove = amd_pmc_remove, From 001f61c4688f1dad18cfaa35ae364b35fb3cd66c Mon Sep 17 00:00:00 2001 From: Armin Wolf Date: Sat, 18 Feb 2023 12:53:17 +0100 Subject: [PATCH 191/778] platform/x86: dell-ddv: Fix cache invalidation on resume If one or both sensor buffers could not be initialized, either due to missing hardware support or due to some error during probing, the resume handler will encounter undefined behaviour when attempting to lock buffers then protected by an uninitialized or destroyed mutex. Fix this by introducing a "active" flag which is set during probe, and only invalidate buffers which where flaged as "active". Tested on a Dell Inspiron 3505. Fixes: 3b7eeff93d29 ("platform/x86: dell-ddv: Add hwmon support") Signed-off-by: Armin Wolf Link: https://lore.kernel.org/r/20230218115318.20662-1-W_Armin@gmx.de Signed-off-by: Hans de Goede Reviewed-by: Hans de Goede --- drivers/platform/x86/dell/dell-wmi-ddv.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/platform/x86/dell/dell-wmi-ddv.c b/drivers/platform/x86/dell/dell-wmi-ddv.c index d547c9d09725..eff4e9649faf 100644 --- a/drivers/platform/x86/dell/dell-wmi-ddv.c +++ b/drivers/platform/x86/dell/dell-wmi-ddv.c @@ -96,6 +96,7 @@ struct combined_chip_info { }; struct dell_wmi_ddv_sensors { + bool active; struct mutex lock; /* protect caching */ unsigned long timestamp; union acpi_object *obj; @@ -520,6 +521,9 @@ static struct hwmon_channel_info *dell_wmi_ddv_channel_create(struct device *dev static void dell_wmi_ddv_hwmon_cache_invalidate(struct dell_wmi_ddv_sensors *sensors) { + if (!sensors->active) + return; + mutex_lock(&sensors->lock); kfree(sensors->obj); sensors->obj = NULL; @@ -530,6 +534,7 @@ static void dell_wmi_ddv_hwmon_cache_destroy(void *data) { struct dell_wmi_ddv_sensors *sensors = data; + sensors->active = false; mutex_destroy(&sensors->lock); kfree(sensors->obj); } @@ -549,6 +554,7 @@ static struct hwmon_channel_info *dell_wmi_ddv_channel_init(struct wmi_device *w return ERR_PTR(ret); mutex_init(&sensors->lock); + sensors->active = true; ret = devm_add_action_or_reset(&wdev->dev, dell_wmi_ddv_hwmon_cache_destroy, sensors); if (ret < 0) @@ -852,7 +858,7 @@ static int dell_wmi_ddv_resume(struct device *dev) { struct dell_wmi_ddv_data *data = dev_get_drvdata(dev); - /* Force re-reading of all sensors */ + /* Force re-reading of all active sensors */ dell_wmi_ddv_hwmon_cache_invalidate(&data->fans); dell_wmi_ddv_hwmon_cache_invalidate(&data->temps); From 0331b1b0ba65376ecf1c69414aa7696fef0930cb Mon Sep 17 00:00:00 2001 From: Armin Wolf Date: Sat, 18 Feb 2023 12:53:18 +0100 Subject: [PATCH 192/778] platform/x86: dell-ddv: Fix temperature scaling After using the built-in UEFI hardware diagnostics to compare the measured battery temperature, i noticed that the temperature is actually expressed in tenth degree kelvin, similar to the SBS-Data standard. For example, a value of 2992 is displayed as 26 degrees celsius. Fix the scaling so that the correct values are being displayed. Tested on a Dell Inspiron 3505. Fixes: a77272c16041 ("platform/x86: dell: Add new dell-wmi-ddv driver") Signed-off-by: Armin Wolf Link: https://lore.kernel.org/r/20230218115318.20662-2-W_Armin@gmx.de Signed-off-by: Hans de Goede Reviewed-by: Hans de Goede --- drivers/platform/x86/dell/dell-wmi-ddv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/platform/x86/dell/dell-wmi-ddv.c b/drivers/platform/x86/dell/dell-wmi-ddv.c index eff4e9649faf..2750dee99c3e 100644 --- a/drivers/platform/x86/dell/dell-wmi-ddv.c +++ b/drivers/platform/x86/dell/dell-wmi-ddv.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include @@ -665,7 +664,8 @@ static ssize_t temp_show(struct device *dev, struct device_attribute *attr, char if (ret < 0) return ret; - return sysfs_emit(buf, "%d\n", DIV_ROUND_CLOSEST(value, 10)); + /* Use 2731 instead of 2731.5 to avoid unnecessary rounding */ + return sysfs_emit(buf, "%d\n", value - 2731); } static ssize_t eppid_show(struct device *dev, struct device_attribute *attr, char *buf) From 95ecf90158522269749f1b7ce98b1eed66ca087b Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Sun, 26 Feb 2023 21:35:04 -0800 Subject: [PATCH 193/778] platform/x86: ISST: Increase range of valid mail box commands A new command CONFIG_TDP_GET_RATIO_INFO is added, with sub command type of 0x0C. The previous range of valid sub commands was from 0x00 to 0x0B. Change the valid range from 0x00 to 0x0C. Signed-off-by: Srinivas Pandruvada Link: https://lore.kernel.org/r/20230227053504.2734214-1-srinivas.pandruvada@linux.intel.com Signed-off-by: Hans de Goede Reviewed-by: Hans de Goede --- drivers/platform/x86/intel/speed_select_if/isst_if_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/x86/intel/speed_select_if/isst_if_common.c b/drivers/platform/x86/intel/speed_select_if/isst_if_common.c index a7e02b24a87a..0829e793a8fc 100644 --- a/drivers/platform/x86/intel/speed_select_if/isst_if_common.c +++ b/drivers/platform/x86/intel/speed_select_if/isst_if_common.c @@ -47,7 +47,7 @@ struct isst_cmd_set_req_type { static const struct isst_valid_cmd_ranges isst_valid_cmds[] = { {0xD0, 0x00, 0x03}, - {0x7F, 0x00, 0x0B}, + {0x7F, 0x00, 0x0C}, {0x7F, 0x10, 0x12}, {0x7F, 0x20, 0x23}, {0x94, 0x03, 0x03}, From 6a192c0cbf38a6ba10847590d680975086844dbb Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Mon, 27 Feb 2023 06:06:14 -0800 Subject: [PATCH 194/778] platform/x86/intel/tpmi: Fix double free reported by Smatch Fix warning: drivers/platform/x86/intel/tpmi.c:253 tpmi_create_device() warn: 'feature_vsec_dev' was already freed. If there is some error, feature_vsec_dev memory is freed as part of resource managed call intel_vsec_add_aux(). So, additional kfree() call is not required. Reordered res allocation and feature_vsec_dev, so that on error only res is freed. Reported-by: Dan Carpenter Link: https://lore.kernel.org/platform-driver-x86/Y%2FxYR7WGiPayZu%2FR@kili/T/#u Fixes: 47731fd2865f ("platform/x86/intel: Intel TPMI enumeration driver") Signed-off-by: Srinivas Pandruvada Link: https://lore.kernel.org/r/20230227140614.2913474-1-srinivas.pandruvada@linux.intel.com Signed-off-by: Hans de Goede Reviewed-by: Hans de Goede --- drivers/platform/x86/intel/tpmi.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/platform/x86/intel/tpmi.c b/drivers/platform/x86/intel/tpmi.c index c60733261c89..c999732b0f1e 100644 --- a/drivers/platform/x86/intel/tpmi.c +++ b/drivers/platform/x86/intel/tpmi.c @@ -209,14 +209,14 @@ static int tpmi_create_device(struct intel_tpmi_info *tpmi_info, if (!name) return -EOPNOTSUPP; - feature_vsec_dev = kzalloc(sizeof(*feature_vsec_dev), GFP_KERNEL); - if (!feature_vsec_dev) + res = kcalloc(pfs->pfs_header.num_entries, sizeof(*res), GFP_KERNEL); + if (!res) return -ENOMEM; - res = kcalloc(pfs->pfs_header.num_entries, sizeof(*res), GFP_KERNEL); - if (!res) { + feature_vsec_dev = kzalloc(sizeof(*feature_vsec_dev), GFP_KERNEL); + if (!feature_vsec_dev) { ret = -ENOMEM; - goto free_vsec; + goto free_res; } snprintf(feature_id_name, sizeof(feature_id_name), "tpmi-%s", name); @@ -239,6 +239,8 @@ static int tpmi_create_device(struct intel_tpmi_info *tpmi_info, /* * intel_vsec_add_aux() is resource managed, no explicit * delete is required on error or on module unload. + * feature_vsec_dev memory is also freed as part of device + * delete. */ ret = intel_vsec_add_aux(vsec_dev->pcidev, &vsec_dev->auxdev.dev, feature_vsec_dev, feature_id_name); @@ -249,8 +251,6 @@ static int tpmi_create_device(struct intel_tpmi_info *tpmi_info, free_res: kfree(res); -free_vsec: - kfree(feature_vsec_dev); return ret; } From 03f5eb300ad1241f854269a3e521b119189a4493 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sat, 25 Feb 2023 21:39:50 -0800 Subject: [PATCH 195/778] platform: mellanox: select REGMAP instead of depending on it REGMAP is a hidden (not user visible) symbol. Users cannot set it directly thru "make *config", so drivers should select it instead of depending on it if they need it. Consistently using "select" or "depends on" can also help reduce Kconfig circular dependency issues. Therefore, change the use of "depends on REGMAP" to "select REGMAP". For NVSW_SN2201, select REGMAP_I2C instead of depending on it. Fixes: c6acad68eb2d ("platform/mellanox: mlxreg-hotplug: Modify to use a regmap interface") Fixes: 5ec4a8ace06c ("platform/mellanox: Introduce support for Mellanox register access driver") Fixes: 62f9529b8d5c ("platform/mellanox: mlxreg-lc: Add initial support for Nvidia line card devices") Fixes: 662f24826f95 ("platform/mellanox: Add support for new SN2201 system") Signed-off-by: Randy Dunlap Cc: Darren Hart Cc: Hans de Goede Cc: Michael Shych Cc: Mark Gross Cc: Vadim Pasternak Cc: platform-driver-x86@vger.kernel.org Link: https://lore.kernel.org/r/20230226053953.4681-6-rdunlap@infradead.org Signed-off-by: Hans de Goede Reviewed-by: Hans de Goede --- drivers/platform/mellanox/Kconfig | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/platform/mellanox/Kconfig b/drivers/platform/mellanox/Kconfig index 09c7829e95c4..382793e73a60 100644 --- a/drivers/platform/mellanox/Kconfig +++ b/drivers/platform/mellanox/Kconfig @@ -16,17 +16,17 @@ if MELLANOX_PLATFORM config MLXREG_HOTPLUG tristate "Mellanox platform hotplug driver support" - depends on REGMAP depends on HWMON depends on I2C + select REGMAP help This driver handles hot-plug events for the power suppliers, power cables and fans on the wide range Mellanox IB and Ethernet systems. config MLXREG_IO tristate "Mellanox platform register access driver support" - depends on REGMAP depends on HWMON + select REGMAP help This driver allows access to Mellanox programmable device register space through sysfs interface. The sets of registers for sysfs access @@ -36,9 +36,9 @@ config MLXREG_IO config MLXREG_LC tristate "Mellanox line card platform driver support" - depends on REGMAP depends on HWMON depends on I2C + select REGMAP help This driver provides support for the Mellanox MSN4800-XX line cards, which are the part of MSN4800 Ethernet modular switch systems @@ -80,10 +80,9 @@ config MLXBF_PMC config NVSW_SN2201 tristate "Nvidia SN2201 platform driver support" - depends on REGMAP depends on HWMON depends on I2C - depends on REGMAP_I2C + select REGMAP_I2C help This driver provides support for the Nvidia SN2201 platform. The SN2201 is a highly integrated for one rack unit system with From 7e7e1541c91615e9950d0b96bcd1806d297e970e Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sat, 25 Feb 2023 21:39:51 -0800 Subject: [PATCH 196/778] platform: x86: MLX_PLATFORM: select REGMAP instead of depending on it REGMAP is a hidden (not user visible) symbol. Users cannot set it directly thru "make *config", so drivers should select it instead of depending on it if they need it. Consistently using "select" or "depends on" can also help reduce Kconfig circular dependency issues. Therefore, change the use of "depends on REGMAP" to "select REGMAP". Fixes: ef0f62264b2a ("platform/x86: mlx-platform: Add physical bus number auto detection") Signed-off-by: Randy Dunlap Cc: Vadim Pasternak Cc: Darren Hart Cc: Hans de Goede Cc: Mark Gross Cc: platform-driver-x86@vger.kernel.org Link: https://lore.kernel.org/r/20230226053953.4681-7-rdunlap@infradead.org Signed-off-by: Hans de Goede Reviewed-by: Hans de Goede --- drivers/platform/x86/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index ec7c2b4e1721..4a01b315e0a9 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -955,7 +955,8 @@ config SERIAL_MULTI_INSTANTIATE config MLX_PLATFORM tristate "Mellanox Technologies platform support" - depends on I2C && REGMAP + depends on I2C + select REGMAP help This option enables system support for the Mellanox Technologies platform. The Mellanox systems provide data center networking From 94e9cbda06a317f886f63fab511dedf441c81c54 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Fri, 10 Feb 2023 22:32:46 -0800 Subject: [PATCH 197/778] platform/x86: ISST: Fix kernel documentation warnings Fix warning displayed for "make W=1" for kernel documentation. Signed-off-by: Srinivas Pandruvada Link: https://lore.kernel.org/r/20230211063257.311746-2-srinivas.pandruvada@linux.intel.com Signed-off-by: Hans de Goede Reviewed-by: Hans de Goede --- drivers/platform/x86/intel/speed_select_if/isst_if_common.c | 3 ++- drivers/platform/x86/intel/speed_select_if/isst_if_common.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/platform/x86/intel/speed_select_if/isst_if_common.c b/drivers/platform/x86/intel/speed_select_if/isst_if_common.c index 0829e793a8fc..0954a04623ed 100644 --- a/drivers/platform/x86/intel/speed_select_if/isst_if_common.c +++ b/drivers/platform/x86/intel/speed_select_if/isst_if_common.c @@ -112,6 +112,7 @@ static void isst_delete_hash(void) * isst_store_cmd() - Store command to a hash table * @cmd: Mailbox command. * @sub_cmd: Mailbox sub-command or MSR id. + * @cpu: Target CPU for the command * @mbox_cmd_type: Mailbox or MSR command. * @param: Mailbox parameter. * @data: Mailbox request data or MSR data. @@ -363,7 +364,7 @@ static struct pci_dev *_isst_if_get_pci_dev(int cpu, int bus_no, int dev, int fn /** * isst_if_get_pci_dev() - Get the PCI device instance for a CPU * @cpu: Logical CPU number. - * @bus_number: The bus number assigned by the hardware. + * @bus_no: The bus number assigned by the hardware. * @dev: The device number assigned by the hardware. * @fn: The function number assigned by the hardware. * diff --git a/drivers/platform/x86/intel/speed_select_if/isst_if_common.h b/drivers/platform/x86/intel/speed_select_if/isst_if_common.h index fdecdae248d7..35ff506b402e 100644 --- a/drivers/platform/x86/intel/speed_select_if/isst_if_common.h +++ b/drivers/platform/x86/intel/speed_select_if/isst_if_common.h @@ -40,6 +40,7 @@ * @offset: Offset to the first valid member in command structure. * This will be the offset of the start of the command * after command count field + * @owner: Registered module owner * @cmd_callback: Callback function to handle IOCTL. The callback has the * command pointer with data for command. There is a pointer * called write_only, which when set, will not copy the From e8059d393158e927e36898aca89986a52025b9f3 Mon Sep 17 00:00:00 2001 From: Daniel Scally Date: Thu, 2 Mar 2023 10:26:11 +0000 Subject: [PATCH 198/778] platform/x86: int3472: Add GPIOs to Surface Go 3 Board data Add the INT347E GPIO lookup table to the board data for the Surface Go 3. This is necessary to allow the ov7251 IR camera to probe properly on that platform. Signed-off-by: Daniel Scally Link: https://lore.kernel.org/r/20230302102611.314341-1-dan.scally@ideasonboard.com Reviewed-by: Hans de Goede Signed-off-by: Hans de Goede --- drivers/platform/x86/intel/int3472/tps68470_board_data.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/platform/x86/intel/int3472/tps68470_board_data.c b/drivers/platform/x86/intel/int3472/tps68470_board_data.c index 309eab9c0558..322237e056f3 100644 --- a/drivers/platform/x86/intel/int3472/tps68470_board_data.c +++ b/drivers/platform/x86/intel/int3472/tps68470_board_data.c @@ -159,9 +159,10 @@ static const struct int3472_tps68470_board_data surface_go_tps68470_board_data = static const struct int3472_tps68470_board_data surface_go3_tps68470_board_data = { .dev_name = "i2c-INT3472:01", .tps68470_regulator_pdata = &surface_go_tps68470_pdata, - .n_gpiod_lookups = 1, + .n_gpiod_lookups = 2, .tps68470_gpio_lookup_tables = { - &surface_go_int347a_gpios + &surface_go_int347a_gpios, + &surface_go_int347e_gpios, }, }; From 1a0009abfa7893b9cfcd3884658af1cbee6b26ce Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 7 Mar 2023 11:58:42 +0100 Subject: [PATCH 199/778] platform: mellanox: mlx-platform: Initialize shift variable to 0 Initialize shift variable in mlxplat_mlxcpld_verify_bus_topology() to 0 to avoid the following compile error: drivers/platform/x86/mlx-platform.c:6013 mlxplat_mlxcpld_verify_bus_topology() error: uninitialized symbol 'shift'. Fixes: 50b823fdd357 ("platform: mellanox: mlx-platform: Move bus shift assignment out of the loop") Cc: Vadim Pasternak Cc: Michael Shych Signed-off-by: Hans de Goede Link: https://lore.kernel.org/r/20230307105842.286118-1-hdegoede@redhat.com --- drivers/platform/x86/mlx-platform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c index 7b6779cdb134..67367f010139 100644 --- a/drivers/platform/x86/mlx-platform.c +++ b/drivers/platform/x86/mlx-platform.c @@ -5980,7 +5980,7 @@ MODULE_DEVICE_TABLE(dmi, mlxplat_dmi_table); static int mlxplat_mlxcpld_verify_bus_topology(int *nr) { struct i2c_adapter *search_adap; - int shift, i; + int i, shift = 0; /* Scan adapters from expected id to verify it is free. */ *nr = MLXPLAT_CPLD_PHYS_ADAPTER_DEF_NR; From 11f45690b3f6c6a2b5c57dbb036df3f838f7c016 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 7 Mar 2023 14:35:54 +0200 Subject: [PATCH 200/778] ASoC: SOF: ipc4: Add macro to set the core_id in create_pipe message The create pipeline message can carry the target code_id which is set to 0 at the moment. Add macros to set the core_id in the message extension. Signed-off-by: Peter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20230307123556.31328-2-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof/ipc4/header.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/sound/sof/ipc4/header.h b/include/sound/sof/ipc4/header.h index d31349bf011d..49ff1558a171 100644 --- a/include/sound/sof/ipc4/header.h +++ b/include/sound/sof/ipc4/header.h @@ -176,6 +176,10 @@ enum sof_ipc4_pipeline_state { #define SOF_IPC4_GLB_PIPE_EXT_LP_MASK BIT(0) #define SOF_IPC4_GLB_PIPE_EXT_LP(x) ((x) << SOF_IPC4_GLB_PIPE_EXT_LP_SHIFT) +#define SOF_IPC4_GLB_PIPE_EXT_CORE_ID_SHIFT 20 +#define SOF_IPC4_GLB_PIPE_EXT_CORE_ID_MASK GENMASK(23, 20) +#define SOF_IPC4_GLB_PIPE_EXT_CORE_ID(x) ((x) << SOF_IPC4_GLB_PIPE_EXT_CORE_ID_SHIFT) + /* pipeline set state ipc msg */ #define SOF_IPC4_GLB_PIPE_STATE_ID_SHIFT 16 #define SOF_IPC4_GLB_PIPE_STATE_ID_MASK GENMASK(23, 16) From 05ade472278a1a2fccc465ace205d6cfa9b521d5 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 7 Mar 2023 14:35:55 +0200 Subject: [PATCH 201/778] ASoC: SOF: ipc4-topology: Add support for core_id for pipelines Token SOF_TKN_SCHED_CORE in topology file can specify the target core for the pipeline, if it is missing it is going to be 0 (as it is right now). Firmware will double-check all information retrieved by topology and report errors if required. This will allow policy and changes in topologies without a need for a synchronized kernel change. Signed-off-by: Peter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20230307123556.31328-3-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 11 ++++++++--- sound/soc/sof/ipc4-topology.h | 2 ++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index 3e27c7a48ebd..12d8228d0828 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -24,7 +24,9 @@ static DEFINE_IDA(pipeline_ida); static const struct sof_topology_token ipc4_sched_tokens[] = { {SOF_TKN_SCHED_LP_MODE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, - offsetof(struct sof_ipc4_pipeline, lp_mode)} + offsetof(struct sof_ipc4_pipeline, lp_mode)}, + {SOF_TKN_SCHED_CORE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, + offsetof(struct sof_ipc4_pipeline, core_id)}, }; static const struct sof_topology_token pipeline_tokens[] = { @@ -629,6 +631,8 @@ static int sof_ipc4_widget_setup_comp_pipeline(struct snd_sof_widget *swidget) goto err; } + swidget->core = pipeline->core_id; + /* parse one set of pipeline tokens */ ret = sof_update_ipc_object(scomp, swidget, SOF_PIPELINE_TOKENS, swidget->tuples, swidget->num_tuples, sizeof(*swidget), 1); @@ -640,9 +644,9 @@ static int sof_ipc4_widget_setup_comp_pipeline(struct snd_sof_widget *swidget) /* TODO: Get priority from topology */ pipeline->priority = 0; - dev_dbg(scomp->dev, "pipeline '%s': id %d pri %d lp mode %d\n", + dev_dbg(scomp->dev, "pipeline '%s': id %d, pri %d, core_id %u, lp mode %d\n", swidget->widget->name, swidget->pipeline_id, - pipeline->priority, pipeline->lp_mode); + pipeline->priority, pipeline->core_id, pipeline->lp_mode); swidget->private = pipeline; @@ -652,6 +656,7 @@ static int sof_ipc4_widget_setup_comp_pipeline(struct snd_sof_widget *swidget) pipeline->msg.primary |= SOF_IPC4_MSG_TARGET(SOF_IPC4_FW_GEN_MSG); pipeline->msg.extension = pipeline->lp_mode; + pipeline->msg.extension |= SOF_IPC4_GLB_PIPE_EXT_CORE_ID(pipeline->core_id); pipeline->state = SOF_IPC4_PIPE_UNINITIALIZED; return 0; diff --git a/sound/soc/sof/ipc4-topology.h b/sound/soc/sof/ipc4-topology.h index 8507171a6e4d..7877f0638011 100644 --- a/sound/soc/sof/ipc4-topology.h +++ b/sound/soc/sof/ipc4-topology.h @@ -117,6 +117,7 @@ struct sof_ipc4_copier_config_set_sink_format { * @priority: Priority of this pipeline * @lp_mode: Low power mode * @mem_usage: Memory usage + * @core_id: Target core for the pipeline * @state: Pipeline state * @msg: message structure for pipeline * @skip_during_fe_trigger: skip triggering this pipeline during the FE DAI trigger @@ -125,6 +126,7 @@ struct sof_ipc4_pipeline { uint32_t priority; uint32_t lp_mode; uint32_t mem_usage; + uint32_t core_id; int state; struct sof_ipc4_msg msg; bool skip_during_fe_trigger; From 755ddc3acd50ca70e46b032c5c4a078e7b1b7d46 Mon Sep 17 00:00:00 2001 From: Rander Wang Date: Tue, 7 Mar 2023 14:35:56 +0200 Subject: [PATCH 202/778] ASoC: SOF: ipc4-topology: add core token in each module extended token list Add core token in extended token list for each module to support multi-core feature. Signed-off-by: Rander Wang Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Reviewed-by: Chao Song Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307123556.31328-4-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index 12d8228d0828..b27d85a68426 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -102,6 +102,8 @@ static const struct sof_topology_token dai_tokens[] = { static const struct sof_topology_token comp_ext_tokens[] = { {SOF_TKN_COMP_UUID, SND_SOC_TPLG_TUPLE_TYPE_UUID, get_token_uuid, offsetof(struct snd_sof_widget, uuid)}, + {SOF_TKN_COMP_CORE_ID, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, + offsetof(struct snd_sof_widget, core)}, }; static const struct sof_topology_token gain_tokens[] = { From 611fddf58862a9e77ae300605b2c00d54e973b1f Mon Sep 17 00:00:00 2001 From: Curtis Malainey Date: Tue, 7 Mar 2023 13:50:18 +0200 Subject: [PATCH 203/778] ASoC: SOF: loader: Remove log prefixes for snd_sof_run_firmware MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prefixs are unneeded since log level explains the same information Signed-off-by: Curtis Malainey Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307115018.5588-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/loader.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/loader.c b/sound/soc/sof/loader.c index 81d202e5ce53..2f8555f11c03 100644 --- a/sound/soc/sof/loader.c +++ b/sound/soc/sof/loader.c @@ -123,7 +123,7 @@ int snd_sof_run_firmware(struct snd_sof_dev *sdev) "fw_version", 0444); /* errors are only due to memory allocation, not debugfs */ if (ret < 0) { - dev_err(sdev->dev, "error: snd_sof_debugfs_buf_item failed\n"); + dev_err(sdev->dev, "snd_sof_debugfs_buf_item failed\n"); return ret; } } @@ -131,7 +131,7 @@ int snd_sof_run_firmware(struct snd_sof_dev *sdev) /* perform pre fw run operations */ ret = snd_sof_dsp_pre_fw_run(sdev); if (ret < 0) { - dev_err(sdev->dev, "error: failed pre fw run op\n"); + dev_err(sdev->dev, "failed pre fw run op\n"); return ret; } From 1d045d77756d07495ce379343455b1f829fe737d Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 7 Mar 2023 11:51:58 +0200 Subject: [PATCH 204/778] ASoC: SOF: Intel: hda-loader: use SOF helper for consistency Update code to remove mix between legacy and SOF definitions. No functionality change. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307095158.2818-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-loader.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c index d680562edb35..de8d9ad89bc7 100644 --- a/sound/soc/sof/intel/hda-loader.c +++ b/sound/soc/sof/intel/hda-loader.c @@ -321,13 +321,13 @@ int hda_cl_copy_fw(struct snd_sof_dev *sdev, struct hdac_ext_stream *hext_stream int hda_dsp_cl_boot_firmware_iccmax(struct snd_sof_dev *sdev) { struct hdac_ext_stream *iccmax_stream; - struct hdac_bus *bus = sof_to_bus(sdev); struct snd_dma_buffer dmab_bdl; int ret, ret1; u8 original_gb; /* save the original LTRP guardband value */ - original_gb = snd_hdac_chip_readb(bus, VS_LTRP) & HDA_VS_INTEL_LTRP_GB_MASK; + original_gb = snd_sof_dsp_read8(sdev, HDA_DSP_HDA_BAR, HDA_VS_INTEL_LTRP) & + HDA_VS_INTEL_LTRP_GB_MASK; /* * Prepare capture stream for ICCMAX. We do not need to store @@ -356,7 +356,8 @@ int hda_dsp_cl_boot_firmware_iccmax(struct snd_sof_dev *sdev) } /* restore the original guardband value after FW boot */ - snd_hdac_chip_updateb(bus, VS_LTRP, HDA_VS_INTEL_LTRP_GB_MASK, original_gb); + snd_sof_dsp_update8(sdev, HDA_DSP_HDA_BAR, HDA_VS_INTEL_LTRP, + HDA_VS_INTEL_LTRP_GB_MASK, original_gb); return ret; } From 418d2b2fad7cdce5d39d0e2fdbe2460f584b5432 Mon Sep 17 00:00:00 2001 From: Yong Zhi Date: Tue, 7 Mar 2023 11:52:51 +0200 Subject: [PATCH 205/778] ASoC: SOF: Intel: mtl: Access MTL_HFPWRCTL from HDA_DSP_BAR The Host Power Management/Clock Control (ULP) Registers in the HDA BAR shadow the values of the same registers in the DSP BAR, so let's modify the latter - as done already for other accesses. Signed-off-by: Yong Zhi Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307095251.3058-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/mtl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sof/intel/mtl.c b/sound/soc/sof/intel/mtl.c index 216fd07a3a93..8f0ed1cbf3b5 100644 --- a/sound/soc/sof/intel/mtl.c +++ b/sound/soc/sof/intel/mtl.c @@ -256,7 +256,7 @@ static int mtl_dsp_pre_fw_run(struct snd_sof_dev *sdev) dev_err(sdev->dev, "failed to power up gated DSP domain\n"); /* make sure SoundWire is not power-gated */ - snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, MTL_HFPWRCTL, + snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_HFPWRCTL, MTL_HfPWRCTL_WPIOXPG(1), MTL_HfPWRCTL_WPIOXPG(1)); return ret; } From 3c50211f2d534a5b766b1ff3c6cf6f7bd0bae753 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Tue, 7 Mar 2023 13:08:30 +0200 Subject: [PATCH 206/778] ASoC: SOF: ipc4-topology: don't allocate blob if it will not be used A copier blob will be only used when a copier is connected in the topology. An ALH copier in playback direction that doesn't have any source means the copier is not connected in the topology. Thus, we don't need to allocate the blob. The patch doesn't do the same test before freeing the blob because the blob is null and it is fine to free null. Signed-off-by: Bard Liao Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307110830.2178-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index 3e27c7a48ebd..93b2855388d5 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -517,7 +517,23 @@ static int sof_ipc4_widget_setup_comp_dai(struct snd_sof_widget *swidget) { struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); struct sof_ipc4_alh_configuration_blob *blob; + struct snd_soc_dapm_path *p; struct snd_sof_widget *w; + int src_num = 0; + + snd_soc_dapm_widget_for_each_source_path(swidget->widget, p) + src_num++; + + if (swidget->id == snd_soc_dapm_dai_in && src_num == 0) { + /* + * The blob will not be used if the ALH copier is playback direction + * and doesn't connect to any source. + * It is fine to call kfree(ipc4_copier->copier_config) since + * ipc4_copier->copier_config is null. + */ + ret = 0; + break; + } blob = kzalloc(sizeof(*blob), GFP_KERNEL); if (!blob) { From db97cc0f7459a2bee68e6e8bf0b2f7a286137fa8 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Tue, 7 Mar 2023 13:08:46 +0200 Subject: [PATCH 207/778] ASoC: SOF: ipc4-mtrace: process pending logs upon FW crash MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the DSP firmware has crashed, some log messages may be pending in the mtrace buffer, but not consumed by the driver as no IPC notification has been sent by the firmware. Check the buffer status for all mtrace slots and ensure any pending log messages are processed before DSP is possibly powered down and the log buffer contents is lost. Signed-off-by: Kai Vehmanen Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307110846.2265-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-mtrace.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/sound/soc/sof/ipc4-mtrace.c b/sound/soc/sof/ipc4-mtrace.c index 0ec6ef681012..2b4659a1768e 100644 --- a/sound/soc/sof/ipc4-mtrace.c +++ b/sound/soc/sof/ipc4-mtrace.c @@ -609,6 +609,16 @@ static void ipc4_mtrace_free(struct snd_sof_dev *sdev) ipc4_mtrace_disable(sdev); } +static int sof_ipc4_mtrace_update_pos_all_cores(struct snd_sof_dev *sdev) +{ + int i; + + for (i = 0; i < sdev->num_cores; i++) + sof_ipc4_mtrace_update_pos(sdev, i); + + return 0; +} + int sof_ipc4_mtrace_update_pos(struct snd_sof_dev *sdev, int core) { struct sof_mtrace_priv *priv = sdev->fw_trace_data; @@ -642,6 +652,16 @@ int sof_ipc4_mtrace_update_pos(struct snd_sof_dev *sdev, int core) return 0; } +static void ipc4_mtrace_fw_crashed(struct snd_sof_dev *sdev) +{ + /* + * The DSP might not be able to send SOF_IPC4_NOTIFY_LOG_BUFFER_STATUS + * messages anymore, so check the log buffer status on all + * cores and process any pending messages. + */ + sof_ipc4_mtrace_update_pos_all_cores(sdev); +} + static int ipc4_mtrace_resume(struct snd_sof_dev *sdev) { return ipc4_mtrace_enable(sdev); @@ -655,6 +675,7 @@ static void ipc4_mtrace_suspend(struct snd_sof_dev *sdev, pm_message_t pm_state) const struct sof_ipc_fw_tracing_ops ipc4_mtrace_ops = { .init = ipc4_mtrace_init, .free = ipc4_mtrace_free, + .fw_crashed = ipc4_mtrace_fw_crashed, .suspend = ipc4_mtrace_suspend, .resume = ipc4_mtrace_resume, }; From 428913bce1e67ccb4dae317fd0332545bf8c9233 Mon Sep 17 00:00:00 2001 From: Yu Kuai Date: Tue, 7 Mar 2023 18:55:52 +0800 Subject: [PATCH 208/778] block: fix wrong mode for blkdev_put() from disk_scan_partitions() If disk_scan_partitions() is called with 'FMODE_EXCL', blkdev_get_by_dev() will be called without 'FMODE_EXCL', however, follow blkdev_put() is still called with 'FMODE_EXCL', which will cause 'bd_holders' counter to leak. Fix the problem by using the right mode for blkdev_put(). Reported-by: syzbot+2bcc0d79e548c4f62a59@syzkaller.appspotmail.com Link: https://lore.kernel.org/lkml/f9649d501bc8c3444769418f6c26263555d9d3be.camel@linux.ibm.com/T/ Tested-by: Julian Ruess Fixes: e5cfefa97bcc ("block: fix scan partition for exclusively open device again") Signed-off-by: Yu Kuai Reviewed-by: Jan Kara Signed-off-by: Jens Axboe --- block/genhd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/block/genhd.c b/block/genhd.c index 3ee5577e1586..02d9cfb9e077 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -385,7 +385,7 @@ int disk_scan_partitions(struct gendisk *disk, fmode_t mode) if (IS_ERR(bdev)) ret = PTR_ERR(bdev); else - blkdev_put(bdev, mode); + blkdev_put(bdev, mode & ~FMODE_EXCL); if (!(mode & FMODE_EXCL)) bd_abort_claiming(disk->part0, disk_scan_partitions); From 418383e6ed6b4624a54ec05c535f13d184fbf33b Mon Sep 17 00:00:00 2001 From: Enrico Sau Date: Mon, 6 Mar 2023 12:59:33 +0100 Subject: [PATCH 209/778] net: usb: cdc_mbim: avoid altsetting toggling for Telit FE990 Add quirk CDC_MBIM_FLAG_AVOID_ALTSETTING_TOGGLE for Telit FE990 0x1081 composition in order to avoid bind error. Signed-off-by: Enrico Sau Link: https://lore.kernel.org/r/20230306115933.198259-1-enrico.sau@gmail.com Signed-off-by: Paolo Abeni --- drivers/net/usb/cdc_mbim.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/usb/cdc_mbim.c b/drivers/net/usb/cdc_mbim.c index c89639381eca..cd4083e0b3b9 100644 --- a/drivers/net/usb/cdc_mbim.c +++ b/drivers/net/usb/cdc_mbim.c @@ -665,6 +665,11 @@ static const struct usb_device_id mbim_devs[] = { .driver_info = (unsigned long)&cdc_mbim_info_avoid_altsetting_toggle, }, + /* Telit FE990 */ + { USB_DEVICE_AND_INTERFACE_INFO(0x1bc7, 0x1081, USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE), + .driver_info = (unsigned long)&cdc_mbim_info_avoid_altsetting_toggle, + }, + /* default entry */ { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE), .driver_info = (unsigned long)&cdc_mbim_info_zlp, From 382e363d5bed0cec5807b35761d14e55955eee63 Mon Sep 17 00:00:00 2001 From: Enrico Sau Date: Mon, 6 Mar 2023 13:05:28 +0100 Subject: [PATCH 210/778] net: usb: qmi_wwan: add Telit 0x1080 composition Add the following Telit FE990 composition: 0x1080: tty, adb, rmnet, tty, tty, tty, tty Signed-off-by: Enrico Sau Link: https://lore.kernel.org/r/20230306120528.198842-1-enrico.sau@gmail.com Signed-off-by: Paolo Abeni --- drivers/net/usb/qmi_wwan.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index a808d718c012..571e37e67f9c 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -1364,6 +1364,7 @@ static const struct usb_device_id products[] = { {QMI_QUIRK_SET_DTR(0x1bc7, 0x1057, 2)}, /* Telit FN980 */ {QMI_QUIRK_SET_DTR(0x1bc7, 0x1060, 2)}, /* Telit LN920 */ {QMI_QUIRK_SET_DTR(0x1bc7, 0x1070, 2)}, /* Telit FN990 */ + {QMI_QUIRK_SET_DTR(0x1bc7, 0x1080, 2)}, /* Telit FE990 */ {QMI_FIXED_INTF(0x1bc7, 0x1100, 3)}, /* Telit ME910 */ {QMI_FIXED_INTF(0x1bc7, 0x1101, 3)}, /* Telit ME910 dual modem */ {QMI_FIXED_INTF(0x1bc7, 0x1200, 5)}, /* Telit LE920 */ From fd9a2e1d513823e840960cb3bc26d8b7749d4ac2 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Mon, 6 Mar 2023 10:43:47 -0500 Subject: [PATCH 211/778] NFSD: Protect against filesystem freezing Flole observes this WARNING on occasion: [1210423.486503] WARNING: CPU: 8 PID: 1524732 at fs/ext4/ext4_jbd2.c:75 ext4_journal_check_start+0x68/0xb0 Reported-by: Suggested-by: Jan Kara Link: https://bugzilla.kernel.org/show_bug.cgi?id=217123 Fixes: 73da852e3831 ("nfsd: use vfs_iter_read/write") Reviewed-by: Jeff Layton Reviewed-by: Jan Kara Signed-off-by: Chuck Lever --- fs/nfsd/vfs.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 21d5209f6e04..ba34a31a7c70 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -1104,7 +1104,9 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct nfsd_file *nf, since = READ_ONCE(file->f_wb_err); if (verf) nfsd_copy_write_verifier(verf, nn); + file_start_write(file); host_err = vfs_iter_write(file, &iter, &pos, flags); + file_end_write(file); if (host_err < 0) { nfsd_reset_write_verifier(nn); trace_nfsd_writeverf_reset(nn, rqstp, host_err); From 274f8a3b4eb855bb14e38f6f12421ed32a2e670b Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 7 Mar 2023 16:04:22 +0200 Subject: [PATCH 212/778] ASoC: SOF: Intel: hda-dai: Remove BE DAI DRV ops for SSP DAI's MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that the DAI_CONFIG IPC is sent after widget setup and before widget free, there is no need for the BE DAI DRV ops that do the same thing. So remove them. Signed-off-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307140435.2808-2-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai.c | 113 ---------------------------------- 1 file changed, 113 deletions(-) diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index 8d9c38d562d3..c7f89c18d5c2 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -605,115 +605,6 @@ static const struct snd_soc_dai_ops ipc4_hda_dai_ops = { #endif -/* only one flag used so far to harden hw_params/hw_free/trigger/prepare */ -struct ssp_dai_dma_data { - bool setup; -}; - -static int ssp_dai_setup_or_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai, - bool setup) -{ - struct snd_soc_dapm_widget *w; - - w = snd_soc_dai_get_widget(dai, substream->stream); - - if (setup) - return hda_ctrl_dai_widget_setup(w, SOF_DAI_CONFIG_FLAGS_NONE, NULL); - - return hda_ctrl_dai_widget_free(w, SOF_DAI_CONFIG_FLAGS_NONE, NULL); -} - -static int ssp_dai_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct ssp_dai_dma_data *dma_data; - - dma_data = kzalloc(sizeof(*dma_data), GFP_KERNEL); - if (!dma_data) - return -ENOMEM; - - snd_soc_dai_set_dma_data(dai, substream, dma_data); - - return 0; -} - -static int ssp_dai_setup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai, - bool setup) -{ - struct ssp_dai_dma_data *dma_data; - int ret = 0; - - dma_data = snd_soc_dai_get_dma_data(dai, substream); - if (!dma_data) { - dev_err(dai->dev, "%s: failed to get dma_data\n", __func__); - return -EIO; - } - - if (dma_data->setup != setup) { - ret = ssp_dai_setup_or_free(substream, dai, setup); - if (!ret) - dma_data->setup = setup; - } - return ret; -} - -static int ssp_dai_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - /* params are ignored for now */ - return ssp_dai_setup(substream, dai, true); -} - -static int ssp_dai_prepare(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - /* - * the SSP will only be reconfigured during resume operations and - * not in case of xruns - */ - return ssp_dai_setup(substream, dai, true); -} - -static int ipc3_ssp_dai_trigger(struct snd_pcm_substream *substream, - int cmd, struct snd_soc_dai *dai) -{ - if (cmd != SNDRV_PCM_TRIGGER_SUSPEND) - return 0; - - return ssp_dai_setup(substream, dai, false); -} - -static int ssp_dai_hw_free(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - return ssp_dai_setup(substream, dai, false); -} - -static void ssp_dai_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct ssp_dai_dma_data *dma_data; - - dma_data = snd_soc_dai_get_dma_data(dai, substream); - if (!dma_data) { - dev_err(dai->dev, "%s: failed to get dma_data\n", __func__); - return; - } - snd_soc_dai_set_dma_data(dai, substream, NULL); - kfree(dma_data); -} - -static const struct snd_soc_dai_ops ipc3_ssp_dai_ops = { - .startup = ssp_dai_startup, - .hw_params = ssp_dai_hw_params, - .prepare = ssp_dai_prepare, - .trigger = ipc3_ssp_dai_trigger, - .hw_free = ssp_dai_hw_free, - .shutdown = ssp_dai_shutdown, -}; - void hda_set_dai_drv_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *ops) { int i; @@ -721,10 +612,6 @@ void hda_set_dai_drv_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *ops) switch (sdev->pdata->ipc_type) { case SOF_IPC: for (i = 0; i < ops->num_drv; i++) { - if (strstr(ops->drv[i].name, "SSP")) { - ops->drv[i].ops = &ipc3_ssp_dai_ops; - continue; - } #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) if (strstr(ops->drv[i].name, "iDisp") || strstr(ops->drv[i].name, "Analog") || From a8310c0093f4ebeb3a317b4b70e864b91739fc50 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 7 Mar 2023 16:04:23 +0200 Subject: [PATCH 213/778] ASoC: SOF: Intel: hda-dai: Remove hda_link_dma_params() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No code change. Just code move from hda_link_dma_params() to hda_link_dma_hw_params(). Signed-off-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307140435.2808-3-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai.c | 62 ++++++++++++++++------------------- 1 file changed, 28 insertions(+), 34 deletions(-) diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index c7f89c18d5c2..770c00ae29ac 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -168,39 +168,6 @@ static int hda_link_dma_cleanup(struct snd_pcm_substream *substream, return 0; } -static int hda_link_dma_params(struct hdac_ext_stream *hext_stream, - struct hda_pipe_params *params) -{ - struct hdac_stream *hstream = &hext_stream->hstream; - unsigned char stream_tag = hstream->stream_tag; - struct hdac_bus *bus = hstream->bus; - struct hdac_ext_link *hlink; - unsigned int format_val; - - snd_hdac_ext_stream_reset(hext_stream); - - format_val = snd_hdac_calc_stream_format(params->s_freq, params->ch, - params->format, - params->link_bps, 0); - - dev_dbg(bus->dev, "format_val=%d, rate=%d, ch=%d, format=%d\n", - format_val, params->s_freq, params->ch, params->format); - - snd_hdac_ext_stream_setup(hext_stream, format_val); - - if (hext_stream->hstream.direction == SNDRV_PCM_STREAM_PLAYBACK) { - list_for_each_entry(hlink, &bus->hlink_list, list) { - if (hlink->index == params->link_index) - snd_hdac_ext_bus_link_set_stream_id(hlink, - stream_tag); - } - } - - hext_stream->link_prepared = 1; - - return 0; -} - static int hda_link_dma_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { @@ -209,9 +176,12 @@ static int hda_link_dma_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct hda_pipe_params p_params = {0}; struct hdac_ext_stream *hext_stream; + struct hdac_stream *hstream; struct hdac_ext_link *hlink; struct snd_sof_dev *sdev; struct hdac_bus *bus; + unsigned int format_val; + unsigned char stream_tag; sdev = snd_soc_component_get_drvdata(cpu_dai->component); bus = sof_to_bus(sdev); @@ -229,6 +199,9 @@ static int hda_link_dma_hw_params(struct snd_pcm_substream *substream, snd_soc_dai_set_dma_data(cpu_dai, substream, (void *)hext_stream); } + hstream = &hext_stream->hstream; + stream_tag = hstream->stream_tag; + /* set the hdac_stream in the codec dai */ snd_soc_dai_set_stream(codec_dai, hdac_stream(hext_stream), substream->stream); @@ -242,7 +215,28 @@ static int hda_link_dma_hw_params(struct snd_pcm_substream *substream, else p_params.link_bps = codec_dai->driver->capture.sig_bits; - return hda_link_dma_params(hext_stream, &p_params); + snd_hdac_ext_stream_reset(hext_stream); + + format_val = snd_hdac_calc_stream_format(p_params.s_freq, p_params.ch, + p_params.format, + p_params.link_bps, 0); + + dev_dbg(bus->dev, "format_val=%d, rate=%d, ch=%d, format=%d\n", + format_val, p_params.s_freq, p_params.ch, p_params.format); + + snd_hdac_ext_stream_setup(hext_stream, format_val); + + if (hext_stream->hstream.direction == SNDRV_PCM_STREAM_PLAYBACK) { + list_for_each_entry(hlink, &bus->hlink_list, list) { + if (hlink->index == p_params.link_index) + snd_hdac_ext_bus_link_set_stream_id(hlink, + stream_tag); + } + } + + hext_stream->link_prepared = 1; + + return 0; } static int hda_link_dma_prepare(struct snd_pcm_substream *substream) From 2a6afac248b08a0bcec72a6a605f11319738f6db Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 7 Mar 2023 16:04:24 +0200 Subject: [PATCH 214/778] ASoC: SOF: Intel: hda-dai: remove struct hda_pipe_params MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the struct definition and use the params argument directly. Also, use the hlink pointer to set the stream ID instead of looking it up again. Signed-off-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307140435.2808-4-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai.c | 37 +++++++++-------------------------- 1 file changed, 9 insertions(+), 28 deletions(-) diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index 770c00ae29ac..009299c6de40 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -29,14 +29,6 @@ MODULE_PARM_DESC(sof_use_tplg_nhlt, "SOF topology nhlt override"); #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) -struct hda_pipe_params { - u32 ch; - u32 s_freq; - snd_pcm_format_t format; - int link_index; - unsigned int link_bps; -}; - /* * This function checks if the host dma channel corresponding * to the link DMA stream_tag argument is assigned to one @@ -174,13 +166,13 @@ static int hda_link_dma_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); - struct hda_pipe_params p_params = {0}; struct hdac_ext_stream *hext_stream; struct hdac_stream *hstream; struct hdac_ext_link *hlink; struct snd_sof_dev *sdev; struct hdac_bus *bus; unsigned int format_val; + unsigned int link_bps; unsigned char stream_tag; sdev = snd_soc_component_get_drvdata(cpu_dai->component); @@ -202,38 +194,27 @@ static int hda_link_dma_hw_params(struct snd_pcm_substream *substream, hstream = &hext_stream->hstream; stream_tag = hstream->stream_tag; + if (hext_stream->hstream.direction == SNDRV_PCM_STREAM_PLAYBACK) + snd_hdac_ext_bus_link_set_stream_id(hlink, stream_tag); + /* set the hdac_stream in the codec dai */ snd_soc_dai_set_stream(codec_dai, hdac_stream(hext_stream), substream->stream); - p_params.ch = params_channels(params); - p_params.s_freq = params_rate(params); - p_params.link_index = hlink->index; - p_params.format = params_format(params); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - p_params.link_bps = codec_dai->driver->playback.sig_bits; + link_bps = codec_dai->driver->playback.sig_bits; else - p_params.link_bps = codec_dai->driver->capture.sig_bits; + link_bps = codec_dai->driver->capture.sig_bits; snd_hdac_ext_stream_reset(hext_stream); - format_val = snd_hdac_calc_stream_format(p_params.s_freq, p_params.ch, - p_params.format, - p_params.link_bps, 0); + format_val = snd_hdac_calc_stream_format(params_rate(params), params_channels(params), + params_format(params), link_bps, 0); dev_dbg(bus->dev, "format_val=%d, rate=%d, ch=%d, format=%d\n", - format_val, p_params.s_freq, p_params.ch, p_params.format); + format_val, params_rate(params), params_channels(params), params_format(params)); snd_hdac_ext_stream_setup(hext_stream, format_val); - if (hext_stream->hstream.direction == SNDRV_PCM_STREAM_PLAYBACK) { - list_for_each_entry(hlink, &bus->hlink_list, list) { - if (hlink->index == p_params.link_index) - snd_hdac_ext_bus_link_set_stream_id(hlink, - stream_tag); - } - } - hext_stream->link_prepared = 1; return 0; From 2be2caf481c7200b29116cea83cf8dd45c9e097f Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 7 Mar 2023 16:04:25 +0200 Subject: [PATCH 215/778] ASoC: SOF: Intel: hda-dai: Modify the signature of hda_link_dma_cleanup() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the trigger_suspend_stop argument from hda_link_dma_cleanup() and move the call to snd_hdac_ext_stream_clear() into snd_hdac_ext_stream_clear(). This is a preparatory step to unify the trigger ops for IPC3 and IPC4. Signed-off-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307140435.2808-5-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index 009299c6de40..d4b98bfe2adf 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -129,8 +129,7 @@ hda_link_stream_assign(struct hdac_bus *bus, static int hda_link_dma_cleanup(struct snd_pcm_substream *substream, struct hdac_ext_stream *hext_stream, struct snd_soc_dai *cpu_dai, - struct snd_soc_dai *codec_dai, - bool trigger_suspend_stop) + struct snd_soc_dai *codec_dai) { struct hdac_stream *hstream = &hext_stream->hstream; struct hdac_bus *bus = hstream->bus; @@ -142,9 +141,6 @@ static int hda_link_dma_cleanup(struct snd_pcm_substream *substream, if (!hlink) return -EINVAL; - if (trigger_suspend_stop) - snd_hdac_ext_stream_clear(hext_stream); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { stream_tag = hdac_stream(hext_stream)->stream_tag; snd_hdac_ext_bus_link_clear_stream_id(hlink, stream_tag); @@ -246,7 +242,8 @@ static int hda_link_dma_trigger(struct snd_pcm_substream *substream, int cmd) break; case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_STOP: - ret = hda_link_dma_cleanup(substream, hext_stream, cpu_dai, codec_dai, true); + snd_hdac_ext_stream_clear(hext_stream); + ret = hda_link_dma_cleanup(substream, hext_stream, cpu_dai, codec_dai); if (ret < 0) return ret; @@ -272,7 +269,7 @@ static int hda_link_dma_hw_free(struct snd_pcm_substream *substream) if (!hext_stream) return 0; - return hda_link_dma_cleanup(substream, hext_stream, cpu_dai, codec_dai, false); + return hda_link_dma_cleanup(substream, hext_stream, cpu_dai, codec_dai); } static int hda_dai_widget_update(struct snd_soc_dapm_widget *w, @@ -483,7 +480,7 @@ static int ipc4_hda_dai_trigger(struct snd_pcm_substream *substream, pipeline->state = SOF_IPC4_PIPE_RESET; - ret = hda_link_dma_cleanup(substream, hext_stream, cpu_dai, codec_dai, false); + ret = hda_link_dma_cleanup(substream, hext_stream, cpu_dai, codec_dai); if (ret < 0) { dev_err(sdev->dev, "%s: failed to clean up link DMA\n", __func__); return ret; @@ -557,7 +554,7 @@ static int hda_dai_suspend(struct hdac_bus *bus) ret = hda_link_dma_cleanup(hext_stream->link_substream, hext_stream, - cpu_dai, codec_dai, false); + cpu_dai, codec_dai); if (ret < 0) return ret; From b436ed8dd071cae10ac3f94c541a783a094971ff Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 7 Mar 2023 16:04:26 +0200 Subject: [PATCH 216/778] ASoC: SOF: Intel: hda-dai: Pass the CPU dai pointer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pass the CPU DAI pointer from the ASoC core to hda_link_dma_hw_params() and ipc3_hda_dai_trigger(). This will avoid looking up the CPU DAI pointer multiple times. Signed-off-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307140435.2808-6-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index d4b98bfe2adf..e448c653cfe1 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -157,10 +157,9 @@ static int hda_link_dma_cleanup(struct snd_pcm_substream *substream, } static int hda_link_dma_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) + struct snd_pcm_hw_params *params, struct snd_soc_dai *cpu_dai) { struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); - struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct hdac_ext_stream *hext_stream; struct hdac_stream *hstream; @@ -216,18 +215,18 @@ static int hda_link_dma_hw_params(struct snd_pcm_substream *substream, return 0; } -static int hda_link_dma_prepare(struct snd_pcm_substream *substream) +static int hda_link_dma_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); int stream = substream->stream; - return hda_link_dma_hw_params(substream, &rtd->dpcm[stream].hw_params); + return hda_link_dma_hw_params(substream, &rtd->dpcm[stream].hw_params, cpu_dai); } -static int hda_link_dma_trigger(struct snd_pcm_substream *substream, int cmd) +static int hda_link_dma_trigger(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai, + int cmd) { struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); - struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct hdac_ext_stream *hext_stream = snd_soc_dai_get_dma_data(cpu_dai, substream); int ret; @@ -258,10 +257,9 @@ static int hda_link_dma_trigger(struct snd_pcm_substream *substream, int cmd) return 0; } -static int hda_link_dma_hw_free(struct snd_pcm_substream *substream) +static int hda_link_dma_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); - struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct hdac_ext_stream *hext_stream; @@ -317,7 +315,7 @@ static int hda_dai_hw_params(struct snd_pcm_substream *substream, if (hext_stream && hext_stream->link_prepared) return 0; - ret = hda_link_dma_hw_params(substream, params); + ret = hda_link_dma_hw_params(substream, params, dai); if (ret < 0) return ret; @@ -357,7 +355,7 @@ static int hda_dai_prepare(struct snd_pcm_substream *substream, struct snd_soc_d dev_dbg(sdev->dev, "prepare stream dir %d\n", substream->stream); - ret = hda_link_dma_prepare(substream); + ret = hda_link_dma_prepare(substream, dai); if (ret < 0) return ret; @@ -384,7 +382,7 @@ static int ipc3_hda_dai_trigger(struct snd_pcm_substream *substream, dev_dbg(dai->dev, "cmd=%d dai %s direction %d\n", cmd, dai->name, substream->stream); - ret = hda_link_dma_trigger(substream, cmd); + ret = hda_link_dma_trigger(substream, dai, cmd); if (ret < 0) return ret; @@ -512,7 +510,7 @@ static int hda_dai_hw_free(struct snd_pcm_substream *substream, { int ret; - ret = hda_link_dma_hw_free(substream); + ret = hda_link_dma_hw_free(substream, dai); if (ret < 0) return ret; From be7f4f8d0bee110505750d85e6e11c59f8ceb65f Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 7 Mar 2023 16:04:27 +0200 Subject: [PATCH 217/778] ASoC: SOF: Intel: hda-dai: Use the dai argument in ipc4_hda_dai_trigger MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No need to define a new variable and look it up again. Signed-off-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307140435.2808-7-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index e448c653cfe1..49f25e55b15d 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -426,14 +426,12 @@ static int ipc4_hda_dai_trigger(struct snd_pcm_substream *substream, struct snd_sof_widget *swidget; struct snd_soc_dapm_widget *w; struct snd_soc_dai *codec_dai; - struct snd_soc_dai *cpu_dai; int ret; dev_dbg(dai->dev, "cmd=%d dai %s direction %d\n", cmd, dai->name, substream->stream); rtd = asoc_substream_to_rtd(substream); - cpu_dai = asoc_rtd_to_cpu(rtd, 0); codec_dai = asoc_rtd_to_codec(rtd, 0); w = snd_soc_dai_get_widget(dai, substream->stream); @@ -478,7 +476,7 @@ static int ipc4_hda_dai_trigger(struct snd_pcm_substream *substream, pipeline->state = SOF_IPC4_PIPE_RESET; - ret = hda_link_dma_cleanup(substream, hext_stream, cpu_dai, codec_dai); + ret = hda_link_dma_cleanup(substream, hext_stream, dai, codec_dai); if (ret < 0) { dev_err(sdev->dev, "%s: failed to clean up link DMA\n", __func__); return ret; From 2ae49c6fe060baf432472aba48743e72b8345c52 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 7 Mar 2023 16:04:28 +0200 Subject: [PATCH 218/778] ASoC: SOF: Intel: hda-dai: Introduce DAI widget ops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce a new ops structure for HDA DAI widget DMA ops and add a new field to struct snd_sof_dai that will be used to set the ops pointer for DAI widgets. Signed-off-by: Ranjani Sridharan Reviewed-by: Bard Liao Reviewed-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Rander Wang Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307140435.2808-8-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda.h | 31 +++++++++++++++++++++++++++++++ sound/soc/sof/sof-audio.h | 2 ++ 2 files changed, 33 insertions(+) diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 0679bebe4ad7..c6243827f8d0 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -928,4 +928,35 @@ extern struct sdw_intel_ops sdw_callback; struct sof_ipc4_fw_library; int hda_dsp_ipc4_load_library(struct snd_sof_dev *sdev, struct sof_ipc4_fw_library *fw_lib, bool reload); + +/** + * struct hda_dai_widget_dma_ops - DAI DMA ops optional by default unless specified otherwise + * @get_hext_stream: Mandatory function pointer to get the saved pointer to struct hdac_ext_stream + * @assign_hext_stream: Function pointer to assign a hdac_ext_stream + * @release_hext_stream: Function pointer to release the hdac_ext_stream + * @setup_hext_stream: Function pointer for hdac_ext_stream setup + * @reset_hext_stream: Function pointer for hdac_ext_stream reset + * @pre_trigger: Function pointer for DAI DMA pre-trigger actions + * @trigger: Function pointer for DAI DMA trigger actions + * @post_trigger: Function pointer for DAI DMA post-trigger actions + */ +struct hda_dai_widget_dma_ops { + struct hdac_ext_stream *(*get_hext_stream)(struct snd_sof_dev *sdev, + struct snd_soc_dai *cpu_dai, + struct snd_pcm_substream *substream); + struct hdac_ext_stream *(*assign_hext_stream)(struct snd_sof_dev *sdev, + struct snd_soc_dai *cpu_dai, + struct snd_pcm_substream *substream); + void (*release_hext_stream)(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai, + struct snd_pcm_substream *substream); + void (*setup_hext_stream)(struct snd_sof_dev *sdev, struct hdac_ext_stream *hext_stream, + unsigned int format_val); + void (*reset_hext_stream)(struct snd_sof_dev *sdev, struct hdac_ext_stream *hext_sream); + int (*pre_trigger)(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai, + struct snd_pcm_substream *substream, int cmd); + int (*trigger)(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai, + struct snd_pcm_substream *substream, int cmd); + int (*post_trigger)(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai, + struct snd_pcm_substream *substream, int cmd); +}; #endif diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h index e0579af9d281..239b82f37976 100644 --- a/sound/soc/sof/sof-audio.h +++ b/sound/soc/sof/sof-audio.h @@ -502,6 +502,8 @@ struct snd_sof_dai { int number_configs; int current_config; struct list_head list; /* list in sdev dai list */ + /* core should not touch this */ + const void *platform_private; void *private; }; From 80afde34e8f9c2459f7cd37ea2d5f71751fedd69 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 7 Mar 2023 16:04:29 +0200 Subject: [PATCH 219/778] ASoC: SOF: Intel: hda-dai: Define and set the HDA DAI widget DMA ops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Define and set the get_hext_stream, assign_hext_stream and release_hext_stream DMA ops for HDA DAIs. Signed-off-by: Ranjani Sridharan Reviewed-by: Bard Liao Reviewed-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Rander Wang Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307140435.2808-9-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/Makefile | 2 +- sound/soc/sof/intel/hda-dai-ops.c | 183 ++++++++++++++++++++++++++++ sound/soc/sof/intel/hda-dai.c | 194 ++++++++++++------------------ sound/soc/sof/intel/hda.h | 4 + 4 files changed, 262 insertions(+), 121 deletions(-) create mode 100644 sound/soc/sof/intel/hda-dai-ops.c diff --git a/sound/soc/sof/intel/Makefile b/sound/soc/sof/intel/Makefile index 8201cbdd654c..38ab86b6a9fe 100644 --- a/sound/soc/sof/intel/Makefile +++ b/sound/soc/sof/intel/Makefile @@ -5,7 +5,7 @@ snd-sof-acpi-intel-bdw-objs := bdw.o snd-sof-intel-hda-common-objs := hda.o hda-loader.o hda-stream.o hda-trace.o \ hda-dsp.o hda-ipc.o hda-ctrl.o hda-pcm.o \ - hda-dai.o hda-bus.o hda-mlink.o \ + hda-dai.o hda-dai-ops.o hda-bus.o hda-mlink.o \ skl.o hda-loader-skl.o \ apl.o cnl.o tgl.o icl.o mtl.o hda-common-ops.o diff --git a/sound/soc/sof/intel/hda-dai-ops.c b/sound/soc/sof/intel/hda-dai-ops.c new file mode 100644 index 000000000000..9dfcafeab9e4 --- /dev/null +++ b/sound/soc/sof/intel/hda-dai-ops.c @@ -0,0 +1,183 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) +// +// This file is provided under a dual BSD/GPLv2 license. When using or +// redistributing this file, you may do so under either license. +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. + +#include +#include +#include +#include +#include "../ipc4-priv.h" +#include "../ipc4-topology.h" +#include "../sof-priv.h" +#include "../sof-audio.h" +#include "hda.h" + +/* These ops are only applicable for the HDA DAI's in their current form */ +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) +/* + * This function checks if the host dma channel corresponding + * to the link DMA stream_tag argument is assigned to one + * of the FEs connected to the BE DAI. + */ +static bool hda_check_fes(struct snd_soc_pcm_runtime *rtd, + int dir, int stream_tag) +{ + struct snd_pcm_substream *fe_substream; + struct hdac_stream *fe_hstream; + struct snd_soc_dpcm *dpcm; + + for_each_dpcm_fe(rtd, dir, dpcm) { + fe_substream = snd_soc_dpcm_get_substream(dpcm->fe, dir); + fe_hstream = fe_substream->runtime->private_data; + if (fe_hstream->stream_tag == stream_tag) + return true; + } + + return false; +} + +static struct hdac_ext_stream * +hda_link_stream_assign(struct hdac_bus *bus, struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct sof_intel_hda_stream *hda_stream; + const struct sof_intel_dsp_desc *chip; + struct snd_sof_dev *sdev; + struct hdac_ext_stream *res = NULL; + struct hdac_stream *hstream = NULL; + + int stream_dir = substream->stream; + + if (!bus->ppcap) { + dev_err(bus->dev, "stream type not supported\n"); + return NULL; + } + + spin_lock_irq(&bus->reg_lock); + list_for_each_entry(hstream, &bus->stream_list, list) { + struct hdac_ext_stream *hext_stream = + stream_to_hdac_ext_stream(hstream); + if (hstream->direction != substream->stream) + continue; + + hda_stream = hstream_to_sof_hda_stream(hext_stream); + sdev = hda_stream->sdev; + chip = get_chip_info(sdev->pdata); + + /* check if link is available */ + if (!hext_stream->link_locked) { + /* + * choose the first available link for platforms that do not have the + * PROCEN_FMT_QUIRK set. + */ + if (!(chip->quirks & SOF_INTEL_PROCEN_FMT_QUIRK)) { + res = hext_stream; + break; + } + + if (hstream->opened) { + /* + * check if the stream tag matches the stream + * tag of one of the connected FEs + */ + if (hda_check_fes(rtd, stream_dir, + hstream->stream_tag)) { + res = hext_stream; + break; + } + } else { + res = hext_stream; + + /* + * This must be a hostless stream. + * So reserve the host DMA channel. + */ + hda_stream->host_reserved = 1; + break; + } + } + } + + if (res) { + /* Make sure that host and link DMA is decoupled. */ + snd_hdac_ext_stream_decouple_locked(bus, res, true); + + res->link_locked = 1; + res->link_substream = substream; + } + spin_unlock_irq(&bus->reg_lock); + + return res; +} + +static struct hdac_ext_stream *hda_get_hext_stream(struct snd_sof_dev *sdev, + struct snd_soc_dai *cpu_dai, + struct snd_pcm_substream *substream) +{ + return snd_soc_dai_get_dma_data(cpu_dai, substream); +} + +static struct hdac_ext_stream *hda_assign_hext_stream(struct snd_sof_dev *sdev, + struct snd_soc_dai *cpu_dai, + struct snd_pcm_substream *substream) +{ + struct hdac_ext_stream *hext_stream; + + hext_stream = hda_link_stream_assign(sof_to_bus(sdev), substream); + if (!hext_stream) + return NULL; + + snd_soc_dai_set_dma_data(cpu_dai, substream, (void *)hext_stream); + + return hext_stream; +} + +static void hda_release_hext_stream(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai, + struct snd_pcm_substream *substream) +{ + struct hdac_ext_stream *hext_stream = hda_get_hext_stream(sdev, cpu_dai, substream); + + snd_soc_dai_set_dma_data(cpu_dai, substream, NULL); + snd_hdac_ext_stream_release(hext_stream, HDAC_EXT_STREAM_TYPE_LINK); +} + +static const struct hda_dai_widget_dma_ops hda_dma_ops = { + .get_hext_stream = hda_get_hext_stream, + .assign_hext_stream = hda_assign_hext_stream, + .release_hext_stream = hda_release_hext_stream, +}; + +#endif + +const struct hda_dai_widget_dma_ops * +hda_select_dai_widget_ops(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) +{ +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) + struct snd_sof_dai *sdai = swidget->private; + + switch (sdev->pdata->ipc_type) { + case SOF_IPC: + { + struct sof_dai_private_data *private = sdai->private; + + if (private->dai_config->type == SOF_DAI_INTEL_HDA) + return &hda_dma_ops; + break; + } + case SOF_INTEL_IPC4: + { + struct sof_ipc4_copier *ipc4_copier = sdai->private; + + if (ipc4_copier->dai_type == SOF_DAI_INTEL_HDA) + return &hda_dma_ops; + break; + } + default: + break; + } +#endif + return NULL; +} diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index 49f25e55b15d..963c40d8a10b 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -29,101 +29,30 @@ MODULE_PARM_DESC(sof_use_tplg_nhlt, "SOF topology nhlt override"); #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) -/* - * This function checks if the host dma channel corresponding - * to the link DMA stream_tag argument is assigned to one - * of the FEs connected to the BE DAI. - */ -static bool hda_check_fes(struct snd_soc_pcm_runtime *rtd, - int dir, int stream_tag) +static const struct hda_dai_widget_dma_ops * +hda_dai_get_ops(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { - struct snd_pcm_substream *fe_substream; - struct hdac_stream *fe_hstream; - struct snd_soc_dpcm *dpcm; + struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream); + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(cpu_dai->component); + struct snd_sof_widget *swidget = w->dobj.private; + struct snd_sof_dai *sdai = swidget->private; - for_each_dpcm_fe(rtd, dir, dpcm) { - fe_substream = snd_soc_dpcm_get_substream(dpcm->fe, dir); - fe_hstream = fe_substream->runtime->private_data; - if (fe_hstream->stream_tag == stream_tag) - return true; + /* select and set the DAI widget ops if not set already */ + if (!sdai->platform_private) { + const struct hda_dai_widget_dma_ops *ops = + hda_select_dai_widget_ops(sdev, swidget); + + if (!ops) + return NULL; + + /* check if mandatory ops are set */ + if (!ops || !ops->get_hext_stream) + return NULL; + + sdai->platform_private = ops; } - return false; -} - -static struct hdac_ext_stream * -hda_link_stream_assign(struct hdac_bus *bus, - struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); - struct sof_intel_hda_stream *hda_stream; - const struct sof_intel_dsp_desc *chip; - struct snd_sof_dev *sdev; - struct hdac_ext_stream *res = NULL; - struct hdac_stream *hstream = NULL; - - int stream_dir = substream->stream; - - if (!bus->ppcap) { - dev_err(bus->dev, "stream type not supported\n"); - return NULL; - } - - spin_lock_irq(&bus->reg_lock); - list_for_each_entry(hstream, &bus->stream_list, list) { - struct hdac_ext_stream *hext_stream = - stream_to_hdac_ext_stream(hstream); - if (hstream->direction != substream->stream) - continue; - - hda_stream = hstream_to_sof_hda_stream(hext_stream); - sdev = hda_stream->sdev; - chip = get_chip_info(sdev->pdata); - - /* check if link is available */ - if (!hext_stream->link_locked) { - /* - * choose the first available link for platforms that do not have the - * PROCEN_FMT_QUIRK set. - */ - if (!(chip->quirks & SOF_INTEL_PROCEN_FMT_QUIRK)) { - res = hext_stream; - break; - } - - if (hstream->opened) { - /* - * check if the stream tag matches the stream - * tag of one of the connected FEs - */ - if (hda_check_fes(rtd, stream_dir, - hstream->stream_tag)) { - res = hext_stream; - break; - } - } else { - res = hext_stream; - - /* - * This must be a hostless stream. - * So reserve the host DMA channel. - */ - hda_stream->host_reserved = 1; - break; - } - } - } - - if (res) { - /* Make sure that host and link DMA is decoupled. */ - snd_hdac_ext_stream_decouple_locked(bus, res, true); - - res->link_locked = 1; - res->link_substream = substream; - } - spin_unlock_irq(&bus->reg_lock); - - return res; + return sdai->platform_private; } static int hda_link_dma_cleanup(struct snd_pcm_substream *substream, @@ -131,6 +60,8 @@ static int hda_link_dma_cleanup(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai, struct snd_soc_dai *codec_dai) { + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(cpu_dai->component); + const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, cpu_dai); struct hdac_stream *hstream = &hext_stream->hstream; struct hdac_bus *bus = hstream->bus; struct sof_intel_hda_stream *hda_stream; @@ -145,8 +76,10 @@ static int hda_link_dma_cleanup(struct snd_pcm_substream *substream, stream_tag = hdac_stream(hext_stream)->stream_tag; snd_hdac_ext_bus_link_clear_stream_id(hlink, stream_tag); } - snd_soc_dai_set_dma_data(cpu_dai, substream, NULL); - snd_hdac_ext_stream_release(hext_stream, HDAC_EXT_STREAM_TYPE_LINK); + + if (ops->release_hext_stream) + ops->release_hext_stream(sdev, cpu_dai, substream); + hext_stream->link_prepared = 0; /* free the host DMA channel reserved by hostless streams */ @@ -159,6 +92,7 @@ static int hda_link_dma_cleanup(struct snd_pcm_substream *substream, static int hda_link_dma_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *cpu_dai) { + const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, cpu_dai); struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct hdac_ext_stream *hext_stream; @@ -168,7 +102,7 @@ static int hda_link_dma_hw_params(struct snd_pcm_substream *substream, struct hdac_bus *bus; unsigned int format_val; unsigned int link_bps; - unsigned char stream_tag; + int stream_tag; sdev = snd_soc_component_get_drvdata(cpu_dai->component); bus = sof_to_bus(sdev); @@ -177,15 +111,16 @@ static int hda_link_dma_hw_params(struct snd_pcm_substream *substream, if (!hlink) return -EINVAL; - hext_stream = snd_soc_dai_get_dma_data(cpu_dai, substream); - if (!hext_stream) { - hext_stream = hda_link_stream_assign(bus, substream); - if (!hext_stream) - return -EBUSY; + hext_stream = ops->get_hext_stream(sdev, cpu_dai, substream); - snd_soc_dai_set_dma_data(cpu_dai, substream, (void *)hext_stream); + if (!hext_stream) { + if (ops->assign_hext_stream) + hext_stream = ops->assign_hext_stream(sdev, cpu_dai, substream); } + if (!hext_stream) + return -EBUSY; + hstream = &hext_stream->hstream; stream_tag = hstream->stream_tag; @@ -226,11 +161,15 @@ static int hda_link_dma_prepare(struct snd_pcm_substream *substream, struct snd_ static int hda_link_dma_trigger(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai, int cmd) { + const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, cpu_dai); struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(cpu_dai->component); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); - struct hdac_ext_stream *hext_stream = snd_soc_dai_get_dma_data(cpu_dai, substream); + struct hdac_ext_stream *hext_stream; int ret; + hext_stream = ops->get_hext_stream(sdev, cpu_dai, substream); + if (!hext_stream) return 0; @@ -259,11 +198,18 @@ static int hda_link_dma_trigger(struct snd_pcm_substream *substream, struct snd_ static int hda_link_dma_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(cpu_dai->component); + const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, cpu_dai); struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct hdac_ext_stream *hext_stream; - hext_stream = snd_soc_dai_get_dma_data(cpu_dai, substream); + if (!ops) { + dev_err(sdev->dev, "DAI widget ops not set\n"); + return -EINVAL; + } + + hext_stream = ops->get_hext_stream(sdev, cpu_dai, substream); if (!hext_stream) return 0; @@ -288,18 +234,18 @@ static int hda_dai_hw_params_update(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { + struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(dai, substream->stream); + const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, dai); + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(dai->component); struct hdac_ext_stream *hext_stream; - struct snd_soc_dapm_widget *w; int stream_tag; - hext_stream = snd_soc_dai_get_dma_data(dai, substream); + hext_stream = ops->get_hext_stream(sdev, dai, substream); if (!hext_stream) return -EINVAL; stream_tag = hdac_stream(hext_stream)->stream_tag; - w = snd_soc_dai_get_widget(dai, substream->stream); - /* set up the DAI widget and send the DAI_CONFIG with the new tag */ return hda_dai_widget_update(w, stream_tag - 1, true); } @@ -308,10 +254,17 @@ static int hda_dai_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct hdac_ext_stream *hext_stream = - snd_soc_dai_get_dma_data(dai, substream); + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(dai->component); + const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, dai); + struct hdac_ext_stream *hext_stream; int ret; + if (!ops) { + dev_err(sdev->dev, "DAI widget ops not set\n"); + return -EINVAL; + } + + hext_stream = ops->get_hext_stream(sdev, dai, substream); if (hext_stream && hext_stream->link_prepared) return 0; @@ -343,13 +296,14 @@ static int hda_dai_config_pause_push_ipc(struct snd_soc_dapm_widget *w) static int hda_dai_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct hdac_ext_stream *hext_stream = - snd_soc_dai_get_dma_data(dai, substream); struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(dai->component); + const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, dai); struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct hdac_ext_stream *hext_stream; int stream = substream->stream; int ret; + hext_stream = ops->get_hext_stream(sdev, dai, substream); if (hext_stream && hext_stream->link_prepared) return 0; @@ -418,27 +372,27 @@ static int ipc3_hda_dai_trigger(struct snd_pcm_substream *substream, static int ipc4_hda_dai_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { - struct hdac_ext_stream *hext_stream = snd_soc_dai_get_dma_data(dai, substream); + struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(dai, substream->stream); struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(dai->component); - struct snd_sof_widget *pipe_widget; - struct sof_ipc4_pipeline *pipeline; + const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, dai); + struct snd_sof_widget *swidget = w->dobj.private; + struct hdac_ext_stream *hext_stream; + struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget; + struct sof_ipc4_pipeline *pipeline = pipe_widget->private; struct snd_soc_pcm_runtime *rtd; - struct snd_sof_widget *swidget; - struct snd_soc_dapm_widget *w; struct snd_soc_dai *codec_dai; int ret; dev_dbg(dai->dev, "cmd=%d dai %s direction %d\n", cmd, dai->name, substream->stream); + hext_stream = ops->get_hext_stream(sdev, dai, substream); + if (!hext_stream) + return -EINVAL; + rtd = asoc_substream_to_rtd(substream); codec_dai = asoc_rtd_to_codec(rtd, 0); - w = snd_soc_dai_get_widget(dai, substream->stream); - swidget = w->dobj.private; - pipe_widget = swidget->spipe->pipe_widget; - pipeline = pipe_widget->private; - switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index c6243827f8d0..e0469f86fa63 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -959,4 +959,8 @@ struct hda_dai_widget_dma_ops { int (*post_trigger)(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai, struct snd_pcm_substream *substream, int cmd); }; + +const struct hda_dai_widget_dma_ops * +hda_select_dai_widget_ops(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget); + #endif From e2d6569aba39f4b98da8e56999a19dc901188e5e Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 7 Mar 2023 16:04:30 +0200 Subject: [PATCH 220/778] ASoC: SOF: Intel: hda-dai: Add setup_hext_stream/reset_hext_stream DMA ops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Define and use the setup_hext_stream/reset_hext_stream DMA ops during link hw_params and cleanup. Signed-off-by: Ranjani Sridharan Reviewed-by: Bard Liao Reviewed-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Rander Wang Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307140435.2808-10-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai-ops.c | 13 +++++++++++++ sound/soc/sof/intel/hda-dai.c | 6 ++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/intel/hda-dai-ops.c b/sound/soc/sof/intel/hda-dai-ops.c index 9dfcafeab9e4..57db589906db 100644 --- a/sound/soc/sof/intel/hda-dai-ops.c +++ b/sound/soc/sof/intel/hda-dai-ops.c @@ -144,10 +144,23 @@ static void hda_release_hext_stream(struct snd_sof_dev *sdev, struct snd_soc_dai snd_hdac_ext_stream_release(hext_stream, HDAC_EXT_STREAM_TYPE_LINK); } +static void hda_setup_hext_stream(struct snd_sof_dev *sdev, struct hdac_ext_stream *hext_stream, + unsigned int format_val) +{ + snd_hdac_ext_stream_setup(hext_stream, format_val); +} + +static void hda_reset_hext_stream(struct snd_sof_dev *sdev, struct hdac_ext_stream *hext_stream) +{ + snd_hdac_ext_stream_reset(hext_stream); +} + static const struct hda_dai_widget_dma_ops hda_dma_ops = { .get_hext_stream = hda_get_hext_stream, .assign_hext_stream = hda_assign_hext_stream, .release_hext_stream = hda_release_hext_stream, + .setup_hext_stream = hda_setup_hext_stream, + .reset_hext_stream = hda_reset_hext_stream, }; #endif diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index 963c40d8a10b..9616cdba79b6 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -135,7 +135,8 @@ static int hda_link_dma_hw_params(struct snd_pcm_substream *substream, else link_bps = codec_dai->driver->capture.sig_bits; - snd_hdac_ext_stream_reset(hext_stream); + if (ops->reset_hext_stream) + ops->reset_hext_stream(sdev, hext_stream); format_val = snd_hdac_calc_stream_format(params_rate(params), params_channels(params), params_format(params), link_bps, 0); @@ -143,7 +144,8 @@ static int hda_link_dma_hw_params(struct snd_pcm_substream *substream, dev_dbg(bus->dev, "format_val=%d, rate=%d, ch=%d, format=%d\n", format_val, params_rate(params), params_channels(params), params_format(params)); - snd_hdac_ext_stream_setup(hext_stream, format_val); + if (ops->setup_hext_stream) + ops->setup_hext_stream(sdev, hext_stream, format_val); hext_stream->link_prepared = 1; From e6ffb0d5eda751371d030bb8ae324493b2d1abc2 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 7 Mar 2023 16:04:31 +0200 Subject: [PATCH 221/778] ASoC: SOF: Intel: hda-dai: Use the topology IPC dai_config op MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the topology IPC dai_config to update the dai_config for HDA DAI widgets. Signed-off-by: Ranjani Sridharan Reviewed-by: Bard Liao Reviewed-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Rander Wang Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307140435.2808-11-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai.c | 86 +++++++++++++++++------------------ 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index 9616cdba79b6..b726c0225110 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -29,6 +29,27 @@ MODULE_PARM_DESC(sof_use_tplg_nhlt, "SOF topology nhlt override"); #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) +static int hda_dai_config(struct snd_soc_dapm_widget *w, unsigned int flags, + struct snd_sof_dai_config_data *data) +{ + struct snd_sof_widget *swidget = w->dobj.private; + struct snd_soc_component *component = swidget->scomp; + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); + const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); + int ret; + + if (tplg_ops && tplg_ops->dai_config) { + ret = tplg_ops->dai_config(sdev, swidget, flags, data); + if (ret < 0) { + dev_err(sdev->dev, "DAI config with flags %x failed for widget %s\n", + flags, w->name); + return ret; + } + } + + return 0; +} + static const struct hda_dai_widget_dma_ops * hda_dai_get_ops(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { @@ -232,33 +253,16 @@ static int hda_dai_widget_update(struct snd_soc_dapm_widget *w, return hda_ctrl_dai_widget_free(w, SOF_DAI_CONFIG_FLAGS_NONE, &data); } -static int hda_dai_hw_params_update(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(dai, substream->stream); - const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, dai); - struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(dai->component); - struct hdac_ext_stream *hext_stream; - int stream_tag; - - hext_stream = ops->get_hext_stream(sdev, dai, substream); - if (!hext_stream) - return -EINVAL; - - stream_tag = hdac_stream(hext_stream)->stream_tag; - - /* set up the DAI widget and send the DAI_CONFIG with the new tag */ - return hda_dai_widget_update(w, stream_tag - 1, true); -} - static int hda_dai_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { + struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(dai, substream->stream); struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(dai->component); const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, dai); struct hdac_ext_stream *hext_stream; + struct snd_sof_dai_config_data data = { 0 }; + unsigned int flags = SOF_DAI_CONFIG_FLAGS_HW_PARAMS; int ret; if (!ops) { @@ -274,35 +278,22 @@ static int hda_dai_hw_params(struct snd_pcm_substream *substream, if (ret < 0) return ret; - return hda_dai_hw_params_update(substream, params, dai); -} + hext_stream = ops->get_hext_stream(sdev, dai, substream); + flags |= SOF_DAI_CONFIG_FLAGS_2_STEP_STOP << SOF_DAI_CONFIG_FLAGS_QUIRK_SHIFT; + data.dai_data = hdac_stream(hext_stream)->stream_tag - 1; -static int hda_dai_config_pause_push_ipc(struct snd_soc_dapm_widget *w) -{ - struct snd_sof_widget *swidget = w->dobj.private; - struct snd_soc_component *component = swidget->scomp; - struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); - const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; - int ret = 0; - - if (tplg_ops->dai_config) { - ret = tplg_ops->dai_config(sdev, swidget, SOF_DAI_CONFIG_FLAGS_PAUSE, NULL); - if (ret < 0) - dev_err(sdev->dev, "%s: DAI config failed for widget %s\n", __func__, - w->name); - } - - return ret; + return hda_dai_config(w, flags, &data); } static int hda_dai_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { + struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(dai, substream->stream); struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(dai->component); const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, dai); - struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct hdac_ext_stream *hext_stream; - int stream = substream->stream; + struct snd_sof_dai_config_data data = { 0 }; + unsigned int flags = SOF_DAI_CONFIG_FLAGS_HW_PARAMS; int ret; hext_stream = ops->get_hext_stream(sdev, dai, substream); @@ -315,7 +306,12 @@ static int hda_dai_prepare(struct snd_pcm_substream *substream, struct snd_soc_d if (ret < 0) return ret; - return hda_dai_hw_params_update(substream, &rtd->dpcm[stream].hw_params, dai); + hext_stream = ops->get_hext_stream(sdev, dai, substream); + + flags |= SOF_DAI_CONFIG_FLAGS_2_STEP_STOP << SOF_DAI_CONFIG_FLAGS_QUIRK_SHIFT; + data.dai_data = hdac_stream(hext_stream)->stream_tag - 1; + + return hda_dai_config(w, flags, &data); } static int hda_dai_hw_free_ipc(int stream, /* direction */ @@ -356,7 +352,7 @@ static int ipc3_hda_dai_trigger(struct snd_pcm_substream *substream, break; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - ret = hda_dai_config_pause_push_ipc(w); + ret = hda_dai_config(w, SOF_DAI_CONFIG_FLAGS_PAUSE, NULL); if (ret < 0) return ret; break; @@ -462,13 +458,17 @@ static int ipc4_hda_dai_trigger(struct snd_pcm_substream *substream, static int hda_dai_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { + struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(dai, substream->stream); + struct snd_sof_dai_config_data data = { 0 }; int ret; ret = hda_link_dma_hw_free(substream, dai); if (ret < 0) return ret; - return hda_dai_hw_free_ipc(substream->stream, dai); + data.dai_data = DMA_CHAN_INVALID; + + return hda_dai_config(w, SOF_DAI_CONFIG_FLAGS_HW_FREE, &data); } static const struct snd_soc_dai_ops ipc3_hda_dai_ops = { From 4b2ee4cd7103607b303a079c0469c06694be87e9 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 7 Mar 2023 16:04:32 +0200 Subject: [PATCH 222/778] ASoC: SOF: Intel: hda-dai: Define DAI widget DMA trigger ops for IPC4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Define and use the SOF widget's DMA pre_trigger/trigger/post_trigger ops in ipc4_hda_dai_trigger(). Signed-off-by: Ranjani Sridharan Reviewed-by: Bard Liao Reviewed-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Rander Wang Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307140435.2808-12-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai-ops.c | 128 +++++++++++++++++++++++++++++- sound/soc/sof/intel/hda-dai.c | 70 +++++----------- 2 files changed, 143 insertions(+), 55 deletions(-) diff --git a/sound/soc/sof/intel/hda-dai-ops.c b/sound/soc/sof/intel/hda-dai-ops.c index 57db589906db..992c31772593 100644 --- a/sound/soc/sof/intel/hda-dai-ops.c +++ b/sound/soc/sof/intel/hda-dai-ops.c @@ -155,7 +155,129 @@ static void hda_reset_hext_stream(struct snd_sof_dev *sdev, struct hdac_ext_stre snd_hdac_ext_stream_reset(hext_stream); } -static const struct hda_dai_widget_dma_ops hda_dma_ops = { +static int hda_ipc4_pre_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai, + struct snd_pcm_substream *substream, int cmd) +{ + struct snd_sof_widget *pipe_widget; + struct sof_ipc4_pipeline *pipeline; + struct snd_sof_widget *swidget; + struct snd_soc_dapm_widget *w; + int ret; + + w = snd_soc_dai_get_widget(cpu_dai, substream->stream); + swidget = w->dobj.private; + pipe_widget = swidget->spipe->pipe_widget; + pipeline = pipe_widget->private; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + break; + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_STOP: + ret = sof_ipc4_set_pipeline_state(sdev, pipe_widget->instance_id, + SOF_IPC4_PIPE_PAUSED); + if (ret < 0) + return ret; + + pipeline->state = SOF_IPC4_PIPE_PAUSED; + break; + default: + dev_err(sdev->dev, "unknown trigger command %d\n", cmd); + return -EINVAL; + } + + return 0; +} + +static int hda_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai, + struct snd_pcm_substream *substream, int cmd) +{ + struct hdac_ext_stream *hext_stream = snd_soc_dai_get_dma_data(cpu_dai, substream); + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + snd_hdac_ext_stream_start(hext_stream); + break; + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + snd_hdac_ext_stream_clear(hext_stream); + break; + default: + dev_err(sdev->dev, "unknown trigger command %d\n", cmd); + return -EINVAL; + } + + return 0; +} + +static int hda_ipc4_post_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai, + struct snd_pcm_substream *substream, int cmd) +{ + struct snd_sof_widget *pipe_widget; + struct sof_ipc4_pipeline *pipeline; + struct snd_sof_widget *swidget; + struct snd_soc_dapm_widget *w; + int ret; + + w = snd_soc_dai_get_widget(cpu_dai, substream->stream); + swidget = w->dobj.private; + pipe_widget = swidget->spipe->pipe_widget; + pipeline = pipe_widget->private; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + if (pipeline->state != SOF_IPC4_PIPE_PAUSED) { + ret = sof_ipc4_set_pipeline_state(sdev, pipe_widget->instance_id, + SOF_IPC4_PIPE_PAUSED); + if (ret < 0) + return ret; + pipeline->state = SOF_IPC4_PIPE_PAUSED; + } + + ret = sof_ipc4_set_pipeline_state(sdev, pipe_widget->instance_id, + SOF_IPC4_PIPE_RUNNING); + if (ret < 0) + return ret; + pipeline->state = SOF_IPC4_PIPE_RUNNING; + break; + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_STOP: + { + ret = sof_ipc4_set_pipeline_state(sdev, pipe_widget->instance_id, + SOF_IPC4_PIPE_RESET); + if (ret < 0) + return ret; + + pipeline->state = SOF_IPC4_PIPE_RESET; + break; + } + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + break; + default: + dev_err(sdev->dev, "unknown trigger command %d\n", cmd); + return -EINVAL; + } + + return 0; +} + +static const struct hda_dai_widget_dma_ops hda_ipc4_dma_ops = { + .get_hext_stream = hda_get_hext_stream, + .assign_hext_stream = hda_assign_hext_stream, + .release_hext_stream = hda_release_hext_stream, + .setup_hext_stream = hda_setup_hext_stream, + .reset_hext_stream = hda_reset_hext_stream, + .pre_trigger = hda_ipc4_pre_trigger, + .trigger = hda_trigger, + .post_trigger = hda_ipc4_post_trigger +}; + +static const struct hda_dai_widget_dma_ops hda_ipc3_dma_ops = { .get_hext_stream = hda_get_hext_stream, .assign_hext_stream = hda_assign_hext_stream, .release_hext_stream = hda_release_hext_stream, @@ -177,7 +299,7 @@ hda_select_dai_widget_ops(struct snd_sof_dev *sdev, struct snd_sof_widget *swidg struct sof_dai_private_data *private = sdai->private; if (private->dai_config->type == SOF_DAI_INTEL_HDA) - return &hda_dma_ops; + return &hda_ipc3_dma_ops; break; } case SOF_INTEL_IPC4: @@ -185,7 +307,7 @@ hda_select_dai_widget_ops(struct snd_sof_dev *sdev, struct snd_sof_widget *swidg struct sof_ipc4_copier *ipc4_copier = sdai->private; if (ipc4_copier->dai_type == SOF_DAI_INTEL_HDA) - return &hda_dma_ops; + return &hda_ipc4_dma_ops; break; } default: diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index b726c0225110..60c65ce994a0 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -370,13 +370,9 @@ static int ipc3_hda_dai_trigger(struct snd_pcm_substream *substream, static int ipc4_hda_dai_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { - struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(dai, substream->stream); struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(dai->component); const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, dai); - struct snd_sof_widget *swidget = w->dobj.private; struct hdac_ext_stream *hext_stream; - struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget; - struct sof_ipc4_pipeline *pipeline = pipe_widget->private; struct snd_soc_pcm_runtime *rtd; struct snd_soc_dai *codec_dai; int ret; @@ -391,65 +387,35 @@ static int ipc4_hda_dai_trigger(struct snd_pcm_substream *substream, rtd = asoc_substream_to_rtd(substream); codec_dai = asoc_rtd_to_codec(rtd, 0); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - snd_hdac_ext_stream_start(hext_stream); - if (pipeline->state != SOF_IPC4_PIPE_PAUSED) { - ret = sof_ipc4_set_pipeline_state(sdev, pipe_widget->instance_id, - SOF_IPC4_PIPE_PAUSED); - if (ret < 0) - return ret; - pipeline->state = SOF_IPC4_PIPE_PAUSED; - } - - ret = sof_ipc4_set_pipeline_state(sdev, pipe_widget->instance_id, - SOF_IPC4_PIPE_RUNNING); + if (ops->pre_trigger) { + ret = ops->pre_trigger(sdev, dai, substream, cmd); if (ret < 0) return ret; - pipeline->state = SOF_IPC4_PIPE_RUNNING; - break; + } + + if (ops->trigger) { + ret = ops->trigger(sdev, dai, substream, cmd); + if (ret < 0) + return ret; + } + + if (ops->post_trigger) { + ret = ops->post_trigger(sdev, dai, substream, cmd); + if (ret < 0) + return ret; + } + + switch (cmd) { case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_STOP: - { - ret = sof_ipc4_set_pipeline_state(sdev, pipe_widget->instance_id, - SOF_IPC4_PIPE_PAUSED); - if (ret < 0) - return ret; - - pipeline->state = SOF_IPC4_PIPE_PAUSED; - - snd_hdac_ext_stream_clear(hext_stream); - - ret = sof_ipc4_set_pipeline_state(sdev, pipe_widget->instance_id, - SOF_IPC4_PIPE_RESET); - if (ret < 0) - return ret; - - pipeline->state = SOF_IPC4_PIPE_RESET; - ret = hda_link_dma_cleanup(substream, hext_stream, dai, codec_dai); if (ret < 0) { dev_err(sdev->dev, "%s: failed to clean up link DMA\n", __func__); return ret; } break; - } - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - { - ret = sof_ipc4_set_pipeline_state(sdev, pipe_widget->instance_id, - SOF_IPC4_PIPE_PAUSED); - if (ret < 0) - return ret; - - pipeline->state = SOF_IPC4_PIPE_PAUSED; - - snd_hdac_ext_stream_clear(hext_stream); - break; - } default: - dev_err(sdev->dev, "%s: unknown trigger command %d\n", __func__, cmd); - return -EINVAL; + break; } return 0; From 2b009fa0823c1510700fd17a0780ddd06a460fb4 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 7 Mar 2023 16:04:33 +0200 Subject: [PATCH 223/778] ASoC: SOF: Intel: hda: Unify DAI drv ops for IPC3 and IPC4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Define the post_trigger DMA op for IPC3 and unify the DAI driver ops for IPC3 and IPC4 for HDA DAI's. Also, use the post_trigger op to stop the paused streams properly in the hda_dai_suspend() function. This fixes the suspend while paused case for IPC4 because previously we weren't resetting the pipeline when suspending the system with some paused streams. Signed-off-by: Ranjani Sridharan Reviewed-by: Bard Liao Reviewed-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Rander Wang Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307140435.2808-13-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai-ops.c | 25 ++++ sound/soc/sof/intel/hda-dai.c | 183 ++++++------------------------ sound/soc/sof/intel/hda.h | 2 + 3 files changed, 62 insertions(+), 148 deletions(-) diff --git a/sound/soc/sof/intel/hda-dai-ops.c b/sound/soc/sof/intel/hda-dai-ops.c index 992c31772593..be109f33715f 100644 --- a/sound/soc/sof/intel/hda-dai-ops.c +++ b/sound/soc/sof/intel/hda-dai-ops.c @@ -277,12 +277,37 @@ static const struct hda_dai_widget_dma_ops hda_ipc4_dma_ops = { .post_trigger = hda_ipc4_post_trigger }; +static int hda_ipc3_post_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai, + struct snd_pcm_substream *substream, int cmd) +{ + struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream); + + switch (cmd) { + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_STOP: + { + struct snd_sof_dai_config_data data = { 0 }; + + data.dai_data = DMA_CHAN_INVALID; + return hda_dai_config(w, SOF_DAI_CONFIG_FLAGS_HW_FREE, &data); + } + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + return hda_dai_config(w, SOF_DAI_CONFIG_FLAGS_PAUSE, NULL); + default: + break; + } + + return 0; +} + static const struct hda_dai_widget_dma_ops hda_ipc3_dma_ops = { .get_hext_stream = hda_get_hext_stream, .assign_hext_stream = hda_assign_hext_stream, .release_hext_stream = hda_release_hext_stream, .setup_hext_stream = hda_setup_hext_stream, .reset_hext_stream = hda_reset_hext_stream, + .trigger = hda_trigger, + .post_trigger = hda_ipc3_post_trigger, }; #endif diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index 60c65ce994a0..4ac6148940ae 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -27,10 +27,8 @@ static bool hda_use_tplg_nhlt; module_param_named(sof_use_tplg_nhlt, hda_use_tplg_nhlt, bool, 0444); MODULE_PARM_DESC(sof_use_tplg_nhlt, "SOF topology nhlt override"); -#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) - -static int hda_dai_config(struct snd_soc_dapm_widget *w, unsigned int flags, - struct snd_sof_dai_config_data *data) +int hda_dai_config(struct snd_soc_dapm_widget *w, unsigned int flags, + struct snd_sof_dai_config_data *data) { struct snd_sof_widget *swidget = w->dobj.private; struct snd_soc_component *component = swidget->scomp; @@ -50,6 +48,8 @@ static int hda_dai_config(struct snd_soc_dapm_widget *w, unsigned int flags, return 0; } +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) + static const struct hda_dai_widget_dma_ops * hda_dai_get_ops(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { @@ -181,44 +181,6 @@ static int hda_link_dma_prepare(struct snd_pcm_substream *substream, struct snd_ return hda_link_dma_hw_params(substream, &rtd->dpcm[stream].hw_params, cpu_dai); } -static int hda_link_dma_trigger(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai, - int cmd) -{ - const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, cpu_dai); - struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); - struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(cpu_dai->component); - struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); - struct hdac_ext_stream *hext_stream; - int ret; - - hext_stream = ops->get_hext_stream(sdev, cpu_dai, substream); - - if (!hext_stream) - return 0; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - snd_hdac_ext_stream_start(hext_stream); - break; - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_STOP: - snd_hdac_ext_stream_clear(hext_stream); - ret = hda_link_dma_cleanup(substream, hext_stream, cpu_dai, codec_dai); - if (ret < 0) - return ret; - - break; - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - snd_hdac_ext_stream_clear(hext_stream); - - break; - default: - return -EINVAL; - } - return 0; -} - static int hda_link_dma_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(cpu_dai->component); @@ -239,20 +201,6 @@ static int hda_link_dma_hw_free(struct snd_pcm_substream *substream, struct snd_ return hda_link_dma_cleanup(substream, hext_stream, cpu_dai, codec_dai); } -static int hda_dai_widget_update(struct snd_soc_dapm_widget *w, - int channel, bool widget_setup) -{ - struct snd_sof_dai_config_data data; - - data.dai_data = channel; - - /* set up/free DAI widget and send DAI_CONFIG IPC */ - if (widget_setup) - return hda_ctrl_dai_widget_setup(w, SOF_DAI_CONFIG_FLAGS_2_STEP_STOP, &data); - - return hda_ctrl_dai_widget_free(w, SOF_DAI_CONFIG_FLAGS_NONE, &data); -} - static int hda_dai_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) @@ -314,61 +262,11 @@ static int hda_dai_prepare(struct snd_pcm_substream *substream, struct snd_soc_d return hda_dai_config(w, flags, &data); } -static int hda_dai_hw_free_ipc(int stream, /* direction */ - struct snd_soc_dai *dai) -{ - struct snd_soc_dapm_widget *w; - - w = snd_soc_dai_get_widget(dai, stream); - - /* free the link DMA channel in the FW and the DAI widget */ - return hda_dai_widget_update(w, DMA_CHAN_INVALID, false); -} - -static int ipc3_hda_dai_trigger(struct snd_pcm_substream *substream, - int cmd, struct snd_soc_dai *dai) -{ - struct snd_soc_dapm_widget *w; - int ret; - - dev_dbg(dai->dev, "cmd=%d dai %s direction %d\n", cmd, - dai->name, substream->stream); - - ret = hda_link_dma_trigger(substream, dai, cmd); - if (ret < 0) - return ret; - - w = snd_soc_dai_get_widget(dai, substream->stream); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_STOP: - /* - * free DAI widget during stop/suspend to keep widget use_count's balanced. - */ - ret = hda_dai_hw_free_ipc(substream->stream, dai); - if (ret < 0) - return ret; - - break; - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - ret = hda_dai_config(w, SOF_DAI_CONFIG_FLAGS_PAUSE, NULL); - if (ret < 0) - return ret; - break; - - default: - break; - } - return 0; -} - /* * In contrast to IPC3, the dai trigger in IPC4 mixes pipeline state changes * (over IPC channel) and DMA state change (direct host register changes). */ -static int ipc4_hda_dai_trigger(struct snd_pcm_substream *substream, - int cmd, struct snd_soc_dai *dai) +static int hda_dai_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(dai->component); const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, dai); @@ -437,10 +335,10 @@ static int hda_dai_hw_free(struct snd_pcm_substream *substream, return hda_dai_config(w, SOF_DAI_CONFIG_FLAGS_HW_FREE, &data); } -static const struct snd_soc_dai_ops ipc3_hda_dai_ops = { +static const struct snd_soc_dai_ops hda_dai_ops = { .hw_params = hda_dai_hw_params, .hw_free = hda_dai_hw_free, - .trigger = ipc3_hda_dai_trigger, + .trigger = hda_dai_trigger, .prepare = hda_dai_prepare, }; @@ -463,12 +361,22 @@ static int hda_dai_suspend(struct hdac_bus *bus) * explicitly during suspend. */ if (hext_stream->link_substream) { - struct snd_soc_dai *cpu_dai; + const struct hda_dai_widget_dma_ops *ops; + struct snd_sof_widget *swidget; + struct snd_soc_dapm_widget *w; struct snd_soc_dai *codec_dai; + struct snd_soc_dai *cpu_dai; + struct snd_sof_dev *sdev; + struct snd_sof_dai *sdai; rtd = asoc_substream_to_rtd(hext_stream->link_substream); cpu_dai = asoc_rtd_to_cpu(rtd, 0); codec_dai = asoc_rtd_to_codec(rtd, 0); + w = snd_soc_dai_get_widget(cpu_dai, hdac_stream(hext_stream)->direction); + swidget = w->dobj.private; + sdev = snd_soc_component_get_drvdata(swidget->scomp); + sdai = swidget->private; + ops = sdai->platform_private; ret = hda_link_dma_cleanup(hext_stream->link_substream, hext_stream, @@ -476,60 +384,39 @@ static int hda_dai_suspend(struct hdac_bus *bus) if (ret < 0) return ret; - /* for consistency with TRIGGER_SUSPEND we free DAI resources */ - ret = hda_dai_hw_free_ipc(hdac_stream(hext_stream)->direction, cpu_dai); - if (ret < 0) - return ret; + /* for consistency with TRIGGER_SUSPEND */ + if (ops->post_trigger) { + ret = ops->post_trigger(sdev, cpu_dai, + hext_stream->link_substream, + SNDRV_PCM_TRIGGER_SUSPEND); + if (ret < 0) + return ret; + } } } return 0; } -static const struct snd_soc_dai_ops ipc4_hda_dai_ops = { - .hw_params = hda_dai_hw_params, - .hw_free = hda_dai_hw_free, - .trigger = ipc4_hda_dai_trigger, - .prepare = hda_dai_prepare, -}; - #endif void hda_set_dai_drv_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *ops) { int i; - switch (sdev->pdata->ipc_type) { - case SOF_IPC: - for (i = 0; i < ops->num_drv; i++) { + for (i = 0; i < ops->num_drv; i++) { #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) - if (strstr(ops->drv[i].name, "iDisp") || - strstr(ops->drv[i].name, "Analog") || - strstr(ops->drv[i].name, "Digital")) - ops->drv[i].ops = &ipc3_hda_dai_ops; + if (strstr(ops->drv[i].name, "iDisp") || + strstr(ops->drv[i].name, "Analog") || + strstr(ops->drv[i].name, "Digital")) + ops->drv[i].ops = &hda_dai_ops; #endif - } - break; - case SOF_INTEL_IPC4: - { + } + + if (sdev->pdata->ipc_type == SOF_INTEL_IPC4 && !hda_use_tplg_nhlt) { struct sof_ipc4_fw_data *ipc4_data = sdev->private; - for (i = 0; i < ops->num_drv; i++) { -#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) - if (strstr(ops->drv[i].name, "iDisp") || - strstr(ops->drv[i].name, "Analog") || - strstr(ops->drv[i].name, "Digital")) - ops->drv[i].ops = &ipc4_hda_dai_ops; -#endif - } - - if (!hda_use_tplg_nhlt) - ipc4_data->nhlt = intel_nhlt_init(sdev->dev); - - break; - } - default: - break; + ipc4_data->nhlt = intel_nhlt_init(sdev->dev); } } diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index e0469f86fa63..815f73d3acd2 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -962,5 +962,7 @@ struct hda_dai_widget_dma_ops { const struct hda_dai_widget_dma_ops * hda_select_dai_widget_ops(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget); +int hda_dai_config(struct snd_soc_dapm_widget *w, unsigned int flags, + struct snd_sof_dai_config_data *data); #endif From a492da0ce6450d6fdea49ec89006d7692c0c1382 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 7 Mar 2023 16:04:34 +0200 Subject: [PATCH 224/778] ASoC: SOF: Intel: hda: Remove hda_ctrl_dai_widget_setup/free() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove these functions and reuse hda_dai_config(). Signed-off-by: Ranjani Sridharan Reviewed-by: Bard Liao Reviewed-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Rander Wang Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307140435.2808-14-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda.c | 78 +++------------------------------------ sound/soc/sof/intel/hda.h | 4 -- 2 files changed, 6 insertions(+), 76 deletions(-) diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 81c697e20108..890993b2f14b 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -44,70 +44,6 @@ #define EXCEPT_MAX_HDR_SIZE 0x400 #define HDA_EXT_ROM_STATUS_SIZE 8 -int hda_ctrl_dai_widget_setup(struct snd_soc_dapm_widget *w, unsigned int quirk_flags, - struct snd_sof_dai_config_data *data) -{ - struct snd_sof_widget *swidget = w->dobj.private; - struct snd_soc_component *component = swidget->scomp; - struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); - const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; - struct snd_sof_dai *sof_dai = swidget->private; - int ret; - - if (!sof_dai) { - dev_err(sdev->dev, "%s: No DAI for DAI widget %s\n", __func__, w->name); - return -EINVAL; - } - - if (tplg_ops->dai_config) { - unsigned int flags; - - /* set HW_PARAMS flag along with quirks */ - flags = SOF_DAI_CONFIG_FLAGS_HW_PARAMS | - quirk_flags << SOF_DAI_CONFIG_FLAGS_QUIRK_SHIFT; - - ret = tplg_ops->dai_config(sdev, swidget, flags, data); - if (ret < 0) { - dev_err(sdev->dev, "%s: DAI config failed for widget %s\n", __func__, - w->name); - return ret; - } - } - - return 0; -} - -int hda_ctrl_dai_widget_free(struct snd_soc_dapm_widget *w, unsigned int quirk_flags, - struct snd_sof_dai_config_data *data) -{ - struct snd_sof_widget *swidget = w->dobj.private; - struct snd_soc_component *component = swidget->scomp; - struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); - const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; - struct snd_sof_dai *sof_dai = swidget->private; - - if (!sof_dai) { - dev_err(sdev->dev, "%s: No DAI for BE DAI widget %s\n", __func__, w->name); - return -EINVAL; - } - - if (tplg_ops->dai_config) { - unsigned int flags; - int ret; - - /* set HW_FREE flag along with any quirks */ - flags = SOF_DAI_CONFIG_FLAGS_HW_FREE | - quirk_flags << SOF_DAI_CONFIG_FLAGS_QUIRK_SHIFT; - - ret = tplg_ops->dai_config(sdev, swidget, flags, data); - if (ret < 0) - dev_err(sdev->dev, "%s: DAI config failed for widget '%s'\n", __func__, - w->name); - } - - return 0; -} - #if IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE) /* @@ -124,30 +60,28 @@ static int sdw_params_stream(struct device *dev, struct sdw_intel_stream_params_data *params_data) { struct snd_soc_dai *d = params_data->dai; - struct snd_sof_dai_config_data data; - struct snd_soc_dapm_widget *w; + struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(d, params_data->stream); + struct snd_sof_dai_config_data data = { 0 }; - w = snd_soc_dai_get_widget(d, params_data->stream); data.dai_index = (params_data->link_id << 8) | d->id; data.dai_data = params_data->alh_stream_id; - return hda_ctrl_dai_widget_setup(w, SOF_DAI_CONFIG_FLAGS_NONE, &data); + return hda_dai_config(w, SOF_DAI_CONFIG_FLAGS_HW_PARAMS, &data); } static int sdw_free_stream(struct device *dev, struct sdw_intel_stream_free_data *free_data) { struct snd_soc_dai *d = free_data->dai; - struct snd_sof_dai_config_data data; - struct snd_soc_dapm_widget *w; + struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(d, free_data->stream); + struct snd_sof_dai_config_data data = { 0 }; - w = snd_soc_dai_get_widget(d, free_data->stream); data.dai_index = (free_data->link_id << 8) | d->id; /* send invalid stream_id */ data.dai_data = 0xFFFF; - return hda_ctrl_dai_widget_free(w, SOF_DAI_CONFIG_FLAGS_NONE, &data); + return hda_dai_config(w, SOF_DAI_CONFIG_FLAGS_HW_FREE, &data); } struct sdw_intel_ops sdw_callback = { diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 815f73d3acd2..2a43bfc14583 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -896,10 +896,6 @@ int hda_pci_intel_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) struct snd_sof_dai; struct sof_ipc_dai_config; -int hda_ctrl_dai_widget_setup(struct snd_soc_dapm_widget *w, unsigned int quirk_flags, - struct snd_sof_dai_config_data *data); -int hda_ctrl_dai_widget_free(struct snd_soc_dapm_widget *w, unsigned int quirk_flags, - struct snd_sof_dai_config_data *data); #define SOF_HDA_POSITION_QUIRK_USE_SKYLAKE_LEGACY (0) /* previous implementation */ #define SOF_HDA_POSITION_QUIRK_USE_DPIB_REGISTERS (1) /* recommended if VC0 only */ From 8c29e78b8ecbec208bdd6d8b385ada71c1e730cd Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 7 Mar 2023 16:04:35 +0200 Subject: [PATCH 225/778] ASoC: SOF: Intel: hda: remove redundant DAI config during hw_free The DAI widget is freed during FE DAI hw_free and therefore the DAI config during BE DAI hw_free is redundant. Signed-off-by: Ranjani Sridharan Reviewed-by: Bard Liao Reviewed-by: Rander Wang Reviewed-by: Pierre-Louis Bossart Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307140435.2808-15-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai.c | 18 +----------------- sound/soc/sof/intel/hda.c | 16 ---------------- 2 files changed, 1 insertion(+), 33 deletions(-) diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index 4ac6148940ae..9637f0f44b01 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -181,7 +181,7 @@ static int hda_link_dma_prepare(struct snd_pcm_substream *substream, struct snd_ return hda_link_dma_hw_params(substream, &rtd->dpcm[stream].hw_params, cpu_dai); } -static int hda_link_dma_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) +static int hda_dai_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(cpu_dai->component); const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, cpu_dai); @@ -319,22 +319,6 @@ static int hda_dai_trigger(struct snd_pcm_substream *substream, int cmd, struct return 0; } -static int hda_dai_hw_free(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(dai, substream->stream); - struct snd_sof_dai_config_data data = { 0 }; - int ret; - - ret = hda_link_dma_hw_free(substream, dai); - if (ret < 0) - return ret; - - data.dai_data = DMA_CHAN_INVALID; - - return hda_dai_config(w, SOF_DAI_CONFIG_FLAGS_HW_FREE, &data); -} - static const struct snd_soc_dai_ops hda_dai_ops = { .hw_params = hda_dai_hw_params, .hw_free = hda_dai_hw_free, diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 890993b2f14b..65389c7278e2 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -69,24 +69,8 @@ static int sdw_params_stream(struct device *dev, return hda_dai_config(w, SOF_DAI_CONFIG_FLAGS_HW_PARAMS, &data); } -static int sdw_free_stream(struct device *dev, - struct sdw_intel_stream_free_data *free_data) -{ - struct snd_soc_dai *d = free_data->dai; - struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(d, free_data->stream); - struct snd_sof_dai_config_data data = { 0 }; - - data.dai_index = (free_data->link_id << 8) | d->id; - - /* send invalid stream_id */ - data.dai_data = 0xFFFF; - - return hda_dai_config(w, SOF_DAI_CONFIG_FLAGS_HW_FREE, &data); -} - struct sdw_intel_ops sdw_callback = { .params_stream = sdw_params_stream, - .free_stream = sdw_free_stream, }; void hda_common_enable_sdw_irq(struct snd_sof_dev *sdev, bool enable) From 63355b9884b3d1677de6bd1517cd2b8a9bf53978 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 7 Mar 2023 12:16:18 -0800 Subject: [PATCH 226/778] cpumask: be more careful with 'cpumask_setall()' Commit 596ff4a09b89 ("cpumask: re-introduce constant-sized cpumask optimizations") changed cpumask_setall() to use "bitmap_set()" instead of "bitmap_fill()", because bitmap_fill() would explicitly set all the bits of a constant sized small bitmap, and that's exactly what we don't want: we want to only set bits up to 'nr_cpu_ids', which is what "bitmap_set()" does. However, Yury correctly points out that while "bitmap_set()" does indeed only set bits up to the required bitmap size, it doesn't _clear_ bits above that size, so the upper bits would still not have well-defined values. Now, none of this should really matter, since any bits set past 'nr_cpu_ids' should always be ignored in the first place. Yes, the bit scanning functions might return them as a result, but since users should always consider the ">= nr_cpu_ids" condition to mean "no more bits", that shouldn't have any actual effect (see previous commit 8ca09d5fa354 "cpumask: fix incorrect cpumask scanning result checks"). But let's just do it right, the way the code was _intended_ to work. We have had enough lazy code that works but bites us in the *rse later (again, see previous commit) that there's no reason to not just do this properly. It turns out that "bitmap_fill()" gets this all right for the complex case, and really only fails for the inlined optimized case that just fills the whole word. And while we could just fix bitmap_fill() to use the proper last word mask, there's two issues with that: - the cpumask case wants to do the _optimization_ based on "NR_CPUS is a small constant", but then wants to do the actual bit _fill_ based on "nr_cpu_ids" that isn't necessarily that same constant - we have lots of non-cpumask users of bitmap_fill(), and while they hopefully don't care, and probably would want the proper semantics anyway ("only set bits up to the limit"), I do not want the cpumask changes to impact other parts So this ends up just doing the single-word optimization by hand in the cpumask code. If our cpumask is fundamentally limited to a single word, just do the proper "fill in that word" exactly. And if it's the more complex multi-word case, then the generic bitmap_fill() will DTRT. This is all an example of how our bitmap function optimizations really are somewhat broken. They conflate the "this is size of the bitmap" optimizations with the actual bit(s) we want to set. In many cases we really want to have the two be separate things: sometimes we base our optimizations on the size of the whole bitmap ("I know this whole bitmap fits in a single word, so I'll just use single-word accesses"), and sometimes we base them on the bit we are looking at ("this is just acting on bits that are in the first word, so I'll use single-word accesses"). Notice how the end result of the two optimizations are the same, but the way we get to them are quite different. And all our cpumask optimization games are really about that fundamental distinction, and we'd often really want to pass in both the "this is the bit I'm working on" (which _can_ be a small constant but might be variable), and "I know it's in this range even if it's variable" (based on CONFIG_NR_CPUS). So this cpumask_setall() implementation just makes that explicit. It checks the "I statically know the size is small" using the known static size of the cpumask (which is what that 'small_cpumask_bits' is all about), but then sets the actual bits using the exact number of cpus we have (ie 'nr_cpumask_bits') Of course, in a perfect world, the compiler would have done all the range analysis (possibly with help from us just telling it that "this value is always in this range"), and would do all of this for us. But that is not the world we live in. While we dream of that perfect world, this does that manual logic to make it all work out. And this was a very long explanation for a small code change that shouldn't even matter. Reported-by: Yury Norov Link: https://lore.kernel.org/lkml/ZAV9nGG9e1%2FrV+L%2F@yury-laptop/ Signed-off-by: Linus Torvalds --- include/linux/cpumask.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h index ce8eb7ef2107..63d637d18e79 100644 --- a/include/linux/cpumask.h +++ b/include/linux/cpumask.h @@ -518,14 +518,14 @@ static __always_inline bool cpumask_test_and_clear_cpu(int cpu, struct cpumask * /** * cpumask_setall - set all cpus (< nr_cpu_ids) in a cpumask * @dstp: the cpumask pointer - * - * Note: since we set bits, we should use the tighter 'bitmap_set()' with - * the eact number of bits, not 'bitmap_fill()' that will fill past the - * end. */ static inline void cpumask_setall(struct cpumask *dstp) { - bitmap_set(cpumask_bits(dstp), 0, nr_cpumask_bits); + if (small_const_nbits(small_cpumask_bits)) { + cpumask_bits(dstp)[0] = BITMAP_LAST_WORD_MASK(nr_cpumask_bits); + return; + } + bitmap_fill(cpumask_bits(dstp), nr_cpumask_bits); } /** From bf89b7ee52af5a5944fa3539e86089f72475055b Mon Sep 17 00:00:00 2001 From: Conor Dooley Date: Thu, 2 Mar 2023 17:41:55 +0000 Subject: [PATCH 227/778] RISC-V: fix taking the text_mutex twice during sifive errata patching Chris pointed out that some bonehead, *cough* me *cough*, added two mutex_locks() to the SiFive errata patching. The second was meant to have been a mutex_unlock(). This results in errors such as Unable to handle kernel NULL pointer dereference at virtual address 0000000000000030 Oops [#1] Modules linked in: CPU: 0 PID: 0 Comm: swapper Not tainted 6.2.0-rc1-starlight-00079-g9493e6f3ce02 #229 Hardware name: BeagleV Starlight Beta (DT) epc : __schedule+0x42/0x500 ra : schedule+0x46/0xce epc : ffffffff8065957c ra : ffffffff80659a80 sp : ffffffff81203c80 gp : ffffffff812d50a0 tp : ffffffff8120db40 t0 : ffffffff81203d68 t1 : 0000000000000001 t2 : 4c45203a76637369 s0 : ffffffff81203cf0 s1 : ffffffff8120db40 a0 : 0000000000000000 a1 : ffffffff81213958 a2 : ffffffff81213958 a3 : 0000000000000000 a4 : 0000000000000000 a5 : ffffffff80a1bd00 a6 : 0000000000000000 a7 : 0000000052464e43 s2 : ffffffff8120db41 s3 : ffffffff80a1ad00 s4 : 0000000000000000 s5 : 0000000000000002 s6 : ffffffff81213938 s7 : 0000000000000000 s8 : 0000000000000000 s9 : 0000000000000001 s10: ffffffff812d7204 s11: ffffffff80d3c920 t3 : 0000000000000001 t4 : ffffffff812e6dd7 t5 : ffffffff812e6dd8 t6 : ffffffff81203bb8 status: 0000000200000100 badaddr: 0000000000000030 cause: 000000000000000d [] schedule+0x46/0xce [] schedule_preempt_disabled+0x16/0x28 [] __mutex_lock.constprop.0+0x3fe/0x652 [] __mutex_lock_slowpath+0xe/0x16 [] mutex_lock+0x42/0x4c [] sifive_errata_patch_func+0xf6/0x18c [] _apply_alternatives+0x74/0x76 [] apply_boot_alternatives+0x3c/0xfa [] setup_arch+0x60c/0x640 [] start_kernel+0x8e/0x99c ---[ end trace 0000000000000000 ]--- Reported-by: Chris Hofstaedtler Fixes: 9493e6f3ce02 ("RISC-V: take text_mutex during alternative patching") Signed-off-by: Conor Dooley Tested-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20230302174154.970746-1-conor@kernel.org [Palmer: pick up Geert's bug report from the thread] Signed-off-by: Palmer Dabbelt --- arch/riscv/errata/sifive/errata.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/riscv/errata/sifive/errata.c b/arch/riscv/errata/sifive/errata.c index da55cb247e89..31d2ebea4286 100644 --- a/arch/riscv/errata/sifive/errata.c +++ b/arch/riscv/errata/sifive/errata.c @@ -111,7 +111,7 @@ void __init_or_module sifive_errata_patch_func(struct alt_entry *begin, mutex_lock(&text_mutex); patch_text_nosync(ALT_OLD_PTR(alt), ALT_ALT_PTR(alt), alt->alt_len); - mutex_lock(&text_mutex); + mutex_unlock(&text_mutex); cpu_apply_errata |= tmp; } } From e5eef23e267c72521d81f23f7f82d1f523d4a253 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Fri, 13 Jan 2023 11:24:08 -0500 Subject: [PATCH 228/778] drm/display: Don't block HDR_OUTPUT_METADATA on unknown EOTF MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The EDID of an HDR display defines EOTFs that are supported by the display and can be set in the HDR metadata infoframe. Userspace is expected to read the EDID and set an appropriate HDR_OUTPUT_METADATA. In drm_parse_hdr_metadata_block the kernel reads the supported EOTFs from the EDID and stores them in the drm_connector->hdr_sink_metadata. While doing so it also filters the EOTFs to the EOTFs the kernel knows about. When an HDR_OUTPUT_METADATA is set it then checks to make sure the EOTF is a supported EOTF. In cases where the kernel doesn't know about a new EOTF this check will fail, even if the EDID advertises support. Since it is expected that userspace reads the EDID to understand what the display supports it doesn't make sense for DRM to block an HDR_OUTPUT_METADATA if it contains an EOTF the kernel doesn't understand. This comes with the added benefit of future-proofing metadata support. If the spec defines a new EOTF there is no need to update DRM and an compositor can immediately make use of it. Bug: https://gitlab.freedesktop.org/wayland/weston/-/issues/609 v2: Distinguish EOTFs defind in kernel and ones defined in EDID in the commit description (Pekka) v3: Rebase; drm_hdmi_infoframe_set_hdr_metadata moved to drm_hdmi_helper.c Signed-off-by: Harry Wentland Cc: Pekka Paalanen Cc: Sebastian Wick Cc: Vitaly.Prosyak@amd.com Cc: Uma Shankar Cc: Ville Syrjälä Cc: Joshua Ashton Cc: Jani Nikula Cc: dri-devel@lists.freedesktop.org Cc: amd-gfx@lists.freedesktop.org Acked-by: Pekka Paalanen Reviewed-By: Joshua Ashton Link: https://patchwork.freedesktop.org/patch/msgid/20230113162428.33874-2-harry.wentland@amd.com Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/display/drm_hdmi_helper.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/display/drm_hdmi_helper.c b/drivers/gpu/drm/display/drm_hdmi_helper.c index 0264abe55278..faf5e9efa7d3 100644 --- a/drivers/gpu/drm/display/drm_hdmi_helper.c +++ b/drivers/gpu/drm/display/drm_hdmi_helper.c @@ -44,10 +44,8 @@ int drm_hdmi_infoframe_set_hdr_metadata(struct hdmi_drm_infoframe *frame, /* Sink EOTF is Bit map while infoframe is absolute values */ if (!is_eotf_supported(hdr_metadata->hdmi_metadata_type1.eotf, - connector->hdr_sink_metadata.hdmi_type1.eotf)) { - DRM_DEBUG_KMS("EOTF Not Supported\n"); - return -EINVAL; - } + connector->hdr_sink_metadata.hdmi_type1.eotf)) + DRM_DEBUG_KMS("Unknown EOTF %d\n", hdr_metadata->hdmi_metadata_type1.eotf); err = hdmi_drm_infoframe_init(frame); if (err < 0) From 7d386975f6a495902e679a3a250a7456d7e54765 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Fri, 13 Jan 2023 11:24:09 -0500 Subject: [PATCH 229/778] drm/connector: print max_requested_bpc in state debugfs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is useful to understand the bpc defaults and support of a driver. Signed-off-by: Harry Wentland Cc: Pekka Paalanen Cc: Sebastian Wick Cc: Vitaly.Prosyak@amd.com Cc: Uma Shankar Cc: Ville Syrjälä Cc: Joshua Ashton Cc: Jani Nikula Cc: dri-devel@lists.freedesktop.org Cc: amd-gfx@lists.freedesktop.org Reviewed-By: Joshua Ashton Link: https://patchwork.freedesktop.org/patch/msgid/20230113162428.33874-3-harry.wentland@amd.com Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/drm_atomic.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 5457c02ca1ab..fed41800fea7 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -1070,6 +1070,7 @@ static void drm_atomic_connector_print_state(struct drm_printer *p, drm_printf(p, "connector[%u]: %s\n", connector->base.id, connector->name); drm_printf(p, "\tcrtc=%s\n", state->crtc ? state->crtc->name : "(null)"); drm_printf(p, "\tself_refresh_aware=%d\n", state->self_refresh_aware); + drm_printf(p, "\tmax_requested_bpc=%d\n", state->max_requested_bpc); if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK) if (state->writeback_job && state->writeback_job->fb) From 06630fb9fcd761254a8d8b53dd6f859b3ecf3707 Mon Sep 17 00:00:00 2001 From: Candice Li Date: Fri, 24 Feb 2023 17:26:33 +0800 Subject: [PATCH 230/778] drm/amdgpu: Support umc node harvest config on umc v8_10 Don't need to query error count and error address on harvest umc nodes. v2: Fix code bug, use active_mask instead of harvsest_config and remove unnecessary argument in LOOP macro. v3: Leave adev->gmc.num_umc unchanged. Signed-off-by: Candice Li Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 10 +++++++++- drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h | 7 +++++-- drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c | 1 - drivers/gpu/drm/amd/amdgpu/umc_v8_10.h | 4 ++-- 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c index b719852daa07..1a3cb53d2e0d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c @@ -543,6 +543,7 @@ static void amdgpu_discovery_read_from_harvest_table(struct amdgpu_device *adev, struct harvest_table *harvest_info; u16 offset; int i; + uint32_t umc_harvest_config = 0; bhdr = (struct binary_header *)adev->mman.discovery_bin; offset = le16_to_cpu(bhdr->table_list[HARVEST_INFO].offset); @@ -570,12 +571,17 @@ static void amdgpu_discovery_read_from_harvest_table(struct amdgpu_device *adev, adev->harvest_ip_mask |= AMD_HARVEST_IP_DMU_MASK; break; case UMC_HWID: + umc_harvest_config |= + 1 << (le16_to_cpu(harvest_info->list[i].number_instance)); (*umc_harvest_count)++; break; default: break; } } + + adev->umc.active_mask = ((1 << adev->umc.node_inst_num) - 1) & + ~umc_harvest_config; } /* ================================================== */ @@ -1156,8 +1162,10 @@ static int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev) AMDGPU_MAX_SDMA_INSTANCES); } - if (le16_to_cpu(ip->hw_id) == UMC_HWID) + if (le16_to_cpu(ip->hw_id) == UMC_HWID) { adev->gmc.num_umc++; + adev->umc.node_inst_num++; + } for (k = 0; k < num_base_address; k++) { /* diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h index f2bf979af588..36e19336f3b3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h @@ -42,7 +42,7 @@ #define LOOP_UMC_INST_AND_CH(umc_inst, ch_inst) LOOP_UMC_INST((umc_inst)) LOOP_UMC_CH_INST((ch_inst)) #define LOOP_UMC_NODE_INST(node_inst) \ - for ((node_inst) = 0; (node_inst) < adev->umc.node_inst_num; (node_inst)++) + for_each_set_bit((node_inst), &(adev->umc.active_mask), adev->umc.node_inst_num) #define LOOP_UMC_EACH_NODE_INST_AND_CH(node_inst, umc_inst, ch_inst) \ LOOP_UMC_NODE_INST((node_inst)) LOOP_UMC_INST_AND_CH((umc_inst), (ch_inst)) @@ -69,7 +69,7 @@ struct amdgpu_umc { /* number of umc instance with memory map register access */ uint32_t umc_inst_num; - /*number of umc node instance with memory map register access*/ + /* Total number of umc node instance including harvest one */ uint32_t node_inst_num; /* UMC regiser per channel offset */ @@ -82,6 +82,9 @@ struct amdgpu_umc { const struct amdgpu_umc_funcs *funcs; struct amdgpu_umc_ras *ras; + + /* active mask for umc node instance */ + unsigned long active_mask; }; int amdgpu_umc_ras_late_init(struct amdgpu_device *adev, struct ras_common_if *ras_block); diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c index 85e0afc3d4f7..af7b3ba1ca00 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c @@ -567,7 +567,6 @@ static void gmc_v11_0_set_umc_funcs(struct amdgpu_device *adev) case IP_VERSION(8, 10, 0): adev->umc.channel_inst_num = UMC_V8_10_CHANNEL_INSTANCE_NUM; adev->umc.umc_inst_num = UMC_V8_10_UMC_INSTANCE_NUM; - adev->umc.node_inst_num = adev->gmc.num_umc; adev->umc.max_ras_err_cnt_per_query = UMC_V8_10_TOTAL_CHANNEL_NUM(adev); adev->umc.channel_offs = UMC_V8_10_PER_CHANNEL_OFFSET; adev->umc.retire_unit = UMC_V8_10_NA_COL_2BITS_POWER_OF_2_NUM; diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v8_10.h b/drivers/gpu/drm/amd/amdgpu/umc_v8_10.h index 25eaf4af5fcf..c6dfd433fec7 100644 --- a/drivers/gpu/drm/amd/amdgpu/umc_v8_10.h +++ b/drivers/gpu/drm/amd/amdgpu/umc_v8_10.h @@ -31,9 +31,9 @@ /* number of umc instance with memory map register access */ #define UMC_V8_10_UMC_INSTANCE_NUM 2 -/* Total channel instances for all umc nodes */ +/* Total channel instances for all available umc nodes */ #define UMC_V8_10_TOTAL_CHANNEL_NUM(adev) \ - (UMC_V8_10_CHANNEL_INSTANCE_NUM * UMC_V8_10_UMC_INSTANCE_NUM * (adev)->umc.node_inst_num) + (UMC_V8_10_CHANNEL_INSTANCE_NUM * UMC_V8_10_UMC_INSTANCE_NUM * (adev)->gmc.num_umc) /* UMC regiser per channel offset */ #define UMC_V8_10_PER_CHANNEL_OFFSET 0x400 From c53899138c99236482a3c25d674f44723336afa3 Mon Sep 17 00:00:00 2001 From: Candice Li Date: Mon, 16 Jan 2023 16:23:21 +0800 Subject: [PATCH 231/778] drm/amd/pm: Enable ecc_info table support for smu v13_0_10 Support EccInfoTable which includes umc ras error count and error address. Signed-off-by: Candice Li Reviewed-by: Evan Quan Reviewed-by: Stanley.Yang Signed-off-by: Alex Deucher --- .../drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c index 923a9fb3c887..27448ffe60a4 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c @@ -46,6 +46,7 @@ #include "asic_reg/mp/mp_13_0_0_sh_mask.h" #include "smu_cmn.h" #include "amdgpu_ras.h" +#include "umc_v8_10.h" /* * DO NOT use these for err/warn/info/debug messages. @@ -90,6 +91,12 @@ #define DEBUGSMC_MSG_Mode1Reset 2 +/* + * SMU_v13_0_10 supports ECCTABLE since version 80.34.0, + * use this to check ECCTABLE feature whether support + */ +#define SUPPORT_ECCTABLE_SMU_13_0_10_VERSION 0x00502200 + static struct cmn2asic_msg_mapping smu_v13_0_0_message_map[SMU_MSG_MAX_COUNT] = { MSG_MAP(TestMessage, PPSMC_MSG_TestMessage, 1), MSG_MAP(GetSmuVersion, PPSMC_MSG_GetSmuVersion, 1), @@ -229,6 +236,7 @@ static struct cmn2asic_mapping smu_v13_0_0_table_map[SMU_TABLE_COUNT] = { TAB_MAP(ACTIVITY_MONITOR_COEFF), [SMU_TABLE_COMBO_PPTABLE] = {1, TABLE_COMBO_PPTABLE}, TAB_MAP(I2C_COMMANDS), + TAB_MAP(ECCINFO), }; static struct cmn2asic_mapping smu_v13_0_0_pwr_src_map[SMU_POWER_SOURCE_COUNT] = { @@ -462,6 +470,8 @@ static int smu_v13_0_0_tables_init(struct smu_context *smu) AMDGPU_GEM_DOMAIN_VRAM); SMU_TABLE_INIT(tables, SMU_TABLE_COMBO_PPTABLE, MP0_MP1_DATA_REGION_SIZE_COMBOPPTABLE, PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); + SMU_TABLE_INIT(tables, SMU_TABLE_ECCINFO, sizeof(EccInfoTable_t), + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); smu_table->metrics_table = kzalloc(sizeof(SmuMetricsExternal_t), GFP_KERNEL); if (!smu_table->metrics_table) @@ -477,8 +487,14 @@ static int smu_v13_0_0_tables_init(struct smu_context *smu) if (!smu_table->watermarks_table) goto err2_out; + smu_table->ecc_table = kzalloc(tables[SMU_TABLE_ECCINFO].size, GFP_KERNEL); + if (!smu_table->ecc_table) + goto err3_out; + return 0; +err3_out: + kfree(smu_table->watermarks_table); err2_out: kfree(smu_table->gpu_metrics_table); err1_out: @@ -2036,6 +2052,64 @@ static int smu_v13_0_0_send_bad_mem_channel_flag(struct smu_context *smu, return ret; } +static int smu_v13_0_0_check_ecc_table_support(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + uint32_t if_version = 0xff, smu_version = 0xff; + int ret = 0; + + ret = smu_cmn_get_smc_version(smu, &if_version, &smu_version); + if (ret) + return -EOPNOTSUPP; + + if ((adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 10)) && + (smu_version >= SUPPORT_ECCTABLE_SMU_13_0_10_VERSION)) + return ret; + else + return -EOPNOTSUPP; +} + +static ssize_t smu_v13_0_0_get_ecc_info(struct smu_context *smu, + void *table) +{ + struct smu_table_context *smu_table = &smu->smu_table; + struct amdgpu_device *adev = smu->adev; + EccInfoTable_t *ecc_table = NULL; + struct ecc_info_per_ch *ecc_info_per_channel = NULL; + int i, ret = 0; + struct umc_ecc_info *eccinfo = (struct umc_ecc_info *)table; + + ret = smu_v13_0_0_check_ecc_table_support(smu); + if (ret) + return ret; + + ret = smu_cmn_update_table(smu, + SMU_TABLE_ECCINFO, + 0, + smu_table->ecc_table, + false); + if (ret) { + dev_info(adev->dev, "Failed to export SMU ecc table!\n"); + return ret; + } + + ecc_table = (EccInfoTable_t *)smu_table->ecc_table; + + for (i = 0; i < UMC_V8_10_TOTAL_CHANNEL_NUM(adev); i++) { + ecc_info_per_channel = &(eccinfo->ecc[i]); + ecc_info_per_channel->ce_count_lo_chip = + ecc_table->EccInfo[i].ce_count_lo_chip; + ecc_info_per_channel->ce_count_hi_chip = + ecc_table->EccInfo[i].ce_count_hi_chip; + ecc_info_per_channel->mca_umc_status = + ecc_table->EccInfo[i].mca_umc_status; + ecc_info_per_channel->mca_umc_addr = + ecc_table->EccInfo[i].mca_umc_addr; + } + + return ret; +} + static const struct pptable_funcs smu_v13_0_0_ppt_funcs = { .get_allowed_feature_mask = smu_v13_0_0_get_allowed_feature_mask, .set_default_dpm_table = smu_v13_0_0_set_default_dpm_table, @@ -2111,6 +2185,7 @@ static const struct pptable_funcs smu_v13_0_0_ppt_funcs = { .send_hbm_bad_pages_num = smu_v13_0_0_smu_send_bad_mem_page_num, .send_hbm_bad_channel_flag = smu_v13_0_0_send_bad_mem_channel_flag, .gpo_control = smu_v13_0_gpo_control, + .get_ecc_info = smu_v13_0_0_get_ecc_info, }; void smu_v13_0_0_set_ppt_funcs(struct smu_context *smu) From 2d99a7ec25cf456cd3680eb314d6454138e5aa64 Mon Sep 17 00:00:00 2001 From: Swapnil Patel Date: Wed, 1 Mar 2023 14:33:33 -0500 Subject: [PATCH 232/778] drm/amd/display: Update clock table to include highest clock setting [Why] Currently, the clk manager matches SocVoltage with voltage from fused settings (dfPstate clock table). And then corresponding clocks are selected. However in certain situations, this leads to clk manager not including at least one entry with highest supported clock setting. [How] Update the clk manager to include at least one entry with highest supported clock setting. Reviewed-by: Pavle Kotarac Acked-by: Qingqing Zhuo Signed-off-by: Swapnil Patel Signed-off-by: Alex Deucher --- .../display/dc/clk_mgr/dcn301/vg_clk_mgr.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c index 24715ca2fa94..01383aac6b41 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c @@ -529,6 +529,19 @@ static struct clk_bw_params vg_bw_params = { }; +static uint32_t find_max_clk_value(const uint32_t clocks[], uint32_t num_clocks) +{ + uint32_t max = 0; + int i; + + for (i = 0; i < num_clocks; ++i) { + if (clocks[i] > max) + max = clocks[i]; + } + + return max; +} + static unsigned int find_dcfclk_for_voltage(const struct vg_dpm_clocks *clock_table, unsigned int voltage) { @@ -572,12 +585,16 @@ static void vg_clk_mgr_helper_populate_bw_params( bw_params->clk_table.num_entries = j + 1; - for (i = 0; i < bw_params->clk_table.num_entries; i++, j--) { + for (i = 0; i < bw_params->clk_table.num_entries - 1; i++, j--) { bw_params->clk_table.entries[i].fclk_mhz = clock_table->DfPstateTable[j].fclk; bw_params->clk_table.entries[i].memclk_mhz = clock_table->DfPstateTable[j].memclk; bw_params->clk_table.entries[i].voltage = clock_table->DfPstateTable[j].voltage; bw_params->clk_table.entries[i].dcfclk_mhz = find_dcfclk_for_voltage(clock_table, clock_table->DfPstateTable[j].voltage); } + bw_params->clk_table.entries[i].fclk_mhz = clock_table->DfPstateTable[j].fclk; + bw_params->clk_table.entries[i].memclk_mhz = clock_table->DfPstateTable[j].memclk; + bw_params->clk_table.entries[i].voltage = clock_table->DfPstateTable[j].voltage; + bw_params->clk_table.entries[i].dcfclk_mhz = find_max_clk_value(clock_table->DcfClocks, VG_NUM_DCFCLK_DPM_LEVELS); bw_params->vram_type = bios_info->memory_type; bw_params->num_channels = bios_info->ma_channel_number; From fef3f92e8a4214652d8f33f50330dc5a92efbf11 Mon Sep 17 00:00:00 2001 From: Dave Ertman Date: Fri, 27 Jan 2023 14:24:10 +0100 Subject: [PATCH 233/778] ice: Fix DSCP PFC TLV creation When creating the TLV to send to the FW for configuring DSCP mode PFC,the PFCENABLE field was being masked with a 4 bit mask (0xF), but this is an 8 bit bitmask for enabled classes for PFC. This means that traffic classes 4-7 could not be enabled for PFC. Remove the mask completely, as it is not necessary, as we are assigning 8 bits to an 8 bit field. Fixes: 2a87bd73e50d ("ice: Add DSCP support") Signed-off-by: Dave Ertman Signed-off-by: Karen Ostrowska Tested-by: Gurucharan G (A Contingent worker at Intel) Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_dcb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/ice/ice_dcb.c b/drivers/net/ethernet/intel/ice/ice_dcb.c index c557dfc50aad..396e555023aa 100644 --- a/drivers/net/ethernet/intel/ice/ice_dcb.c +++ b/drivers/net/ethernet/intel/ice/ice_dcb.c @@ -1411,7 +1411,7 @@ ice_add_dscp_pfc_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg) tlv->ouisubtype = htonl(ouisubtype); buf[0] = dcbcfg->pfc.pfccap & 0xF; - buf[1] = dcbcfg->pfc.pfcena & 0xF; + buf[1] = dcbcfg->pfc.pfcena; } /** From c4a9c8e78aad0fd9b79c9b1e83bab3288a15ce3c Mon Sep 17 00:00:00 2001 From: Michal Swiatkowski Date: Mon, 13 Feb 2023 12:27:33 +0100 Subject: [PATCH 234/778] ice: don't ignore return codes in VSI related code There were few smatch warnings reported by Dan: - ice_vsi_cfg_xdp_txqs can return 0 instead of ret, which is cleaner - return values in ice_vsi_cfg_def were ignored - in ice_vsi_rebuild return value was ignored in case rebuild failed, it was a never reached code, however, rewrite it for clarity. - ice_vsi_cfg_tc can return 0 instead of ret Fixes: 6624e780a577 ("ice: split ice_vsi_setup into smaller functions") Reported-by: Dan Carpenter Signed-off-by: Michal Swiatkowski Tested-by: Gurucharan G (A Contingent worker at Intel) Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_lib.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c index 781475480ff2..0f52ea38b6f3 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_lib.c @@ -2126,7 +2126,7 @@ int ice_vsi_cfg_xdp_txqs(struct ice_vsi *vsi) ice_for_each_rxq(vsi, i) ice_tx_xsk_pool(vsi, i); - return ret; + return 0; } /** @@ -2693,12 +2693,14 @@ ice_vsi_cfg_def(struct ice_vsi *vsi, struct ice_vsi_cfg_params *params) return ret; /* allocate memory for Tx/Rx ring stat pointers */ - if (ice_vsi_alloc_stat_arrays(vsi)) + ret = ice_vsi_alloc_stat_arrays(vsi); + if (ret) goto unroll_vsi_alloc; ice_alloc_fd_res(vsi); - if (ice_vsi_get_qs(vsi)) { + ret = ice_vsi_get_qs(vsi); + if (ret) { dev_err(dev, "Failed to allocate queues. vsi->idx = %d\n", vsi->idx); goto unroll_vsi_alloc_stat; @@ -2811,6 +2813,7 @@ ice_vsi_cfg_def(struct ice_vsi *vsi, struct ice_vsi_cfg_params *params) break; default: /* clean up the resources and exit */ + ret = -EINVAL; goto unroll_vsi_init; } @@ -3508,10 +3511,10 @@ int ice_vsi_rebuild(struct ice_vsi *vsi, u32 vsi_flags) if (vsi_flags & ICE_VSI_FLAG_INIT) { ret = -EIO; goto err_vsi_cfg_tc_lan; - } else { - kfree(coalesce); - return ice_schedule_reset(pf, ICE_RESET_PFR); } + + kfree(coalesce); + return ice_schedule_reset(pf, ICE_RESET_PFR); } ice_vsi_realloc_stat_arrays(vsi, prev_txq, prev_rxq); @@ -3759,7 +3762,7 @@ int ice_vsi_cfg_tc(struct ice_vsi *vsi, u8 ena_tc) dev = ice_pf_to_dev(pf); if (vsi->tc_cfg.ena_tc == ena_tc && vsi->mqprio_qopt.mode != TC_MQPRIO_MODE_CHANNEL) - return ret; + return 0; ice_for_each_traffic_class(i) { /* build bitmap of enabled TCs */ From 8f5c5a790e3025d6eca96bf7ee5e3873dc92373f Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 14 Feb 2023 16:25:36 +0100 Subject: [PATCH 235/778] ethernet: ice: avoid gcc-9 integer overflow warning With older compilers like gcc-9, the calculation of the vlan priority field causes a false-positive warning from the byteswap: In file included from drivers/net/ethernet/intel/ice/ice_tc_lib.c:4: drivers/net/ethernet/intel/ice/ice_tc_lib.c: In function 'ice_parse_cls_flower': include/uapi/linux/swab.h:15:15: error: integer overflow in expression '(int)(short unsigned int)((int)match.key->..vlan_priority << 13) & 57344 & 255' of type 'int' results in '0' [-Werror=overflow] 15 | (((__u16)(x) & (__u16)0x00ffU) << 8) | \ | ~~~~~~~~~~~~^~~~~~~~~~~~~~~~~ include/uapi/linux/swab.h:106:2: note: in expansion of macro '___constant_swab16' 106 | ___constant_swab16(x) : \ | ^~~~~~~~~~~~~~~~~~ include/uapi/linux/byteorder/little_endian.h:42:43: note: in expansion of macro '__swab16' 42 | #define __cpu_to_be16(x) ((__force __be16)__swab16((x))) | ^~~~~~~~ include/linux/byteorder/generic.h:96:21: note: in expansion of macro '__cpu_to_be16' 96 | #define cpu_to_be16 __cpu_to_be16 | ^~~~~~~~~~~~~ drivers/net/ethernet/intel/ice/ice_tc_lib.c:1458:5: note: in expansion of macro 'cpu_to_be16' 1458 | cpu_to_be16((match.key->vlan_priority << | ^~~~~~~~~~~ After a change to be16_encode_bits(), the code becomes more readable to both people and compilers, which avoids the warning. Fixes: 34800178b302 ("ice: Add support for VLAN priority filters in switchdev") Suggested-by: Alexander Lobakin Signed-off-by: Arnd Bergmann Reviewed-by: Alexander Lobakin Tested-by: Sujai Buvaneswaran Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_tc_lib.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_tc_lib.c b/drivers/net/ethernet/intel/ice/ice_tc_lib.c index 6b48cbc049c6..76f29a5bf8d7 100644 --- a/drivers/net/ethernet/intel/ice/ice_tc_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_tc_lib.c @@ -1455,8 +1455,8 @@ ice_parse_cls_flower(struct net_device *filter_dev, struct ice_vsi *vsi, if (match.mask->vlan_priority) { fltr->flags |= ICE_TC_FLWR_FIELD_VLAN_PRIO; headers->vlan_hdr.vlan_prio = - cpu_to_be16((match.key->vlan_priority << - VLAN_PRIO_SHIFT) & VLAN_PRIO_MASK); + be16_encode_bits(match.key->vlan_priority, + VLAN_PRIO_MASK); } if (match.mask->vlan_tpid) @@ -1489,8 +1489,8 @@ ice_parse_cls_flower(struct net_device *filter_dev, struct ice_vsi *vsi, if (match.mask->vlan_priority) { fltr->flags |= ICE_TC_FLWR_FIELD_CVLAN_PRIO; headers->cvlan_hdr.vlan_prio = - cpu_to_be16((match.key->vlan_priority << - VLAN_PRIO_SHIFT) & VLAN_PRIO_MASK); + be16_encode_bits(match.key->vlan_priority, + VLAN_PRIO_MASK); } } From 7d834b4d1ab66c48e8c0810fdeadaabb80fa2c81 Mon Sep 17 00:00:00 2001 From: Fedor Pchelkin Date: Tue, 7 Mar 2023 00:26:50 +0300 Subject: [PATCH 236/778] nfc: change order inside nfc_se_io error path cb_context should be freed on the error path in nfc_se_io as stated by commit 25ff6f8a5a3b ("nfc: fix memory leak of se_io context in nfc_genl_se_io"). Make the error path in nfc_se_io unwind everything in reverse order, i.e. free the cb_context after unlocking the device. Suggested-by: Krzysztof Kozlowski Signed-off-by: Fedor Pchelkin Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230306212650.230322-1-pchelkin@ispras.ru Signed-off-by: Jakub Kicinski --- net/nfc/netlink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c index 348bf561bc9f..b9264e730fd9 100644 --- a/net/nfc/netlink.c +++ b/net/nfc/netlink.c @@ -1446,8 +1446,8 @@ static int nfc_se_io(struct nfc_dev *dev, u32 se_idx, return rc; error: - kfree(cb_context); device_unlock(&dev->dev); + kfree(cb_context); return rc; } From e7b15acdc10f74872fdae1482b3f837818362085 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Mon, 6 Mar 2023 11:20:18 -0800 Subject: [PATCH 237/778] mailmap: add entry for Maxim Mikityanskiy Map Maxim's old corporate addresses to his personal one. Link: https://lore.kernel.org/r/20230306192018.3894988-1-kuba@kernel.org Signed-off-by: Jakub Kicinski --- .mailmap | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.mailmap b/.mailmap index a872c9683958..04bd44774ad0 100644 --- a/.mailmap +++ b/.mailmap @@ -304,6 +304,8 @@ Mauro Carvalho Chehab Mauro Carvalho Chehab Mauro Carvalho Chehab Mauro Carvalho Chehab +Maxim Mikityanskiy +Maxim Mikityanskiy Maxime Ripard Maxime Ripard Mayuresh Janorkar From b1649b0fe98c2c7eed156c957f6f524d5660d859 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 6 Mar 2023 11:44:05 -0800 Subject: [PATCH 238/778] mailmap: update entries for Stephen Hemminger Map all my old email addresses to current address. Signed-off-by: Stephen Hemminger Link: https://lore.kernel.org/r/20230306194405.108236-1-stephen@networkplumber.org Signed-off-by: Jakub Kicinski --- .mailmap | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.mailmap b/.mailmap index 04bd44774ad0..4f37ff13a346 100644 --- a/.mailmap +++ b/.mailmap @@ -411,7 +411,10 @@ Shuah Khan Simon Arlott Simon Kelley Stéphane Witzmann -Stephen Hemminger +Stephen Hemminger +Stephen Hemminger +Stephen Hemminger +Stephen Hemminger Steve Wise Steve Wise Subash Abhinov Kasiviswanathan From 37d9df224d1eec1b434fe9ffa40104c756478c29 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Mon, 6 Mar 2023 12:04:57 -0800 Subject: [PATCH 239/778] ynl: re-license uniformly under GPL-2.0 OR BSD-3-Clause I was intending to make all the Netlink Spec code BSD-3-Clause to ease the adoption but it appears that: - I fumbled the uAPI and used "GPL WITH uAPI note" there - it gives people pause as they expect GPL in the kernel As suggested by Chuck re-license under dual. This gives us benefit of full BSD freedom while fulfilling the broad "kernel is under GPL" expectations. Link: https://lore.kernel.org/all/20230304120108.05dd44c5@kernel.org/ Link: https://lore.kernel.org/r/20230306200457.3903854-1-kuba@kernel.org Signed-off-by: Jakub Kicinski --- Documentation/netlink/genetlink-c.yaml | 2 +- Documentation/netlink/genetlink-legacy.yaml | 2 +- Documentation/netlink/genetlink.yaml | 2 +- Documentation/netlink/specs/ethtool.yaml | 2 ++ Documentation/netlink/specs/fou.yaml | 2 ++ Documentation/netlink/specs/netdev.yaml | 2 ++ Documentation/userspace-api/netlink/specs.rst | 3 +++ include/uapi/linux/fou.h | 2 +- include/uapi/linux/netdev.h | 2 +- net/core/netdev-genl-gen.c | 2 +- net/core/netdev-genl-gen.h | 2 +- net/ipv4/fou_nl.c | 2 +- net/ipv4/fou_nl.h | 2 +- tools/include/uapi/linux/netdev.h | 2 +- tools/net/ynl/cli.py | 2 +- tools/net/ynl/lib/__init__.py | 2 +- tools/net/ynl/lib/nlspec.py | 2 +- tools/net/ynl/lib/ynl.py | 2 +- tools/net/ynl/ynl-gen-c.py | 7 ++++--- tools/net/ynl/ynl-regen.sh | 2 +- 20 files changed, 28 insertions(+), 18 deletions(-) diff --git a/Documentation/netlink/genetlink-c.yaml b/Documentation/netlink/genetlink-c.yaml index bbcfa2472b04..f082a5ad7cf1 100644 --- a/Documentation/netlink/genetlink-c.yaml +++ b/Documentation/netlink/genetlink-c.yaml @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: GPL-2.0 +# SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause %YAML 1.2 --- $id: http://kernel.org/schemas/netlink/genetlink-c.yaml# diff --git a/Documentation/netlink/genetlink-legacy.yaml b/Documentation/netlink/genetlink-legacy.yaml index 5642925c4ceb..c6b8c77f7d12 100644 --- a/Documentation/netlink/genetlink-legacy.yaml +++ b/Documentation/netlink/genetlink-legacy.yaml @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: GPL-2.0 +# SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause %YAML 1.2 --- $id: http://kernel.org/schemas/netlink/genetlink-legacy.yaml# diff --git a/Documentation/netlink/genetlink.yaml b/Documentation/netlink/genetlink.yaml index 62a922755ce2..b2d56ab9e615 100644 --- a/Documentation/netlink/genetlink.yaml +++ b/Documentation/netlink/genetlink.yaml @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: GPL-2.0 +# SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause %YAML 1.2 --- $id: http://kernel.org/schemas/netlink/genetlink-legacy.yaml# diff --git a/Documentation/netlink/specs/ethtool.yaml b/Documentation/netlink/specs/ethtool.yaml index 35c462bce56f..18ecb7d90cbe 100644 --- a/Documentation/netlink/specs/ethtool.yaml +++ b/Documentation/netlink/specs/ethtool.yaml @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause + name: ethtool protocol: genetlink-legacy diff --git a/Documentation/netlink/specs/fou.yaml b/Documentation/netlink/specs/fou.yaml index cca4cf98f03a..cff104288723 100644 --- a/Documentation/netlink/specs/fou.yaml +++ b/Documentation/netlink/specs/fou.yaml @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause + name: fou protocol: genetlink-legacy diff --git a/Documentation/netlink/specs/netdev.yaml b/Documentation/netlink/specs/netdev.yaml index ba9ee13cf729..24de747b5344 100644 --- a/Documentation/netlink/specs/netdev.yaml +++ b/Documentation/netlink/specs/netdev.yaml @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause + name: netdev doc: diff --git a/Documentation/userspace-api/netlink/specs.rst b/Documentation/userspace-api/netlink/specs.rst index 32e53328d113..2122e0c4a399 100644 --- a/Documentation/userspace-api/netlink/specs.rst +++ b/Documentation/userspace-api/netlink/specs.rst @@ -24,6 +24,9 @@ YAML specifications can be found under ``Documentation/netlink/specs/`` This document describes details of the schema. See :doc:`intro-specs` for a practical starting guide. +All specs must be licensed under ``GPL-2.0-only OR BSD-3-Clause`` +to allow for easy adoption in user space code. + Compatibility levels ==================== diff --git a/include/uapi/linux/fou.h b/include/uapi/linux/fou.h index 19ebbef41a63..5041c3598493 100644 --- a/include/uapi/linux/fou.h +++ b/include/uapi/linux/fou.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* SPDX-License-Identifier: (GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause */ /* Do not edit directly, auto-generated from: */ /* Documentation/netlink/specs/fou.yaml */ /* YNL-GEN uapi header */ diff --git a/include/uapi/linux/netdev.h b/include/uapi/linux/netdev.h index 588391447bfb..8c4e3e536c04 100644 --- a/include/uapi/linux/netdev.h +++ b/include/uapi/linux/netdev.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* SPDX-License-Identifier: (GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause */ /* Do not edit directly, auto-generated from: */ /* Documentation/netlink/specs/netdev.yaml */ /* YNL-GEN uapi header */ diff --git a/net/core/netdev-genl-gen.c b/net/core/netdev-genl-gen.c index 48812ec843f5..9e10802587fc 100644 --- a/net/core/netdev-genl-gen.c +++ b/net/core/netdev-genl-gen.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: BSD-3-Clause +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* Do not edit directly, auto-generated from: */ /* Documentation/netlink/specs/netdev.yaml */ /* YNL-GEN kernel source */ diff --git a/net/core/netdev-genl-gen.h b/net/core/netdev-genl-gen.h index b16dc7e026bb..2c5fc7d1e8a7 100644 --- a/net/core/netdev-genl-gen.h +++ b/net/core/netdev-genl-gen.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* Do not edit directly, auto-generated from: */ /* Documentation/netlink/specs/netdev.yaml */ /* YNL-GEN kernel header */ diff --git a/net/ipv4/fou_nl.c b/net/ipv4/fou_nl.c index 6c3820f41dd5..5c14fe030eda 100644 --- a/net/ipv4/fou_nl.c +++ b/net/ipv4/fou_nl.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: BSD-3-Clause +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* Do not edit directly, auto-generated from: */ /* Documentation/netlink/specs/fou.yaml */ /* YNL-GEN kernel source */ diff --git a/net/ipv4/fou_nl.h b/net/ipv4/fou_nl.h index b7a68121ce6f..58b1e1ed4b3b 100644 --- a/net/ipv4/fou_nl.h +++ b/net/ipv4/fou_nl.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* Do not edit directly, auto-generated from: */ /* Documentation/netlink/specs/fou.yaml */ /* YNL-GEN kernel header */ diff --git a/tools/include/uapi/linux/netdev.h b/tools/include/uapi/linux/netdev.h index 588391447bfb..8c4e3e536c04 100644 --- a/tools/include/uapi/linux/netdev.h +++ b/tools/include/uapi/linux/netdev.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* SPDX-License-Identifier: (GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause */ /* Do not edit directly, auto-generated from: */ /* Documentation/netlink/specs/netdev.yaml */ /* YNL-GEN uapi header */ diff --git a/tools/net/ynl/cli.py b/tools/net/ynl/cli.py index db410b74d539..ffaa8038aa8c 100755 --- a/tools/net/ynl/cli.py +++ b/tools/net/ynl/cli.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# SPDX-License-Identifier: BSD-3-Clause +# SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause import argparse import json diff --git a/tools/net/ynl/lib/__init__.py b/tools/net/ynl/lib/__init__.py index 3c73f59eabab..a2cb8b16d6f1 100644 --- a/tools/net/ynl/lib/__init__.py +++ b/tools/net/ynl/lib/__init__.py @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: BSD-3-Clause +# SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause from .nlspec import SpecAttr, SpecAttrSet, SpecFamily, SpecOperation from .ynl import YnlFamily diff --git a/tools/net/ynl/lib/nlspec.py b/tools/net/ynl/lib/nlspec.py index 9d394e50de23..0a2cfb5862aa 100644 --- a/tools/net/ynl/lib/nlspec.py +++ b/tools/net/ynl/lib/nlspec.py @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: BSD-3-Clause +# SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause import collections import importlib diff --git a/tools/net/ynl/lib/ynl.py b/tools/net/ynl/lib/ynl.py index 1c7411ee04dc..a842adc8e87e 100644 --- a/tools/net/ynl/lib/ynl.py +++ b/tools/net/ynl/lib/ynl.py @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: BSD-3-Clause +# SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause import functools import os diff --git a/tools/net/ynl/ynl-gen-c.py b/tools/net/ynl/ynl-gen-c.py index 62f8f2c3c56c..c940ca834d3f 100755 --- a/tools/net/ynl/ynl-gen-c.py +++ b/tools/net/ynl/ynl-gen-c.py @@ -1,4 +1,5 @@ #!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause import argparse import collections @@ -2127,12 +2128,12 @@ def main(): _, spec_kernel = find_kernel_root(args.spec) if args.mode == 'uapi': - cw.p('/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */') + cw.p('/* SPDX-License-Identifier: (GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause */') else: if args.header: - cw.p('/* SPDX-License-Identifier: BSD-3-Clause */') + cw.p('/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */') else: - cw.p('// SPDX-License-Identifier: BSD-3-Clause') + cw.p('// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause') cw.p("/* Do not edit directly, auto-generated from: */") cw.p(f"/*\t{spec_kernel} */") cw.p(f"/* YNL-GEN {args.mode} {'header' if args.header else 'source'} */") diff --git a/tools/net/ynl/ynl-regen.sh b/tools/net/ynl/ynl-regen.sh index 43989ae48ed0..74f5de1c2399 100755 --- a/tools/net/ynl/ynl-regen.sh +++ b/tools/net/ynl/ynl-regen.sh @@ -1,5 +1,5 @@ #!/bin/bash -# SPDX-License-Identifier: BSD-3-Clause +# SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause TOOL=$(dirname $(realpath $0))/ynl-gen-c.py From e33062213ff2f9151e0d125e1c00f524c2b7acfe Mon Sep 17 00:00:00 2001 From: Sagi Grimberg Date: Fri, 3 Mar 2023 10:43:23 +0200 Subject: [PATCH 240/778] docs: sysfs-block: document hidden sysfs entry /sys/block//hidden is undocumented. Document it. Signed-off-by: Sagi Grimberg Reviewed-by: Chaitanya Kulkarni Link: https://lore.kernel.org/r/20230303084323.228098-1-sagi@grimberg.me Signed-off-by: Jens Axboe --- Documentation/ABI/stable/sysfs-block | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Documentation/ABI/stable/sysfs-block b/Documentation/ABI/stable/sysfs-block index ac1e519272aa..282de3680367 100644 --- a/Documentation/ABI/stable/sysfs-block +++ b/Documentation/ABI/stable/sysfs-block @@ -705,6 +705,15 @@ Description: zoned will report "none". +What: /sys/block//hidden +Date: March 2023 +Contact: linux-block@vger.kernel.org +Description: + [RO] the block device is hidden. it doesn’t produce events, and + can’t be opened from userspace or using blkdev_get*. + Used for the underlying components of multipath devices. + + What: /sys/block//stat Date: February 2008 Contact: Jerome Marchand From 675dfe1223a69e270b3d52cb0211c8a501455cec Mon Sep 17 00:00:00 2001 From: Filipe Manana Date: Mon, 6 Mar 2023 10:13:34 +0000 Subject: [PATCH 241/778] btrfs: fix block group item corruption after inserting new block group We can often end up inserting a block group item, for a new block group, with a wrong value for the used bytes field. This happens if for the new allocated block group, in the same transaction that created the block group, we have tasks allocating extents from it as well as tasks removing extents from it. For example: 1) Task A creates a metadata block group X; 2) Two extents are allocated from block group X, so its "used" field is updated to 32K, and its "commit_used" field remains as 0; 3) Transaction commit starts, by some task B, and it enters btrfs_start_dirty_block_groups(). There it tries to update the block group item for block group X, which currently has its "used" field with a value of 32K. But that fails since the block group item was not yet inserted, and so on failure update_block_group_item() sets the "commit_used" field of the block group back to 0; 4) The block group item is inserted by task A, when for example btrfs_create_pending_block_groups() is called when releasing its transaction handle. This results in insert_block_group_item() inserting the block group item in the extent tree (or block group tree), with a "used" field having a value of 32K, but without updating the "commit_used" field in the block group, which remains with value of 0; 5) The two extents are freed from block X, so its "used" field changes from 32K to 0; 6) The transaction commit by task B continues, it enters btrfs_write_dirty_block_groups() which calls update_block_group_item() for block group X, and there it decides to skip the block group item update, because "used" has a value of 0 and "commit_used" has a value of 0 too. As a result, we end up with a block item having a 32K "used" field but no extents allocated from it. When this issue happens, a btrfs check reports an error like this: [1/7] checking root items [2/7] checking extents block group [1104150528 1073741824] used 39796736 but extent items used 0 ERROR: errors found in extent allocation tree or chunk allocation (...) Fix this by making insert_block_group_item() update the block group's "commit_used" field. Fixes: 7248e0cebbef ("btrfs: skip update of block group item if used bytes are the same") CC: stable@vger.kernel.org # 6.2+ Reviewed-by: Qu Wenruo Signed-off-by: Filipe Manana Signed-off-by: David Sterba --- fs/btrfs/block-group.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c index 0eec3084fb00..0ef8b8926bfa 100644 --- a/fs/btrfs/block-group.c +++ b/fs/btrfs/block-group.c @@ -2484,18 +2484,29 @@ static int insert_block_group_item(struct btrfs_trans_handle *trans, struct btrfs_block_group_item bgi; struct btrfs_root *root = btrfs_block_group_root(fs_info); struct btrfs_key key; + u64 old_commit_used; + int ret; spin_lock(&block_group->lock); btrfs_set_stack_block_group_used(&bgi, block_group->used); btrfs_set_stack_block_group_chunk_objectid(&bgi, block_group->global_root_id); btrfs_set_stack_block_group_flags(&bgi, block_group->flags); + old_commit_used = block_group->commit_used; + block_group->commit_used = block_group->used; key.objectid = block_group->start; key.type = BTRFS_BLOCK_GROUP_ITEM_KEY; key.offset = block_group->length; spin_unlock(&block_group->lock); - return btrfs_insert_item(trans, root, &key, &bgi, sizeof(bgi)); + ret = btrfs_insert_item(trans, root, &key, &bgi, sizeof(bgi)); + if (ret < 0) { + spin_lock(&block_group->lock); + block_group->commit_used = old_commit_used; + spin_unlock(&block_group->lock); + } + + return ret; } static int insert_dev_extent(struct btrfs_trans_handle *trans, From ffec85d53d0f39ee4680a2cf0795255e000e1feb Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 2 Feb 2023 16:55:03 -0800 Subject: [PATCH 242/778] ext4: fix cgroup writeback accounting with fs-layer encryption When writing a page from an encrypted file that is using filesystem-layer encryption (not inline encryption), ext4 encrypts the pagecache page into a bounce page, then writes the bounce page. It also passes the bounce page to wbc_account_cgroup_owner(). That's incorrect, because the bounce page is a newly allocated temporary page that doesn't have the memory cgroup of the original pagecache page. This makes wbc_account_cgroup_owner() not account the I/O to the owner of the pagecache page as it should. Fix this by always passing the pagecache page to wbc_account_cgroup_owner(). Fixes: 001e4a8775f6 ("ext4: implement cgroup writeback support") Cc: stable@vger.kernel.org Reported-by: Matthew Wilcox (Oracle) Signed-off-by: Eric Biggers Acked-by: Tejun Heo Link: https://lore.kernel.org/r/20230203005503.141557-1-ebiggers@kernel.org Signed-off-by: Theodore Ts'o --- fs/ext4/page-io.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c index beaec6d81074..1e4db96a04e6 100644 --- a/fs/ext4/page-io.c +++ b/fs/ext4/page-io.c @@ -409,7 +409,8 @@ static void io_submit_init_bio(struct ext4_io_submit *io, static void io_submit_add_bh(struct ext4_io_submit *io, struct inode *inode, - struct page *page, + struct page *pagecache_page, + struct page *bounce_page, struct buffer_head *bh) { int ret; @@ -421,10 +422,11 @@ submit_and_retry: } if (io->io_bio == NULL) io_submit_init_bio(io, bh); - ret = bio_add_page(io->io_bio, page, bh->b_size, bh_offset(bh)); + ret = bio_add_page(io->io_bio, bounce_page ?: pagecache_page, + bh->b_size, bh_offset(bh)); if (ret != bh->b_size) goto submit_and_retry; - wbc_account_cgroup_owner(io->io_wbc, page, bh->b_size); + wbc_account_cgroup_owner(io->io_wbc, pagecache_page, bh->b_size); io->io_next_block++; } @@ -561,8 +563,7 @@ int ext4_bio_write_page(struct ext4_io_submit *io, do { if (!buffer_async_write(bh)) continue; - io_submit_add_bh(io, inode, - bounce_page ? bounce_page : page, bh); + io_submit_add_bh(io, inode, page, bounce_page, bh); } while ((bh = bh->b_this_page) != head); unlock: unlock_page(page); From 60db00e0a1490adcdc8b80887f7caf954d8bcd3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Thu, 9 Feb 2023 03:18:35 +0000 Subject: [PATCH 243/778] ext4: make kobj_type structures constant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since commit ee6d3dd4ed48 ("driver core: make kobj_type constant.") the driver core allows the usage of const struct kobj_type. Take advantage of this to constify the structure definitions to prevent modification at runtime. Signed-off-by: Thomas Weißschuh Reviewed-by: Jan Kara Link: https://lore.kernel.org/r/20230209-kobj_type-ext4-v1-1-6865fb05c1f8@weissschuh.net Signed-off-by: Theodore Ts'o --- fs/ext4/sysfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/ext4/sysfs.c b/fs/ext4/sysfs.c index e2b8b3437c58..12d6252e3e22 100644 --- a/fs/ext4/sysfs.c +++ b/fs/ext4/sysfs.c @@ -501,13 +501,13 @@ static const struct sysfs_ops ext4_attr_ops = { .store = ext4_attr_store, }; -static struct kobj_type ext4_sb_ktype = { +static const struct kobj_type ext4_sb_ktype = { .default_groups = ext4_groups, .sysfs_ops = &ext4_attr_ops, .release = ext4_sb_release, }; -static struct kobj_type ext4_feat_ktype = { +static const struct kobj_type ext4_feat_ktype = { .default_groups = ext4_feat_groups, .sysfs_ops = &ext4_attr_ops, .release = ext4_feat_release, From c9f62c8b2dbf7240536c0cc9a4529397bb8bf38e Mon Sep 17 00:00:00 2001 From: Eric Whitney Date: Fri, 10 Feb 2023 12:32:44 -0500 Subject: [PATCH 244/778] ext4: fix RENAME_WHITEOUT handling for inline directories A significant number of xfstests can cause ext4 to log one or more warning messages when they are run on a test file system where the inline_data feature has been enabled. An example: "EXT4-fs warning (device vdc): ext4_dirblock_csum_set:425: inode #16385: comm fsstress: No space for directory leaf checksum. Please run e2fsck -D." The xfstests include: ext4/057, 058, and 307; generic/013, 051, 068, 070, 076, 078, 083, 232, 269, 270, 390, 461, 475, 476, 482, 579, 585, 589, 626, 631, and 650. In this situation, the warning message indicates a bug in the code that performs the RENAME_WHITEOUT operation on a directory entry that has been stored inline. It doesn't detect that the directory is stored inline, and incorrectly attempts to compute a dirent block checksum on the whiteout inode when creating it. This attempt fails as a result of the integrity checking in get_dirent_tail (usually due to a failure to match the EXT4_FT_DIR_CSUM magic cookie), and the warning message is then emitted. Fix this by simply collecting the inlined data state at the time the search for the source directory entry is performed. Existing code handles the rest, and this is sufficient to eliminate all spurious warning messages produced by the tests above. Go one step further and do the same in the code that resets the source directory entry in the event of failure. The inlined state should be present in the "old" struct, but given the possibility of a race there's no harm in taking a conservative approach and getting that information again since the directory entry is being reread anyway. Fixes: b7ff91fd030d ("ext4: find old entry again if failed to rename whiteout") Cc: stable@kernel.org Signed-off-by: Eric Whitney Reviewed-by: Jan Kara Link: https://lore.kernel.org/r/20230210173244.679890-1-enwlinux@gmail.com Signed-off-by: Theodore Ts'o --- fs/ext4/namei.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 270fbcba75b6..e8f429330f3c 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -1595,11 +1595,10 @@ static struct buffer_head *__ext4_find_entry(struct inode *dir, int has_inline_data = 1; ret = ext4_find_inline_entry(dir, fname, res_dir, &has_inline_data); - if (has_inline_data) { - if (inlined) - *inlined = 1; + if (inlined) + *inlined = has_inline_data; + if (has_inline_data) goto cleanup_and_exit; - } } if ((namelen <= 2) && (name[0] == '.') && @@ -3646,7 +3645,8 @@ static void ext4_resetent(handle_t *handle, struct ext4_renament *ent, * so the old->de may no longer valid and need to find it again * before reset old inode info. */ - old.bh = ext4_find_entry(old.dir, &old.dentry->d_name, &old.de, NULL); + old.bh = ext4_find_entry(old.dir, &old.dentry->d_name, &old.de, + &old.inlined); if (IS_ERR(old.bh)) retval = PTR_ERR(old.bh); if (!old.bh) @@ -3813,7 +3813,8 @@ static int ext4_rename(struct user_namespace *mnt_userns, struct inode *old_dir, return retval; } - old.bh = ext4_find_entry(old.dir, &old.dentry->d_name, &old.de, NULL); + old.bh = ext4_find_entry(old.dir, &old.dentry->d_name, &old.de, + &old.inlined); if (IS_ERR(old.bh)) return PTR_ERR(old.bh); /* From c993799baf9c5861f8df91beb80e1611b12efcbd Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Thu, 16 Feb 2023 10:55:48 -0800 Subject: [PATCH 245/778] ext4: fix another off-by-one fsmap error on 1k block filesystems Apparently syzbot figured out that issuing this FSMAP call: struct fsmap_head cmd = { .fmh_count = ...; .fmh_keys = { { .fmr_device = /* ext4 dev */, .fmr_physical = 0, }, { .fmr_device = /* ext4 dev */, .fmr_physical = 0, }, }, ... }; ret = ioctl(fd, FS_IOC_GETFSMAP, &cmd); Produces this crash if the underlying filesystem is a 1k-block ext4 filesystem: kernel BUG at fs/ext4/ext4.h:3331! invalid opcode: 0000 [#1] PREEMPT SMP CPU: 3 PID: 3227965 Comm: xfs_io Tainted: G W O 6.2.0-rc8-achx Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.15.0-1 04/01/2014 RIP: 0010:ext4_mb_load_buddy_gfp+0x47c/0x570 [ext4] RSP: 0018:ffffc90007c03998 EFLAGS: 00010246 RAX: ffff888004978000 RBX: ffffc90007c03a20 RCX: ffff888041618000 RDX: 0000000000000000 RSI: 00000000000005a4 RDI: ffffffffa0c99b11 RBP: ffff888012330000 R08: ffffffffa0c2b7d0 R09: 0000000000000400 R10: ffffc90007c03950 R11: 0000000000000000 R12: 0000000000000001 R13: 00000000ffffffff R14: 0000000000000c40 R15: ffff88802678c398 FS: 00007fdf2020c880(0000) GS:ffff88807e100000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007ffd318a5fe8 CR3: 000000007f80f001 CR4: 00000000001706e0 Call Trace: ext4_mballoc_query_range+0x4b/0x210 [ext4 dfa189daddffe8fecd3cdfd00564e0f265a8ab80] ext4_getfsmap_datadev+0x713/0x890 [ext4 dfa189daddffe8fecd3cdfd00564e0f265a8ab80] ext4_getfsmap+0x2b7/0x330 [ext4 dfa189daddffe8fecd3cdfd00564e0f265a8ab80] ext4_ioc_getfsmap+0x153/0x2b0 [ext4 dfa189daddffe8fecd3cdfd00564e0f265a8ab80] __ext4_ioctl+0x2a7/0x17e0 [ext4 dfa189daddffe8fecd3cdfd00564e0f265a8ab80] __x64_sys_ioctl+0x82/0xa0 do_syscall_64+0x2b/0x80 entry_SYSCALL_64_after_hwframe+0x46/0xb0 RIP: 0033:0x7fdf20558aff RSP: 002b:00007ffd318a9e30 EFLAGS: 00000246 ORIG_RAX: 0000000000000010 RAX: ffffffffffffffda RBX: 00000000000200c0 RCX: 00007fdf20558aff RDX: 00007fdf1feb2010 RSI: 00000000c0c0583b RDI: 0000000000000003 RBP: 00005625c0634be0 R08: 00005625c0634c40 R09: 0000000000000001 R10: 0000000000000000 R11: 0000000000000246 R12: 00007fdf1feb2010 R13: 00005625be70d994 R14: 0000000000000800 R15: 0000000000000000 For GETFSMAP calls, the caller selects a physical block device by writing its block number into fsmap_head.fmh_keys[01].fmr_device. To query mappings for a subrange of the device, the starting byte of the range is written to fsmap_head.fmh_keys[0].fmr_physical and the last byte of the range goes in fsmap_head.fmh_keys[1].fmr_physical. IOWs, to query what mappings overlap with bytes 3-14 of /dev/sda, you'd set the inputs as follows: fmh_keys[0] = { .fmr_device = major(8, 0), .fmr_physical = 3}, fmh_keys[1] = { .fmr_device = major(8, 0), .fmr_physical = 14}, Which would return you whatever is mapped in the 12 bytes starting at physical offset 3. The crash is due to insufficient range validation of keys[1] in ext4_getfsmap_datadev. On 1k-block filesystems, block 0 is not part of the filesystem, which means that s_first_data_block is nonzero. ext4_get_group_no_and_offset subtracts this quantity from the blocknr argument before cracking it into a group number and a block number within a group. IOWs, block group 0 spans blocks 1-8192 (1-based) instead of 0-8191 (0-based) like what happens with larger blocksizes. The net result of this encoding is that blocknr < s_first_data_block is not a valid input to this function. The end_fsb variable is set from the keys that are copied from userspace, which means that in the above example, its value is zero. That leads to an underflow here: blocknr = blocknr - le32_to_cpu(es->s_first_data_block); The division then operates on -1: offset = do_div(blocknr, EXT4_BLOCKS_PER_GROUP(sb)) >> EXT4_SB(sb)->s_cluster_bits; Leaving an impossibly large group number (2^32-1) in blocknr. ext4_getfsmap_check_keys checked that keys[0].fmr_physical and keys[1].fmr_physical are in increasing order, but ext4_getfsmap_datadev adjusts keys[0].fmr_physical to be at least s_first_data_block. This implies that we have to check it again after the adjustment, which is the piece that I forgot. Reported-by: syzbot+6be2b977c89f79b6b153@syzkaller.appspotmail.com Fixes: 4a4956249dac ("ext4: fix off-by-one fsmap error on 1k block filesystems") Link: https://syzkaller.appspot.com/bug?id=79d5768e9bfe362911ac1a5057a36fc6b5c30002 Cc: stable@vger.kernel.org Signed-off-by: Darrick J. Wong Link: https://lore.kernel.org/r/Y+58NPTH7VNGgzdd@magnolia Signed-off-by: Theodore Ts'o --- fs/ext4/fsmap.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/ext4/fsmap.c b/fs/ext4/fsmap.c index 4493ef0c715e..cdf9bfe10137 100644 --- a/fs/ext4/fsmap.c +++ b/fs/ext4/fsmap.c @@ -486,6 +486,8 @@ static int ext4_getfsmap_datadev(struct super_block *sb, keys[0].fmr_physical = bofs; if (keys[1].fmr_physical >= eofs) keys[1].fmr_physical = eofs - 1; + if (keys[1].fmr_physical < keys[0].fmr_physical) + return 0; start_fsb = keys[0].fmr_physical; end_fsb = keys[1].fmr_physical; From b7eef407e5271f5135ce97bfd6e2e5009922331e Mon Sep 17 00:00:00 2001 From: Wu Bo Date: Wed, 22 Feb 2023 09:35:24 +0800 Subject: [PATCH 246/778] docs: ext4: modify the group desc size to 64 Since the default ext4 group desc size is 64 now (assuming that the 64-bit feature is enbled). And the size mentioned in this doc is 64 too. Change it to 64. Signed-off-by: Wu Bo Acked-by: Darrick J. Wong Link: https://lore.kernel.org/r/20230222013525.14748-1-bo.wu@vivo.com Signed-off-by: Theodore Ts'o --- Documentation/filesystems/ext4/blockgroup.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/filesystems/ext4/blockgroup.rst b/Documentation/filesystems/ext4/blockgroup.rst index 46d78f860623..ed5a5cac6d40 100644 --- a/Documentation/filesystems/ext4/blockgroup.rst +++ b/Documentation/filesystems/ext4/blockgroup.rst @@ -105,9 +105,9 @@ descriptors. Instead, the superblock and a single block group descriptor block is placed at the beginning of the first, second, and last block groups in a meta-block group. A meta-block group is a collection of block groups which can be described by a single block group descriptor -block. Since the size of the block group descriptor structure is 32 -bytes, a meta-block group contains 32 block groups for filesystems with -a 1KB block size, and 128 block groups for filesystems with a 4KB +block. Since the size of the block group descriptor structure is 64 +bytes, a meta-block group contains 16 block groups for filesystems with +a 1KB block size, and 64 block groups for filesystems with a 4KB blocksize. Filesystems can either be created using this new block group descriptor layout, or existing filesystems can be resized on-line, and the field s_first_meta_bg in the superblock will indicate the first From 7fc1f5c28ae4c615ccc5346f39a7bf4c4e0900ac Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Wed, 1 Mar 2023 13:38:42 +0000 Subject: [PATCH 247/778] ext4: Fix comment about the 64BIT feature 64BIT is part of the incompatible feature set, update the comment accordingly. Signed-off-by: Tudor Ambarus Reviewed-by: Darrick J. Wong Link: https://lore.kernel.org/r/20230301133842.671821-1-tudor.ambarus@linaro.org Signed-off-by: Theodore Ts'o --- fs/ext4/ext4.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 6479146140d2..9dec84fff826 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -1387,7 +1387,7 @@ struct ext4_super_block { __le32 s_first_meta_bg; /* First metablock block group */ __le32 s_mkfs_time; /* When the filesystem was created */ __le32 s_jnl_blocks[17]; /* Backup of the journal inode */ - /* 64bit support valid if EXT4_FEATURE_COMPAT_64BIT */ + /* 64bit support valid if EXT4_FEATURE_INCOMPAT_64BIT */ /*150*/ __le32 s_blocks_count_hi; /* Blocks count */ __le32 s_r_blocks_count_hi; /* Reserved blocks count */ __le32 s_free_blocks_count_hi; /* Free blocks count */ From 3c92792da8506a295afb6d032b4476e46f979725 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 1 Mar 2023 15:10:04 +0100 Subject: [PATCH 248/778] ext4: Fix deadlock during directory rename As lockdep properly warns, we should not be locking i_rwsem while having transactions started as the proper lock ordering used by all directory handling operations is i_rwsem -> transaction start. Fix the lock ordering by moving the locking of the directory earlier in ext4_rename(). Reported-by: syzbot+9d16c39efb5fade84574@syzkaller.appspotmail.com Fixes: 0813299c586b ("ext4: Fix possible corruption when moving a directory") Link: https://syzkaller.appspot.com/bug?extid=9d16c39efb5fade84574 Signed-off-by: Jan Kara Link: https://lore.kernel.org/r/20230301141004.15087-1-jack@suse.cz Signed-off-by: Theodore Ts'o --- fs/ext4/namei.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index e8f429330f3c..7cc3918e2f18 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -3813,10 +3813,20 @@ static int ext4_rename(struct user_namespace *mnt_userns, struct inode *old_dir, return retval; } + /* + * We need to protect against old.inode directory getting converted + * from inline directory format into a normal one. + */ + if (S_ISDIR(old.inode->i_mode)) + inode_lock_nested(old.inode, I_MUTEX_NONDIR2); + old.bh = ext4_find_entry(old.dir, &old.dentry->d_name, &old.de, &old.inlined); - if (IS_ERR(old.bh)) - return PTR_ERR(old.bh); + if (IS_ERR(old.bh)) { + retval = PTR_ERR(old.bh); + goto unlock_moved_dir; + } + /* * Check for inode number is _not_ due to possible IO errors. * We might rmdir the source, keep it as pwd of some process @@ -3873,11 +3883,6 @@ static int ext4_rename(struct user_namespace *mnt_userns, struct inode *old_dir, if (new.dir != old.dir && EXT4_DIR_LINK_MAX(new.dir)) goto end_rename; } - /* - * We need to protect against old.inode directory getting - * converted from inline directory format into a normal one. - */ - inode_lock_nested(old.inode, I_MUTEX_NONDIR2); retval = ext4_rename_dir_prepare(handle, &old); if (retval) { inode_unlock(old.inode); @@ -4014,12 +4019,15 @@ end_rename: } else { ext4_journal_stop(handle); } - if (old.dir_bh) - inode_unlock(old.inode); release_bh: brelse(old.dir_bh); brelse(old.bh); brelse(new.bh); + +unlock_moved_dir: + if (S_ISDIR(old.inode->i_mode)) + inode_unlock(old.inode); + return retval; } From 03e1d60e177eedbd302b77af4ea5e21b5a7ade31 Mon Sep 17 00:00:00 2001 From: David Disseldorp Date: Tue, 7 Mar 2023 16:21:06 +0100 Subject: [PATCH 249/778] watch_queue: fix IOC_WATCH_QUEUE_SET_SIZE alloc error paths The watch_queue_set_size() allocation error paths return the ret value set via the prior pipe_resize_ring() call, which will always be zero. As a result, IOC_WATCH_QUEUE_SET_SIZE callers such as "keyctl watch" fail to detect kernel wqueue->notes allocation failures and proceed to KEYCTL_WATCH_KEY, with any notifications subsequently lost. Fixes: c73be61cede58 ("pipe: Add general notification queue support") Signed-off-by: David Disseldorp Signed-off-by: Christian Brauner (Microsoft) --- kernel/watch_queue.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/watch_queue.c b/kernel/watch_queue.c index a6f9bdd956c3..f10f403104e7 100644 --- a/kernel/watch_queue.c +++ b/kernel/watch_queue.c @@ -273,6 +273,7 @@ long watch_queue_set_size(struct pipe_inode_info *pipe, unsigned int nr_notes) if (ret < 0) goto error; + ret = -ENOMEM; pages = kcalloc(sizeof(struct page *), nr_pages, GFP_KERNEL); if (!pages) goto error; From a402f1e35313fc7ce2ca60f543c4402c2c7c3544 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Wed, 8 Mar 2023 11:51:26 +0100 Subject: [PATCH 250/778] fork: allow CLONE_NEWTIME in clone3 flags Currently, calling clone3() with CLONE_NEWTIME in clone_args->flags fails with -EINVAL. This is because CLONE_NEWTIME intersects with CSIGNAL. However, CSIGNAL was deprecated when clone3 was introduced in commit 7f192e3cd316 ("fork: add clone3"), allowing re-use of that part of clone flags. Fix this by explicitly allowing CLONE_NEWTIME in clone3_args_valid. This is also in line with the respective check in check_unshare_flags which allow CLONE_NEWTIME for unshare(). Fixes: 769071ac9f20 ("ns: Introduce Time Namespace") Cc: Andrey Vagin Cc: Christian Brauner Cc: stable@vger.kernel.org Signed-off-by: Tobias Klauser Reviewed-by: Christian Brauner Signed-off-by: Christian Brauner (Microsoft) --- kernel/fork.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/fork.c b/kernel/fork.c index f68954d05e89..d8cda4c6de6c 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -2936,7 +2936,7 @@ static bool clone3_args_valid(struct kernel_clone_args *kargs) * - make the CLONE_DETACHED bit reusable for clone3 * - make the CSIGNAL bits reusable for clone3 */ - if (kargs->flags & (CLONE_DETACHED | CSIGNAL)) + if (kargs->flags & (CLONE_DETACHED | (CSIGNAL & (~CLONE_NEWTIME)))) return false; if ((kargs->flags & (CLONE_SIGHAND | CLONE_CLEAR_SIGHAND)) == From 515bddf0ec4155cbd666d72daf5bd68c8b7cd987 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Wed, 8 Mar 2023 11:53:20 +0100 Subject: [PATCH 251/778] selftests/clone3: test clone3 with CLONE_NEWTIME Verify that clone3 can be called successfully with CLONE_NEWTIME in flags. Cc: Andrey Vagin Cc: Christian Brauner Cc: Shuah Khan Signed-off-by: Tobias Klauser Signed-off-by: Christian Brauner (Microsoft) --- tools/testing/selftests/clone3/clone3.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/testing/selftests/clone3/clone3.c b/tools/testing/selftests/clone3/clone3.c index cd4582129c7d..4fce46afe6db 100644 --- a/tools/testing/selftests/clone3/clone3.c +++ b/tools/testing/selftests/clone3/clone3.c @@ -195,5 +195,8 @@ int main(int argc, char *argv[]) test_clone3(CLONE_NEWPID, getpagesize() + 8, -E2BIG, CLONE3_ARGS_NO_TEST); + /* Do a clone3() in a new time namespace */ + test_clone3(CLONE_NEWTIME, 0, 0, CLONE3_ARGS_NO_TEST); + return !ksft_get_fail_cnt() ? ksft_exit_pass() : ksft_exit_fail(); } From ce7ca794712f186da99719e8b4e97bd5ddbb04c3 Mon Sep 17 00:00:00 2001 From: "D. Wythe" Date: Tue, 7 Mar 2023 11:23:46 +0800 Subject: [PATCH 252/778] net/smc: fix fallback failed while sendmsg with fastopen Before determining whether the msg has unsupported options, it has been prematurely terminated by the wrong status check. For the application, the general usages of MSG_FASTOPEN likes fd = socket(...) /* rather than connect */ sendto(fd, data, len, MSG_FASTOPEN) Hence, We need to check the flag before state check, because the sock state here is always SMC_INIT when applications tries MSG_FASTOPEN. Once we found unsupported options, fallback it to TCP. Fixes: ee9dfbef02d1 ("net/smc: handle sockopts forcing fallback") Signed-off-by: D. Wythe Signed-off-by: Simon Horman v2 -> v1: Optimize code style Reviewed-by: Tony Lu Signed-off-by: David S. Miller --- net/smc/af_smc.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c index a4cccdfdc00a..ff6dd86bdc9f 100644 --- a/net/smc/af_smc.c +++ b/net/smc/af_smc.c @@ -2657,16 +2657,14 @@ static int smc_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) { struct sock *sk = sock->sk; struct smc_sock *smc; - int rc = -EPIPE; + int rc; smc = smc_sk(sk); lock_sock(sk); - if ((sk->sk_state != SMC_ACTIVE) && - (sk->sk_state != SMC_APPCLOSEWAIT1) && - (sk->sk_state != SMC_INIT)) - goto out; + /* SMC does not support connect with fastopen */ if (msg->msg_flags & MSG_FASTOPEN) { + /* not connected yet, fallback */ if (sk->sk_state == SMC_INIT && !smc->connect_nonblock) { rc = smc_switch_to_fallback(smc, SMC_CLC_DECL_OPTUNSUPP); if (rc) @@ -2675,6 +2673,11 @@ static int smc_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) rc = -EINVAL; goto out; } + } else if ((sk->sk_state != SMC_ACTIVE) && + (sk->sk_state != SMC_APPCLOSEWAIT1) && + (sk->sk_state != SMC_INIT)) { + rc = -EPIPE; + goto out; } if (smc->use_fallback) { From ea9dd2e5c6d12c8b65ce7514c8359a70eeaa0e70 Mon Sep 17 00:00:00 2001 From: Suman Ghosh Date: Tue, 7 Mar 2023 16:19:08 +0530 Subject: [PATCH 253/778] octeontx2-af: Unlock contexts in the queue context cache in case of fault detection NDC caches contexts of frequently used queue's (Rx and Tx queues) contexts. Due to a HW errata when NDC detects fault/poision while accessing contexts it could go into an illegal state where a cache line could get locked forever. To makesure all cache lines in NDC are available for optimum performance upon fault/lockerror/posion errors scan through all cache lines in NDC and clear the lock bit. Fixes: 4a3581cd5995 ("octeontx2-af: NPA AQ instruction enqueue support") Signed-off-by: Suman Ghosh Signed-off-by: Sunil Kovvuri Goutham Signed-off-by: Sai Krishna Reviewed-by: Simon Horman Signed-off-by: David S. Miller --- .../net/ethernet/marvell/octeontx2/af/rvu.h | 5 ++ .../marvell/octeontx2/af/rvu_debugfs.c | 7 +-- .../ethernet/marvell/octeontx2/af/rvu_nix.c | 16 ++++- .../ethernet/marvell/octeontx2/af/rvu_npa.c | 58 ++++++++++++++++++- .../ethernet/marvell/octeontx2/af/rvu_reg.h | 3 + 5 files changed, 82 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h index 389663a13d1d..ef721caeac49 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h @@ -884,6 +884,9 @@ int rvu_cpt_lf_teardown(struct rvu *rvu, u16 pcifunc, int blkaddr, int lf, int rvu_cpt_ctx_flush(struct rvu *rvu, u16 pcifunc); int rvu_cpt_init(struct rvu *rvu); +#define NDC_AF_BANK_MASK GENMASK_ULL(7, 0) +#define NDC_AF_BANK_LINE_MASK GENMASK_ULL(31, 16) + /* CN10K RVU */ int rvu_set_channels_base(struct rvu *rvu); void rvu_program_channels(struct rvu *rvu); @@ -902,6 +905,8 @@ static inline void rvu_dbg_init(struct rvu *rvu) {} static inline void rvu_dbg_exit(struct rvu *rvu) {} #endif +int rvu_ndc_fix_locked_cacheline(struct rvu *rvu, int blkaddr); + /* RVU Switch */ void rvu_switch_enable(struct rvu *rvu); void rvu_switch_disable(struct rvu *rvu); diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c index fa280ebd3052..26cfa501f1a1 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c @@ -198,9 +198,6 @@ enum cpt_eng_type { CPT_IE_TYPE = 3, }; -#define NDC_MAX_BANK(rvu, blk_addr) (rvu_read64(rvu, \ - blk_addr, NDC_AF_CONST) & 0xFF) - #define rvu_dbg_NULL NULL #define rvu_dbg_open_NULL NULL @@ -1448,6 +1445,7 @@ static int ndc_blk_hits_miss_stats(struct seq_file *s, int idx, int blk_addr) struct nix_hw *nix_hw; struct rvu *rvu; int bank, max_bank; + u64 ndc_af_const; if (blk_addr == BLKADDR_NDC_NPA0) { rvu = s->private; @@ -1456,7 +1454,8 @@ static int ndc_blk_hits_miss_stats(struct seq_file *s, int idx, int blk_addr) rvu = nix_hw->rvu; } - max_bank = NDC_MAX_BANK(rvu, blk_addr); + ndc_af_const = rvu_read64(rvu, blk_addr, NDC_AF_CONST); + max_bank = FIELD_GET(NDC_AF_BANK_MASK, ndc_af_const); for (bank = 0; bank < max_bank; bank++) { seq_printf(s, "BANK:%d\n", bank); seq_printf(s, "\tHits:\t%lld\n", diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c index 26e639e57dae..4ad707e758b9 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c @@ -790,6 +790,7 @@ static int nix_aq_enqueue_wait(struct rvu *rvu, struct rvu_block *block, struct nix_aq_res_s *result; int timeout = 1000; u64 reg, head; + int ret; result = (struct nix_aq_res_s *)aq->res->base; @@ -813,9 +814,22 @@ static int nix_aq_enqueue_wait(struct rvu *rvu, struct rvu_block *block, return -EBUSY; } - if (result->compcode != NIX_AQ_COMP_GOOD) + if (result->compcode != NIX_AQ_COMP_GOOD) { /* TODO: Replace this with some error code */ + if (result->compcode == NIX_AQ_COMP_CTX_FAULT || + result->compcode == NIX_AQ_COMP_LOCKERR || + result->compcode == NIX_AQ_COMP_CTX_POISON) { + ret = rvu_ndc_fix_locked_cacheline(rvu, BLKADDR_NDC_NIX0_RX); + ret |= rvu_ndc_fix_locked_cacheline(rvu, BLKADDR_NDC_NIX0_TX); + ret |= rvu_ndc_fix_locked_cacheline(rvu, BLKADDR_NDC_NIX1_RX); + ret |= rvu_ndc_fix_locked_cacheline(rvu, BLKADDR_NDC_NIX1_TX); + if (ret) + dev_err(rvu->dev, + "%s: Not able to unlock cachelines\n", __func__); + } + return -EBUSY; + } return 0; } diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npa.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npa.c index 70bd036ed76e..4f5ca5ab13a4 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npa.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npa.c @@ -4,7 +4,7 @@ * Copyright (C) 2018 Marvell. * */ - +#include #include #include @@ -42,9 +42,18 @@ static int npa_aq_enqueue_wait(struct rvu *rvu, struct rvu_block *block, return -EBUSY; } - if (result->compcode != NPA_AQ_COMP_GOOD) + if (result->compcode != NPA_AQ_COMP_GOOD) { /* TODO: Replace this with some error code */ + if (result->compcode == NPA_AQ_COMP_CTX_FAULT || + result->compcode == NPA_AQ_COMP_LOCKERR || + result->compcode == NPA_AQ_COMP_CTX_POISON) { + if (rvu_ndc_fix_locked_cacheline(rvu, BLKADDR_NDC_NPA0)) + dev_err(rvu->dev, + "%s: Not able to unlock cachelines\n", __func__); + } + return -EBUSY; + } return 0; } @@ -545,3 +554,48 @@ void rvu_npa_lf_teardown(struct rvu *rvu, u16 pcifunc, int npalf) npa_ctx_free(rvu, pfvf); } + +/* Due to an Hardware errata, in some corner cases, AQ context lock + * operations can result in a NDC way getting into an illegal state + * of not valid but locked. + * + * This API solves the problem by clearing the lock bit of the NDC block. + * The operation needs to be done for each line of all the NDC banks. + */ +int rvu_ndc_fix_locked_cacheline(struct rvu *rvu, int blkaddr) +{ + int bank, max_bank, line, max_line, err; + u64 reg, ndc_af_const; + + /* Set the ENABLE bit(63) to '0' */ + reg = rvu_read64(rvu, blkaddr, NDC_AF_CAMS_RD_INTERVAL); + rvu_write64(rvu, blkaddr, NDC_AF_CAMS_RD_INTERVAL, reg & GENMASK_ULL(62, 0)); + + /* Poll until the BUSY bits(47:32) are set to '0' */ + err = rvu_poll_reg(rvu, blkaddr, NDC_AF_CAMS_RD_INTERVAL, GENMASK_ULL(47, 32), true); + if (err) { + dev_err(rvu->dev, "Timed out while polling for NDC CAM busy bits.\n"); + return err; + } + + ndc_af_const = rvu_read64(rvu, blkaddr, NDC_AF_CONST); + max_bank = FIELD_GET(NDC_AF_BANK_MASK, ndc_af_const); + max_line = FIELD_GET(NDC_AF_BANK_LINE_MASK, ndc_af_const); + for (bank = 0; bank < max_bank; bank++) { + for (line = 0; line < max_line; line++) { + /* Check if 'cache line valid bit(63)' is not set + * but 'cache line lock bit(60)' is set and on + * success, reset the lock bit(60). + */ + reg = rvu_read64(rvu, blkaddr, + NDC_AF_BANKX_LINEX_METADATA(bank, line)); + if (!(reg & BIT_ULL(63)) && (reg & BIT_ULL(60))) { + rvu_write64(rvu, blkaddr, + NDC_AF_BANKX_LINEX_METADATA(bank, line), + reg & ~BIT_ULL(60)); + } + } + } + + return 0; +} diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_reg.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu_reg.h index 1729b22580ce..7007f0b8e659 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_reg.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_reg.h @@ -694,6 +694,7 @@ #define NDC_AF_INTR_ENA_W1S (0x00068) #define NDC_AF_INTR_ENA_W1C (0x00070) #define NDC_AF_ACTIVE_PC (0x00078) +#define NDC_AF_CAMS_RD_INTERVAL (0x00080) #define NDC_AF_BP_TEST_ENABLE (0x001F8) #define NDC_AF_BP_TEST(a) (0x00200 | (a) << 3) #define NDC_AF_BLK_RST (0x002F0) @@ -709,6 +710,8 @@ (0x00F00 | (a) << 5 | (b) << 4) #define NDC_AF_BANKX_HIT_PC(a) (0x01000 | (a) << 3) #define NDC_AF_BANKX_MISS_PC(a) (0x01100 | (a) << 3) +#define NDC_AF_BANKX_LINEX_METADATA(a, b) \ + (0x10000 | (a) << 12 | (b) << 3) /* LBK */ #define LBK_CONST (0x10ull) From cdd28833100c18a469c85a1cc3de9f6bbbe6caa0 Mon Sep 17 00:00:00 2001 From: Daniel Machon Date: Tue, 7 Mar 2023 12:21:03 +0100 Subject: [PATCH 254/778] net: microchip: sparx5: fix deletion of existing DSCP mappings Fix deletion of existing DSCP mappings in the APP table. Adding and deleting DSCP entries are replicated per-port, since the mapping table is global for all ports in the chip. Whenever a mapping for a DSCP value already exists, the old mapping is deleted first. However, it is only deleted for the specified port. Fix this by calling sparx5_dcb_ieee_delapp() instead of dcb_ieee_delapp() as it ought to be. Reproduce: // Map and remap DSCP value 63 $ dcb app add dev eth0 dscp-prio 63:1 $ dcb app add dev eth0 dscp-prio 63:2 $ dcb app show dev eth0 dscp-prio dscp-prio 63:2 $ dcb app show dev eth1 dscp-prio dscp-prio 63:1 63:2 <-- 63:1 should not be there Fixes: 8dcf69a64118 ("net: microchip: sparx5: add support for offloading dscp table") Signed-off-by: Daniel Machon Reviewed-by: Simon Horman Signed-off-by: David S. Miller --- .../ethernet/microchip/sparx5/sparx5_dcb.c | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_dcb.c b/drivers/net/ethernet/microchip/sparx5/sparx5_dcb.c index 871a3e62f852..2d763664dcda 100644 --- a/drivers/net/ethernet/microchip/sparx5/sparx5_dcb.c +++ b/drivers/net/ethernet/microchip/sparx5/sparx5_dcb.c @@ -249,6 +249,21 @@ static int sparx5_dcb_ieee_dscp_setdel(struct net_device *dev, return 0; } +static int sparx5_dcb_ieee_delapp(struct net_device *dev, struct dcb_app *app) +{ + int err; + + if (app->selector == IEEE_8021QAZ_APP_SEL_DSCP) + err = sparx5_dcb_ieee_dscp_setdel(dev, app, dcb_ieee_delapp); + else + err = dcb_ieee_delapp(dev, app); + + if (err < 0) + return err; + + return sparx5_dcb_app_update(dev); +} + static int sparx5_dcb_ieee_setapp(struct net_device *dev, struct dcb_app *app) { struct dcb_app app_itr; @@ -264,7 +279,7 @@ static int sparx5_dcb_ieee_setapp(struct net_device *dev, struct dcb_app *app) if (prio) { app_itr = *app; app_itr.priority = prio; - dcb_ieee_delapp(dev, &app_itr); + sparx5_dcb_ieee_delapp(dev, &app_itr); } if (app->selector == IEEE_8021QAZ_APP_SEL_DSCP) @@ -281,21 +296,6 @@ out: return err; } -static int sparx5_dcb_ieee_delapp(struct net_device *dev, struct dcb_app *app) -{ - int err; - - if (app->selector == IEEE_8021QAZ_APP_SEL_DSCP) - err = sparx5_dcb_ieee_dscp_setdel(dev, app, dcb_ieee_delapp); - else - err = dcb_ieee_delapp(dev, app); - - if (err < 0) - return err; - - return sparx5_dcb_app_update(dev); -} - static int sparx5_dcb_setapptrust(struct net_device *dev, u8 *selectors, int nselectors) { From 9ca6705d9d609441d34f8b853e1e4a6369b3b171 Mon Sep 17 00:00:00 2001 From: Benjamin Coddington Date: Fri, 3 Mar 2023 16:08:32 -0500 Subject: [PATCH 255/778] SUNRPC: Fix a server shutdown leak Fix a race where kthread_stop() may prevent the threadfn from ever getting called. If that happens the svc_rqst will not be cleaned up. Fixes: ed6473ddc704 ("NFSv4: Fix callback server shutdown") Signed-off-by: Benjamin Coddington Reviewed-by: Jeff Layton Signed-off-by: Chuck Lever --- net/sunrpc/svc.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index 1fd3f5e57285..fea7ce8fba14 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c @@ -798,6 +798,7 @@ svc_start_kthreads(struct svc_serv *serv, struct svc_pool *pool, int nrservs) static int svc_stop_kthreads(struct svc_serv *serv, struct svc_pool *pool, int nrservs) { + struct svc_rqst *rqstp; struct task_struct *task; unsigned int state = serv->sv_nrthreads-1; @@ -806,7 +807,10 @@ svc_stop_kthreads(struct svc_serv *serv, struct svc_pool *pool, int nrservs) task = choose_victim(serv, pool, &state); if (task == NULL) break; - kthread_stop(task); + rqstp = kthread_data(task); + /* Did we lose a race to svo_function threadfn? */ + if (kthread_stop(task) == -EINTR) + svc_exit_thread(rqstp); nrservs++; } while (nrservs < 0); return 0; From e2f2a39452c43b64ea3191642a2661cb8d03827a Mon Sep 17 00:00:00 2001 From: Yu Kuai Date: Wed, 8 Mar 2023 10:32:08 +0800 Subject: [PATCH 256/778] block, bfq: fix uaf for 'stable_merge_bfqq' Before commit fd571df0ac5b ("block, bfq: turn bfqq_data into an array in bfq_io_cq"), process reference is read before bfq_put_stable_ref(), and it's safe if bfq_put_stable_ref() put the last reference, because process reference will be 0 and 'stable_merge_bfqq' won't be accessed in this case. However, the commit changed the order and will cause uaf for 'stable_merge_bfqq'. In order to emphasize that bfq_put_stable_ref() can drop the last reference, fix the problem by moving bfq_put_stable_ref() to the end of bfq_setup_stable_merge(). Fixes: fd571df0ac5b ("block, bfq: turn bfqq_data into an array in bfq_io_cq") Reported-and-tested-by: Shinichiro Kawasaki Link: https://lore.kernel.org/linux-block/20230307071448.rzihxbm4jhbf5krj@shindev/ Signed-off-by: Yu Kuai Reviewed-by: Jan Kara Signed-off-by: Jens Axboe --- block/bfq-iosched.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c index 8a8d4441519c..d9ed3108c17a 100644 --- a/block/bfq-iosched.c +++ b/block/bfq-iosched.c @@ -2854,11 +2854,11 @@ bfq_setup_stable_merge(struct bfq_data *bfqd, struct bfq_queue *bfqq, { int proc_ref = min(bfqq_process_refs(bfqq), bfqq_process_refs(stable_merge_bfqq)); - struct bfq_queue *new_bfqq; + struct bfq_queue *new_bfqq = NULL; - if (idling_boosts_thr_without_issues(bfqd, bfqq) || - proc_ref == 0) - return NULL; + bfqq_data->stable_merge_bfqq = NULL; + if (idling_boosts_thr_without_issues(bfqd, bfqq) || proc_ref == 0) + goto out; /* next function will take at least one ref */ new_bfqq = bfq_setup_merge(bfqq, stable_merge_bfqq); @@ -2873,6 +2873,11 @@ bfq_setup_stable_merge(struct bfq_data *bfqd, struct bfq_queue *bfqq, new_bfqq_data->stably_merged = true; } } + +out: + /* deschedule stable merge, because done or aborted here */ + bfq_put_stable_ref(stable_merge_bfqq); + return new_bfqq; } @@ -2933,11 +2938,6 @@ bfq_setup_cooperator(struct bfq_data *bfqd, struct bfq_queue *bfqq, struct bfq_queue *stable_merge_bfqq = bfqq_data->stable_merge_bfqq; - /* deschedule stable merge, because done or aborted here */ - bfq_put_stable_ref(stable_merge_bfqq); - - bfqq_data->stable_merge_bfqq = NULL; - return bfq_setup_stable_merge(bfqd, bfqq, stable_merge_bfqq, bfqq_data); From df6380dca2727bca62efdf332eaadd2e225f7c4d Mon Sep 17 00:00:00 2001 From: V sujith kumar Reddy Date: Wed, 8 Mar 2023 14:15:08 +0530 Subject: [PATCH 257/778] ASoC: SOF: amd: Add pcm pointer callback for amd platforms. Add pcm pointer callback for amd platforms to read host position update from stream box. Signed-off-by: V sujith kumar Reddy Link: https://lore.kernel.org/r/20230308084509.1496256-2-Vsujithkumar.Reddy@amd.com Signed-off-by: Mark Brown --- sound/soc/sof/amd/acp-common.c | 1 + sound/soc/sof/amd/acp-pcm.c | 33 +++++++++++++++++++++++++++++++++ sound/soc/sof/amd/acp.h | 2 ++ 3 files changed, 36 insertions(+) diff --git a/sound/soc/sof/amd/acp-common.c b/sound/soc/sof/amd/acp-common.c index bd6c1b198736..8ce4c8956933 100644 --- a/sound/soc/sof/amd/acp-common.c +++ b/sound/soc/sof/amd/acp-common.c @@ -187,6 +187,7 @@ struct snd_sof_dsp_ops sof_acp_common_ops = { .pcm_open = acp_pcm_open, .pcm_close = acp_pcm_close, .pcm_hw_params = acp_pcm_hw_params, + .pcm_pointer = acp_pcm_pointer, .hw_info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | diff --git a/sound/soc/sof/amd/acp-pcm.c b/sound/soc/sof/amd/acp-pcm.c index 727c3a784a20..f342f0bac4a3 100644 --- a/sound/soc/sof/amd/acp-pcm.c +++ b/sound/soc/sof/amd/acp-pcm.c @@ -84,3 +84,36 @@ int acp_pcm_close(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream) return acp_dsp_stream_put(sdev, stream); } EXPORT_SYMBOL_NS(acp_pcm_close, SND_SOC_SOF_AMD_COMMON); + +snd_pcm_uframes_t acp_pcm_pointer(struct snd_sof_dev *sdev, + struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_soc_component *scomp = sdev->component; + struct snd_sof_pcm_stream *stream; + struct sof_ipc_stream_posn posn; + struct snd_sof_pcm *spcm; + snd_pcm_uframes_t pos; + int ret; + + spcm = snd_sof_find_spcm_dai(scomp, rtd); + if (!spcm) { + dev_warn_ratelimited(sdev->dev, "warn: can't find PCM with DAI ID %d\n", + rtd->dai_link->id); + return 0; + } + + stream = &spcm->stream[substream->stream]; + ret = snd_sof_ipc_msg_data(sdev, stream, &posn, sizeof(posn)); + if (ret < 0) { + dev_warn(sdev->dev, "failed to read stream position: %d\n", ret); + return 0; + } + + memcpy(&stream->posn, &posn, sizeof(posn)); + pos = spcm->stream[substream->stream].posn.host_posn; + pos = bytes_to_frames(substream->runtime, pos); + + return pos; +} +EXPORT_SYMBOL_NS(acp_pcm_pointer, SND_SOC_SOF_AMD_COMMON); diff --git a/sound/soc/sof/amd/acp.h b/sound/soc/sof/amd/acp.h index 39165ebf684b..acad57947616 100644 --- a/sound/soc/sof/amd/acp.h +++ b/sound/soc/sof/amd/acp.h @@ -238,6 +238,8 @@ int acp_pcm_close(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream) int acp_pcm_hw_params(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_sof_platform_stream_params *platform_params); +snd_pcm_uframes_t acp_pcm_pointer(struct snd_sof_dev *sdev, + struct snd_pcm_substream *substream); extern struct snd_sof_dsp_ops sof_acp_common_ops; From b7f5c11761691a6f330411cb0490c6d0ee16c5f0 Mon Sep 17 00:00:00 2001 From: V sujith kumar Reddy Date: Wed, 8 Mar 2023 14:15:09 +0530 Subject: [PATCH 258/778] ASoC: SOF: amd: Enable cont_update_posn variable in pcm hw_params. Enable cont_update_posn variable to update host position in streambox for every dma copy. Signed-off-by: V sujith kumar Reddy Link: https://lore.kernel.org/r/20230308084509.1496256-3-Vsujithkumar.Reddy@amd.com Signed-off-by: Mark Brown --- sound/soc/sof/amd/acp-pcm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/sof/amd/acp-pcm.c b/sound/soc/sof/amd/acp-pcm.c index f342f0bac4a3..0828245bbb99 100644 --- a/sound/soc/sof/amd/acp-pcm.c +++ b/sound/soc/sof/amd/acp-pcm.c @@ -39,6 +39,7 @@ int acp_pcm_hw_params(struct snd_sof_dev *sdev, struct snd_pcm_substream *substr platform_params->use_phy_address = true; platform_params->phy_addr = stream->reg_offset; platform_params->stream_tag = stream->stream_tag; + platform_params->cont_update_posn = 1; /* write buffer size of stream in scratch memory */ From 5b8e5319affc977d24b8ce7edd295907e969e217 Mon Sep 17 00:00:00 2001 From: Lukas Bulwahn Date: Wed, 8 Mar 2023 15:36:40 +0100 Subject: [PATCH 259/778] MAINTAINERS: repair a malformed T: entry in IDMAPPED MOUNTS The T: entries shall be composed of a SCM tree type (git, hg, quilt, stgit or topgit) and location. Add the SCM tree type to the T: entry and reorder the file entries in alphabetical order. Fixes: ddc84c90538e ("MAINTAINERS: update idmapping tree") Signed-off-by: Lukas Bulwahn Signed-off-by: Christian Brauner (Microsoft) --- MAINTAINERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 8d5bc223f305..2c2e54e2cd67 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9871,10 +9871,10 @@ M: Christian Brauner M: Seth Forshee L: linux-fsdevel@vger.kernel.org S: Maintained -T: git://git.kernel.org/pub/scm/linux/kernel/git/vfs/idmapping.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/vfs/idmapping.git F: Documentation/filesystems/idmappings.rst -F: tools/testing/selftests/mount_setattr/ F: include/linux/mnt_idmapping.* +F: tools/testing/selftests/mount_setattr/ IDT VersaClock 5 CLOCK DRIVER M: Luca Ceresoli From 01e68ce08a30db3d842ce7a55f7f6e0474a55f9a Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 8 Mar 2023 07:18:51 -0700 Subject: [PATCH 260/778] io_uring/io-wq: stop setting PF_NO_SETAFFINITY on io-wq workers Every now and then reports come in that are puzzled on why changing affinity on the io-wq workers fails with EINVAL. This happens because they set PF_NO_SETAFFINITY as part of their creation, as io-wq organizes workers into groups based on what CPU they are running on. However, this is purely an optimization and not a functional requirement. We can allow setting affinity, and just lazily update our worker to wqe mappings. If a given io-wq thread times out, it normally exits if there's no more work to do. The exception is if it's the last worker available. For the timeout case, check the affinity of the worker against group mask and exit even if it's the last worker. New workers should be created with the right mask and in the right location. Reported-by:Daniel Dao Link: https://lore.kernel.org/io-uring/CA+wXwBQwgxB3_UphSny-yAP5b26meeOu1W4TwYVcD_+5gOhvPw@mail.gmail.com/ Signed-off-by: Jens Axboe --- io_uring/io-wq.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/io_uring/io-wq.c b/io_uring/io-wq.c index 411bb2d1acd4..f81c0a7136a5 100644 --- a/io_uring/io-wq.c +++ b/io_uring/io-wq.c @@ -616,7 +616,7 @@ static int io_wqe_worker(void *data) struct io_wqe_acct *acct = io_wqe_get_acct(worker); struct io_wqe *wqe = worker->wqe; struct io_wq *wq = wqe->wq; - bool last_timeout = false; + bool exit_mask = false, last_timeout = false; char buf[TASK_COMM_LEN]; worker->flags |= (IO_WORKER_F_UP | IO_WORKER_F_RUNNING); @@ -632,8 +632,11 @@ static int io_wqe_worker(void *data) io_worker_handle_work(worker); raw_spin_lock(&wqe->lock); - /* timed out, exit unless we're the last worker */ - if (last_timeout && acct->nr_workers > 1) { + /* + * Last sleep timed out. Exit if we're not the last worker, + * or if someone modified our affinity. + */ + if (last_timeout && (exit_mask || acct->nr_workers > 1)) { acct->nr_workers--; raw_spin_unlock(&wqe->lock); __set_current_state(TASK_RUNNING); @@ -652,7 +655,11 @@ static int io_wqe_worker(void *data) continue; break; } - last_timeout = !ret; + if (!ret) { + last_timeout = true; + exit_mask = !cpumask_test_cpu(raw_smp_processor_id(), + wqe->cpu_mask); + } } if (test_bit(IO_WQ_BIT_EXIT, &wq->state)) @@ -704,7 +711,6 @@ static void io_init_new_worker(struct io_wqe *wqe, struct io_worker *worker, tsk->worker_private = worker; worker->task = tsk; set_cpus_allowed_ptr(tsk, wqe->cpu_mask); - tsk->flags |= PF_NO_SETAFFINITY; raw_spin_lock(&wqe->lock); hlist_nulls_add_head_rcu(&worker->nulls_node, &wqe->free_list); From b0563468eeac88ebc70559d52a0b66efc37e4e9d Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Tue, 7 Mar 2023 17:46:43 +0000 Subject: [PATCH 261/778] x86/CPU/AMD: Disable XSAVES on AMD family 0x17 AMD Erratum 1386 is summarised as: XSAVES Instruction May Fail to Save XMM Registers to the Provided State Save Area This piece of accidental chronomancy causes the %xmm registers to occasionally reset back to an older value. Ignore the XSAVES feature on all AMD Zen1/2 hardware. The XSAVEC instruction (which works fine) is equivalent on affected parts. [ bp: Typos, move it into the F17h-specific function. ] Reported-by: Tavis Ormandy Signed-off-by: Andrew Cooper Signed-off-by: Borislav Petkov (AMD) Cc: Link: https://lore.kernel.org/r/20230307174643.1240184-1-andrew.cooper3@citrix.com --- arch/x86/kernel/cpu/amd.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index 380753b14cab..95cdd08c4cbb 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -880,6 +880,15 @@ void init_spectral_chicken(struct cpuinfo_x86 *c) } } #endif + /* + * Work around Erratum 1386. The XSAVES instruction malfunctions in + * certain circumstances on Zen1/2 uarch, and not all parts have had + * updated microcode at the time of writing (March 2023). + * + * Affected parts all have no supervisor XSAVE states, meaning that + * the XSAVEC instruction (which works fine) is equivalent. + */ + clear_cpu_cap(c, X86_FEATURE_XSAVES); } static void init_amd_zn(struct cpuinfo_x86 *c) From a98fc23cc2c1e4382a79ff137ca1a93d6a73b451 Mon Sep 17 00:00:00 2001 From: Philipp Hortmann Date: Tue, 28 Feb 2023 21:28:57 +0100 Subject: [PATCH 262/778] staging: rtl8192e: Remove function ..dm_check_ac_dc_power calling a script Remove function _rtl92e_dm_check_ac_dc_power calling a script /etc/acpi/wireless-rtl-ac-dc-power.sh that is not available. This script is not part of the kernel and it is not available on the www. The result is that this function is just dead code. Signed-off-by: Philipp Hortmann Cc: stable Link: https://lore.kernel.org/r/20230228202857.GA16442@matrix-ESPRIMO-P710 Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtl8192e/rtl_dm.c | 23 ---------------------- 1 file changed, 23 deletions(-) diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c index d8455b23e555..c04eb15c4044 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c @@ -185,7 +185,6 @@ static void _rtl92e_dm_init_fsync(struct net_device *dev); static void _rtl92e_dm_deinit_fsync(struct net_device *dev); static void _rtl92e_dm_check_txrateandretrycount(struct net_device *dev); -static void _rtl92e_dm_check_ac_dc_power(struct net_device *dev); static void _rtl92e_dm_check_fsync(struct net_device *dev); static void _rtl92e_dm_check_rf_ctrl_gpio(void *data); static void _rtl92e_dm_fsync_timer_callback(struct timer_list *t); @@ -236,8 +235,6 @@ void rtl92e_dm_watchdog(struct net_device *dev) if (priv->being_init_adapter) return; - _rtl92e_dm_check_ac_dc_power(dev); - _rtl92e_dm_check_txrateandretrycount(dev); _rtl92e_dm_check_edca_turbo(dev); @@ -255,26 +252,6 @@ void rtl92e_dm_watchdog(struct net_device *dev) _rtl92e_dm_cts_to_self(dev); } -static void _rtl92e_dm_check_ac_dc_power(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - static const char ac_dc_script[] = "/etc/acpi/wireless-rtl-ac-dc-power.sh"; - char *argv[] = {(char *)ac_dc_script, DRV_NAME, NULL}; - static char *envp[] = {"HOME=/", - "TERM=linux", - "PATH=/usr/bin:/bin", - NULL}; - - if (priv->rst_progress == RESET_TYPE_SILENT) - return; - if (priv->rtllib->state != RTLLIB_LINKED) - return; - call_usermodehelper(ac_dc_script, argv, envp, UMH_WAIT_PROC); - - return; -}; - - void rtl92e_init_adaptive_rate(struct net_device *dev) { From fe413a074a93d56f89e322c786aad8639afe76b4 Mon Sep 17 00:00:00 2001 From: Philipp Hortmann Date: Wed, 1 Mar 2023 22:54:41 +0100 Subject: [PATCH 263/778] staging: rtl8192e: Remove call_usermodehelper starting RadioPower.sh Remove call_usermodehelper starting /etc/acpi/events/RadioPower.sh that is not available. This script is not part of the kernel and it is not officially available on the www. The result is that this lines are just dead code. Signed-off-by: Philipp Hortmann Cc: stable Link: https://lore.kernel.org/r/20230301215441.GA14049@matrix-ESPRIMO-P710 Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtl8192e/rtl_dm.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c index c04eb15c4044..d8408acfc763 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c @@ -1637,10 +1637,6 @@ static void _rtl92e_dm_check_rf_ctrl_gpio(void *data) u8 tmp1byte; enum rt_rf_power_state rf_power_state_to_set; bool bActuallySet = false; - char *argv[3]; - static const char RadioPowerPath[] = "/etc/acpi/events/RadioPower.sh"; - static char *envp[] = {"HOME=/", "TERM=linux", "PATH=/usr/bin:/bin", - NULL}; bActuallySet = false; @@ -1670,14 +1666,6 @@ static void _rtl92e_dm_check_rf_ctrl_gpio(void *data) mdelay(1000); priv->hw_rf_off_action = 1; rtl92e_set_rf_state(dev, rf_power_state_to_set, RF_CHANGE_BY_HW); - if (priv->hw_radio_off) - argv[1] = "RFOFF"; - else - argv[1] = "RFON"; - - argv[0] = (char *)RadioPowerPath; - argv[2] = NULL; - call_usermodehelper(RadioPowerPath, argv, envp, UMH_WAIT_PROC); } } From 05cbcc415c9b8c8bc4f9a09f8e03610a89042f03 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 6 Mar 2023 16:35:11 +0100 Subject: [PATCH 264/778] staging: rtl8723bs: Fix key-store index handling There are 2 issues with the key-store index handling 1. The non WEP key stores can store keys with indexes 0 - BIP_MAX_KEYID, this means that they should be an array with BIP_MAX_KEYID + 1 entries. But some of the arrays where just BIP_MAX_KEYID entries big. While one other array was hardcoded to a size of 6 entries, instead of using the BIP_MAX_KEYID define. 2. The rtw_cfg80211_set_encryption() and wpa_set_encryption() functions index check where checking that the passed in key-index would fit inside both the WEP key store (which only has 4 entries) as well as in the non WEP key stores. This breaks any attempts to set non WEP keys with index 4 or 5. Issue 2. specifically breaks wifi connection with some access points which advertise PMF support. Without this fix connecting to these access points fails with the following wpa_supplicant messages: nl80211: kernel reports: key addition failed wlan0: WPA: Failed to configure IGTK to the driver wlan0: RSN: Failed to configure IGTK wlan0: CTRL-EVENT-DISCONNECTED bssid=... reason=1 locally_generated=1 Fix 1. by using the right size for the key-stores. After this 2. can safely be fixed by checking the right max-index value depending on the used algorithm, fixing wifi not working with some PMF capable APs. Cc: stable@vger.kernel.org Signed-off-by: Hans de Goede Link: https://lore.kernel.org/r/20230306153512.162104-1-hdegoede@redhat.com Signed-off-by: Greg Kroah-Hartman --- .../staging/rtl8723bs/include/rtw_security.h | 8 ++--- .../staging/rtl8723bs/os_dep/ioctl_cfg80211.c | 26 ++++++++------- .../staging/rtl8723bs/os_dep/ioctl_linux.c | 33 ++++++++++--------- 3 files changed, 36 insertions(+), 31 deletions(-) diff --git a/drivers/staging/rtl8723bs/include/rtw_security.h b/drivers/staging/rtl8723bs/include/rtw_security.h index a68b73858462..7587fa888527 100644 --- a/drivers/staging/rtl8723bs/include/rtw_security.h +++ b/drivers/staging/rtl8723bs/include/rtw_security.h @@ -107,13 +107,13 @@ struct security_priv { u32 dot118021XGrpPrivacy; /* This specify the privacy algthm. used for Grp key */ u32 dot118021XGrpKeyid; /* key id used for Grp Key (tx key index) */ - union Keytype dot118021XGrpKey[BIP_MAX_KEYID]; /* 802.1x Group Key, for inx0 and inx1 */ - union Keytype dot118021XGrptxmickey[BIP_MAX_KEYID]; - union Keytype dot118021XGrprxmickey[BIP_MAX_KEYID]; + union Keytype dot118021XGrpKey[BIP_MAX_KEYID + 1]; /* 802.1x Group Key, for inx0 and inx1 */ + union Keytype dot118021XGrptxmickey[BIP_MAX_KEYID + 1]; + union Keytype dot118021XGrprxmickey[BIP_MAX_KEYID + 1]; union pn48 dot11Grptxpn; /* PN48 used for Grp Key xmit. */ union pn48 dot11Grprxpn; /* PN48 used for Grp Key recv. */ u32 dot11wBIPKeyid; /* key id used for BIP Key (tx key index) */ - union Keytype dot11wBIPKey[6]; /* BIP Key, for index4 and index5 */ + union Keytype dot11wBIPKey[BIP_MAX_KEYID + 1]; /* BIP Key, for index4 and index5 */ union pn48 dot11wBIPtxpn; /* PN48 used for Grp Key xmit. */ union pn48 dot11wBIPrxpn; /* PN48 used for Grp Key recv. */ diff --git a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c index 54004f846cf0..3aba4e6eec8a 100644 --- a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c +++ b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c @@ -711,6 +711,7 @@ exit: static int rtw_cfg80211_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len) { int ret = 0; + u8 max_idx; u32 wep_key_idx, wep_key_len; struct adapter *padapter = rtw_netdev_priv(dev); struct mlme_priv *pmlmepriv = &padapter->mlmepriv; @@ -724,26 +725,29 @@ static int rtw_cfg80211_set_encryption(struct net_device *dev, struct ieee_param goto exit; } - if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff && - param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff && - param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) { - if (param->u.crypt.idx >= WEP_KEYS - || param->u.crypt.idx >= BIP_MAX_KEYID) { - ret = -EINVAL; - goto exit; - } - } else { - { + if (param->sta_addr[0] != 0xff || param->sta_addr[1] != 0xff || + param->sta_addr[2] != 0xff || param->sta_addr[3] != 0xff || + param->sta_addr[4] != 0xff || param->sta_addr[5] != 0xff) { ret = -EINVAL; goto exit; } + + if (strcmp(param->u.crypt.alg, "WEP") == 0) + max_idx = WEP_KEYS - 1; + else + max_idx = BIP_MAX_KEYID; + + if (param->u.crypt.idx > max_idx) { + netdev_err(dev, "Error crypt.idx %d > %d\n", param->u.crypt.idx, max_idx); + ret = -EINVAL; + goto exit; } if (strcmp(param->u.crypt.alg, "WEP") == 0) { wep_key_idx = param->u.crypt.idx; wep_key_len = param->u.crypt.key_len; - if ((wep_key_idx >= WEP_KEYS) || (wep_key_len <= 0)) { + if (wep_key_len <= 0) { ret = -EINVAL; goto exit; } diff --git a/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c b/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c index 30374a820496..40a3157fb735 100644 --- a/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c +++ b/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c @@ -46,6 +46,7 @@ static int wpa_set_auth_algs(struct net_device *dev, u32 value) static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len) { int ret = 0; + u8 max_idx; u32 wep_key_idx, wep_key_len, wep_total_len; struct ndis_802_11_wep *pwep = NULL; struct adapter *padapter = rtw_netdev_priv(dev); @@ -60,19 +61,22 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param, goto exit; } - if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff && - param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff && - param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) { - if (param->u.crypt.idx >= WEP_KEYS || - param->u.crypt.idx >= BIP_MAX_KEYID) { - ret = -EINVAL; - goto exit; - } - } else { - { - ret = -EINVAL; - goto exit; - } + if (param->sta_addr[0] != 0xff || param->sta_addr[1] != 0xff || + param->sta_addr[2] != 0xff || param->sta_addr[3] != 0xff || + param->sta_addr[4] != 0xff || param->sta_addr[5] != 0xff) { + ret = -EINVAL; + goto exit; + } + + if (strcmp(param->u.crypt.alg, "WEP") == 0) + max_idx = WEP_KEYS - 1; + else + max_idx = BIP_MAX_KEYID; + + if (param->u.crypt.idx > max_idx) { + netdev_err(dev, "Error crypt.idx %d > %d\n", param->u.crypt.idx, max_idx); + ret = -EINVAL; + goto exit; } if (strcmp(param->u.crypt.alg, "WEP") == 0) { @@ -84,9 +88,6 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param, wep_key_idx = param->u.crypt.idx; wep_key_len = param->u.crypt.key_len; - if (wep_key_idx > WEP_KEYS) - return -EINVAL; - if (wep_key_len > 0) { wep_key_len = wep_key_len <= 5 ? 5 : 13; wep_total_len = wep_key_len + FIELD_OFFSET(struct ndis_802_11_wep, key_material); From d17789edd6a8270c38459e592ee536a84c6202db Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 6 Mar 2023 16:35:12 +0100 Subject: [PATCH 265/778] staging: rtl8723bs: Pass correct parameters to cfg80211_get_bss() To last 2 parameters to cfg80211_get_bss() should be of the enum ieee80211_bss_type resp. enum ieee80211_privacy types, which WLAN_CAPABILITY_ESS very much is not. Fix both cfg80211_get_bss() calls in ioctl_cfg80211.c to pass the right parameters. Note that the second call was already somewhat fixed by commenting out WLAN_CAPABILITY_ESS and passing in 0 instead. This was still not entirely correct though since that would limit returned BSS-es to ESS type BSS-es with privacy on. Cc: stable@vger.kernel.org Signed-off-by: Hans de Goede Link: https://lore.kernel.org/r/20230306153512.162104-2-hdegoede@redhat.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c index 3aba4e6eec8a..84a9f4dd8f95 100644 --- a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c +++ b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c @@ -350,7 +350,7 @@ int rtw_cfg80211_check_bss(struct adapter *padapter) bss = cfg80211_get_bss(padapter->rtw_wdev->wiphy, notify_channel, pnetwork->mac_address, pnetwork->ssid.ssid, pnetwork->ssid.ssid_length, - WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); + IEEE80211_BSS_TYPE_ANY, IEEE80211_PRIVACY_ANY); cfg80211_put_bss(padapter->rtw_wdev->wiphy, bss); @@ -1139,8 +1139,8 @@ void rtw_cfg80211_unlink_bss(struct adapter *padapter, struct wlan_network *pnet bss = cfg80211_get_bss(wiphy, NULL/*notify_channel*/, select_network->mac_address, select_network->ssid.ssid, - select_network->ssid.ssid_length, 0/*WLAN_CAPABILITY_ESS*/, - 0/*WLAN_CAPABILITY_ESS*/); + select_network->ssid.ssid_length, IEEE80211_BSS_TYPE_ANY, + IEEE80211_PRIVACY_ANY); if (bss) { cfg80211_unlink_bss(wiphy, bss); From 33a33005b2db0966c00d4f58dd2a36e5a44217db Mon Sep 17 00:00:00 2001 From: Herve Codina Date: Tue, 7 Mar 2023 15:15:01 +0100 Subject: [PATCH 266/778] dt-bindings: soc: fsl: cpm_qe: cpm1-scc-qmc: Remove unneeded property Remove the unneeded and unused #fsl,chan-cells property. Signed-off-by: Herve Codina Link: https://lore.kernel.org/r/20230307141503.159766-2-herve.codina@bootlin.com Signed-off-by: Mark Brown --- .../bindings/soc/fsl/cpm_qe/fsl,cpm1-scc-qmc.yaml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/Documentation/devicetree/bindings/soc/fsl/cpm_qe/fsl,cpm1-scc-qmc.yaml b/Documentation/devicetree/bindings/soc/fsl/cpm_qe/fsl,cpm1-scc-qmc.yaml index 4ebbc7d52981..ec888f48cac8 100644 --- a/Documentation/devicetree/bindings/soc/fsl/cpm_qe/fsl,cpm1-scc-qmc.yaml +++ b/Documentation/devicetree/bindings/soc/fsl/cpm_qe/fsl,cpm1-scc-qmc.yaml @@ -59,14 +59,6 @@ properties: '#size-cells': const: 0 - '#fsl,chan-cells': - $ref: /schemas/types.yaml#/definitions/uint32 - const: 1 - description: - QMC consumers that use a phandle to QMC need to pass the channel number - with this phandle. - For instance "fsl,qmc-chan = <&qmc 16>;". - patternProperties: '^channel@([0-9]|[1-5][0-9]|6[0-3])$': description: @@ -121,7 +113,6 @@ required: - fsl,tsa-serial - '#address-cells' - '#size-cells' - - '#fsl,chan-cells' additionalProperties: false @@ -140,7 +131,6 @@ examples: #address-cells = <1>; #size-cells = <0>; - #fsl,chan-cells = <1>; fsl,tsa-serial = <&tsa FSL_CPM_TSA_SCC4>; From 0fb6f518cb46cf8bac7c30c29171050e355cd738 Mon Sep 17 00:00:00 2001 From: Herve Codina Date: Tue, 7 Mar 2023 15:15:02 +0100 Subject: [PATCH 267/778] dt-bindings: soc: fsl: cpm_qe: cpm1-tsa: Remove unneeded property Remove the unneeded and unused #fsl,serial-cells property. Signed-off-by: Herve Codina Link: https://lore.kernel.org/r/20230307141503.159766-3-herve.codina@bootlin.com Signed-off-by: Mark Brown --- .../bindings/soc/fsl/cpm_qe/fsl,cpm1-tsa.yaml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/Documentation/devicetree/bindings/soc/fsl/cpm_qe/fsl,cpm1-tsa.yaml b/Documentation/devicetree/bindings/soc/fsl/cpm_qe/fsl,cpm1-tsa.yaml index 332e902bcc21..7e51c639a79a 100644 --- a/Documentation/devicetree/bindings/soc/fsl/cpm_qe/fsl,cpm1-tsa.yaml +++ b/Documentation/devicetree/bindings/soc/fsl/cpm_qe/fsl,cpm1-tsa.yaml @@ -38,14 +38,6 @@ properties: '#size-cells': const: 0 - '#fsl,serial-cells': - $ref: /schemas/types.yaml#/definitions/uint32 - const: 1 - description: - TSA consumers that use a phandle to TSA need to pass the serial identifier - with this phandle (defined in dt-bindings/soc/fsl,tsa.h). - For instance "fsl,tsa-serial = <&tsa FSL_CPM_TSA_SCC4>;". - patternProperties: '^tdm@[0-1]$': description: @@ -174,7 +166,6 @@ required: - reg-names - '#address-cells' - '#size-cells' - - '#fsl,serial-cells' additionalProperties: false @@ -190,7 +181,6 @@ examples: #address-cells = <1>; #size-cells = <0>; - #fsl,serial-cells = <1>; tdm@0 { /* TDMa */ From f37acbde076d8dbf5e4c694f29760e608fdffe11 Mon Sep 17 00:00:00 2001 From: Herve Codina via Alsa-devel Date: Tue, 7 Mar 2023 15:15:03 +0100 Subject: [PATCH 268/778] soc: fsl: cpm1: qmc: Fix assigned timeslot masks The assigned timeslot masks are 64bit values. In case of 64 timeslots the code uses (1 << 64) which is undefined on a 64bit value. On the PowerPC architecture, this lead to an incorrect result as (1 << 64) produces the same result as (1 << 0). Fix the masks values taking care of the 64 timeslots case. Signed-off-by: Herve Codina Link: https://lore.kernel.org/r/167819855177.26.11163930602844526001@mailman-core.alsa-project.org Signed-off-by: Mark Brown --- drivers/soc/fsl/qe/qmc.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/soc/fsl/qe/qmc.c b/drivers/soc/fsl/qe/qmc.c index cfa7207353e0..b3c292c9a14e 100644 --- a/drivers/soc/fsl/qe/qmc.c +++ b/drivers/soc/fsl/qe/qmc.c @@ -754,6 +754,11 @@ static int qmc_check_chans(struct qmc *qmc) if (ret) return ret; + if ((info.nb_tx_ts > 64) || (info.nb_rx_ts > 64)) { + dev_err(qmc->dev, "Number of TSA Tx/Rx TS assigned not supported\n"); + return -EINVAL; + } + /* * If more than 32 TS are assigned to this serial, one common table is * used for Tx and Rx and so masks must be equal for all channels. @@ -766,9 +771,8 @@ static int qmc_check_chans(struct qmc *qmc) is_one_table = true; } - - tx_ts_assigned_mask = (((u64)1) << info.nb_tx_ts) - 1; - rx_ts_assigned_mask = (((u64)1) << info.nb_rx_ts) - 1; + tx_ts_assigned_mask = info.nb_tx_ts == 64 ? U64_MAX : (((u64)1) << info.nb_tx_ts) - 1; + rx_ts_assigned_mask = info.nb_rx_ts == 64 ? U64_MAX : (((u64)1) << info.nb_rx_ts) - 1; list_for_each_entry(chan, &qmc->chan_head, list) { if (chan->tx_ts_mask > tx_ts_assigned_mask) { From 7fef099702527c3b2c5234a2ea6a24411485a13a Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 7 Mar 2023 13:06:29 -0800 Subject: [PATCH 269/778] x86/resctl: fix scheduler confusion with 'current' The implementation of 'current' on x86 is very intentionally special: it is a very common thing to look up, and it uses 'this_cpu_read_stable()' to get the current thread pointer efficiently from per-cpu storage. And the keyword in there is 'stable': the current thread pointer never changes as far as a single thread is concerned. Even if when a thread is preempted, or moved to another CPU, or even across an explicit call 'schedule()' that thread will still have the same value for 'current'. It is, after all, the kernel base pointer to thread-local storage. That's why it's stable to begin with, but it's also why it's important enough that we have that special 'this_cpu_read_stable()' access for it. So this is all done very intentionally to allow the compiler to treat 'current' as a value that never visibly changes, so that the compiler can do CSE and combine multiple different 'current' accesses into one. However, there is obviously one very special situation when the currently running thread does actually change: inside the scheduler itself. So the scheduler code paths are special, and do not have a 'current' thread at all. Instead there are _two_ threads: the previous and the next thread - typically called 'prev' and 'next' (or prev_p/next_p) internally. So this is all actually quite straightforward and simple, and not all that complicated. Except for when you then have special code that is run in scheduler context, that code then has to be aware that 'current' isn't really a valid thing. Did you mean 'prev'? Did you mean 'next'? In fact, even if then look at the code, and you use 'current' after the new value has been assigned to the percpu variable, we have explicitly told the compiler that 'current' is magical and always stable. So the compiler is quite free to use an older (or newer) value of 'current', and the actual assignment to the percpu storage is not relevant even if it might look that way. Which is exactly what happened in the resctl code, that blithely used 'current' in '__resctrl_sched_in()' when it really wanted the new process state (as implied by the name: we're scheduling 'into' that new resctl state). And clang would end up just using the old thread pointer value at least in some configurations. This could have happened with gcc too, and purely depends on random compiler details. Clang just seems to have been more aggressive about moving the read of the per-cpu current_task pointer around. The fix is trivial: just make the resctl code adhere to the scheduler rules of using the prev/next thread pointer explicitly, instead of using 'current' in a situation where it just wasn't valid. That same code is then also used outside of the scheduler context (when a thread resctl state is explicitly changed), and then we will just pass in 'current' as that pointer, of course. There is no ambiguity in that case. The fix may be trivial, but noticing and figuring out what went wrong was not. The credit for that goes to Stephane Eranian. Reported-by: Stephane Eranian Link: https://lore.kernel.org/lkml/20230303231133.1486085-1-eranian@google.com/ Link: https://lore.kernel.org/lkml/alpine.LFD.2.01.0908011214330.3304@localhost.localdomain/ Reviewed-by: Nick Desaulniers Tested-by: Tony Luck Tested-by: Stephane Eranian Tested-by: Babu Moger Cc: stable@kernel.org Signed-off-by: Linus Torvalds --- arch/x86/include/asm/resctrl.h | 12 ++++++------ arch/x86/kernel/cpu/resctrl/rdtgroup.c | 4 ++-- arch/x86/kernel/process_32.c | 2 +- arch/x86/kernel/process_64.c | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/arch/x86/include/asm/resctrl.h b/arch/x86/include/asm/resctrl.h index 52788f79786f..255a78d9d906 100644 --- a/arch/x86/include/asm/resctrl.h +++ b/arch/x86/include/asm/resctrl.h @@ -49,7 +49,7 @@ DECLARE_STATIC_KEY_FALSE(rdt_mon_enable_key); * simple as possible. * Must be called with preemption disabled. */ -static void __resctrl_sched_in(void) +static inline void __resctrl_sched_in(struct task_struct *tsk) { struct resctrl_pqr_state *state = this_cpu_ptr(&pqr_state); u32 closid = state->default_closid; @@ -61,13 +61,13 @@ static void __resctrl_sched_in(void) * Else use the closid/rmid assigned to this cpu. */ if (static_branch_likely(&rdt_alloc_enable_key)) { - tmp = READ_ONCE(current->closid); + tmp = READ_ONCE(tsk->closid); if (tmp) closid = tmp; } if (static_branch_likely(&rdt_mon_enable_key)) { - tmp = READ_ONCE(current->rmid); + tmp = READ_ONCE(tsk->rmid); if (tmp) rmid = tmp; } @@ -88,17 +88,17 @@ static inline unsigned int resctrl_arch_round_mon_val(unsigned int val) return val * scale; } -static inline void resctrl_sched_in(void) +static inline void resctrl_sched_in(struct task_struct *tsk) { if (static_branch_likely(&rdt_enable_key)) - __resctrl_sched_in(); + __resctrl_sched_in(tsk); } void resctrl_cpu_detect(struct cpuinfo_x86 *c); #else -static inline void resctrl_sched_in(void) {} +static inline void resctrl_sched_in(struct task_struct *tsk) {} static inline void resctrl_cpu_detect(struct cpuinfo_x86 *c) {} #endif /* CONFIG_X86_CPU_RESCTRL */ diff --git a/arch/x86/kernel/cpu/resctrl/rdtgroup.c b/arch/x86/kernel/cpu/resctrl/rdtgroup.c index e2c1599d1b37..884b6e9a7e31 100644 --- a/arch/x86/kernel/cpu/resctrl/rdtgroup.c +++ b/arch/x86/kernel/cpu/resctrl/rdtgroup.c @@ -314,7 +314,7 @@ static void update_cpu_closid_rmid(void *info) * executing task might have its own closid selected. Just reuse * the context switch code. */ - resctrl_sched_in(); + resctrl_sched_in(current); } /* @@ -530,7 +530,7 @@ static void _update_task_closid_rmid(void *task) * Otherwise, the MSR is updated when the task is scheduled in. */ if (task == current) - resctrl_sched_in(); + resctrl_sched_in(task); } static void update_task_closid_rmid(struct task_struct *t) diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 470c128759ea..708c87b88cc1 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c @@ -212,7 +212,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) switch_fpu_finish(); /* Load the Intel cache allocation PQR MSR. */ - resctrl_sched_in(); + resctrl_sched_in(next_p); return prev_p; } diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 4e34b3b68ebd..bb65a68b4b49 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -656,7 +656,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) } /* Load the Intel cache allocation PQR MSR. */ - resctrl_sched_in(); + resctrl_sched_in(next_p); return prev_p; } From a722511b18268bd1f7084eee243af416b85f288f Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sun, 19 Feb 2023 17:04:28 -0800 Subject: [PATCH 270/778] drm/msm: DEVFREQ_GOV_SIMPLE_ONDEMAND is no longer needed DRM_MSM no longer needs DEVFREQ_GOV_SIMPLE_ONDEMAND (since commit dbd7a2a941b8 ("PM / devfreq: Fix build issues with devfreq disabled") in linux-next), so remove that select from the DRM_MSM Kconfig file. Fixes: 6563f60f14cb ("drm/msm/gpu: Add devfreq tuning debugfs") Signed-off-by: Randy Dunlap Cc: Rob Clark Cc: Abhinav Kumar Cc: Dmitry Baryshkov Cc: Sean Paul Cc: David Airlie Cc: Daniel Vetter Cc: linux-arm-msm@vger.kernel.org Cc: dri-devel@lists.freedesktop.org Cc: freedreno@lists.freedesktop.org Reviewed-by: Rob Clark Patchwork: https://patchwork.freedesktop.org/patch/523353/ Link: https://lore.kernel.org/r/20230220010428.16910-1-rdunlap@infradead.org [rob: tweak commit message to make checkpatch.pl happy] Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig index 871870ddf7ec..949b18a29a55 100644 --- a/drivers/gpu/drm/msm/Kconfig +++ b/drivers/gpu/drm/msm/Kconfig @@ -23,7 +23,6 @@ config DRM_MSM select SHMEM select TMPFS select QCOM_SCM - select DEVFREQ_GOV_SIMPLE_ONDEMAND select WANT_DEV_COREDUMP select SND_SOC_HDMI_CODEC if SND_SOC select SYNC_FILE From c8b8a3c601f2cfad25ab5ce5b04df700048aef6e Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Tue, 7 Mar 2023 17:54:11 +0200 Subject: [PATCH 271/778] net: dsa: mt7530: permit port 5 to work without port 6 on MT7621 SoC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The MT7530 switch from the MT7621 SoC has 2 ports which can be set up as internal: port 5 and 6. Arınç reports that the GMAC1 attached to port 5 receives corrupted frames, unless port 6 (attached to GMAC0) has been brought up by the driver. This is true regardless of whether port 5 is used as a user port or as a CPU port (carrying DSA tags). Offline debugging (blind for me) which began in the linked thread showed experimentally that the configuration done by the driver for port 6 contains a step which is needed by port 5 as well - the write to CORE_GSWPLL_GRP2 (note that I've no idea as to what it does, apart from the comment "Set core clock into 500Mhz"). Prints put by Arınç show that the reset value of CORE_GSWPLL_GRP2 is RG_GSWPLL_POSDIV_500M(1) | RG_GSWPLL_FBKDIV_500M(40) (0x128), both on the MCM MT7530 from the MT7621 SoC, as well as on the standalone MT7530 from MT7623NI Bananapi BPI-R2. Apparently, port 5 on the standalone MT7530 can work under both values of the register, while on the MT7621 SoC it cannot. The call path that triggers the register write is: mt753x_phylink_mac_config() for port 6 -> mt753x_pad_setup() -> mt7530_pad_clk_setup() so this fully explains the behavior noticed by Arınç, that bringing port 6 up is necessary. The simplest fix for the problem is to extract the register writes which are needed for both port 5 and 6 into a common mt7530_pll_setup() function, which is called at mt7530_setup() time, immediately after switch reset. We can argue that this mirrors the code layout introduced in mt7531_setup() by commit 42bc4fafe359 ("net: mt7531: only do PLL once after the reset"), in that the PLL setup has the exact same positioning, and further work to consolidate the separate setup() functions is not hindered. Testing confirms that: - the slight reordering of writes to MT7530_P6ECR and to CORE_GSWPLL_GRP1 / CORE_GSWPLL_GRP2 introduced by this change does not appear to cause problems for the operation of port 6 on MT7621 and on MT7623 (where port 5 also always worked) - packets sent through port 5 are not corrupted anymore, regardless of whether port 6 is enabled by phylink or not (or even present in the device tree) My algorithm for determining the Fixes: tag is as follows. Testing shows that some logic from mt7530_pad_clk_setup() is needed even for port 5. Prior to commit ca366d6c889b ("net: dsa: mt7530: Convert to PHYLINK API"), a call did exist for all phy_is_pseudo_fixed_link() ports - so port 5 included. That commit replaced it with a temporary "Port 5 is not supported!" comment, and the following commit 38f790a80560 ("net: dsa: mt7530: Add support for port 5") replaced that comment with a configuration procedure in mt7530_setup_port5() which was insufficient for port 5 to work. I'm laying the blame on the patch that claimed support for port 5, although one would have also needed the change from commit c3b8e07909db ("net: dsa: mt7530: setup core clock even in TRGMII mode") for the write to be performed completely independently from port 6's configuration. Thanks go to Arınç for describing the problem, for debugging and for testing. Reported-by: Arınç ÜNAL Link: https://lore.kernel.org/netdev/f297c2c4-6e7c-57ac-2394-f6025d309b9d@arinc9.com/ Fixes: 38f790a80560 ("net: dsa: mt7530: Add support for port 5") Signed-off-by: Vladimir Oltean Tested-by: Arınç ÜNAL Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/20230307155411.868573-1-vladimir.oltean@nxp.com Signed-off-by: Jakub Kicinski --- drivers/net/dsa/mt7530.c | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c index 3a15015bc409..a508402c4ecb 100644 --- a/drivers/net/dsa/mt7530.c +++ b/drivers/net/dsa/mt7530.c @@ -393,6 +393,24 @@ mt7530_fdb_write(struct mt7530_priv *priv, u16 vid, mt7530_write(priv, MT7530_ATA1 + (i * 4), reg[i]); } +/* Set up switch core clock for MT7530 */ +static void mt7530_pll_setup(struct mt7530_priv *priv) +{ + /* Disable PLL */ + core_write(priv, CORE_GSWPLL_GRP1, 0); + + /* Set core clock into 500Mhz */ + core_write(priv, CORE_GSWPLL_GRP2, + RG_GSWPLL_POSDIV_500M(1) | + RG_GSWPLL_FBKDIV_500M(25)); + + /* Enable PLL */ + core_write(priv, CORE_GSWPLL_GRP1, + RG_GSWPLL_EN_PRE | + RG_GSWPLL_POSDIV_200M(2) | + RG_GSWPLL_FBKDIV_200M(32)); +} + /* Setup TX circuit including relevant PAD and driving */ static int mt7530_pad_clk_setup(struct dsa_switch *ds, phy_interface_t interface) @@ -453,21 +471,6 @@ mt7530_pad_clk_setup(struct dsa_switch *ds, phy_interface_t interface) core_clear(priv, CORE_TRGMII_GSW_CLK_CG, REG_GSWCK_EN | REG_TRGMIICK_EN); - /* Setup core clock for MT7530 */ - /* Disable PLL */ - core_write(priv, CORE_GSWPLL_GRP1, 0); - - /* Set core clock into 500Mhz */ - core_write(priv, CORE_GSWPLL_GRP2, - RG_GSWPLL_POSDIV_500M(1) | - RG_GSWPLL_FBKDIV_500M(25)); - - /* Enable PLL */ - core_write(priv, CORE_GSWPLL_GRP1, - RG_GSWPLL_EN_PRE | - RG_GSWPLL_POSDIV_200M(2) | - RG_GSWPLL_FBKDIV_200M(32)); - /* Setup the MT7530 TRGMII Tx Clock */ core_write(priv, CORE_PLL_GROUP5, RG_LCDDS_PCW_NCPO1(ncpo1)); core_write(priv, CORE_PLL_GROUP6, RG_LCDDS_PCW_NCPO0(0)); @@ -2196,6 +2199,8 @@ mt7530_setup(struct dsa_switch *ds) SYS_CTRL_PHY_RST | SYS_CTRL_SW_RST | SYS_CTRL_REG_RST); + mt7530_pll_setup(priv); + /* Enable Port 6 only; P5 as GMAC5 which currently is not supported */ val = mt7530_read(priv, MT7530_MHWTRAP); val &= ~MHWTRAP_P6_DIS & ~MHWTRAP_PHY_ACCESS; From 8f14820801042c221bb9fe51643a2585cac5dec2 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 7 Mar 2023 09:19:30 -0800 Subject: [PATCH 272/778] eth: fealnx: bring back this old driver This reverts commit d5e2d038dbece821f1af57acbeded3aa9a1832c1. We have a report of this chip being used on a SURECOM EP-320X-S 100/10M Ethernet PCI Adapter which could still have been purchased in some parts of the world 3 years ago. Cc: stable@vger.kernel.org Link: https://bugzilla.kernel.org/show_bug.cgi?id=217151 Fixes: d5e2d038dbec ("eth: fealnx: delete the driver for Myson MTD-800") Link: https://lore.kernel.org/r/20230307171930.4008454-1-kuba@kernel.org Signed-off-by: Jakub Kicinski --- arch/mips/configs/mtx1_defconfig | 1 + arch/powerpc/configs/ppc6xx_defconfig | 1 + drivers/net/ethernet/Kconfig | 10 + drivers/net/ethernet/Makefile | 1 + drivers/net/ethernet/fealnx.c | 1953 +++++++++++++++++++++++++ 5 files changed, 1966 insertions(+) create mode 100644 drivers/net/ethernet/fealnx.c diff --git a/arch/mips/configs/mtx1_defconfig b/arch/mips/configs/mtx1_defconfig index 89a1511d2ee4..edf9634aa8ee 100644 --- a/arch/mips/configs/mtx1_defconfig +++ b/arch/mips/configs/mtx1_defconfig @@ -284,6 +284,7 @@ CONFIG_IXGB=m CONFIG_SKGE=m CONFIG_SKY2=m CONFIG_MYRI10GE=m +CONFIG_FEALNX=m CONFIG_NATSEMI=m CONFIG_NS83820=m CONFIG_S2IO=m diff --git a/arch/powerpc/configs/ppc6xx_defconfig b/arch/powerpc/configs/ppc6xx_defconfig index 110258277959..f73c98be56c8 100644 --- a/arch/powerpc/configs/ppc6xx_defconfig +++ b/arch/powerpc/configs/ppc6xx_defconfig @@ -461,6 +461,7 @@ CONFIG_MV643XX_ETH=m CONFIG_SKGE=m CONFIG_SKY2=m CONFIG_MYRI10GE=m +CONFIG_FEALNX=m CONFIG_NATSEMI=m CONFIG_NS83820=m CONFIG_PCMCIA_AXNET=m diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig index 323ec56e8a74..1917da784191 100644 --- a/drivers/net/ethernet/Kconfig +++ b/drivers/net/ethernet/Kconfig @@ -132,6 +132,16 @@ source "drivers/net/ethernet/mscc/Kconfig" source "drivers/net/ethernet/microsoft/Kconfig" source "drivers/net/ethernet/moxa/Kconfig" source "drivers/net/ethernet/myricom/Kconfig" + +config FEALNX + tristate "Myson MTD-8xx PCI Ethernet support" + depends on PCI + select CRC32 + select MII + help + Say Y here to support the Myson MTD-800 family of PCI-based Ethernet + cards. + source "drivers/net/ethernet/ni/Kconfig" source "drivers/net/ethernet/natsemi/Kconfig" source "drivers/net/ethernet/neterion/Kconfig" diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile index 2fedbaa545eb..0d872d4efcd1 100644 --- a/drivers/net/ethernet/Makefile +++ b/drivers/net/ethernet/Makefile @@ -64,6 +64,7 @@ obj-$(CONFIG_NET_VENDOR_MICROCHIP) += microchip/ obj-$(CONFIG_NET_VENDOR_MICROSEMI) += mscc/ obj-$(CONFIG_NET_VENDOR_MOXART) += moxa/ obj-$(CONFIG_NET_VENDOR_MYRI) += myricom/ +obj-$(CONFIG_FEALNX) += fealnx.o obj-$(CONFIG_NET_VENDOR_NATSEMI) += natsemi/ obj-$(CONFIG_NET_VENDOR_NETERION) += neterion/ obj-$(CONFIG_NET_VENDOR_NETRONOME) += netronome/ diff --git a/drivers/net/ethernet/fealnx.c b/drivers/net/ethernet/fealnx.c new file mode 100644 index 000000000000..ed18450fd2cc --- /dev/null +++ b/drivers/net/ethernet/fealnx.c @@ -0,0 +1,1953 @@ +/* + Written 1998-2000 by Donald Becker. + + This software may be used and distributed according to the terms of + the GNU General Public License (GPL), incorporated herein by reference. + Drivers based on or derived from this code fall under the GPL and must + retain the authorship, copyright and license notice. This file is not + a complete program and may only be used when the entire operating + system is licensed under the GPL. + + The author may be reached as becker@scyld.com, or C/O + Scyld Computing Corporation + 410 Severn Ave., Suite 210 + Annapolis MD 21403 + + Support information and updates available at + http://www.scyld.com/network/pci-skeleton.html + + Linux kernel updates: + + Version 2.51, Nov 17, 2001 (jgarzik): + - Add ethtool support + - Replace some MII-related magic numbers with constants + +*/ + +#define DRV_NAME "fealnx" + +static int debug; /* 1-> print debug message */ +static int max_interrupt_work = 20; + +/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). */ +static int multicast_filter_limit = 32; + +/* Set the copy breakpoint for the copy-only-tiny-frames scheme. */ +/* Setting to > 1518 effectively disables this feature. */ +static int rx_copybreak; + +/* Used to pass the media type, etc. */ +/* Both 'options[]' and 'full_duplex[]' should exist for driver */ +/* interoperability. */ +/* The media type is usually passed in 'options[]'. */ +#define MAX_UNITS 8 /* More are supported, limit only on options */ +static int options[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 }; +static int full_duplex[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 }; + +/* Operational parameters that are set at compile time. */ +/* Keep the ring sizes a power of two for compile efficiency. */ +/* The compiler will convert '%'<2^N> into a bit mask. */ +/* Making the Tx ring too large decreases the effectiveness of channel */ +/* bonding and packet priority. */ +/* There are no ill effects from too-large receive rings. */ +// 88-12-9 modify, +// #define TX_RING_SIZE 16 +// #define RX_RING_SIZE 32 +#define TX_RING_SIZE 6 +#define RX_RING_SIZE 12 +#define TX_TOTAL_SIZE TX_RING_SIZE*sizeof(struct fealnx_desc) +#define RX_TOTAL_SIZE RX_RING_SIZE*sizeof(struct fealnx_desc) + +/* Operational parameters that usually are not changed. */ +/* Time in jiffies before concluding the transmitter is hung. */ +#define TX_TIMEOUT (2*HZ) + +#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer. */ + + +/* Include files, designed to support most kernel versions 2.0.0 and later. */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include /* Processor type for cache alignment. */ +#include +#include +#include + +/* This driver was written to use PCI memory space, however some x86 systems + work only with I/O space accesses. */ +#ifndef __alpha__ +#define USE_IO_OPS +#endif + +/* Kernel compatibility defines, some common to David Hinds' PCMCIA package. */ +/* This is only in the support-all-kernels source code. */ + +#define RUN_AT(x) (jiffies + (x)) + +MODULE_AUTHOR("Myson or whoever"); +MODULE_DESCRIPTION("Myson MTD-8xx 100/10M Ethernet PCI Adapter Driver"); +MODULE_LICENSE("GPL"); +module_param(max_interrupt_work, int, 0); +module_param(debug, int, 0); +module_param(rx_copybreak, int, 0); +module_param(multicast_filter_limit, int, 0); +module_param_array(options, int, NULL, 0); +module_param_array(full_duplex, int, NULL, 0); +MODULE_PARM_DESC(max_interrupt_work, "fealnx maximum events handled per interrupt"); +MODULE_PARM_DESC(debug, "fealnx enable debugging (0-1)"); +MODULE_PARM_DESC(rx_copybreak, "fealnx copy breakpoint for copy-only-tiny-frames"); +MODULE_PARM_DESC(multicast_filter_limit, "fealnx maximum number of filtered multicast addresses"); +MODULE_PARM_DESC(options, "fealnx: Bits 0-3: media type, bit 17: full duplex"); +MODULE_PARM_DESC(full_duplex, "fealnx full duplex setting(s) (1)"); + +enum { + MIN_REGION_SIZE = 136, +}; + +/* A chip capabilities table, matching the entries in pci_tbl[] above. */ +enum chip_capability_flags { + HAS_MII_XCVR, + HAS_CHIP_XCVR, +}; + +/* 89/6/13 add, */ +/* for different PHY */ +enum phy_type_flags { + MysonPHY = 1, + AhdocPHY = 2, + SeeqPHY = 3, + MarvellPHY = 4, + Myson981 = 5, + LevelOnePHY = 6, + OtherPHY = 10, +}; + +struct chip_info { + char *chip_name; + int flags; +}; + +static const struct chip_info skel_netdrv_tbl[] = { + { "100/10M Ethernet PCI Adapter", HAS_MII_XCVR }, + { "100/10M Ethernet PCI Adapter", HAS_CHIP_XCVR }, + { "1000/100/10M Ethernet PCI Adapter", HAS_MII_XCVR }, +}; + +/* Offsets to the Command and Status Registers. */ +enum fealnx_offsets { + PAR0 = 0x0, /* physical address 0-3 */ + PAR1 = 0x04, /* physical address 4-5 */ + MAR0 = 0x08, /* multicast address 0-3 */ + MAR1 = 0x0C, /* multicast address 4-7 */ + FAR0 = 0x10, /* flow-control address 0-3 */ + FAR1 = 0x14, /* flow-control address 4-5 */ + TCRRCR = 0x18, /* receive & transmit configuration */ + BCR = 0x1C, /* bus command */ + TXPDR = 0x20, /* transmit polling demand */ + RXPDR = 0x24, /* receive polling demand */ + RXCWP = 0x28, /* receive current word pointer */ + TXLBA = 0x2C, /* transmit list base address */ + RXLBA = 0x30, /* receive list base address */ + ISR = 0x34, /* interrupt status */ + IMR = 0x38, /* interrupt mask */ + FTH = 0x3C, /* flow control high/low threshold */ + MANAGEMENT = 0x40, /* bootrom/eeprom and mii management */ + TALLY = 0x44, /* tally counters for crc and mpa */ + TSR = 0x48, /* tally counter for transmit status */ + BMCRSR = 0x4c, /* basic mode control and status */ + PHYIDENTIFIER = 0x50, /* phy identifier */ + ANARANLPAR = 0x54, /* auto-negotiation advertisement and link + partner ability */ + ANEROCR = 0x58, /* auto-negotiation expansion and pci conf. */ + BPREMRPSR = 0x5c, /* bypass & receive error mask and phy status */ +}; + +/* Bits in the interrupt status/enable registers. */ +/* The bits in the Intr Status/Enable registers, mostly interrupt sources. */ +enum intr_status_bits { + RFCON = 0x00020000, /* receive flow control xon packet */ + RFCOFF = 0x00010000, /* receive flow control xoff packet */ + LSCStatus = 0x00008000, /* link status change */ + ANCStatus = 0x00004000, /* autonegotiation completed */ + FBE = 0x00002000, /* fatal bus error */ + FBEMask = 0x00001800, /* mask bit12-11 */ + ParityErr = 0x00000000, /* parity error */ + TargetErr = 0x00001000, /* target abort */ + MasterErr = 0x00000800, /* master error */ + TUNF = 0x00000400, /* transmit underflow */ + ROVF = 0x00000200, /* receive overflow */ + ETI = 0x00000100, /* transmit early int */ + ERI = 0x00000080, /* receive early int */ + CNTOVF = 0x00000040, /* counter overflow */ + RBU = 0x00000020, /* receive buffer unavailable */ + TBU = 0x00000010, /* transmit buffer unavilable */ + TI = 0x00000008, /* transmit interrupt */ + RI = 0x00000004, /* receive interrupt */ + RxErr = 0x00000002, /* receive error */ +}; + +/* Bits in the NetworkConfig register, W for writing, R for reading */ +/* FIXME: some names are invented by me. Marked with (name?) */ +/* If you have docs and know bit names, please fix 'em */ +enum rx_mode_bits { + CR_W_ENH = 0x02000000, /* enhanced mode (name?) */ + CR_W_FD = 0x00100000, /* full duplex */ + CR_W_PS10 = 0x00080000, /* 10 mbit */ + CR_W_TXEN = 0x00040000, /* tx enable (name?) */ + CR_W_PS1000 = 0x00010000, /* 1000 mbit */ + /* CR_W_RXBURSTMASK= 0x00000e00, Im unsure about this */ + CR_W_RXMODEMASK = 0x000000e0, + CR_W_PROM = 0x00000080, /* promiscuous mode */ + CR_W_AB = 0x00000040, /* accept broadcast */ + CR_W_AM = 0x00000020, /* accept mutlicast */ + CR_W_ARP = 0x00000008, /* receive runt pkt */ + CR_W_ALP = 0x00000004, /* receive long pkt */ + CR_W_SEP = 0x00000002, /* receive error pkt */ + CR_W_RXEN = 0x00000001, /* rx enable (unicast?) (name?) */ + + CR_R_TXSTOP = 0x04000000, /* tx stopped (name?) */ + CR_R_FD = 0x00100000, /* full duplex detected */ + CR_R_PS10 = 0x00080000, /* 10 mbit detected */ + CR_R_RXSTOP = 0x00008000, /* rx stopped (name?) */ +}; + +/* The Tulip Rx and Tx buffer descriptors. */ +struct fealnx_desc { + s32 status; + s32 control; + u32 buffer; + u32 next_desc; + struct fealnx_desc *next_desc_logical; + struct sk_buff *skbuff; + u32 reserved1; + u32 reserved2; +}; + +/* Bits in network_desc.status */ +enum rx_desc_status_bits { + RXOWN = 0x80000000, /* own bit */ + FLNGMASK = 0x0fff0000, /* frame length */ + FLNGShift = 16, + MARSTATUS = 0x00004000, /* multicast address received */ + BARSTATUS = 0x00002000, /* broadcast address received */ + PHYSTATUS = 0x00001000, /* physical address received */ + RXFSD = 0x00000800, /* first descriptor */ + RXLSD = 0x00000400, /* last descriptor */ + ErrorSummary = 0x80, /* error summary */ + RUNTPKT = 0x40, /* runt packet received */ + LONGPKT = 0x20, /* long packet received */ + FAE = 0x10, /* frame align error */ + CRC = 0x08, /* crc error */ + RXER = 0x04, /* receive error */ +}; + +enum rx_desc_control_bits { + RXIC = 0x00800000, /* interrupt control */ + RBSShift = 0, +}; + +enum tx_desc_status_bits { + TXOWN = 0x80000000, /* own bit */ + JABTO = 0x00004000, /* jabber timeout */ + CSL = 0x00002000, /* carrier sense lost */ + LC = 0x00001000, /* late collision */ + EC = 0x00000800, /* excessive collision */ + UDF = 0x00000400, /* fifo underflow */ + DFR = 0x00000200, /* deferred */ + HF = 0x00000100, /* heartbeat fail */ + NCRMask = 0x000000ff, /* collision retry count */ + NCRShift = 0, +}; + +enum tx_desc_control_bits { + TXIC = 0x80000000, /* interrupt control */ + ETIControl = 0x40000000, /* early transmit interrupt */ + TXLD = 0x20000000, /* last descriptor */ + TXFD = 0x10000000, /* first descriptor */ + CRCEnable = 0x08000000, /* crc control */ + PADEnable = 0x04000000, /* padding control */ + RetryTxLC = 0x02000000, /* retry late collision */ + PKTSMask = 0x3ff800, /* packet size bit21-11 */ + PKTSShift = 11, + TBSMask = 0x000007ff, /* transmit buffer bit 10-0 */ + TBSShift = 0, +}; + +/* BootROM/EEPROM/MII Management Register */ +#define MASK_MIIR_MII_READ 0x00000000 +#define MASK_MIIR_MII_WRITE 0x00000008 +#define MASK_MIIR_MII_MDO 0x00000004 +#define MASK_MIIR_MII_MDI 0x00000002 +#define MASK_MIIR_MII_MDC 0x00000001 + +/* ST+OP+PHYAD+REGAD+TA */ +#define OP_READ 0x6000 /* ST:01+OP:10+PHYAD+REGAD+TA:Z0 */ +#define OP_WRITE 0x5002 /* ST:01+OP:01+PHYAD+REGAD+TA:10 */ + +/* ------------------------------------------------------------------------- */ +/* Constants for Myson PHY */ +/* ------------------------------------------------------------------------- */ +#define MysonPHYID 0xd0000302 +/* 89-7-27 add, (begin) */ +#define MysonPHYID0 0x0302 +#define StatusRegister 18 +#define SPEED100 0x0400 // bit10 +#define FULLMODE 0x0800 // bit11 +/* 89-7-27 add, (end) */ + +/* ------------------------------------------------------------------------- */ +/* Constants for Seeq 80225 PHY */ +/* ------------------------------------------------------------------------- */ +#define SeeqPHYID0 0x0016 + +#define MIIRegister18 18 +#define SPD_DET_100 0x80 +#define DPLX_DET_FULL 0x40 + +/* ------------------------------------------------------------------------- */ +/* Constants for Ahdoc 101 PHY */ +/* ------------------------------------------------------------------------- */ +#define AhdocPHYID0 0x0022 + +#define DiagnosticReg 18 +#define DPLX_FULL 0x0800 +#define Speed_100 0x0400 + +/* 89/6/13 add, */ +/* -------------------------------------------------------------------------- */ +/* Constants */ +/* -------------------------------------------------------------------------- */ +#define MarvellPHYID0 0x0141 +#define LevelOnePHYID0 0x0013 + +#define MII1000BaseTControlReg 9 +#define MII1000BaseTStatusReg 10 +#define SpecificReg 17 + +/* for 1000BaseT Control Register */ +#define PHYAbletoPerform1000FullDuplex 0x0200 +#define PHYAbletoPerform1000HalfDuplex 0x0100 +#define PHY1000AbilityMask 0x300 + +// for phy specific status register, marvell phy. +#define SpeedMask 0x0c000 +#define Speed_1000M 0x08000 +#define Speed_100M 0x4000 +#define Speed_10M 0 +#define Full_Duplex 0x2000 + +// 89/12/29 add, for phy specific status register, levelone phy, (begin) +#define LXT1000_100M 0x08000 +#define LXT1000_1000M 0x0c000 +#define LXT1000_Full 0x200 +// 89/12/29 add, for phy specific status register, levelone phy, (end) + +/* for 3-in-1 case, BMCRSR register */ +#define LinkIsUp2 0x00040000 + +/* for PHY */ +#define LinkIsUp 0x0004 + + +struct netdev_private { + /* Descriptor rings first for alignment. */ + struct fealnx_desc *rx_ring; + struct fealnx_desc *tx_ring; + + dma_addr_t rx_ring_dma; + dma_addr_t tx_ring_dma; + + spinlock_t lock; + + /* Media monitoring timer. */ + struct timer_list timer; + + /* Reset timer */ + struct timer_list reset_timer; + int reset_timer_armed; + unsigned long crvalue_sv; + unsigned long imrvalue_sv; + + /* Frequently used values: keep some adjacent for cache effect. */ + int flags; + struct pci_dev *pci_dev; + unsigned long crvalue; + unsigned long bcrvalue; + unsigned long imrvalue; + struct fealnx_desc *cur_rx; + struct fealnx_desc *lack_rxbuf; + int really_rx_count; + struct fealnx_desc *cur_tx; + struct fealnx_desc *cur_tx_copy; + int really_tx_count; + int free_tx_count; + unsigned int rx_buf_sz; /* Based on MTU+slack. */ + + /* These values are keep track of the transceiver/media in use. */ + unsigned int linkok; + unsigned int line_speed; + unsigned int duplexmode; + unsigned int default_port:4; /* Last dev->if_port value. */ + unsigned int PHYType; + + /* MII transceiver section. */ + int mii_cnt; /* MII device addresses. */ + unsigned char phys[2]; /* MII device addresses. */ + struct mii_if_info mii; + void __iomem *mem; +}; + + +static int mdio_read(struct net_device *dev, int phy_id, int location); +static void mdio_write(struct net_device *dev, int phy_id, int location, int value); +static int netdev_open(struct net_device *dev); +static void getlinktype(struct net_device *dev); +static void getlinkstatus(struct net_device *dev); +static void netdev_timer(struct timer_list *t); +static void reset_timer(struct timer_list *t); +static void fealnx_tx_timeout(struct net_device *dev, unsigned int txqueue); +static void init_ring(struct net_device *dev); +static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev); +static irqreturn_t intr_handler(int irq, void *dev_instance); +static int netdev_rx(struct net_device *dev); +static void set_rx_mode(struct net_device *dev); +static void __set_rx_mode(struct net_device *dev); +static struct net_device_stats *get_stats(struct net_device *dev); +static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); +static const struct ethtool_ops netdev_ethtool_ops; +static int netdev_close(struct net_device *dev); +static void reset_rx_descriptors(struct net_device *dev); +static void reset_tx_descriptors(struct net_device *dev); + +static void stop_nic_rx(void __iomem *ioaddr, long crvalue) +{ + int delay = 0x1000; + iowrite32(crvalue & ~(CR_W_RXEN), ioaddr + TCRRCR); + while (--delay) { + if ( (ioread32(ioaddr + TCRRCR) & CR_R_RXSTOP) == CR_R_RXSTOP) + break; + } +} + + +static void stop_nic_rxtx(void __iomem *ioaddr, long crvalue) +{ + int delay = 0x1000; + iowrite32(crvalue & ~(CR_W_RXEN+CR_W_TXEN), ioaddr + TCRRCR); + while (--delay) { + if ( (ioread32(ioaddr + TCRRCR) & (CR_R_RXSTOP+CR_R_TXSTOP)) + == (CR_R_RXSTOP+CR_R_TXSTOP) ) + break; + } +} + +static const struct net_device_ops netdev_ops = { + .ndo_open = netdev_open, + .ndo_stop = netdev_close, + .ndo_start_xmit = start_tx, + .ndo_get_stats = get_stats, + .ndo_set_rx_mode = set_rx_mode, + .ndo_eth_ioctl = mii_ioctl, + .ndo_tx_timeout = fealnx_tx_timeout, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; + +static int fealnx_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct netdev_private *np; + int i, option, err, irq; + static int card_idx = -1; + char boardname[12]; + void __iomem *ioaddr; + unsigned long len; + unsigned int chip_id = ent->driver_data; + struct net_device *dev; + void *ring_space; + dma_addr_t ring_dma; + u8 addr[ETH_ALEN]; +#ifdef USE_IO_OPS + int bar = 0; +#else + int bar = 1; +#endif + + card_idx++; + sprintf(boardname, "fealnx%d", card_idx); + + option = card_idx < MAX_UNITS ? options[card_idx] : 0; + + i = pci_enable_device(pdev); + if (i) return i; + pci_set_master(pdev); + + len = pci_resource_len(pdev, bar); + if (len < MIN_REGION_SIZE) { + dev_err(&pdev->dev, + "region size %ld too small, aborting\n", len); + return -ENODEV; + } + + i = pci_request_regions(pdev, boardname); + if (i) + return i; + + irq = pdev->irq; + + ioaddr = pci_iomap(pdev, bar, len); + if (!ioaddr) { + err = -ENOMEM; + goto err_out_res; + } + + dev = alloc_etherdev(sizeof(struct netdev_private)); + if (!dev) { + err = -ENOMEM; + goto err_out_unmap; + } + SET_NETDEV_DEV(dev, &pdev->dev); + + /* read ethernet id */ + for (i = 0; i < 6; ++i) + addr[i] = ioread8(ioaddr + PAR0 + i); + eth_hw_addr_set(dev, addr); + + /* Reset the chip to erase previous misconfiguration. */ + iowrite32(0x00000001, ioaddr + BCR); + + /* Make certain the descriptor lists are aligned. */ + np = netdev_priv(dev); + np->mem = ioaddr; + spin_lock_init(&np->lock); + np->pci_dev = pdev; + np->flags = skel_netdrv_tbl[chip_id].flags; + pci_set_drvdata(pdev, dev); + np->mii.dev = dev; + np->mii.mdio_read = mdio_read; + np->mii.mdio_write = mdio_write; + np->mii.phy_id_mask = 0x1f; + np->mii.reg_num_mask = 0x1f; + + ring_space = dma_alloc_coherent(&pdev->dev, RX_TOTAL_SIZE, &ring_dma, + GFP_KERNEL); + if (!ring_space) { + err = -ENOMEM; + goto err_out_free_dev; + } + np->rx_ring = ring_space; + np->rx_ring_dma = ring_dma; + + ring_space = dma_alloc_coherent(&pdev->dev, TX_TOTAL_SIZE, &ring_dma, + GFP_KERNEL); + if (!ring_space) { + err = -ENOMEM; + goto err_out_free_rx; + } + np->tx_ring = ring_space; + np->tx_ring_dma = ring_dma; + + /* find the connected MII xcvrs */ + if (np->flags == HAS_MII_XCVR) { + int phy, phy_idx = 0; + + for (phy = 1; phy < 32 && phy_idx < ARRAY_SIZE(np->phys); + phy++) { + int mii_status = mdio_read(dev, phy, 1); + + if (mii_status != 0xffff && mii_status != 0x0000) { + np->phys[phy_idx++] = phy; + dev_info(&pdev->dev, + "MII PHY found at address %d, status " + "0x%4.4x.\n", phy, mii_status); + /* get phy type */ + { + unsigned int data; + + data = mdio_read(dev, np->phys[0], 2); + if (data == SeeqPHYID0) + np->PHYType = SeeqPHY; + else if (data == AhdocPHYID0) + np->PHYType = AhdocPHY; + else if (data == MarvellPHYID0) + np->PHYType = MarvellPHY; + else if (data == MysonPHYID0) + np->PHYType = Myson981; + else if (data == LevelOnePHYID0) + np->PHYType = LevelOnePHY; + else + np->PHYType = OtherPHY; + } + } + } + + np->mii_cnt = phy_idx; + if (phy_idx == 0) + dev_warn(&pdev->dev, + "MII PHY not found -- this device may " + "not operate correctly.\n"); + } else { + np->phys[0] = 32; +/* 89/6/23 add, (begin) */ + /* get phy type */ + if (ioread32(ioaddr + PHYIDENTIFIER) == MysonPHYID) + np->PHYType = MysonPHY; + else + np->PHYType = OtherPHY; + } + np->mii.phy_id = np->phys[0]; + + if (dev->mem_start) + option = dev->mem_start; + + /* The lower four bits are the media type. */ + if (option > 0) { + if (option & 0x200) + np->mii.full_duplex = 1; + np->default_port = option & 15; + } + + if (card_idx < MAX_UNITS && full_duplex[card_idx] > 0) + np->mii.full_duplex = full_duplex[card_idx]; + + if (np->mii.full_duplex) { + dev_info(&pdev->dev, "Media type forced to Full Duplex.\n"); +/* 89/6/13 add, (begin) */ +// if (np->PHYType==MarvellPHY) + if ((np->PHYType == MarvellPHY) || (np->PHYType == LevelOnePHY)) { + unsigned int data; + + data = mdio_read(dev, np->phys[0], 9); + data = (data & 0xfcff) | 0x0200; + mdio_write(dev, np->phys[0], 9, data); + } +/* 89/6/13 add, (end) */ + if (np->flags == HAS_MII_XCVR) + mdio_write(dev, np->phys[0], MII_ADVERTISE, ADVERTISE_FULL); + else + iowrite32(ADVERTISE_FULL, ioaddr + ANARANLPAR); + np->mii.force_media = 1; + } + + dev->netdev_ops = &netdev_ops; + dev->ethtool_ops = &netdev_ethtool_ops; + dev->watchdog_timeo = TX_TIMEOUT; + + err = register_netdev(dev); + if (err) + goto err_out_free_tx; + + printk(KERN_INFO "%s: %s at %p, %pM, IRQ %d.\n", + dev->name, skel_netdrv_tbl[chip_id].chip_name, ioaddr, + dev->dev_addr, irq); + + return 0; + +err_out_free_tx: + dma_free_coherent(&pdev->dev, TX_TOTAL_SIZE, np->tx_ring, + np->tx_ring_dma); +err_out_free_rx: + dma_free_coherent(&pdev->dev, RX_TOTAL_SIZE, np->rx_ring, + np->rx_ring_dma); +err_out_free_dev: + free_netdev(dev); +err_out_unmap: + pci_iounmap(pdev, ioaddr); +err_out_res: + pci_release_regions(pdev); + return err; +} + + +static void fealnx_remove_one(struct pci_dev *pdev) +{ + struct net_device *dev = pci_get_drvdata(pdev); + + if (dev) { + struct netdev_private *np = netdev_priv(dev); + + dma_free_coherent(&pdev->dev, TX_TOTAL_SIZE, np->tx_ring, + np->tx_ring_dma); + dma_free_coherent(&pdev->dev, RX_TOTAL_SIZE, np->rx_ring, + np->rx_ring_dma); + unregister_netdev(dev); + pci_iounmap(pdev, np->mem); + free_netdev(dev); + pci_release_regions(pdev); + } else + printk(KERN_ERR "fealnx: remove for unknown device\n"); +} + + +static ulong m80x_send_cmd_to_phy(void __iomem *miiport, int opcode, int phyad, int regad) +{ + ulong miir; + int i; + unsigned int mask, data; + + /* enable MII output */ + miir = (ulong) ioread32(miiport); + miir &= 0xfffffff0; + + miir |= MASK_MIIR_MII_WRITE + MASK_MIIR_MII_MDO; + + /* send 32 1's preamble */ + for (i = 0; i < 32; i++) { + /* low MDC; MDO is already high (miir) */ + miir &= ~MASK_MIIR_MII_MDC; + iowrite32(miir, miiport); + + /* high MDC */ + miir |= MASK_MIIR_MII_MDC; + iowrite32(miir, miiport); + } + + /* calculate ST+OP+PHYAD+REGAD+TA */ + data = opcode | (phyad << 7) | (regad << 2); + + /* sent out */ + mask = 0x8000; + while (mask) { + /* low MDC, prepare MDO */ + miir &= ~(MASK_MIIR_MII_MDC + MASK_MIIR_MII_MDO); + if (mask & data) + miir |= MASK_MIIR_MII_MDO; + + iowrite32(miir, miiport); + /* high MDC */ + miir |= MASK_MIIR_MII_MDC; + iowrite32(miir, miiport); + udelay(30); + + /* next */ + mask >>= 1; + if (mask == 0x2 && opcode == OP_READ) + miir &= ~MASK_MIIR_MII_WRITE; + } + return miir; +} + + +static int mdio_read(struct net_device *dev, int phyad, int regad) +{ + struct netdev_private *np = netdev_priv(dev); + void __iomem *miiport = np->mem + MANAGEMENT; + ulong miir; + unsigned int mask, data; + + miir = m80x_send_cmd_to_phy(miiport, OP_READ, phyad, regad); + + /* read data */ + mask = 0x8000; + data = 0; + while (mask) { + /* low MDC */ + miir &= ~MASK_MIIR_MII_MDC; + iowrite32(miir, miiport); + + /* read MDI */ + miir = ioread32(miiport); + if (miir & MASK_MIIR_MII_MDI) + data |= mask; + + /* high MDC, and wait */ + miir |= MASK_MIIR_MII_MDC; + iowrite32(miir, miiport); + udelay(30); + + /* next */ + mask >>= 1; + } + + /* low MDC */ + miir &= ~MASK_MIIR_MII_MDC; + iowrite32(miir, miiport); + + return data & 0xffff; +} + + +static void mdio_write(struct net_device *dev, int phyad, int regad, int data) +{ + struct netdev_private *np = netdev_priv(dev); + void __iomem *miiport = np->mem + MANAGEMENT; + ulong miir; + unsigned int mask; + + miir = m80x_send_cmd_to_phy(miiport, OP_WRITE, phyad, regad); + + /* write data */ + mask = 0x8000; + while (mask) { + /* low MDC, prepare MDO */ + miir &= ~(MASK_MIIR_MII_MDC + MASK_MIIR_MII_MDO); + if (mask & data) + miir |= MASK_MIIR_MII_MDO; + iowrite32(miir, miiport); + + /* high MDC */ + miir |= MASK_MIIR_MII_MDC; + iowrite32(miir, miiport); + + /* next */ + mask >>= 1; + } + + /* low MDC */ + miir &= ~MASK_MIIR_MII_MDC; + iowrite32(miir, miiport); +} + + +static int netdev_open(struct net_device *dev) +{ + struct netdev_private *np = netdev_priv(dev); + void __iomem *ioaddr = np->mem; + const int irq = np->pci_dev->irq; + int rc, i; + + iowrite32(0x00000001, ioaddr + BCR); /* Reset */ + + rc = request_irq(irq, intr_handler, IRQF_SHARED, dev->name, dev); + if (rc) + return -EAGAIN; + + for (i = 0; i < 3; i++) + iowrite16(((const unsigned short *)dev->dev_addr)[i], + ioaddr + PAR0 + i*2); + + init_ring(dev); + + iowrite32(np->rx_ring_dma, ioaddr + RXLBA); + iowrite32(np->tx_ring_dma, ioaddr + TXLBA); + + /* Initialize other registers. */ + /* Configure the PCI bus bursts and FIFO thresholds. + 486: Set 8 longword burst. + 586: no burst limit. + Burst length 5:3 + 0 0 0 1 + 0 0 1 4 + 0 1 0 8 + 0 1 1 16 + 1 0 0 32 + 1 0 1 64 + 1 1 0 128 + 1 1 1 256 + Wait the specified 50 PCI cycles after a reset by initializing + Tx and Rx queues and the address filter list. + FIXME (Ueimor): optimistic for alpha + posted writes ? */ + + np->bcrvalue = 0x10; /* little-endian, 8 burst length */ +#ifdef __BIG_ENDIAN + np->bcrvalue |= 0x04; /* big-endian */ +#endif + +#if defined(__i386__) && !defined(MODULE) && !defined(CONFIG_UML) + if (boot_cpu_data.x86 <= 4) + np->crvalue = 0xa00; + else +#endif + np->crvalue = 0xe00; /* rx 128 burst length */ + + +// 89/12/29 add, +// 90/1/16 modify, +// np->imrvalue=FBE|TUNF|CNTOVF|RBU|TI|RI; + np->imrvalue = TUNF | CNTOVF | RBU | TI | RI; + if (np->pci_dev->device == 0x891) { + np->bcrvalue |= 0x200; /* set PROG bit */ + np->crvalue |= CR_W_ENH; /* set enhanced bit */ + np->imrvalue |= ETI; + } + iowrite32(np->bcrvalue, ioaddr + BCR); + + if (dev->if_port == 0) + dev->if_port = np->default_port; + + iowrite32(0, ioaddr + RXPDR); +// 89/9/1 modify, +// np->crvalue = 0x00e40001; /* tx store and forward, tx/rx enable */ + np->crvalue |= 0x00e40001; /* tx store and forward, tx/rx enable */ + np->mii.full_duplex = np->mii.force_media; + getlinkstatus(dev); + if (np->linkok) + getlinktype(dev); + __set_rx_mode(dev); + + netif_start_queue(dev); + + /* Clear and Enable interrupts by setting the interrupt mask. */ + iowrite32(FBE | TUNF | CNTOVF | RBU | TI | RI, ioaddr + ISR); + iowrite32(np->imrvalue, ioaddr + IMR); + + if (debug) + printk(KERN_DEBUG "%s: Done netdev_open().\n", dev->name); + + /* Set the timer to check for link beat. */ + timer_setup(&np->timer, netdev_timer, 0); + np->timer.expires = RUN_AT(3 * HZ); + + /* timer handler */ + add_timer(&np->timer); + + timer_setup(&np->reset_timer, reset_timer, 0); + np->reset_timer_armed = 0; + return rc; +} + + +static void getlinkstatus(struct net_device *dev) +/* function: Routine will read MII Status Register to get link status. */ +/* input : dev... pointer to the adapter block. */ +/* output : none. */ +{ + struct netdev_private *np = netdev_priv(dev); + unsigned int i, DelayTime = 0x1000; + + np->linkok = 0; + + if (np->PHYType == MysonPHY) { + for (i = 0; i < DelayTime; ++i) { + if (ioread32(np->mem + BMCRSR) & LinkIsUp2) { + np->linkok = 1; + return; + } + udelay(100); + } + } else { + for (i = 0; i < DelayTime; ++i) { + if (mdio_read(dev, np->phys[0], MII_BMSR) & BMSR_LSTATUS) { + np->linkok = 1; + return; + } + udelay(100); + } + } +} + + +static void getlinktype(struct net_device *dev) +{ + struct netdev_private *np = netdev_priv(dev); + + if (np->PHYType == MysonPHY) { /* 3-in-1 case */ + if (ioread32(np->mem + TCRRCR) & CR_R_FD) + np->duplexmode = 2; /* full duplex */ + else + np->duplexmode = 1; /* half duplex */ + if (ioread32(np->mem + TCRRCR) & CR_R_PS10) + np->line_speed = 1; /* 10M */ + else + np->line_speed = 2; /* 100M */ + } else { + if (np->PHYType == SeeqPHY) { /* this PHY is SEEQ 80225 */ + unsigned int data; + + data = mdio_read(dev, np->phys[0], MIIRegister18); + if (data & SPD_DET_100) + np->line_speed = 2; /* 100M */ + else + np->line_speed = 1; /* 10M */ + if (data & DPLX_DET_FULL) + np->duplexmode = 2; /* full duplex mode */ + else + np->duplexmode = 1; /* half duplex mode */ + } else if (np->PHYType == AhdocPHY) { + unsigned int data; + + data = mdio_read(dev, np->phys[0], DiagnosticReg); + if (data & Speed_100) + np->line_speed = 2; /* 100M */ + else + np->line_speed = 1; /* 10M */ + if (data & DPLX_FULL) + np->duplexmode = 2; /* full duplex mode */ + else + np->duplexmode = 1; /* half duplex mode */ + } +/* 89/6/13 add, (begin) */ + else if (np->PHYType == MarvellPHY) { + unsigned int data; + + data = mdio_read(dev, np->phys[0], SpecificReg); + if (data & Full_Duplex) + np->duplexmode = 2; /* full duplex mode */ + else + np->duplexmode = 1; /* half duplex mode */ + data &= SpeedMask; + if (data == Speed_1000M) + np->line_speed = 3; /* 1000M */ + else if (data == Speed_100M) + np->line_speed = 2; /* 100M */ + else + np->line_speed = 1; /* 10M */ + } +/* 89/6/13 add, (end) */ +/* 89/7/27 add, (begin) */ + else if (np->PHYType == Myson981) { + unsigned int data; + + data = mdio_read(dev, np->phys[0], StatusRegister); + + if (data & SPEED100) + np->line_speed = 2; + else + np->line_speed = 1; + + if (data & FULLMODE) + np->duplexmode = 2; + else + np->duplexmode = 1; + } +/* 89/7/27 add, (end) */ +/* 89/12/29 add */ + else if (np->PHYType == LevelOnePHY) { + unsigned int data; + + data = mdio_read(dev, np->phys[0], SpecificReg); + if (data & LXT1000_Full) + np->duplexmode = 2; /* full duplex mode */ + else + np->duplexmode = 1; /* half duplex mode */ + data &= SpeedMask; + if (data == LXT1000_1000M) + np->line_speed = 3; /* 1000M */ + else if (data == LXT1000_100M) + np->line_speed = 2; /* 100M */ + else + np->line_speed = 1; /* 10M */ + } + np->crvalue &= (~CR_W_PS10) & (~CR_W_FD) & (~CR_W_PS1000); + if (np->line_speed == 1) + np->crvalue |= CR_W_PS10; + else if (np->line_speed == 3) + np->crvalue |= CR_W_PS1000; + if (np->duplexmode == 2) + np->crvalue |= CR_W_FD; + } +} + + +/* Take lock before calling this */ +static void allocate_rx_buffers(struct net_device *dev) +{ + struct netdev_private *np = netdev_priv(dev); + + /* allocate skb for rx buffers */ + while (np->really_rx_count != RX_RING_SIZE) { + struct sk_buff *skb; + + skb = netdev_alloc_skb(dev, np->rx_buf_sz); + if (skb == NULL) + break; /* Better luck next round. */ + + while (np->lack_rxbuf->skbuff) + np->lack_rxbuf = np->lack_rxbuf->next_desc_logical; + + np->lack_rxbuf->skbuff = skb; + np->lack_rxbuf->buffer = dma_map_single(&np->pci_dev->dev, + skb->data, + np->rx_buf_sz, + DMA_FROM_DEVICE); + np->lack_rxbuf->status = RXOWN; + ++np->really_rx_count; + } +} + + +static void netdev_timer(struct timer_list *t) +{ + struct netdev_private *np = from_timer(np, t, timer); + struct net_device *dev = np->mii.dev; + void __iomem *ioaddr = np->mem; + int old_crvalue = np->crvalue; + unsigned int old_linkok = np->linkok; + unsigned long flags; + + if (debug) + printk(KERN_DEBUG "%s: Media selection timer tick, status %8.8x " + "config %8.8x.\n", dev->name, ioread32(ioaddr + ISR), + ioread32(ioaddr + TCRRCR)); + + spin_lock_irqsave(&np->lock, flags); + + if (np->flags == HAS_MII_XCVR) { + getlinkstatus(dev); + if ((old_linkok == 0) && (np->linkok == 1)) { /* we need to detect the media type again */ + getlinktype(dev); + if (np->crvalue != old_crvalue) { + stop_nic_rxtx(ioaddr, np->crvalue); + iowrite32(np->crvalue, ioaddr + TCRRCR); + } + } + } + + allocate_rx_buffers(dev); + + spin_unlock_irqrestore(&np->lock, flags); + + np->timer.expires = RUN_AT(10 * HZ); + add_timer(&np->timer); +} + + +/* Take lock before calling */ +/* Reset chip and disable rx, tx and interrupts */ +static void reset_and_disable_rxtx(struct net_device *dev) +{ + struct netdev_private *np = netdev_priv(dev); + void __iomem *ioaddr = np->mem; + int delay=51; + + /* Reset the chip's Tx and Rx processes. */ + stop_nic_rxtx(ioaddr, 0); + + /* Disable interrupts by clearing the interrupt mask. */ + iowrite32(0, ioaddr + IMR); + + /* Reset the chip to erase previous misconfiguration. */ + iowrite32(0x00000001, ioaddr + BCR); + + /* Ueimor: wait for 50 PCI cycles (and flush posted writes btw). + We surely wait too long (address+data phase). Who cares? */ + while (--delay) { + ioread32(ioaddr + BCR); + rmb(); + } +} + + +/* Take lock before calling */ +/* Restore chip after reset */ +static void enable_rxtx(struct net_device *dev) +{ + struct netdev_private *np = netdev_priv(dev); + void __iomem *ioaddr = np->mem; + + reset_rx_descriptors(dev); + + iowrite32(np->tx_ring_dma + ((char*)np->cur_tx - (char*)np->tx_ring), + ioaddr + TXLBA); + iowrite32(np->rx_ring_dma + ((char*)np->cur_rx - (char*)np->rx_ring), + ioaddr + RXLBA); + + iowrite32(np->bcrvalue, ioaddr + BCR); + + iowrite32(0, ioaddr + RXPDR); + __set_rx_mode(dev); /* changes np->crvalue, writes it into TCRRCR */ + + /* Clear and Enable interrupts by setting the interrupt mask. */ + iowrite32(FBE | TUNF | CNTOVF | RBU | TI | RI, ioaddr + ISR); + iowrite32(np->imrvalue, ioaddr + IMR); + + iowrite32(0, ioaddr + TXPDR); +} + + +static void reset_timer(struct timer_list *t) +{ + struct netdev_private *np = from_timer(np, t, reset_timer); + struct net_device *dev = np->mii.dev; + unsigned long flags; + + printk(KERN_WARNING "%s: resetting tx and rx machinery\n", dev->name); + + spin_lock_irqsave(&np->lock, flags); + np->crvalue = np->crvalue_sv; + np->imrvalue = np->imrvalue_sv; + + reset_and_disable_rxtx(dev); + /* works for me without this: + reset_tx_descriptors(dev); */ + enable_rxtx(dev); + netif_start_queue(dev); /* FIXME: or netif_wake_queue(dev); ? */ + + np->reset_timer_armed = 0; + + spin_unlock_irqrestore(&np->lock, flags); +} + + +static void fealnx_tx_timeout(struct net_device *dev, unsigned int txqueue) +{ + struct netdev_private *np = netdev_priv(dev); + void __iomem *ioaddr = np->mem; + unsigned long flags; + int i; + + printk(KERN_WARNING + "%s: Transmit timed out, status %8.8x, resetting...\n", + dev->name, ioread32(ioaddr + ISR)); + + { + printk(KERN_DEBUG " Rx ring %p: ", np->rx_ring); + for (i = 0; i < RX_RING_SIZE; i++) + printk(KERN_CONT " %8.8x", + (unsigned int) np->rx_ring[i].status); + printk(KERN_CONT "\n"); + printk(KERN_DEBUG " Tx ring %p: ", np->tx_ring); + for (i = 0; i < TX_RING_SIZE; i++) + printk(KERN_CONT " %4.4x", np->tx_ring[i].status); + printk(KERN_CONT "\n"); + } + + spin_lock_irqsave(&np->lock, flags); + + reset_and_disable_rxtx(dev); + reset_tx_descriptors(dev); + enable_rxtx(dev); + + spin_unlock_irqrestore(&np->lock, flags); + + netif_trans_update(dev); /* prevent tx timeout */ + dev->stats.tx_errors++; + netif_wake_queue(dev); /* or .._start_.. ?? */ +} + + +/* Initialize the Rx and Tx rings, along with various 'dev' bits. */ +static void init_ring(struct net_device *dev) +{ + struct netdev_private *np = netdev_priv(dev); + int i; + + /* initialize rx variables */ + np->rx_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 32); + np->cur_rx = &np->rx_ring[0]; + np->lack_rxbuf = np->rx_ring; + np->really_rx_count = 0; + + /* initial rx descriptors. */ + for (i = 0; i < RX_RING_SIZE; i++) { + np->rx_ring[i].status = 0; + np->rx_ring[i].control = np->rx_buf_sz << RBSShift; + np->rx_ring[i].next_desc = np->rx_ring_dma + + (i + 1)*sizeof(struct fealnx_desc); + np->rx_ring[i].next_desc_logical = &np->rx_ring[i + 1]; + np->rx_ring[i].skbuff = NULL; + } + + /* for the last rx descriptor */ + np->rx_ring[i - 1].next_desc = np->rx_ring_dma; + np->rx_ring[i - 1].next_desc_logical = np->rx_ring; + + /* allocate skb for rx buffers */ + for (i = 0; i < RX_RING_SIZE; i++) { + struct sk_buff *skb = netdev_alloc_skb(dev, np->rx_buf_sz); + + if (skb == NULL) { + np->lack_rxbuf = &np->rx_ring[i]; + break; + } + + ++np->really_rx_count; + np->rx_ring[i].skbuff = skb; + np->rx_ring[i].buffer = dma_map_single(&np->pci_dev->dev, + skb->data, + np->rx_buf_sz, + DMA_FROM_DEVICE); + np->rx_ring[i].status = RXOWN; + np->rx_ring[i].control |= RXIC; + } + + /* initialize tx variables */ + np->cur_tx = &np->tx_ring[0]; + np->cur_tx_copy = &np->tx_ring[0]; + np->really_tx_count = 0; + np->free_tx_count = TX_RING_SIZE; + + for (i = 0; i < TX_RING_SIZE; i++) { + np->tx_ring[i].status = 0; + /* do we need np->tx_ring[i].control = XXX; ?? */ + np->tx_ring[i].next_desc = np->tx_ring_dma + + (i + 1)*sizeof(struct fealnx_desc); + np->tx_ring[i].next_desc_logical = &np->tx_ring[i + 1]; + np->tx_ring[i].skbuff = NULL; + } + + /* for the last tx descriptor */ + np->tx_ring[i - 1].next_desc = np->tx_ring_dma; + np->tx_ring[i - 1].next_desc_logical = &np->tx_ring[0]; +} + + +static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev) +{ + struct netdev_private *np = netdev_priv(dev); + unsigned long flags; + + spin_lock_irqsave(&np->lock, flags); + + np->cur_tx_copy->skbuff = skb; + +#define one_buffer +#define BPT 1022 +#if defined(one_buffer) + np->cur_tx_copy->buffer = dma_map_single(&np->pci_dev->dev, skb->data, + skb->len, DMA_TO_DEVICE); + np->cur_tx_copy->control = TXIC | TXLD | TXFD | CRCEnable | PADEnable; + np->cur_tx_copy->control |= (skb->len << PKTSShift); /* pkt size */ + np->cur_tx_copy->control |= (skb->len << TBSShift); /* buffer size */ +// 89/12/29 add, + if (np->pci_dev->device == 0x891) + np->cur_tx_copy->control |= ETIControl | RetryTxLC; + np->cur_tx_copy->status = TXOWN; + np->cur_tx_copy = np->cur_tx_copy->next_desc_logical; + --np->free_tx_count; +#elif defined(two_buffer) + if (skb->len > BPT) { + struct fealnx_desc *next; + + /* for the first descriptor */ + np->cur_tx_copy->buffer = dma_map_single(&np->pci_dev->dev, + skb->data, BPT, + DMA_TO_DEVICE); + np->cur_tx_copy->control = TXIC | TXFD | CRCEnable | PADEnable; + np->cur_tx_copy->control |= (skb->len << PKTSShift); /* pkt size */ + np->cur_tx_copy->control |= (BPT << TBSShift); /* buffer size */ + + /* for the last descriptor */ + next = np->cur_tx_copy->next_desc_logical; + next->skbuff = skb; + next->control = TXIC | TXLD | CRCEnable | PADEnable; + next->control |= (skb->len << PKTSShift); /* pkt size */ + next->control |= ((skb->len - BPT) << TBSShift); /* buf size */ +// 89/12/29 add, + if (np->pci_dev->device == 0x891) + np->cur_tx_copy->control |= ETIControl | RetryTxLC; + next->buffer = dma_map_single(&ep->pci_dev->dev, + skb->data + BPT, skb->len - BPT, + DMA_TO_DEVICE); + + next->status = TXOWN; + np->cur_tx_copy->status = TXOWN; + + np->cur_tx_copy = next->next_desc_logical; + np->free_tx_count -= 2; + } else { + np->cur_tx_copy->buffer = dma_map_single(&np->pci_dev->dev, + skb->data, skb->len, + DMA_TO_DEVICE); + np->cur_tx_copy->control = TXIC | TXLD | TXFD | CRCEnable | PADEnable; + np->cur_tx_copy->control |= (skb->len << PKTSShift); /* pkt size */ + np->cur_tx_copy->control |= (skb->len << TBSShift); /* buffer size */ +// 89/12/29 add, + if (np->pci_dev->device == 0x891) + np->cur_tx_copy->control |= ETIControl | RetryTxLC; + np->cur_tx_copy->status = TXOWN; + np->cur_tx_copy = np->cur_tx_copy->next_desc_logical; + --np->free_tx_count; + } +#endif + + if (np->free_tx_count < 2) + netif_stop_queue(dev); + ++np->really_tx_count; + iowrite32(0, np->mem + TXPDR); + + spin_unlock_irqrestore(&np->lock, flags); + return NETDEV_TX_OK; +} + + +/* Take lock before calling */ +/* Chip probably hosed tx ring. Clean up. */ +static void reset_tx_descriptors(struct net_device *dev) +{ + struct netdev_private *np = netdev_priv(dev); + struct fealnx_desc *cur; + int i; + + /* initialize tx variables */ + np->cur_tx = &np->tx_ring[0]; + np->cur_tx_copy = &np->tx_ring[0]; + np->really_tx_count = 0; + np->free_tx_count = TX_RING_SIZE; + + for (i = 0; i < TX_RING_SIZE; i++) { + cur = &np->tx_ring[i]; + if (cur->skbuff) { + dma_unmap_single(&np->pci_dev->dev, cur->buffer, + cur->skbuff->len, DMA_TO_DEVICE); + dev_kfree_skb_any(cur->skbuff); + cur->skbuff = NULL; + } + cur->status = 0; + cur->control = 0; /* needed? */ + /* probably not needed. We do it for purely paranoid reasons */ + cur->next_desc = np->tx_ring_dma + + (i + 1)*sizeof(struct fealnx_desc); + cur->next_desc_logical = &np->tx_ring[i + 1]; + } + /* for the last tx descriptor */ + np->tx_ring[TX_RING_SIZE - 1].next_desc = np->tx_ring_dma; + np->tx_ring[TX_RING_SIZE - 1].next_desc_logical = &np->tx_ring[0]; +} + + +/* Take lock and stop rx before calling this */ +static void reset_rx_descriptors(struct net_device *dev) +{ + struct netdev_private *np = netdev_priv(dev); + struct fealnx_desc *cur = np->cur_rx; + int i; + + allocate_rx_buffers(dev); + + for (i = 0; i < RX_RING_SIZE; i++) { + if (cur->skbuff) + cur->status = RXOWN; + cur = cur->next_desc_logical; + } + + iowrite32(np->rx_ring_dma + ((char*)np->cur_rx - (char*)np->rx_ring), + np->mem + RXLBA); +} + + +/* The interrupt handler does all of the Rx thread work and cleans up + after the Tx thread. */ +static irqreturn_t intr_handler(int irq, void *dev_instance) +{ + struct net_device *dev = (struct net_device *) dev_instance; + struct netdev_private *np = netdev_priv(dev); + void __iomem *ioaddr = np->mem; + long boguscnt = max_interrupt_work; + unsigned int num_tx = 0; + int handled = 0; + + spin_lock(&np->lock); + + iowrite32(0, ioaddr + IMR); + + do { + u32 intr_status = ioread32(ioaddr + ISR); + + /* Acknowledge all of the current interrupt sources ASAP. */ + iowrite32(intr_status, ioaddr + ISR); + + if (debug) + printk(KERN_DEBUG "%s: Interrupt, status %4.4x.\n", dev->name, + intr_status); + + if (!(intr_status & np->imrvalue)) + break; + + handled = 1; + +// 90/1/16 delete, +// +// if (intr_status & FBE) +// { /* fatal error */ +// stop_nic_tx(ioaddr, 0); +// stop_nic_rx(ioaddr, 0); +// break; +// }; + + if (intr_status & TUNF) + iowrite32(0, ioaddr + TXPDR); + + if (intr_status & CNTOVF) { + /* missed pkts */ + dev->stats.rx_missed_errors += + ioread32(ioaddr + TALLY) & 0x7fff; + + /* crc error */ + dev->stats.rx_crc_errors += + (ioread32(ioaddr + TALLY) & 0x7fff0000) >> 16; + } + + if (intr_status & (RI | RBU)) { + if (intr_status & RI) + netdev_rx(dev); + else { + stop_nic_rx(ioaddr, np->crvalue); + reset_rx_descriptors(dev); + iowrite32(np->crvalue, ioaddr + TCRRCR); + } + } + + while (np->really_tx_count) { + long tx_status = np->cur_tx->status; + long tx_control = np->cur_tx->control; + + if (!(tx_control & TXLD)) { /* this pkt is combined by two tx descriptors */ + struct fealnx_desc *next; + + next = np->cur_tx->next_desc_logical; + tx_status = next->status; + tx_control = next->control; + } + + if (tx_status & TXOWN) + break; + + if (!(np->crvalue & CR_W_ENH)) { + if (tx_status & (CSL | LC | EC | UDF | HF)) { + dev->stats.tx_errors++; + if (tx_status & EC) + dev->stats.tx_aborted_errors++; + if (tx_status & CSL) + dev->stats.tx_carrier_errors++; + if (tx_status & LC) + dev->stats.tx_window_errors++; + if (tx_status & UDF) + dev->stats.tx_fifo_errors++; + if ((tx_status & HF) && np->mii.full_duplex == 0) + dev->stats.tx_heartbeat_errors++; + + } else { + dev->stats.tx_bytes += + ((tx_control & PKTSMask) >> PKTSShift); + + dev->stats.collisions += + ((tx_status & NCRMask) >> NCRShift); + dev->stats.tx_packets++; + } + } else { + dev->stats.tx_bytes += + ((tx_control & PKTSMask) >> PKTSShift); + dev->stats.tx_packets++; + } + + /* Free the original skb. */ + dma_unmap_single(&np->pci_dev->dev, + np->cur_tx->buffer, + np->cur_tx->skbuff->len, + DMA_TO_DEVICE); + dev_consume_skb_irq(np->cur_tx->skbuff); + np->cur_tx->skbuff = NULL; + --np->really_tx_count; + if (np->cur_tx->control & TXLD) { + np->cur_tx = np->cur_tx->next_desc_logical; + ++np->free_tx_count; + } else { + np->cur_tx = np->cur_tx->next_desc_logical; + np->cur_tx = np->cur_tx->next_desc_logical; + np->free_tx_count += 2; + } + num_tx++; + } /* end of for loop */ + + if (num_tx && np->free_tx_count >= 2) + netif_wake_queue(dev); + + /* read transmit status for enhanced mode only */ + if (np->crvalue & CR_W_ENH) { + long data; + + data = ioread32(ioaddr + TSR); + dev->stats.tx_errors += (data & 0xff000000) >> 24; + dev->stats.tx_aborted_errors += + (data & 0xff000000) >> 24; + dev->stats.tx_window_errors += + (data & 0x00ff0000) >> 16; + dev->stats.collisions += (data & 0x0000ffff); + } + + if (--boguscnt < 0) { + printk(KERN_WARNING "%s: Too much work at interrupt, " + "status=0x%4.4x.\n", dev->name, intr_status); + if (!np->reset_timer_armed) { + np->reset_timer_armed = 1; + np->reset_timer.expires = RUN_AT(HZ/2); + add_timer(&np->reset_timer); + stop_nic_rxtx(ioaddr, 0); + netif_stop_queue(dev); + /* or netif_tx_disable(dev); ?? */ + /* Prevent other paths from enabling tx,rx,intrs */ + np->crvalue_sv = np->crvalue; + np->imrvalue_sv = np->imrvalue; + np->crvalue &= ~(CR_W_TXEN | CR_W_RXEN); /* or simply = 0? */ + np->imrvalue = 0; + } + + break; + } + } while (1); + + /* read the tally counters */ + /* missed pkts */ + dev->stats.rx_missed_errors += ioread32(ioaddr + TALLY) & 0x7fff; + + /* crc error */ + dev->stats.rx_crc_errors += + (ioread32(ioaddr + TALLY) & 0x7fff0000) >> 16; + + if (debug) + printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n", + dev->name, ioread32(ioaddr + ISR)); + + iowrite32(np->imrvalue, ioaddr + IMR); + + spin_unlock(&np->lock); + + return IRQ_RETVAL(handled); +} + + +/* This routine is logically part of the interrupt handler, but separated + for clarity and better register allocation. */ +static int netdev_rx(struct net_device *dev) +{ + struct netdev_private *np = netdev_priv(dev); + void __iomem *ioaddr = np->mem; + + /* If EOP is set on the next entry, it's a new packet. Send it up. */ + while (!(np->cur_rx->status & RXOWN) && np->cur_rx->skbuff) { + s32 rx_status = np->cur_rx->status; + + if (np->really_rx_count == 0) + break; + + if (debug) + printk(KERN_DEBUG " netdev_rx() status was %8.8x.\n", rx_status); + + if ((!((rx_status & RXFSD) && (rx_status & RXLSD))) || + (rx_status & ErrorSummary)) { + if (rx_status & ErrorSummary) { /* there was a fatal error */ + if (debug) + printk(KERN_DEBUG + "%s: Receive error, Rx status %8.8x.\n", + dev->name, rx_status); + + dev->stats.rx_errors++; /* end of a packet. */ + if (rx_status & (LONGPKT | RUNTPKT)) + dev->stats.rx_length_errors++; + if (rx_status & RXER) + dev->stats.rx_frame_errors++; + if (rx_status & CRC) + dev->stats.rx_crc_errors++; + } else { + int need_to_reset = 0; + int desno = 0; + + if (rx_status & RXFSD) { /* this pkt is too long, over one rx buffer */ + struct fealnx_desc *cur; + + /* check this packet is received completely? */ + cur = np->cur_rx; + while (desno <= np->really_rx_count) { + ++desno; + if ((!(cur->status & RXOWN)) && + (cur->status & RXLSD)) + break; + /* goto next rx descriptor */ + cur = cur->next_desc_logical; + } + if (desno > np->really_rx_count) + need_to_reset = 1; + } else /* RXLSD did not find, something error */ + need_to_reset = 1; + + if (need_to_reset == 0) { + int i; + + dev->stats.rx_length_errors++; + + /* free all rx descriptors related this long pkt */ + for (i = 0; i < desno; ++i) { + if (!np->cur_rx->skbuff) { + printk(KERN_DEBUG + "%s: I'm scared\n", dev->name); + break; + } + np->cur_rx->status = RXOWN; + np->cur_rx = np->cur_rx->next_desc_logical; + } + continue; + } else { /* rx error, need to reset this chip */ + stop_nic_rx(ioaddr, np->crvalue); + reset_rx_descriptors(dev); + iowrite32(np->crvalue, ioaddr + TCRRCR); + } + break; /* exit the while loop */ + } + } else { /* this received pkt is ok */ + + struct sk_buff *skb; + /* Omit the four octet CRC from the length. */ + short pkt_len = ((rx_status & FLNGMASK) >> FLNGShift) - 4; + +#ifndef final_version + if (debug) + printk(KERN_DEBUG " netdev_rx() normal Rx pkt length %d" + " status %x.\n", pkt_len, rx_status); +#endif + + /* Check if the packet is long enough to accept without copying + to a minimally-sized skbuff. */ + if (pkt_len < rx_copybreak && + (skb = netdev_alloc_skb(dev, pkt_len + 2)) != NULL) { + skb_reserve(skb, 2); /* 16 byte align the IP header */ + dma_sync_single_for_cpu(&np->pci_dev->dev, + np->cur_rx->buffer, + np->rx_buf_sz, + DMA_FROM_DEVICE); + /* Call copy + cksum if available. */ + +#if ! defined(__alpha__) + skb_copy_to_linear_data(skb, + np->cur_rx->skbuff->data, pkt_len); + skb_put(skb, pkt_len); +#else + skb_put_data(skb, np->cur_rx->skbuff->data, + pkt_len); +#endif + dma_sync_single_for_device(&np->pci_dev->dev, + np->cur_rx->buffer, + np->rx_buf_sz, + DMA_FROM_DEVICE); + } else { + dma_unmap_single(&np->pci_dev->dev, + np->cur_rx->buffer, + np->rx_buf_sz, + DMA_FROM_DEVICE); + skb_put(skb = np->cur_rx->skbuff, pkt_len); + np->cur_rx->skbuff = NULL; + --np->really_rx_count; + } + skb->protocol = eth_type_trans(skb, dev); + netif_rx(skb); + dev->stats.rx_packets++; + dev->stats.rx_bytes += pkt_len; + } + + np->cur_rx = np->cur_rx->next_desc_logical; + } /* end of while loop */ + + /* allocate skb for rx buffers */ + allocate_rx_buffers(dev); + + return 0; +} + + +static struct net_device_stats *get_stats(struct net_device *dev) +{ + struct netdev_private *np = netdev_priv(dev); + void __iomem *ioaddr = np->mem; + + /* The chip only need report frame silently dropped. */ + if (netif_running(dev)) { + dev->stats.rx_missed_errors += + ioread32(ioaddr + TALLY) & 0x7fff; + dev->stats.rx_crc_errors += + (ioread32(ioaddr + TALLY) & 0x7fff0000) >> 16; + } + + return &dev->stats; +} + + +/* for dev->set_multicast_list */ +static void set_rx_mode(struct net_device *dev) +{ + spinlock_t *lp = &((struct netdev_private *)netdev_priv(dev))->lock; + unsigned long flags; + spin_lock_irqsave(lp, flags); + __set_rx_mode(dev); + spin_unlock_irqrestore(lp, flags); +} + + +/* Take lock before calling */ +static void __set_rx_mode(struct net_device *dev) +{ + struct netdev_private *np = netdev_priv(dev); + void __iomem *ioaddr = np->mem; + u32 mc_filter[2]; /* Multicast hash filter */ + u32 rx_mode; + + if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */ + memset(mc_filter, 0xff, sizeof(mc_filter)); + rx_mode = CR_W_PROM | CR_W_AB | CR_W_AM; + } else if ((netdev_mc_count(dev) > multicast_filter_limit) || + (dev->flags & IFF_ALLMULTI)) { + /* Too many to match, or accept all multicasts. */ + memset(mc_filter, 0xff, sizeof(mc_filter)); + rx_mode = CR_W_AB | CR_W_AM; + } else { + struct netdev_hw_addr *ha; + + memset(mc_filter, 0, sizeof(mc_filter)); + netdev_for_each_mc_addr(ha, dev) { + unsigned int bit; + bit = (ether_crc(ETH_ALEN, ha->addr) >> 26) ^ 0x3F; + mc_filter[bit >> 5] |= (1 << bit); + } + rx_mode = CR_W_AB | CR_W_AM; + } + + stop_nic_rxtx(ioaddr, np->crvalue); + + iowrite32(mc_filter[0], ioaddr + MAR0); + iowrite32(mc_filter[1], ioaddr + MAR1); + np->crvalue &= ~CR_W_RXMODEMASK; + np->crvalue |= rx_mode; + iowrite32(np->crvalue, ioaddr + TCRRCR); +} + +static void netdev_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) +{ + struct netdev_private *np = netdev_priv(dev); + + strscpy(info->driver, DRV_NAME, sizeof(info->driver)); + strscpy(info->bus_info, pci_name(np->pci_dev), sizeof(info->bus_info)); +} + +static int netdev_get_link_ksettings(struct net_device *dev, + struct ethtool_link_ksettings *cmd) +{ + struct netdev_private *np = netdev_priv(dev); + + spin_lock_irq(&np->lock); + mii_ethtool_get_link_ksettings(&np->mii, cmd); + spin_unlock_irq(&np->lock); + + return 0; +} + +static int netdev_set_link_ksettings(struct net_device *dev, + const struct ethtool_link_ksettings *cmd) +{ + struct netdev_private *np = netdev_priv(dev); + int rc; + + spin_lock_irq(&np->lock); + rc = mii_ethtool_set_link_ksettings(&np->mii, cmd); + spin_unlock_irq(&np->lock); + + return rc; +} + +static int netdev_nway_reset(struct net_device *dev) +{ + struct netdev_private *np = netdev_priv(dev); + return mii_nway_restart(&np->mii); +} + +static u32 netdev_get_link(struct net_device *dev) +{ + struct netdev_private *np = netdev_priv(dev); + return mii_link_ok(&np->mii); +} + +static u32 netdev_get_msglevel(struct net_device *dev) +{ + return debug; +} + +static void netdev_set_msglevel(struct net_device *dev, u32 value) +{ + debug = value; +} + +static const struct ethtool_ops netdev_ethtool_ops = { + .get_drvinfo = netdev_get_drvinfo, + .nway_reset = netdev_nway_reset, + .get_link = netdev_get_link, + .get_msglevel = netdev_get_msglevel, + .set_msglevel = netdev_set_msglevel, + .get_link_ksettings = netdev_get_link_ksettings, + .set_link_ksettings = netdev_set_link_ksettings, +}; + +static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +{ + struct netdev_private *np = netdev_priv(dev); + int rc; + + if (!netif_running(dev)) + return -EINVAL; + + spin_lock_irq(&np->lock); + rc = generic_mii_ioctl(&np->mii, if_mii(rq), cmd, NULL); + spin_unlock_irq(&np->lock); + + return rc; +} + + +static int netdev_close(struct net_device *dev) +{ + struct netdev_private *np = netdev_priv(dev); + void __iomem *ioaddr = np->mem; + int i; + + netif_stop_queue(dev); + + /* Disable interrupts by clearing the interrupt mask. */ + iowrite32(0x0000, ioaddr + IMR); + + /* Stop the chip's Tx and Rx processes. */ + stop_nic_rxtx(ioaddr, 0); + + del_timer_sync(&np->timer); + del_timer_sync(&np->reset_timer); + + free_irq(np->pci_dev->irq, dev); + + /* Free all the skbuffs in the Rx queue. */ + for (i = 0; i < RX_RING_SIZE; i++) { + struct sk_buff *skb = np->rx_ring[i].skbuff; + + np->rx_ring[i].status = 0; + if (skb) { + dma_unmap_single(&np->pci_dev->dev, + np->rx_ring[i].buffer, np->rx_buf_sz, + DMA_FROM_DEVICE); + dev_kfree_skb(skb); + np->rx_ring[i].skbuff = NULL; + } + } + + for (i = 0; i < TX_RING_SIZE; i++) { + struct sk_buff *skb = np->tx_ring[i].skbuff; + + if (skb) { + dma_unmap_single(&np->pci_dev->dev, + np->tx_ring[i].buffer, skb->len, + DMA_TO_DEVICE); + dev_kfree_skb(skb); + np->tx_ring[i].skbuff = NULL; + } + } + + return 0; +} + +static const struct pci_device_id fealnx_pci_tbl[] = { + {0x1516, 0x0800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x1516, 0x0803, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, + {0x1516, 0x0891, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2}, + {} /* terminate list */ +}; +MODULE_DEVICE_TABLE(pci, fealnx_pci_tbl); + + +static struct pci_driver fealnx_driver = { + .name = "fealnx", + .id_table = fealnx_pci_tbl, + .probe = fealnx_init_one, + .remove = fealnx_remove_one, +}; + +module_pci_driver(fealnx_driver); From 2aab4b96900272885bc157f8b236abf1cdc02e08 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 7 Mar 2023 16:45:30 +0000 Subject: [PATCH 273/778] af_unix: fix struct pid leaks in OOB support syzbot reported struct pid leak [1]. Issue is that queue_oob() calls maybe_add_creds() which potentially holds a reference on a pid. But skb->destructor is not set (either directly or by calling unix_scm_to_skb()) This means that subsequent kfree_skb() or consume_skb() would leak this reference. In this fix, I chose to fully support scm even for the OOB message. [1] BUG: memory leak unreferenced object 0xffff8881053e7f80 (size 128): comm "syz-executor242", pid 5066, jiffies 4294946079 (age 13.220s) hex dump (first 32 bytes): 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ backtrace: [] alloc_pid+0x6a/0x560 kernel/pid.c:180 [] copy_process+0x169f/0x26c0 kernel/fork.c:2285 [] kernel_clone+0xf7/0x610 kernel/fork.c:2684 [] __do_sys_clone+0x7c/0xb0 kernel/fork.c:2825 [] do_syscall_x64 arch/x86/entry/common.c:50 [inline] [] do_syscall_64+0x39/0xb0 arch/x86/entry/common.c:80 [] entry_SYSCALL_64_after_hwframe+0x63/0xcd Fixes: 314001f0bf92 ("af_unix: Add OOB support") Reported-by: syzbot+7699d9e5635c10253a27@syzkaller.appspotmail.com Signed-off-by: Eric Dumazet Cc: Rao Shoaib Reviewed-by: Kuniyuki Iwashima Link: https://lore.kernel.org/r/20230307164530.771896-1-edumazet@google.com Signed-off-by: Jakub Kicinski --- net/unix/af_unix.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 347122c3575e..0b0f18ecce44 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -2105,7 +2105,8 @@ out: #define UNIX_SKB_FRAGS_SZ (PAGE_SIZE << get_order(32768)) #if IS_ENABLED(CONFIG_AF_UNIX_OOB) -static int queue_oob(struct socket *sock, struct msghdr *msg, struct sock *other) +static int queue_oob(struct socket *sock, struct msghdr *msg, struct sock *other, + struct scm_cookie *scm, bool fds_sent) { struct unix_sock *ousk = unix_sk(other); struct sk_buff *skb; @@ -2116,6 +2117,11 @@ static int queue_oob(struct socket *sock, struct msghdr *msg, struct sock *other if (!skb) return err; + err = unix_scm_to_skb(scm, skb, !fds_sent); + if (err < 0) { + kfree_skb(skb); + return err; + } skb_put(skb, 1); err = skb_copy_datagram_from_iter(skb, 0, &msg->msg_iter, 1); @@ -2243,7 +2249,7 @@ static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg, #if IS_ENABLED(CONFIG_AF_UNIX_OOB) if (msg->msg_flags & MSG_OOB) { - err = queue_oob(sock, msg, other); + err = queue_oob(sock, msg, other, &scm, fds_sent); if (err) goto out_err; sent++; From 649c15c7691e9b13cbe9bf6c65c365350e056067 Mon Sep 17 00:00:00 2001 From: Thadeu Lima de Souza Cascardo Date: Tue, 7 Mar 2023 14:37:07 -0300 Subject: [PATCH 274/778] net: avoid double iput when sock_alloc_file fails When sock_alloc_file fails to allocate a file, it will call sock_release. __sys_socket_file should then not call sock_release again, otherwise there will be a double free. [ 89.319884] ------------[ cut here ]------------ [ 89.320286] kernel BUG at fs/inode.c:1764! [ 89.320656] invalid opcode: 0000 [#1] PREEMPT SMP NOPTI [ 89.321051] CPU: 7 PID: 125 Comm: iou-sqp-124 Not tainted 6.2.0+ #361 [ 89.321535] RIP: 0010:iput+0x1ff/0x240 [ 89.321808] Code: d1 83 e1 03 48 83 f9 02 75 09 48 81 fa 00 10 00 00 77 05 83 e2 01 75 1f 4c 89 ef e8 fb d2 ba 00 e9 80 fe ff ff c3 cc cc cc cc <0f> 0b 0f 0b e9 d0 fe ff ff 0f 0b eb 8d 49 8d b4 24 08 01 00 00 48 [ 89.322760] RSP: 0018:ffffbdd60068bd50 EFLAGS: 00010202 [ 89.323036] RAX: 0000000000000000 RBX: ffff9d7ad3cacac0 RCX: 0000000000001107 [ 89.323412] RDX: 000000000003af00 RSI: 0000000000000000 RDI: ffff9d7ad3cacb40 [ 89.323785] RBP: ffffbdd60068bd68 R08: ffffffffffffffff R09: ffffffffab606438 [ 89.324157] R10: ffffffffacb3dfa0 R11: 6465686361657256 R12: ffff9d7ad3cacb40 [ 89.324529] R13: 0000000080000001 R14: 0000000080000001 R15: 0000000000000002 [ 89.324904] FS: 00007f7b28516740(0000) GS:ffff9d7aeb1c0000(0000) knlGS:0000000000000000 [ 89.325328] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 89.325629] CR2: 00007f0af52e96c0 CR3: 0000000002a02006 CR4: 0000000000770ee0 [ 89.326004] PKRU: 55555554 [ 89.326161] Call Trace: [ 89.326298] [ 89.326419] __sock_release+0xb5/0xc0 [ 89.326632] __sys_socket_file+0xb2/0xd0 [ 89.326844] io_socket+0x88/0x100 [ 89.327039] ? io_issue_sqe+0x6a/0x430 [ 89.327258] io_issue_sqe+0x67/0x430 [ 89.327450] io_submit_sqes+0x1fe/0x670 [ 89.327661] io_sq_thread+0x2e6/0x530 [ 89.327859] ? __pfx_autoremove_wake_function+0x10/0x10 [ 89.328145] ? __pfx_io_sq_thread+0x10/0x10 [ 89.328367] ret_from_fork+0x29/0x50 [ 89.328576] RIP: 0033:0x0 [ 89.328732] Code: Unable to access opcode bytes at 0xffffffffffffffd6. [ 89.329073] RSP: 002b:0000000000000000 EFLAGS: 00000202 ORIG_RAX: 00000000000001a9 [ 89.329477] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 00007f7b28637a3d [ 89.329845] RDX: 00007fff4e4318a8 RSI: 00007fff4e4318b0 RDI: 0000000000000400 [ 89.330216] RBP: 00007fff4e431830 R08: 00007fff4e431711 R09: 00007fff4e4318b0 [ 89.330584] R10: 0000000000000000 R11: 0000000000000202 R12: 00007fff4e441b38 [ 89.330950] R13: 0000563835e3e725 R14: 0000563835e40d10 R15: 00007f7b28784040 [ 89.331318] [ 89.331441] Modules linked in: [ 89.331617] ---[ end trace 0000000000000000 ]--- Fixes: da214a475f8b ("net: add __sys_socket_file()") Signed-off-by: Thadeu Lima de Souza Cascardo Reviewed-by: Jens Axboe Reviewed-by: Eric Dumazet Reviewed-by: Kuniyuki Iwashima Link: https://lore.kernel.org/r/20230307173707.468744-1-cascardo@canonical.com Signed-off-by: Jakub Kicinski --- net/socket.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/net/socket.c b/net/socket.c index 6bae8ce7059e..9c92c0e6c4da 100644 --- a/net/socket.c +++ b/net/socket.c @@ -450,7 +450,9 @@ static struct file_system_type sock_fs_type = { * * Returns the &file bound with @sock, implicitly storing it * in sock->file. If dname is %NULL, sets to "". - * On failure the return is a ERR pointer (see linux/err.h). + * + * On failure @sock is released, and an ERR pointer is returned. + * * This function uses GFP_KERNEL internally. */ @@ -1638,7 +1640,6 @@ static struct socket *__sys_socket_create(int family, int type, int protocol) struct file *__sys_socket_file(int family, int type, int protocol) { struct socket *sock; - struct file *file; int flags; sock = __sys_socket_create(family, type, protocol); @@ -1649,11 +1650,7 @@ struct file *__sys_socket_file(int family, int type, int protocol) if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK)) flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK; - file = sock_alloc_file(sock, flags, NULL); - if (IS_ERR(file)) - sock_release(sock); - - return file; + return sock_alloc_file(sock, flags, NULL); } int __sys_socket(int family, int type, int protocol) From 6517a60b0307abdcca80133c237551cc7cc8e6ae Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 7 Mar 2023 16:39:22 -0800 Subject: [PATCH 275/778] tools: ynl: move the enum classes to shared code Move bulk of the EnumSet and EnumEntry code to shared code for reuse by cli. Signed-off-by: Jakub Kicinski --- tools/net/ynl/lib/__init__.py | 7 ++- tools/net/ynl/lib/nlspec.py | 96 +++++++++++++++++++++++++++++++ tools/net/ynl/ynl-gen-c.py | 105 +++++++--------------------------- 3 files changed, 120 insertions(+), 88 deletions(-) diff --git a/tools/net/ynl/lib/__init__.py b/tools/net/ynl/lib/__init__.py index a2cb8b16d6f1..4b3797fe784b 100644 --- a/tools/net/ynl/lib/__init__.py +++ b/tools/net/ynl/lib/__init__.py @@ -1,7 +1,8 @@ # SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause -from .nlspec import SpecAttr, SpecAttrSet, SpecFamily, SpecOperation +from .nlspec import SpecAttr, SpecAttrSet, SpecEnumEntry, SpecEnumSet, \ + SpecFamily, SpecOperation from .ynl import YnlFamily -__all__ = ["SpecAttr", "SpecAttrSet", "SpecFamily", "SpecOperation", - "YnlFamily"] +__all__ = ["SpecAttr", "SpecAttrSet", "SpecEnumEntry", "SpecEnumSet", + "SpecFamily", "SpecOperation", "YnlFamily"] diff --git a/tools/net/ynl/lib/nlspec.py b/tools/net/ynl/lib/nlspec.py index 0a2cfb5862aa..7c1cf6c1499e 100644 --- a/tools/net/ynl/lib/nlspec.py +++ b/tools/net/ynl/lib/nlspec.py @@ -57,6 +57,91 @@ class SpecElement: pass +class SpecEnumEntry(SpecElement): + """ Entry within an enum declared in the Netlink spec. + + Attributes: + doc documentation string + enum_set back reference to the enum + value numerical value of this enum (use accessors in most situations!) + + Methods: + raw_value raw value, i.e. the id in the enum, unlike user value which is a mask for flags + user_value user value, same as raw value for enums, for flags it's the mask + """ + def __init__(self, enum_set, yaml, prev, value_start): + if isinstance(yaml, str): + yaml = {'name': yaml} + super().__init__(enum_set.family, yaml) + + self.doc = yaml.get('doc', '') + self.enum_set = enum_set + + if 'value' in yaml: + self.value = yaml['value'] + elif prev: + self.value = prev.value + 1 + else: + self.value = value_start + + def has_doc(self): + return bool(self.doc) + + def raw_value(self): + return self.value + + def user_value(self): + if self.enum_set['type'] == 'flags': + return 1 << self.value + else: + return self.value + + +class SpecEnumSet(SpecElement): + """ Enum type + + Represents an enumeration (list of numerical constants) + as declared in the "definitions" section of the spec. + + Attributes: + type enum or flags + entries entries by name + Methods: + get_mask for flags compute the mask of all defined values + """ + def __init__(self, family, yaml): + super().__init__(family, yaml) + + self.type = yaml['type'] + + prev_entry = None + value_start = self.yaml.get('value-start', 0) + self.entries = dict() + for entry in self.yaml['entries']: + e = self.new_entry(entry, prev_entry, value_start) + self.entries[e.name] = e + prev_entry = e + + def new_entry(self, entry, prev_entry, value_start): + return SpecEnumEntry(self, entry, prev_entry, value_start) + + def has_doc(self): + if 'doc' in self.yaml: + return True + for entry in self.entries.values(): + if entry.has_doc(): + return True + return False + + def get_mask(self): + mask = 0 + idx = self.yaml.get('value-start', 0) + for _ in self.entries.values(): + mask |= 1 << idx + idx += 1 + return mask + + class SpecAttr(SpecElement): """ Single Netlink atttribute type @@ -193,6 +278,7 @@ class SpecFamily(SpecElement): msgs dict of all messages (index by name) msgs_by_value dict of all messages (indexed by name) ops dict of all valid requests / responses + consts dict of all constants/enums """ def __init__(self, spec_path, schema_path=None): with open(spec_path, "r") as stream: @@ -222,6 +308,7 @@ class SpecFamily(SpecElement): self.req_by_value = collections.OrderedDict() self.rsp_by_value = collections.OrderedDict() self.ops = collections.OrderedDict() + self.consts = collections.OrderedDict() last_exception = None while len(self._resolution_list) > 0: @@ -242,6 +329,9 @@ class SpecFamily(SpecElement): if len(resolved) == 0: raise last_exception + def new_enum(self, elem): + return SpecEnumSet(self, elem) + def new_attr_set(self, elem): return SpecAttrSet(self, elem) @@ -296,6 +386,12 @@ class SpecFamily(SpecElement): def resolve(self): self.resolve_up(super()) + for elem in self.yaml['definitions']: + if elem['type'] == 'enum' or elem['type'] == 'flags': + self.consts[elem['name']] = self.new_enum(elem) + else: + self.consts[elem['name']] = elem + for elem in self.yaml['attribute-sets']: attr_set = self.new_attr_set(elem) self.attr_sets[elem['name']] = attr_set diff --git a/tools/net/ynl/ynl-gen-c.py b/tools/net/ynl/ynl-gen-c.py index c940ca834d3f..1bcc5354d800 100755 --- a/tools/net/ynl/ynl-gen-c.py +++ b/tools/net/ynl/ynl-gen-c.py @@ -6,7 +6,7 @@ import collections import os import yaml -from lib import SpecFamily, SpecAttrSet, SpecAttr, SpecOperation +from lib import SpecFamily, SpecAttrSet, SpecAttr, SpecOperation, SpecEnumSet, SpecEnumEntry def c_upper(name): @@ -567,97 +567,37 @@ class Struct: self.inherited = [c_lower(x) for x in sorted(self._inherited)] -class EnumEntry: +class EnumEntry(SpecEnumEntry): def __init__(self, enum_set, yaml, prev, value_start): - if isinstance(yaml, str): - self.name = yaml - yaml = {} - self.doc = '' - else: - self.name = yaml['name'] - self.doc = yaml.get('doc', '') + super().__init__(enum_set, yaml, prev, value_start) - self.yaml = yaml - self.enum_set = enum_set - self.c_name = c_upper(enum_set.value_pfx + self.name) - - if 'value' in yaml: - self.value = yaml['value'] - if prev: - self.value_change = (self.value != prev.value + 1) - elif prev: - self.value_change = False - self.value = prev.value + 1 + if prev: + self.value_change = (self.value != prev.value + 1) else: - self.value = value_start self.value_change = (self.value != 0) - self.value_change = self.value_change or self.enum_set['type'] == 'flags' - def __getitem__(self, key): - return self.yaml[key] + # Added by resolve: + self.c_name = None + delattr(self, "c_name") - def __contains__(self, key): - return key in self.yaml + def resolve(self): + self.resolve_up(super()) - def has_doc(self): - return bool(self.doc) - - # raw value, i.e. the id in the enum, unlike user value which is a mask for flags - def raw_value(self): - return self.value - - # user value, same as raw value for enums, for flags it's the mask - def user_value(self): - if self.enum_set['type'] == 'flags': - return 1 << self.value - else: - return self.value + self.c_name = c_upper(self.enum_set.value_pfx + self.name) -class EnumSet: +class EnumSet(SpecEnumSet): def __init__(self, family, yaml): - self.yaml = yaml - self.family = family - self.render_name = c_lower(family.name + '-' + yaml['name']) self.enum_name = 'enum ' + self.render_name self.value_pfx = yaml.get('name-prefix', f"{family.name}-{yaml['name']}-") - self.type = yaml['type'] + super().__init__(family, yaml) - prev_entry = None - value_start = self.yaml.get('value-start', 0) - self.entries = {} - self.entry_list = [] - for entry in self.yaml['entries']: - e = EnumEntry(self, entry, prev_entry, value_start) - self.entries[e.name] = e - self.entry_list.append(e) - prev_entry = e - - def __getitem__(self, key): - return self.yaml[key] - - def __contains__(self, key): - return key in self.yaml - - def has_doc(self): - if 'doc' in self.yaml: - return True - for entry in self.entry_list: - if entry.has_doc(): - return True - return False - - def get_mask(self): - mask = 0 - idx = self.yaml.get('value-start', 0) - for _ in self.entry_list: - mask |= 1 << idx - idx += 1 - return mask + def new_entry(self, entry, prev_entry, value_start): + return EnumEntry(self, entry, prev_entry, value_start) class AttrSet(SpecAttrSet): @@ -792,8 +732,6 @@ class Family(SpecFamily): self.mcgrps = self.yaml.get('mcast-groups', {'list': []}) - self.consts = dict() - self.hooks = dict() for when in ['pre', 'post']: self.hooks[when] = dict() @@ -820,6 +758,9 @@ class Family(SpecFamily): if self.kernel_policy == 'global': self._load_global_policy() + def new_enum(self, elem): + return EnumSet(self, elem) + def new_attr_set(self, elem): return AttrSet(self, elem) @@ -837,12 +778,6 @@ class Family(SpecFamily): } def _dictify(self): - for elem in self.yaml['definitions']: - if elem['type'] == 'enum' or elem['type'] == 'flags': - self.consts[elem['name']] = EnumSet(self, elem) - else: - self.consts[elem['name']] = elem - ntf = [] for msg in self.msgs.values(): if 'notify' in msg: @@ -1980,7 +1915,7 @@ def render_uapi(family, cw): if 'doc' in enum: doc = ' - ' + enum['doc'] cw.write_doc_line(enum.enum_name + doc) - for entry in enum.entry_list: + for entry in enum.entries.values(): if entry.has_doc(): doc = '@' + entry.c_name + ': ' + entry['doc'] cw.write_doc_line(doc) @@ -1988,7 +1923,7 @@ def render_uapi(family, cw): uapi_enum_start(family, cw, const, 'name') name_pfx = const.get('name-prefix', f"{family.name}-{const['name']}-") - for entry in enum.entry_list: + for entry in enum.entries.values(): suffix = ',' if entry.value_change: suffix = f" = {entry.user_value()}" + suffix From c311aaa74ca18bd0781d1d3bebd08484799f840c Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 7 Mar 2023 16:39:23 -0800 Subject: [PATCH 276/778] tools: ynl: fix enum-as-flags in the generic CLI Lorenzo points out that the generic CLI is broken for the netdev family. When I added the support for documentation of enums (and sparse enums) the client script was not updated. It expects the values in enum to be a list of names, now it can also be a dict (YAML object). Reported-by: Lorenzo Bianconi Fixes: e4b48ed460d3 ("tools: ynl: add a completely generic client") Signed-off-by: Jakub Kicinski --- tools/net/ynl/lib/nlspec.py | 7 +++++-- tools/net/ynl/lib/ynl.py | 9 ++------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/tools/net/ynl/lib/nlspec.py b/tools/net/ynl/lib/nlspec.py index 7c1cf6c1499e..a34d088f6743 100644 --- a/tools/net/ynl/lib/nlspec.py +++ b/tools/net/ynl/lib/nlspec.py @@ -104,8 +104,9 @@ class SpecEnumSet(SpecElement): as declared in the "definitions" section of the spec. Attributes: - type enum or flags - entries entries by name + type enum or flags + entries entries by name + entries_by_val entries by value Methods: get_mask for flags compute the mask of all defined values """ @@ -117,9 +118,11 @@ class SpecEnumSet(SpecElement): prev_entry = None value_start = self.yaml.get('value-start', 0) self.entries = dict() + self.entries_by_val = dict() for entry in self.yaml['entries']: e = self.new_entry(entry, prev_entry, value_start) self.entries[e.name] = e + self.entries_by_val[e.raw_value()] = e prev_entry = e def new_entry(self, entry, prev_entry, value_start): diff --git a/tools/net/ynl/lib/ynl.py b/tools/net/ynl/lib/ynl.py index a842adc8e87e..90764a83c646 100644 --- a/tools/net/ynl/lib/ynl.py +++ b/tools/net/ynl/lib/ynl.py @@ -303,11 +303,6 @@ class YnlFamily(SpecFamily): self.sock.setsockopt(Netlink.SOL_NETLINK, Netlink.NETLINK_CAP_ACK, 1) self.sock.setsockopt(Netlink.SOL_NETLINK, Netlink.NETLINK_EXT_ACK, 1) - self._types = dict() - - for elem in self.yaml.get('definitions', []): - self._types[elem['name']] = elem - self.async_msg_ids = set() self.async_msg_queue = [] @@ -353,13 +348,13 @@ class YnlFamily(SpecFamily): def _decode_enum(self, rsp, attr_spec): raw = rsp[attr_spec['name']] - enum = self._types[attr_spec['enum']] + enum = self.consts[attr_spec['enum']] i = attr_spec.get('value-start', 0) if 'enum-as-flags' in attr_spec and attr_spec['enum-as-flags']: value = set() while raw: if raw & 1: - value.add(enum['entries'][i]) + value.add(enum.entries_by_val[i].name) raw >>= 1 i += 1 else: From fdf6c2309f425509cddd002f278c650ad0b7e34b Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 8 Mar 2023 14:19:34 +0100 Subject: [PATCH 277/778] staging: r8188eu: delete driver Now that the same hardware that the r8188eu driver supported is supported by the real wireless driver rtl8xxxu, the r8188eu driver can be deleted. Also the rtl8xxxu driver supports way more devices, and is a fraction of the overall size, making this a much better overall solution. Thanks to the r8188eu developers and maintainers and reviewers over the years, your work allowed Linux users to use their hardware before the real driver was implemented properly. Reported-by: Hans de Goede Cc: Phillip Potter Cc: Pavel Skripkin Acked-by: Larry Finger Acked-by: Hans de Goede Acked-by: Martin Kaiser Tested-by: Philipp Hortmann # Edimax N150 Acked-by: Michael Straube Link: https://lore.kernel.org/r/20230308131934.380395-1-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 7 - drivers/staging/Kconfig | 2 - drivers/staging/Makefile | 1 - drivers/staging/r8188eu/Kconfig | 16 - drivers/staging/r8188eu/Makefile | 48 - drivers/staging/r8188eu/TODO | 16 - drivers/staging/r8188eu/core/rtw_ap.c | 1181 --- drivers/staging/r8188eu/core/rtw_br_ext.c | 658 -- drivers/staging/r8188eu/core/rtw_cmd.c | 1529 ---- drivers/staging/r8188eu/core/rtw_efuse.c | 74 - drivers/staging/r8188eu/core/rtw_fw.c | 335 - drivers/staging/r8188eu/core/rtw_ieee80211.c | 1150 --- drivers/staging/r8188eu/core/rtw_ioctl_set.c | 479 - drivers/staging/r8188eu/core/rtw_iol.c | 160 - drivers/staging/r8188eu/core/rtw_led.c | 255 - drivers/staging/r8188eu/core/rtw_mlme.c | 2067 ----- drivers/staging/r8188eu/core/rtw_mlme_ext.c | 7817 ----------------- drivers/staging/r8188eu/core/rtw_p2p.c | 1918 ---- drivers/staging/r8188eu/core/rtw_pwrctrl.c | 445 - drivers/staging/r8188eu/core/rtw_recv.c | 2010 ----- drivers/staging/r8188eu/core/rtw_rf.c | 29 - drivers/staging/r8188eu/core/rtw_security.c | 1374 --- drivers/staging/r8188eu/core/rtw_sta_mgt.c | 490 -- drivers/staging/r8188eu/core/rtw_wlan_util.c | 1551 ---- drivers/staging/r8188eu/core/rtw_xmit.c | 2179 ----- .../r8188eu/hal/Hal8188ERateAdaptive.c | 654 -- .../staging/r8188eu/hal/HalHWImg8188E_BB.c | 733 -- .../staging/r8188eu/hal/HalHWImg8188E_MAC.c | 212 - .../staging/r8188eu/hal/HalHWImg8188E_RF.c | 269 - drivers/staging/r8188eu/hal/HalPhyRf_8188e.c | 900 -- drivers/staging/r8188eu/hal/HalPwrSeqCmd.c | 149 - drivers/staging/r8188eu/hal/hal_com.c | 139 - drivers/staging/r8188eu/hal/hal_intf.c | 50 - drivers/staging/r8188eu/hal/odm.c | 821 -- drivers/staging/r8188eu/hal/odm_HWConfig.c | 349 - drivers/staging/r8188eu/hal/odm_RTL8188E.c | 264 - drivers/staging/r8188eu/hal/rtl8188e_cmd.c | 694 -- drivers/staging/r8188eu/hal/rtl8188e_dm.c | 146 - .../staging/r8188eu/hal/rtl8188e_hal_init.c | 922 -- drivers/staging/r8188eu/hal/rtl8188e_phycfg.c | 705 -- drivers/staging/r8188eu/hal/rtl8188e_rf6052.c | 405 - drivers/staging/r8188eu/hal/rtl8188e_rxdesc.c | 161 - drivers/staging/r8188eu/hal/rtl8188eu_xmit.c | 627 -- drivers/staging/r8188eu/hal/usb_halinit.c | 1069 --- drivers/staging/r8188eu/hal/usb_ops_linux.c | 476 - .../staging/r8188eu/include/Hal8188EPhyCfg.h | 97 - .../staging/r8188eu/include/Hal8188EPhyReg.h | 1072 --- .../r8188eu/include/Hal8188ERateAdaptive.h | 49 - .../r8188eu/include/HalHWImg8188E_BB.h | 27 - .../r8188eu/include/HalHWImg8188E_MAC.h | 12 - .../r8188eu/include/HalHWImg8188E_RF.h | 13 - .../staging/r8188eu/include/HalPhyRf_8188e.h | 36 - .../staging/r8188eu/include/HalPwrSeqCmd.h | 18 - drivers/staging/r8188eu/include/HalVerDef.h | 42 - drivers/staging/r8188eu/include/drv_types.h | 224 - drivers/staging/r8188eu/include/hal_com.h | 146 - drivers/staging/r8188eu/include/hal_intf.h | 44 - drivers/staging/r8188eu/include/ieee80211.h | 817 -- drivers/staging/r8188eu/include/odm.h | 416 - .../staging/r8188eu/include/odm_HWConfig.h | 69 - .../staging/r8188eu/include/odm_RTL8188E.h | 35 - .../r8188eu/include/odm_RegDefine11N.h | 47 - drivers/staging/r8188eu/include/osdep_intf.h | 30 - .../staging/r8188eu/include/osdep_service.h | 153 - .../staging/r8188eu/include/rtl8188e_cmd.h | 90 - drivers/staging/r8188eu/include/rtl8188e_dm.h | 28 - .../staging/r8188eu/include/rtl8188e_hal.h | 181 - .../staging/r8188eu/include/rtl8188e_recv.h | 40 - drivers/staging/r8188eu/include/rtl8188e_rf.h | 18 - .../staging/r8188eu/include/rtl8188e_spec.h | 1142 --- .../staging/r8188eu/include/rtl8188e_xmit.h | 130 - drivers/staging/r8188eu/include/rtw_ap.h | 34 - drivers/staging/r8188eu/include/rtw_br_ext.h | 43 - drivers/staging/r8188eu/include/rtw_cmd.h | 925 -- drivers/staging/r8188eu/include/rtw_eeprom.h | 15 - drivers/staging/r8188eu/include/rtw_efuse.h | 11 - drivers/staging/r8188eu/include/rtw_event.h | 97 - drivers/staging/r8188eu/include/rtw_fw.h | 17 - drivers/staging/r8188eu/include/rtw_ht.h | 28 - drivers/staging/r8188eu/include/rtw_io.h | 33 - drivers/staging/r8188eu/include/rtw_ioctl.h | 13 - .../staging/r8188eu/include/rtw_ioctl_set.h | 25 - drivers/staging/r8188eu/include/rtw_iol.h | 55 - drivers/staging/r8188eu/include/rtw_led.h | 57 - drivers/staging/r8188eu/include/rtw_mlme.h | 574 -- .../staging/r8188eu/include/rtw_mlme_ext.h | 753 -- drivers/staging/r8188eu/include/rtw_p2p.h | 118 - drivers/staging/r8188eu/include/rtw_pwrctrl.h | 111 - drivers/staging/r8188eu/include/rtw_recv.h | 347 - drivers/staging/r8188eu/include/rtw_rf.h | 80 - .../staging/r8188eu/include/rtw_security.h | 231 - drivers/staging/r8188eu/include/rtw_xmit.h | 334 - drivers/staging/r8188eu/include/sta_info.h | 313 - drivers/staging/r8188eu/include/usb_ops.h | 57 - drivers/staging/r8188eu/include/usb_osintf.h | 21 - drivers/staging/r8188eu/include/wifi.h | 773 -- drivers/staging/r8188eu/include/wlan_bssdef.h | 272 - drivers/staging/r8188eu/os_dep/ioctl_linux.c | 3775 -------- drivers/staging/r8188eu/os_dep/os_intfs.c | 807 -- .../staging/r8188eu/os_dep/osdep_service.c | 227 - drivers/staging/r8188eu/os_dep/usb_intf.c | 445 - .../staging/r8188eu/os_dep/usb_ops_linux.c | 136 - 102 files changed, 51239 deletions(-) delete mode 100644 drivers/staging/r8188eu/Kconfig delete mode 100644 drivers/staging/r8188eu/Makefile delete mode 100644 drivers/staging/r8188eu/TODO delete mode 100644 drivers/staging/r8188eu/core/rtw_ap.c delete mode 100644 drivers/staging/r8188eu/core/rtw_br_ext.c delete mode 100644 drivers/staging/r8188eu/core/rtw_cmd.c delete mode 100644 drivers/staging/r8188eu/core/rtw_efuse.c delete mode 100644 drivers/staging/r8188eu/core/rtw_fw.c delete mode 100644 drivers/staging/r8188eu/core/rtw_ieee80211.c delete mode 100644 drivers/staging/r8188eu/core/rtw_ioctl_set.c delete mode 100644 drivers/staging/r8188eu/core/rtw_iol.c delete mode 100644 drivers/staging/r8188eu/core/rtw_led.c delete mode 100644 drivers/staging/r8188eu/core/rtw_mlme.c delete mode 100644 drivers/staging/r8188eu/core/rtw_mlme_ext.c delete mode 100644 drivers/staging/r8188eu/core/rtw_p2p.c delete mode 100644 drivers/staging/r8188eu/core/rtw_pwrctrl.c delete mode 100644 drivers/staging/r8188eu/core/rtw_recv.c delete mode 100644 drivers/staging/r8188eu/core/rtw_rf.c delete mode 100644 drivers/staging/r8188eu/core/rtw_security.c delete mode 100644 drivers/staging/r8188eu/core/rtw_sta_mgt.c delete mode 100644 drivers/staging/r8188eu/core/rtw_wlan_util.c delete mode 100644 drivers/staging/r8188eu/core/rtw_xmit.c delete mode 100644 drivers/staging/r8188eu/hal/Hal8188ERateAdaptive.c delete mode 100644 drivers/staging/r8188eu/hal/HalHWImg8188E_BB.c delete mode 100644 drivers/staging/r8188eu/hal/HalHWImg8188E_MAC.c delete mode 100644 drivers/staging/r8188eu/hal/HalHWImg8188E_RF.c delete mode 100644 drivers/staging/r8188eu/hal/HalPhyRf_8188e.c delete mode 100644 drivers/staging/r8188eu/hal/HalPwrSeqCmd.c delete mode 100644 drivers/staging/r8188eu/hal/hal_com.c delete mode 100644 drivers/staging/r8188eu/hal/hal_intf.c delete mode 100644 drivers/staging/r8188eu/hal/odm.c delete mode 100644 drivers/staging/r8188eu/hal/odm_HWConfig.c delete mode 100644 drivers/staging/r8188eu/hal/odm_RTL8188E.c delete mode 100644 drivers/staging/r8188eu/hal/rtl8188e_cmd.c delete mode 100644 drivers/staging/r8188eu/hal/rtl8188e_dm.c delete mode 100644 drivers/staging/r8188eu/hal/rtl8188e_hal_init.c delete mode 100644 drivers/staging/r8188eu/hal/rtl8188e_phycfg.c delete mode 100644 drivers/staging/r8188eu/hal/rtl8188e_rf6052.c delete mode 100644 drivers/staging/r8188eu/hal/rtl8188e_rxdesc.c delete mode 100644 drivers/staging/r8188eu/hal/rtl8188eu_xmit.c delete mode 100644 drivers/staging/r8188eu/hal/usb_halinit.c delete mode 100644 drivers/staging/r8188eu/hal/usb_ops_linux.c delete mode 100644 drivers/staging/r8188eu/include/Hal8188EPhyCfg.h delete mode 100644 drivers/staging/r8188eu/include/Hal8188EPhyReg.h delete mode 100644 drivers/staging/r8188eu/include/Hal8188ERateAdaptive.h delete mode 100644 drivers/staging/r8188eu/include/HalHWImg8188E_BB.h delete mode 100644 drivers/staging/r8188eu/include/HalHWImg8188E_MAC.h delete mode 100644 drivers/staging/r8188eu/include/HalHWImg8188E_RF.h delete mode 100644 drivers/staging/r8188eu/include/HalPhyRf_8188e.h delete mode 100644 drivers/staging/r8188eu/include/HalPwrSeqCmd.h delete mode 100644 drivers/staging/r8188eu/include/HalVerDef.h delete mode 100644 drivers/staging/r8188eu/include/drv_types.h delete mode 100644 drivers/staging/r8188eu/include/hal_com.h delete mode 100644 drivers/staging/r8188eu/include/hal_intf.h delete mode 100644 drivers/staging/r8188eu/include/ieee80211.h delete mode 100644 drivers/staging/r8188eu/include/odm.h delete mode 100644 drivers/staging/r8188eu/include/odm_HWConfig.h delete mode 100644 drivers/staging/r8188eu/include/odm_RTL8188E.h delete mode 100644 drivers/staging/r8188eu/include/odm_RegDefine11N.h delete mode 100644 drivers/staging/r8188eu/include/osdep_intf.h delete mode 100644 drivers/staging/r8188eu/include/osdep_service.h delete mode 100644 drivers/staging/r8188eu/include/rtl8188e_cmd.h delete mode 100644 drivers/staging/r8188eu/include/rtl8188e_dm.h delete mode 100644 drivers/staging/r8188eu/include/rtl8188e_hal.h delete mode 100644 drivers/staging/r8188eu/include/rtl8188e_recv.h delete mode 100644 drivers/staging/r8188eu/include/rtl8188e_rf.h delete mode 100644 drivers/staging/r8188eu/include/rtl8188e_spec.h delete mode 100644 drivers/staging/r8188eu/include/rtl8188e_xmit.h delete mode 100644 drivers/staging/r8188eu/include/rtw_ap.h delete mode 100644 drivers/staging/r8188eu/include/rtw_br_ext.h delete mode 100644 drivers/staging/r8188eu/include/rtw_cmd.h delete mode 100644 drivers/staging/r8188eu/include/rtw_eeprom.h delete mode 100644 drivers/staging/r8188eu/include/rtw_efuse.h delete mode 100644 drivers/staging/r8188eu/include/rtw_event.h delete mode 100644 drivers/staging/r8188eu/include/rtw_fw.h delete mode 100644 drivers/staging/r8188eu/include/rtw_ht.h delete mode 100644 drivers/staging/r8188eu/include/rtw_io.h delete mode 100644 drivers/staging/r8188eu/include/rtw_ioctl.h delete mode 100644 drivers/staging/r8188eu/include/rtw_ioctl_set.h delete mode 100644 drivers/staging/r8188eu/include/rtw_iol.h delete mode 100644 drivers/staging/r8188eu/include/rtw_led.h delete mode 100644 drivers/staging/r8188eu/include/rtw_mlme.h delete mode 100644 drivers/staging/r8188eu/include/rtw_mlme_ext.h delete mode 100644 drivers/staging/r8188eu/include/rtw_p2p.h delete mode 100644 drivers/staging/r8188eu/include/rtw_pwrctrl.h delete mode 100644 drivers/staging/r8188eu/include/rtw_recv.h delete mode 100644 drivers/staging/r8188eu/include/rtw_rf.h delete mode 100644 drivers/staging/r8188eu/include/rtw_security.h delete mode 100644 drivers/staging/r8188eu/include/rtw_xmit.h delete mode 100644 drivers/staging/r8188eu/include/sta_info.h delete mode 100644 drivers/staging/r8188eu/include/usb_ops.h delete mode 100644 drivers/staging/r8188eu/include/usb_osintf.h delete mode 100644 drivers/staging/r8188eu/include/wifi.h delete mode 100644 drivers/staging/r8188eu/include/wlan_bssdef.h delete mode 100644 drivers/staging/r8188eu/os_dep/ioctl_linux.c delete mode 100644 drivers/staging/r8188eu/os_dep/os_intfs.c delete mode 100644 drivers/staging/r8188eu/os_dep/osdep_service.c delete mode 100644 drivers/staging/r8188eu/os_dep/usb_intf.c delete mode 100644 drivers/staging/r8188eu/os_dep/usb_ops_linux.c diff --git a/MAINTAINERS b/MAINTAINERS index 8d5bc223f305..93c5fa40c772 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -19863,13 +19863,6 @@ S: Maintained W: http://wiki.laptop.org/go/DCON F: drivers/staging/olpc_dcon/ -STAGING - REALTEK RTL8188EU DRIVERS -M: Larry Finger -M: Phillip Potter -R: Pavel Skripkin -S: Supported -F: drivers/staging/r8188eu/ - STAGING - REALTEK RTL8712U DRIVERS M: Larry Finger M: Florian Schilhabel . diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 5cfabd5376cc..f9aef39cac2e 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -36,8 +36,6 @@ source "drivers/staging/rtl8723bs/Kconfig" source "drivers/staging/rtl8712/Kconfig" -source "drivers/staging/r8188eu/Kconfig" - source "drivers/staging/rts5208/Kconfig" source "drivers/staging/octeon/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index f8c3aa9c2418..ffa70dda481d 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -8,7 +8,6 @@ obj-$(CONFIG_RTL8192U) += rtl8192u/ obj-$(CONFIG_RTL8192E) += rtl8192e/ obj-$(CONFIG_RTL8723BS) += rtl8723bs/ obj-$(CONFIG_R8712U) += rtl8712/ -obj-$(CONFIG_R8188EU) += r8188eu/ obj-$(CONFIG_RTS5208) += rts5208/ obj-$(CONFIG_OCTEON_ETHERNET) += octeon/ obj-$(CONFIG_VT6655) += vt6655/ diff --git a/drivers/staging/r8188eu/Kconfig b/drivers/staging/r8188eu/Kconfig deleted file mode 100644 index f5fe423530f0..000000000000 --- a/drivers/staging/r8188eu/Kconfig +++ /dev/null @@ -1,16 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -config R8188EU - tristate "Realtek RTL8188EU Wireless LAN NIC driver" - depends on WLAN && USB && CFG80211 - depends on m - select WIRELESS_EXT - select WEXT_PRIV - select LIB80211 - select LIB80211_CRYPT_WEP - select LIB80211_CRYPT_CCMP - help - This option adds support for the Realtek RTL8188EU chipset, used in USB - devices such as the ASUS USB-N10 Nano. This newer driver is based on GitHub - sources for version v4.1.4_6773.20130222, and contains modifications for - newer kernel features. If built as a module, it will be called r8188eu. - diff --git a/drivers/staging/r8188eu/Makefile b/drivers/staging/r8188eu/Makefile deleted file mode 100644 index fd494c2299e6..000000000000 --- a/drivers/staging/r8188eu/Makefile +++ /dev/null @@ -1,48 +0,0 @@ - -r8188eu-y = \ - hal/HalHWImg8188E_MAC.o \ - hal/HalHWImg8188E_BB.o \ - hal/HalHWImg8188E_RF.o \ - hal/HalPhyRf_8188e.o \ - hal/HalPwrSeqCmd.o \ - hal/Hal8188ERateAdaptive.o \ - hal/hal_intf.o \ - hal/hal_com.o \ - hal/odm.o \ - hal/odm_HWConfig.o \ - hal/odm_RTL8188E.o \ - hal/rtl8188e_cmd.o \ - hal/rtl8188e_dm.o \ - hal/rtl8188e_hal_init.o \ - hal/rtl8188e_phycfg.o \ - hal/rtl8188e_rf6052.o \ - hal/rtl8188e_rxdesc.o \ - hal/rtl8188eu_xmit.o \ - hal/usb_halinit.o \ - hal/usb_ops_linux.o \ - os_dep/ioctl_linux.o \ - os_dep/os_intfs.o \ - os_dep/osdep_service.o \ - os_dep/usb_intf.o \ - os_dep/usb_ops_linux.o \ - core/rtw_ap.o \ - core/rtw_br_ext.o \ - core/rtw_cmd.o \ - core/rtw_efuse.o \ - core/rtw_fw.o \ - core/rtw_ieee80211.o \ - core/rtw_ioctl_set.o \ - core/rtw_iol.o \ - core/rtw_led.o \ - core/rtw_mlme.o \ - core/rtw_mlme_ext.o \ - core/rtw_pwrctrl.o \ - core/rtw_p2p.o \ - core/rtw_recv.o \ - core/rtw_rf.o \ - core/rtw_security.o \ - core/rtw_sta_mgt.o \ - core/rtw_wlan_util.o \ - core/rtw_xmit.o - -obj-$(CONFIG_R8188EU) := r8188eu.o diff --git a/drivers/staging/r8188eu/TODO b/drivers/staging/r8188eu/TODO deleted file mode 100644 index ab9d5d145b3b..000000000000 --- a/drivers/staging/r8188eu/TODO +++ /dev/null @@ -1,16 +0,0 @@ -To-do list: - -* Correct the coding style according to Linux guidelines; please read the document - at https://www.kernel.org/doc/html/latest/process/coding-style.html. -* Remove unnecessary debugging/printing macros; for those that are still needed - use the proper kernel API (pr_debug(), dev_dbg(), netdev_dbg()). -* Remove dead code such as unusued functions, variables, fields, etc.. -* Use in-kernel API and remove unnecessary wrappers where possible. -* Fix bugs due to code that sleeps in atomic context. -* Remove the HAL layer and migrate its functionality into the relevant parts of - the driver. -* Switch to use LIB80211. -* Switch to use MAC80211. -* Switch to use CFG80211. -* Improve the error handling of various functions, particularly those that use - existing kernel APIs. diff --git a/drivers/staging/r8188eu/core/rtw_ap.c b/drivers/staging/r8188eu/core/rtw_ap.c deleted file mode 100644 index e0ca4b6e17cc..000000000000 --- a/drivers/staging/r8188eu/core/rtw_ap.c +++ /dev/null @@ -1,1181 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2007 - 2012 Realtek Corporation. */ - -#define _RTW_AP_C_ - -#include "../include/osdep_service.h" -#include "../include/drv_types.h" -#include "../include/wifi.h" -#include "../include/ieee80211.h" -#include "../include/rtl8188e_cmd.h" - -void init_mlme_ap_info(struct adapter *padapter) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct sta_priv *pstapriv = &padapter->stapriv; - struct wlan_acl_pool *pacl_list = &pstapriv->acl_list; - - spin_lock_init(&pmlmepriv->bcn_update_lock); - - /* for ACL */ - rtw_init_queue(&pacl_list->acl_node_q); - - start_ap_mode(padapter); -} - -void free_mlme_ap_info(struct adapter *padapter) -{ - struct sta_info *psta = NULL; - struct sta_priv *pstapriv = &padapter->stapriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - pmlmepriv->update_bcn = false; - pmlmeext->bstart_bss = false; - - rtw_sta_flush(padapter); - - pmlmeinfo->state = _HW_STATE_NOLINK_; - - /* free_assoc_sta_resources */ - rtw_free_all_stainfo(padapter); - - /* free bc/mc sta_info */ - psta = rtw_get_bcmc_stainfo(padapter); - spin_lock_bh(&pstapriv->sta_hash_lock); - rtw_free_stainfo(padapter, psta); - spin_unlock_bh(&pstapriv->sta_hash_lock); -} - -static void update_BCNTIM(struct adapter *padapter) -{ - struct sta_priv *pstapriv = &padapter->stapriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *pnetwork_mlmeext = &pmlmeinfo->network; - unsigned char *pie = pnetwork_mlmeext->IEs; - u8 *p, *dst_ie, *premainder_ie = NULL; - u8 *pbackup_remainder_ie = NULL; - __le16 tim_bitmap_le; - uint offset, tmp_len, tim_ielen, tim_ie_offset, remainder_ielen; - - /* update TIM IE */ - - p = rtw_get_ie(pie + _FIXED_IE_LENGTH_, _TIM_IE_, &tim_ielen, - pnetwork_mlmeext->IELength - _FIXED_IE_LENGTH_); - if (p && tim_ielen > 0) { - tim_ielen += 2; - premainder_ie = p + tim_ielen; - tim_ie_offset = (int)(p - pie); - remainder_ielen = pnetwork_mlmeext->IELength - tim_ie_offset - tim_ielen; - /* append TIM IE from dst_ie offset */ - dst_ie = p; - } else { - tim_ielen = 0; - - /* calculate head_len */ - offset = _FIXED_IE_LENGTH_; - offset += pnetwork_mlmeext->Ssid.SsidLength + 2; - - /* get supported rates len */ - p = rtw_get_ie(pie + _BEACON_IE_OFFSET_, _SUPPORTEDRATES_IE_, - &tmp_len, (pnetwork_mlmeext->IELength - _BEACON_IE_OFFSET_)); - if (p) - offset += tmp_len + 2; - - /* DS Parameter Set IE, len = 3 */ - offset += 3; - - premainder_ie = pie + offset; - - remainder_ielen = pnetwork_mlmeext->IELength - offset - tim_ielen; - - /* append TIM IE from offset */ - dst_ie = pie + offset; - } - - if (remainder_ielen > 0) { - pbackup_remainder_ie = kmalloc(remainder_ielen, GFP_ATOMIC); - if (pbackup_remainder_ie && premainder_ie) - memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen); - } - *dst_ie++ = _TIM_IE_; - - if ((pstapriv->tim_bitmap & 0xff00) && (pstapriv->tim_bitmap & 0x00fc)) - tim_ielen = 5; - else - tim_ielen = 4; - - *dst_ie++ = tim_ielen; - - *dst_ie++ = 0;/* DTIM count */ - *dst_ie++ = 1;/* DTIM period */ - - if (pstapriv->tim_bitmap & BIT(0))/* for bc/mc frames */ - *dst_ie++ = BIT(0);/* bitmap ctrl */ - else - *dst_ie++ = 0; - - tim_bitmap_le = cpu_to_le16(pstapriv->tim_bitmap); - - if (tim_ielen == 4) { - *dst_ie++ = *(u8 *)&tim_bitmap_le; - } else if (tim_ielen == 5) { - memcpy(dst_ie, &tim_bitmap_le, 2); - dst_ie += 2; - } - - /* copy remainder IE */ - if (pbackup_remainder_ie) { - memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen); - - kfree(pbackup_remainder_ie); - } - offset = (uint)(dst_ie - pie); - pnetwork_mlmeext->IELength = offset + remainder_ielen; - - set_tx_beacon_cmd(padapter); -} - -static u8 chk_sta_is_alive(struct sta_info *psta) -{ - u8 ret = false; - - if ((psta->sta_stats.last_rx_data_pkts + psta->sta_stats.last_rx_ctrl_pkts) == - (psta->sta_stats.rx_data_pkts + psta->sta_stats.rx_ctrl_pkts)) - ; - else - ret = true; - - sta_update_last_rx_pkts(psta); - - return ret; -} - -void expire_timeout_chk(struct adapter *padapter) -{ - struct list_head *phead, *plist; - u8 updated = 0; - struct sta_info *psta = NULL; - struct sta_priv *pstapriv = &padapter->stapriv; - u8 chk_alive_num = 0; - char chk_alive_list[NUM_STA]; - int i; - - spin_lock_bh(&pstapriv->auth_list_lock); - - phead = &pstapriv->auth_list; - plist = phead->next; - - /* check auth_queue */ - while (phead != plist) { - psta = container_of(plist, struct sta_info, auth_list); - plist = plist->next; - - if (psta->expire_to > 0) { - psta->expire_to--; - if (psta->expire_to == 0) { - list_del_init(&psta->auth_list); - pstapriv->auth_list_cnt--; - - spin_unlock_bh(&pstapriv->auth_list_lock); - - spin_lock_bh(&pstapriv->sta_hash_lock); - rtw_free_stainfo(padapter, psta); - spin_unlock_bh(&pstapriv->sta_hash_lock); - - spin_lock_bh(&pstapriv->auth_list_lock); - } - } - } - spin_unlock_bh(&pstapriv->auth_list_lock); - - psta = NULL; - - spin_lock_bh(&pstapriv->asoc_list_lock); - - phead = &pstapriv->asoc_list; - plist = phead->next; - - /* check asoc_queue */ - while (phead != plist) { - psta = container_of(plist, struct sta_info, asoc_list); - plist = plist->next; - - if (chk_sta_is_alive(psta) || !psta->expire_to) { - psta->expire_to = pstapriv->expire_to; - psta->keep_alive_trycnt = 0; - psta->under_exist_checking = 0; - } else { - psta->expire_to--; - } - - if (psta->expire_to <= 0) { - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - if (padapter->registrypriv.wifi_spec == 1) { - psta->expire_to = pstapriv->expire_to; - continue; - } - - if (psta->state & WIFI_SLEEP_STATE) { - if (!(psta->state & WIFI_STA_ALIVE_CHK_STATE)) { - /* to check if alive by another methods if station is at ps mode. */ - psta->expire_to = pstapriv->expire_to; - psta->state |= WIFI_STA_ALIVE_CHK_STATE; - - /* to update bcn with tim_bitmap for this station */ - pstapriv->tim_bitmap |= BIT(psta->aid); - update_beacon(padapter, _TIM_IE_, NULL, false); - - if (!pmlmeext->active_keep_alive_check) - continue; - } - } - if (pmlmeext->active_keep_alive_check) { - int stainfo_offset; - - stainfo_offset = rtw_stainfo_offset(pstapriv, psta); - if (stainfo_offset_valid(stainfo_offset)) - chk_alive_list[chk_alive_num++] = stainfo_offset; - continue; - } - - list_del_init(&psta->asoc_list); - pstapriv->asoc_list_cnt--; - - updated = ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING); - } else { - /* TODO: Aging mechanism to digest frames in sleep_q to avoid running out of xmitframe */ - if (psta->sleepq_len > (NR_XMITFRAME / pstapriv->asoc_list_cnt) && - padapter->xmitpriv.free_xmitframe_cnt < (NR_XMITFRAME / pstapriv->asoc_list_cnt / 2)) { - wakeup_sta_to_xmit(padapter, psta); - } - } - } - - spin_unlock_bh(&pstapriv->asoc_list_lock); - - if (chk_alive_num) { - u8 backup_oper_channel = 0; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - /* switch to correct channel of current network before issue keep-alive frames */ - if (rtw_get_oper_ch(padapter) != pmlmeext->cur_channel) { - backup_oper_channel = rtw_get_oper_ch(padapter); - SelectChannel(padapter, pmlmeext->cur_channel); - } - - /* issue null data to check sta alive*/ - for (i = 0; i < chk_alive_num; i++) { - int ret = _FAIL; - - psta = rtw_get_stainfo_by_offset(pstapriv, chk_alive_list[i]); - - if (psta->state & WIFI_SLEEP_STATE) - ret = issue_nulldata(padapter, psta->hwaddr, 0, 1, 50); - else - ret = issue_nulldata(padapter, psta->hwaddr, 0, 3, 50); - - psta->keep_alive_trycnt++; - if (ret == _SUCCESS) { - psta->expire_to = pstapriv->expire_to; - psta->keep_alive_trycnt = 0; - continue; - } else if (psta->keep_alive_trycnt <= 3) { - psta->expire_to = 1; - continue; - } - - psta->keep_alive_trycnt = 0; - - spin_lock_bh(&pstapriv->asoc_list_lock); - list_del_init(&psta->asoc_list); - pstapriv->asoc_list_cnt--; - updated = ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING); - spin_unlock_bh(&pstapriv->asoc_list_lock); - } - - if (backup_oper_channel > 0) /* back to the original operation channel */ - SelectChannel(padapter, backup_oper_channel); - } - - associated_clients_update(padapter, updated); -} - -void add_RATid(struct adapter *padapter, struct sta_info *psta, u8 rssi_level) -{ - int i; - u32 init_rate = 0; - unsigned char sta_band = 0, raid, shortGIrate = false; - unsigned char limit; - unsigned int tx_ra_bitmap = 0; - struct ht_priv *psta_ht = NULL; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wlan_bssid_ex *pcur_network = (struct wlan_bssid_ex *)&pmlmepriv->cur_network.network; - - if (psta) - psta_ht = &psta->htpriv; - else - return; - - if (!(psta->state & _FW_LINKED)) - return; - - /* b/g mode ra_bitmap */ - for (i = 0; i < sizeof(psta->bssrateset); i++) { - if (psta->bssrateset[i]) - tx_ra_bitmap |= rtw_get_bit_value_from_ieee_value(psta->bssrateset[i] & 0x7f); - } - /* n mode ra_bitmap */ - if (psta_ht->ht_option) { - limit = 8; /* 1R */ - - for (i = 0; i < limit; i++) { - if (psta_ht->ht_cap.mcs.rx_mask[i / 8] & BIT(i % 8)) - tx_ra_bitmap |= BIT(i + 12); - } - - /* max short GI rate */ - shortGIrate = psta_ht->sgi; - } - - if (pcur_network->Configuration.DSConfig > 14) { - sta_band |= WIRELESS_INVALID; - } else { - if (tx_ra_bitmap & 0xffff000) - sta_band |= WIRELESS_11_24N | WIRELESS_11G | WIRELESS_11B; - else if (tx_ra_bitmap & 0xff0) - sta_band |= WIRELESS_11G | WIRELESS_11B; - else - sta_band |= WIRELESS_11B; - } - - psta->wireless_mode = sta_band; - - raid = networktype_to_raid(sta_band); - init_rate = get_highest_rate_idx(tx_ra_bitmap & 0x0fffffff) & 0x3f; - - if (psta->aid < NUM_STA) { - u8 arg = 0; - - arg = psta->mac_id & 0x1f; - - arg |= BIT(7);/* support entry 2~31 */ - - if (shortGIrate) - arg |= BIT(5); - - tx_ra_bitmap |= ((raid << 28) & 0xf0000000); - - /* bitmap[0:27] = tx_rate_bitmap */ - /* bitmap[28:31]= Rate Adaptive id */ - /* arg[0:4] = macid */ - /* arg[5] = Short GI */ - rtl8188e_Add_RateATid(padapter, tx_ra_bitmap, arg, rssi_level); - - if (shortGIrate) - init_rate |= BIT(6); - - /* set ra_id, init_rate */ - psta->raid = raid; - psta->init_rate = init_rate; - } -} - -void update_bmc_sta(struct adapter *padapter) -{ - u32 init_rate = 0; - unsigned char network_type, raid; - int i, supportRateNum = 0; - unsigned int tx_ra_bitmap = 0; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wlan_bssid_ex *pcur_network = (struct wlan_bssid_ex *)&pmlmepriv->cur_network.network; - struct sta_info *psta = rtw_get_bcmc_stainfo(padapter); - - if (psta) { - psta->aid = 0;/* default set to 0 */ - psta->mac_id = psta->aid + 1; - - psta->qos_option = 0; - psta->htpriv.ht_option = false; - - psta->ieee8021x_blocked = 0; - - memset((void *)&psta->sta_stats, 0, sizeof(struct stainfo_stats)); - - /* prepare for add_RATid */ - supportRateNum = rtw_get_rateset_len((u8 *)&pcur_network->SupportedRates); - network_type = rtw_check_network_type((u8 *)&pcur_network->SupportedRates, supportRateNum, 1); - - memcpy(psta->bssrateset, &pcur_network->SupportedRates, supportRateNum); - psta->bssratelen = supportRateNum; - - /* b/g mode ra_bitmap */ - for (i = 0; i < supportRateNum; i++) { - if (psta->bssrateset[i]) - tx_ra_bitmap |= rtw_get_bit_value_from_ieee_value(psta->bssrateset[i] & 0x7f); - } - - if (pcur_network->Configuration.DSConfig > 14) { - network_type = WIRELESS_INVALID; - } else { - /* force to b mode */ - network_type = WIRELESS_11B; - tx_ra_bitmap = 0xf; - } - - raid = networktype_to_raid(network_type); - init_rate = get_highest_rate_idx(tx_ra_bitmap & 0x0fffffff) & 0x3f; - - /* ap mode */ - rtl8188e_SetHalODMVar(padapter, psta, true); - - { - u8 arg = 0; - - arg = psta->mac_id & 0x1f; - arg |= BIT(7); - tx_ra_bitmap |= ((raid << 28) & 0xf0000000); - - /* bitmap[0:27] = tx_rate_bitmap */ - /* bitmap[28:31]= Rate Adaptive id */ - /* arg[0:4] = macid */ - /* arg[5] = Short GI */ - rtl8188e_Add_RateATid(padapter, tx_ra_bitmap, arg, 0); - } - /* set ra_id, init_rate */ - psta->raid = raid; - psta->init_rate = init_rate; - - rtw_sta_media_status_rpt(padapter, psta, 1); - - spin_lock_bh(&psta->lock); - psta->state = _FW_LINKED; - spin_unlock_bh(&psta->lock); - } -} - -/* notes: */ -/* AID: 1~MAX for sta and 0 for bc/mc in ap/adhoc mode */ -/* MAC_ID = AID+1 for sta in ap/adhoc mode */ -/* MAC_ID = 1 for bc/mc for sta/ap/adhoc */ -/* MAC_ID = 0 for bssid for sta/ap/adhoc */ -/* CAM_ID = 0~3 for default key, cmd_id = macid + 3, macid = aid+1; */ - -void update_sta_info_apmode(struct adapter *padapter, struct sta_info *psta) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv; - struct ht_priv *phtpriv_sta = &psta->htpriv; - u16 sta_cap_info; - u16 ap_cap_info; - - psta->mac_id = psta->aid + 1; - - /* ap mode */ - rtl8188e_SetHalODMVar(padapter, psta, true); - - if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) - psta->ieee8021x_blocked = true; - else - psta->ieee8021x_blocked = false; - - /* update sta's cap */ - - /* ERP */ - VCS_update(padapter, psta); - /* HT related cap */ - if (phtpriv_sta->ht_option) { - /* check if sta supports rx ampdu */ - phtpriv_sta->ampdu_enable = phtpriv_ap->ampdu_enable; - sta_cap_info = le16_to_cpu(phtpriv_sta->ht_cap.cap_info); - ap_cap_info = le16_to_cpu(phtpriv_ap->ht_cap.cap_info); - - /* check if sta support s Short GI */ - if ((sta_cap_info & ap_cap_info) & - (IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40)) - phtpriv_sta->sgi = true; - - /* bwmode */ - if ((sta_cap_info & ap_cap_info) & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { - phtpriv_sta->bwmode = pmlmeext->cur_bwmode; - phtpriv_sta->ch_offset = pmlmeext->cur_ch_offset; - } - psta->qos_option = true; - } else { - phtpriv_sta->ampdu_enable = false; - phtpriv_sta->sgi = false; - phtpriv_sta->bwmode = HT_CHANNEL_WIDTH_20; - phtpriv_sta->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - } - - /* Rx AMPDU */ - send_delba(padapter, 0, psta->hwaddr);/* recipient */ - - /* TX AMPDU */ - send_delba(padapter, 1, psta->hwaddr);/* originator */ - phtpriv_sta->agg_enable_bitmap = 0x0;/* reset */ - phtpriv_sta->candidate_tid_bitmap = 0x0;/* reset */ - - /* todo: init other variables */ - - memset((void *)&psta->sta_stats, 0, sizeof(struct stainfo_stats)); - - spin_lock_bh(&psta->lock); - psta->state |= _FW_LINKED; - spin_unlock_bh(&psta->lock); -} - -static void update_bcn_erpinfo_ie(struct adapter *padapter) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network; - unsigned char *p, *ie = pnetwork->IEs; - u32 len = 0; - - if (!pmlmeinfo->ERP_enable) - return; - - /* parsing ERP_IE */ - p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _ERPINFO_IE_, &len, - (pnetwork->IELength - _BEACON_IE_OFFSET_)); - if (p && len > 0) { - struct ndis_802_11_var_ie *pIE = (struct ndis_802_11_var_ie *)p; - - if (pmlmepriv->num_sta_non_erp == 1) - pIE->data[0] |= RTW_ERP_INFO_NON_ERP_PRESENT | RTW_ERP_INFO_USE_PROTECTION; - else - pIE->data[0] &= ~(RTW_ERP_INFO_NON_ERP_PRESENT | RTW_ERP_INFO_USE_PROTECTION); - - if (pmlmepriv->num_sta_no_short_preamble > 0) - pIE->data[0] |= RTW_ERP_INFO_BARKER_PREAMBLE_MODE; - else - pIE->data[0] &= ~(RTW_ERP_INFO_BARKER_PREAMBLE_MODE); - - ERP_IE_handler(padapter, pIE); - } -} - -static void update_bcn_wps_ie(struct adapter *padapter) -{ - u8 *pwps_ie = NULL, *pwps_ie_src; - u8 *premainder_ie, *pbackup_remainder_ie = NULL; - uint wps_ielen = 0, wps_offset, remainder_ielen; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network; - unsigned char *ie = pnetwork->IEs; - u32 ielen = pnetwork->IELength; - - pwps_ie = rtw_get_wps_ie(ie + _FIXED_IE_LENGTH_, ielen - _FIXED_IE_LENGTH_, NULL, &wps_ielen); - - if (!pwps_ie || wps_ielen == 0) - return; - - wps_offset = (uint)(pwps_ie - ie); - - premainder_ie = pwps_ie + wps_ielen; - - remainder_ielen = ielen - wps_offset - wps_ielen; - - if (remainder_ielen > 0) { - pbackup_remainder_ie = kmalloc(remainder_ielen, GFP_ATOMIC); - if (pbackup_remainder_ie) - memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen); - } - - pwps_ie_src = pmlmepriv->wps_beacon_ie; - if (!pwps_ie_src) - goto exit; - - wps_ielen = (uint)pwps_ie_src[1];/* to get ie data len */ - if ((wps_offset + wps_ielen + 2 + remainder_ielen) <= MAX_IE_SZ) { - memcpy(pwps_ie, pwps_ie_src, wps_ielen + 2); - pwps_ie += (wps_ielen + 2); - - if (pbackup_remainder_ie) - memcpy(pwps_ie, pbackup_remainder_ie, remainder_ielen); - - /* update IELength */ - pnetwork->IELength = wps_offset + (wps_ielen + 2) + remainder_ielen; - } - -exit: - kfree(pbackup_remainder_ie); -} - -static void update_bcn_vendor_spec_ie(struct adapter *padapter, u8 *oui) -{ - if (!memcmp(WPS_OUI, oui, 4)) - update_bcn_wps_ie(padapter); -} - -void update_beacon(struct adapter *padapter, u8 ie_id, u8 *oui, u8 tx) -{ - struct mlme_priv *pmlmepriv; - struct mlme_ext_priv *pmlmeext; - - if (!padapter) - return; - - pmlmepriv = &padapter->mlmepriv; - pmlmeext = &padapter->mlmeextpriv; - - if (!pmlmeext->bstart_bss) - return; - - spin_lock_bh(&pmlmepriv->bcn_update_lock); - - switch (ie_id) { - case _TIM_IE_: - update_BCNTIM(padapter); - break; - case _ERPINFO_IE_: - update_bcn_erpinfo_ie(padapter); - break; - case _VENDOR_SPECIFIC_IE_: - update_bcn_vendor_spec_ie(padapter, oui); - break; - default: - break; - } - - pmlmepriv->update_bcn = true; - - spin_unlock_bh(&pmlmepriv->bcn_update_lock); - - if (tx) - set_tx_beacon_cmd(padapter); -} - -/* op_mode - * Set to 0 (HT pure) under the following conditions - * - all STAs in the BSS are 20/40 MHz HT in 20/40 MHz BSS or - * - all STAs in the BSS are 20 MHz HT in 20 MHz BSS - * Set to 1 (HT non-member protection) if there may be non-HT STAs - * in both the primary and the secondary channel - * Set to 2 if only HT STAs are associated in BSS, - * however and at least one 20 MHz HT STA is associated - * Set to 3 (HT mixed mode) when one or more non-HT STAs are associated - * (currently non-GF HT station is considered as non-HT STA also) - */ -static int rtw_ht_operation_update(struct adapter *padapter) -{ - u16 cur_op_mode, new_op_mode; - int op_mode_changes = 0; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv; - - if (pmlmepriv->htpriv.ht_option) - return 0; - - if (!(pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT) && - pmlmepriv->num_sta_ht_no_gf) { - pmlmepriv->ht_op_mode |= - HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT; - op_mode_changes++; - } else if ((pmlmepriv->ht_op_mode & - HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT) && - pmlmepriv->num_sta_ht_no_gf == 0) { - pmlmepriv->ht_op_mode &= - ~HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT; - op_mode_changes++; - } - - if (!(pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) && - (pmlmepriv->num_sta_no_ht || pmlmepriv->olbc_ht)) { - pmlmepriv->ht_op_mode |= HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT; - op_mode_changes++; - } else if ((pmlmepriv->ht_op_mode & - HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) && - (pmlmepriv->num_sta_no_ht == 0 && !pmlmepriv->olbc_ht)) { - pmlmepriv->ht_op_mode &= - ~HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT; - op_mode_changes++; - } - - /* Note: currently we switch to the MIXED op mode if HT non-greenfield - * station is associated. Probably it's a theoretical case, since - * it looks like all known HT STAs support greenfield. - */ - new_op_mode = 0; - if (pmlmepriv->num_sta_no_ht || - (pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT)) - new_op_mode = OP_MODE_MIXED; - else if ((le16_to_cpu(phtpriv_ap->ht_cap.cap_info) & - IEEE80211_HT_CAP_SUP_WIDTH_20_40) && - pmlmepriv->num_sta_ht_20mhz) - new_op_mode = OP_MODE_20MHZ_HT_STA_ASSOCED; - else if (pmlmepriv->olbc_ht) - new_op_mode = OP_MODE_MAY_BE_LEGACY_STAS; - else - new_op_mode = OP_MODE_PURE; - - cur_op_mode = pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_OP_MODE_MASK; - if (cur_op_mode != new_op_mode) { - pmlmepriv->ht_op_mode &= ~HT_INFO_OPERATION_MODE_OP_MODE_MASK; - pmlmepriv->ht_op_mode |= new_op_mode; - op_mode_changes++; - } - - return op_mode_changes; -} - -void associated_clients_update(struct adapter *padapter, u8 updated) -{ - /* update associated stations cap. */ - if (updated) { - struct list_head *phead, *plist; - struct sta_info *psta = NULL; - struct sta_priv *pstapriv = &padapter->stapriv; - - spin_lock_bh(&pstapriv->asoc_list_lock); - - phead = &pstapriv->asoc_list; - plist = phead->next; - - /* check asoc_queue */ - while (phead != plist) { - psta = container_of(plist, struct sta_info, asoc_list); - - plist = plist->next; - - VCS_update(padapter, psta); - } - spin_unlock_bh(&pstapriv->asoc_list_lock); - } -} - -/* called > TSR LEVEL for USB or SDIO Interface*/ -void bss_cap_update_on_sta_join(struct adapter *padapter, struct sta_info *psta) -{ - u8 beacon_updated = false; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - if (!(psta->flags & WLAN_STA_SHORT_PREAMBLE)) { - if (!psta->no_short_preamble_set) { - psta->no_short_preamble_set = 1; - - pmlmepriv->num_sta_no_short_preamble++; - - if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) && - (pmlmepriv->num_sta_no_short_preamble == 1)) { - beacon_updated = true; - update_beacon(padapter, 0xFF, NULL, true); - } - } - } else { - if (psta->no_short_preamble_set) { - psta->no_short_preamble_set = 0; - - pmlmepriv->num_sta_no_short_preamble--; - - if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) && - (pmlmepriv->num_sta_no_short_preamble == 0)) { - beacon_updated = true; - update_beacon(padapter, 0xFF, NULL, true); - } - } - } - - if (psta->flags & WLAN_STA_NONERP) { - if (!psta->nonerp_set) { - psta->nonerp_set = 1; - - pmlmepriv->num_sta_non_erp++; - - if (pmlmepriv->num_sta_non_erp == 1) { - beacon_updated = true; - update_beacon(padapter, _ERPINFO_IE_, NULL, true); - } - } - } else { - if (psta->nonerp_set) { - psta->nonerp_set = 0; - - pmlmepriv->num_sta_non_erp--; - - if (pmlmepriv->num_sta_non_erp == 0) { - beacon_updated = true; - update_beacon(padapter, _ERPINFO_IE_, NULL, true); - } - } - } - - if (!(psta->capability & WLAN_CAPABILITY_SHORT_SLOT)) { - if (!psta->no_short_slot_time_set) { - psta->no_short_slot_time_set = 1; - - pmlmepriv->num_sta_no_short_slot_time++; - - if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) && - (pmlmepriv->num_sta_no_short_slot_time == 1)) { - beacon_updated = true; - update_beacon(padapter, 0xFF, NULL, true); - } - } - } else { - if (psta->no_short_slot_time_set) { - psta->no_short_slot_time_set = 0; - - pmlmepriv->num_sta_no_short_slot_time--; - - if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) && - (pmlmepriv->num_sta_no_short_slot_time == 0)) { - beacon_updated = true; - update_beacon(padapter, 0xFF, NULL, true); - } - } - } - - if (psta->flags & WLAN_STA_HT) { - u16 ht_capab = le16_to_cpu(psta->htpriv.ht_cap.cap_info); - - if (psta->no_ht_set) { - psta->no_ht_set = 0; - pmlmepriv->num_sta_no_ht--; - } - - if ((ht_capab & IEEE80211_HT_CAP_GRN_FLD) == 0) { - if (!psta->no_ht_gf_set) { - psta->no_ht_gf_set = 1; - pmlmepriv->num_sta_ht_no_gf++; - } - } - - if ((ht_capab & IEEE80211_HT_CAP_SUP_WIDTH_20_40) == 0) { - if (!psta->ht_20mhz_set) { - psta->ht_20mhz_set = 1; - pmlmepriv->num_sta_ht_20mhz++; - } - } - } else { - if (!psta->no_ht_set) { - psta->no_ht_set = 1; - pmlmepriv->num_sta_no_ht++; - } - } - - if (rtw_ht_operation_update(padapter) > 0) { - update_beacon(padapter, _HT_CAPABILITY_IE_, NULL, false); - update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, true); - } - - /* update associated stations cap. */ - associated_clients_update(padapter, beacon_updated); -} - -u8 bss_cap_update_on_sta_leave(struct adapter *padapter, struct sta_info *psta) -{ - u8 beacon_updated = false; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - if (!psta) - return beacon_updated; - - if (psta->no_short_preamble_set) { - psta->no_short_preamble_set = 0; - pmlmepriv->num_sta_no_short_preamble--; - if (pmlmeext->cur_wireless_mode > WIRELESS_11B && - pmlmepriv->num_sta_no_short_preamble == 0) { - beacon_updated = true; - update_beacon(padapter, 0xFF, NULL, true); - } - } - - if (psta->nonerp_set) { - psta->nonerp_set = 0; - pmlmepriv->num_sta_non_erp--; - if (pmlmepriv->num_sta_non_erp == 0) { - beacon_updated = true; - update_beacon(padapter, _ERPINFO_IE_, NULL, true); - } - } - - if (psta->no_short_slot_time_set) { - psta->no_short_slot_time_set = 0; - pmlmepriv->num_sta_no_short_slot_time--; - if (pmlmeext->cur_wireless_mode > WIRELESS_11B && - pmlmepriv->num_sta_no_short_slot_time == 0) { - beacon_updated = true; - update_beacon(padapter, 0xFF, NULL, true); - } - } - - if (psta->no_ht_gf_set) { - psta->no_ht_gf_set = 0; - pmlmepriv->num_sta_ht_no_gf--; - } - - if (psta->no_ht_set) { - psta->no_ht_set = 0; - pmlmepriv->num_sta_no_ht--; - } - - if (psta->ht_20mhz_set) { - psta->ht_20mhz_set = 0; - pmlmepriv->num_sta_ht_20mhz--; - } - - if (rtw_ht_operation_update(padapter) > 0) { - update_beacon(padapter, _HT_CAPABILITY_IE_, NULL, false); - update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, true); - } - - /* update associated stations cap. */ - - return beacon_updated; -} - -void rtw_indicate_sta_assoc_event(struct adapter *padapter, struct sta_info *psta) -{ - union iwreq_data wrqu; - struct sta_priv *pstapriv = &padapter->stapriv; - - if (!psta) - return; - - if (psta->aid > NUM_STA) - return; - - if (pstapriv->sta_aid[psta->aid - 1] != psta) - return; - - wrqu.addr.sa_family = ARPHRD_ETHER; - - memcpy(wrqu.addr.sa_data, psta->hwaddr, ETH_ALEN); - - wireless_send_event(padapter->pnetdev, IWEVREGISTERED, &wrqu, NULL); -} - -static void rtw_indicate_sta_disassoc_event(struct adapter *padapter, struct sta_info *psta) -{ - union iwreq_data wrqu; - struct sta_priv *pstapriv = &padapter->stapriv; - - if (!psta) - return; - - if (psta->aid > NUM_STA) - return; - - if (pstapriv->sta_aid[psta->aid - 1] != psta) - return; - - wrqu.addr.sa_family = ARPHRD_ETHER; - - memcpy(wrqu.addr.sa_data, psta->hwaddr, ETH_ALEN); - - wireless_send_event(padapter->pnetdev, IWEVEXPIRED, &wrqu, NULL); -} - -u8 ap_free_sta(struct adapter *padapter, struct sta_info *psta, - bool active, u16 reason) -{ - u8 beacon_updated = false; - struct sta_priv *pstapriv = &padapter->stapriv; - - if (!psta) - return beacon_updated; - - /* tear down Rx AMPDU */ - send_delba(padapter, 0, psta->hwaddr);/* recipient */ - - /* tear down TX AMPDU */ - send_delba(padapter, 1, psta->hwaddr);/* originator */ - psta->htpriv.agg_enable_bitmap = 0x0;/* reset */ - psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */ - - if (active) - issue_deauth(padapter, psta->hwaddr, reason); - - /* clear cam entry / key */ - rtw_clearstakey_cmd(padapter, (u8 *)psta, (u8)(psta->mac_id + 3), true); - - spin_lock_bh(&psta->lock); - psta->state &= ~_FW_LINKED; - spin_unlock_bh(&psta->lock); - - rtw_indicate_sta_disassoc_event(padapter, psta); - - report_del_sta_event(padapter, psta->hwaddr, reason); - - beacon_updated = bss_cap_update_on_sta_leave(padapter, psta); - - spin_lock_bh(&pstapriv->sta_hash_lock); - rtw_free_stainfo(padapter, psta); - spin_unlock_bh(&pstapriv->sta_hash_lock); - - return beacon_updated; -} - -void rtw_sta_flush(struct adapter *padapter) -{ - struct list_head *phead, *plist; - struct sta_info *psta = NULL; - struct sta_priv *pstapriv = &padapter->stapriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - - if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE) - return; - - spin_lock_bh(&pstapriv->asoc_list_lock); - phead = &pstapriv->asoc_list; - plist = phead->next; - - /* free sta asoc_queue */ - while (phead != plist) { - psta = container_of(plist, struct sta_info, asoc_list); - - plist = plist->next; - - list_del_init(&psta->asoc_list); - pstapriv->asoc_list_cnt--; - - ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING); - } - spin_unlock_bh(&pstapriv->asoc_list_lock); - - issue_deauth(padapter, bc_addr, WLAN_REASON_DEAUTH_LEAVING); - - associated_clients_update(padapter, true); -} - -/* called > TSR LEVEL for USB or SDIO Interface*/ -void sta_info_update(struct adapter *padapter, struct sta_info *psta) -{ - int flags = psta->flags; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - /* update wmm cap. */ - if (WLAN_STA_WME & flags) - psta->qos_option = 1; - else - psta->qos_option = 0; - - if (pmlmepriv->qospriv.qos_option == 0) - psta->qos_option = 0; - - /* update 802.11n ht cap. */ - if (WLAN_STA_HT & flags) { - psta->htpriv.ht_option = true; - psta->qos_option = 1; - } else { - psta->htpriv.ht_option = false; - } - - if (!pmlmepriv->htpriv.ht_option) - psta->htpriv.ht_option = false; - - update_sta_info_apmode(padapter, psta); -} - -void start_ap_mode(struct adapter *padapter) -{ - int i; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct sta_priv *pstapriv = &padapter->stapriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct wlan_acl_pool *pacl_list = &pstapriv->acl_list; - - pmlmepriv->update_bcn = false; - - pmlmeext->bstart_bss = false; - - pmlmepriv->num_sta_non_erp = 0; - - pmlmepriv->num_sta_no_short_slot_time = 0; - - pmlmepriv->num_sta_no_short_preamble = 0; - - pmlmepriv->num_sta_ht_no_gf = 0; - pmlmepriv->num_sta_no_ht = 0; - pmlmepriv->num_sta_ht_20mhz = 0; - - pmlmepriv->olbc = false; - - pmlmepriv->olbc_ht = false; - - pmlmepriv->ht_op_mode = 0; - - for (i = 0; i < NUM_STA; i++) - pstapriv->sta_aid[i] = NULL; - - pmlmepriv->wps_beacon_ie = NULL; - pmlmepriv->wps_probe_resp_ie = NULL; - pmlmepriv->wps_assoc_resp_ie = NULL; - - pmlmepriv->p2p_beacon_ie = NULL; - pmlmepriv->p2p_probe_resp_ie = NULL; - - /* for ACL */ - INIT_LIST_HEAD(&pacl_list->acl_node_q.queue); - pacl_list->num = 0; - pacl_list->mode = 0; - for (i = 0; i < NUM_ACL; i++) { - INIT_LIST_HEAD(&pacl_list->aclnode[i].list); - pacl_list->aclnode[i].valid = false; - } -} - -void stop_ap_mode(struct adapter *padapter) -{ - struct list_head *phead, *plist; - struct rtw_wlan_acl_node *paclnode; - struct sta_info *psta = NULL; - struct sta_priv *pstapriv = &padapter->stapriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct wlan_acl_pool *pacl_list = &pstapriv->acl_list; - struct __queue *pacl_node_q = &pacl_list->acl_node_q; - - pmlmepriv->update_bcn = false; - pmlmeext->bstart_bss = false; - - /* reset and init security priv , this can refine with rtw_reset_securitypriv */ - memset((unsigned char *)&padapter->securitypriv, 0, sizeof(struct security_priv)); - padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen; - padapter->securitypriv.ndisencryptstatus = Ndis802_11WEPDisabled; - - /* for ACL */ - spin_lock_bh(&pacl_node_q->lock); - phead = get_list_head(pacl_node_q); - plist = phead->next; - while (phead != plist) { - paclnode = container_of(plist, struct rtw_wlan_acl_node, list); - plist = plist->next; - - if (paclnode->valid) { - paclnode->valid = false; - - list_del_init(&paclnode->list); - - pacl_list->num--; - } - } - spin_unlock_bh(&pacl_node_q->lock); - - rtw_sta_flush(padapter); - - /* free_assoc_sta_resources */ - rtw_free_all_stainfo(padapter); - - psta = rtw_get_bcmc_stainfo(padapter); - spin_lock_bh(&pstapriv->sta_hash_lock); - rtw_free_stainfo(padapter, psta); - spin_unlock_bh(&pstapriv->sta_hash_lock); - - rtw_init_bcmc_stainfo(padapter); - - rtw_free_mlme_priv_ie_data(pmlmepriv); -} diff --git a/drivers/staging/r8188eu/core/rtw_br_ext.c b/drivers/staging/r8188eu/core/rtw_br_ext.c deleted file mode 100644 index a7c67014dde0..000000000000 --- a/drivers/staging/r8188eu/core/rtw_br_ext.c +++ /dev/null @@ -1,658 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2007 - 2011 Realtek Corporation. i*/ - -#define _RTW_BR_EXT_C_ - -#include "../include/linux/if_arp.h" -#include "../include/net/ip.h" -#include "../include/linux/atalk.h" -#include "../include/linux/udp.h" -#include "../include/linux/if_pppox.h" - -#include "../include/drv_types.h" -#include "../include/rtw_br_ext.h" -#include "../include/usb_osintf.h" - -#ifndef csum_ipv6_magic -#include "../include/net/ip6_checksum.h" -#endif - -#include "../include/linux/ipv6.h" -#include "../include/linux/icmpv6.h" -#include "../include/net/ndisc.h" -#include "../include/net/checksum.h" - -#define NAT25_IPV4 01 -#define NAT25_IPV6 02 -#define NAT25_IPX 03 -#define NAT25_APPLE 04 -#define NAT25_PPPOE 05 - -#define RTL_RELAY_TAG_LEN (ETH_ALEN) -#define TAG_HDR_LEN 4 - -#define MAGIC_CODE 0x8186 -#define MAGIC_CODE_LEN 2 -#define WAIT_TIME_PPPOE 5 /* waiting time for pppoe server in sec */ - -/*----------------------------------------------------------------- - How database records network address: - 0 1 2 3 4 5 6 7 8 9 10 - |----|----|----|----|----|----|----|----|----|----|----| - IPv4 |type| | IP addr | - IPX |type| Net addr | Node addr | - IPX |type| Net addr |Sckt addr| - Apple |type| Network |node| - PPPoE |type| SID | AC MAC | ------------------------------------------------------------------*/ - -/* Find a tag in pppoe frame and return the pointer */ -static unsigned char *__nat25_find_pppoe_tag(struct pppoe_hdr *ph, unsigned short type) -{ - unsigned char *cur_ptr, *start_ptr; - unsigned short tag_len, tag_type; - - start_ptr = (unsigned char *)ph->tag; - cur_ptr = (unsigned char *)ph->tag; - while ((cur_ptr - start_ptr) < ntohs(ph->length)) { - /* prevent un-alignment access */ - tag_type = (unsigned short)((cur_ptr[0] << 8) + cur_ptr[1]); - tag_len = (unsigned short)((cur_ptr[2] << 8) + cur_ptr[3]); - if (tag_type == type) - return cur_ptr; - cur_ptr = cur_ptr + TAG_HDR_LEN + tag_len; - } - return NULL; -} - -static int __nat25_add_pppoe_tag(struct sk_buff *skb, struct pppoe_tag *tag) -{ - struct pppoe_hdr *ph = (struct pppoe_hdr *)(skb->data + ETH_HLEN); - int data_len; - - data_len = be16_to_cpu(tag->tag_len) + TAG_HDR_LEN; - if (skb_tailroom(skb) < data_len) - return -1; - - skb_put(skb, data_len); - /* have a room for new tag */ - memmove(((unsigned char *)ph->tag + data_len), (unsigned char *)ph->tag, ntohs(ph->length)); - ph->length = htons(ntohs(ph->length) + data_len); - memcpy((unsigned char *)ph->tag, tag, data_len); - return data_len; -} - -static int skb_pull_and_merge(struct sk_buff *skb, unsigned char *src, int len) -{ - int tail_len; - unsigned long end, tail; - - if ((src + len) > skb_tail_pointer(skb) || skb->len < len) - return -1; - - tail = (unsigned long)skb_tail_pointer(skb); - end = (unsigned long)src + len; - if (tail < end) - return -1; - - tail_len = (int)(tail - end); - if (tail_len > 0) - memmove(src, src + len, tail_len); - - skb_trim(skb, skb->len - len); - return 0; -} - -static int __nat25_has_expired(struct nat25_network_db_entry *fdb) -{ - if (time_before_eq(fdb->ageing_timer, jiffies - NAT25_AGEING_TIME * HZ)) - return 1; - - return 0; -} - -static void __nat25_generate_ipv4_network_addr(unsigned char *addr, - unsigned int *ip_addr) -{ - memset(addr, 0, MAX_NETWORK_ADDR_LEN); - - addr[0] = NAT25_IPV4; - memcpy(addr + 7, (unsigned char *)ip_addr, 4); -} - -static void __nat25_generate_pppoe_network_addr(unsigned char *addr, - unsigned char *ac_mac, __be16 *sid) -{ - memset(addr, 0, MAX_NETWORK_ADDR_LEN); - - addr[0] = NAT25_PPPOE; - memcpy(addr + 1, (unsigned char *)sid, 2); - memcpy(addr + 3, (unsigned char *)ac_mac, 6); -} - -static void __nat25_generate_ipv6_network_addr(unsigned char *addr, - unsigned int *ip_addr) -{ - memset(addr, 0, MAX_NETWORK_ADDR_LEN); - - addr[0] = NAT25_IPV6; - memcpy(addr + 1, (unsigned char *)ip_addr, 16); -} - -static unsigned char *scan_tlv(unsigned char *data, int len, unsigned char tag, unsigned char len8b) -{ - while (len > 0) { - if (*data == tag && *(data + 1) == len8b && len >= len8b * 8) - return data + 2; - - len -= (*(data + 1)) * 8; - data += (*(data + 1)) * 8; - } - return NULL; -} - -static int update_nd_link_layer_addr(unsigned char *data, int len, unsigned char *replace_mac) -{ - struct icmp6hdr *icmphdr = (struct icmp6hdr *)data; - unsigned char *mac; - - if (icmphdr->icmp6_type == NDISC_ROUTER_SOLICITATION) { - if (len >= 8) { - mac = scan_tlv(&data[8], len - 8, 1, 1); - if (mac) { - memcpy(mac, replace_mac, 6); - return 1; - } - } - } else if (icmphdr->icmp6_type == NDISC_ROUTER_ADVERTISEMENT) { - if (len >= 16) { - mac = scan_tlv(&data[16], len - 16, 1, 1); - if (mac) { - memcpy(mac, replace_mac, 6); - return 1; - } - } - } else if (icmphdr->icmp6_type == NDISC_NEIGHBOUR_SOLICITATION) { - if (len >= 24) { - mac = scan_tlv(&data[24], len - 24, 1, 1); - if (mac) { - memcpy(mac, replace_mac, 6); - return 1; - } - } - } else if (icmphdr->icmp6_type == NDISC_NEIGHBOUR_ADVERTISEMENT) { - if (len >= 24) { - mac = scan_tlv(&data[24], len - 24, 2, 1); - if (mac) { - memcpy(mac, replace_mac, 6); - return 1; - } - } - } else if (icmphdr->icmp6_type == NDISC_REDIRECT) { - if (len >= 40) { - mac = scan_tlv(&data[40], len - 40, 2, 1); - if (mac) { - memcpy(mac, replace_mac, 6); - return 1; - } - } - } - return 0; -} - -static int __nat25_network_hash(unsigned char *addr) -{ - if (addr[0] == NAT25_IPV4) { - unsigned long x; - - x = addr[7] ^ addr[8] ^ addr[9] ^ addr[10]; - - return x & (NAT25_HASH_SIZE - 1); - } else if (addr[0] == NAT25_IPX) { - unsigned long x; - - x = addr[1] ^ addr[2] ^ addr[3] ^ addr[4] ^ addr[5] ^ - addr[6] ^ addr[7] ^ addr[8] ^ addr[9] ^ addr[10]; - - return x & (NAT25_HASH_SIZE - 1); - } else if (addr[0] == NAT25_APPLE) { - unsigned long x; - - x = addr[1] ^ addr[2] ^ addr[3]; - - return x & (NAT25_HASH_SIZE - 1); - } else if (addr[0] == NAT25_PPPOE) { - unsigned long x; - - x = addr[0] ^ addr[1] ^ addr[2] ^ addr[3] ^ addr[4] ^ - addr[5] ^ addr[6] ^ addr[7] ^ addr[8]; - - return x & (NAT25_HASH_SIZE - 1); - } else if (addr[0] == NAT25_IPV6) { - unsigned long x; - - x = addr[1] ^ addr[2] ^ addr[3] ^ addr[4] ^ addr[5] ^ addr[6] ^ - addr[7] ^ addr[8] ^ addr[9] ^ addr[10] ^ addr[11] ^ addr[12] ^ - addr[13] ^ addr[14] ^ addr[15] ^ addr[16]; - - return x & (NAT25_HASH_SIZE - 1); - } else { - unsigned long x = 0; - int i; - - for (i = 0; i < MAX_NETWORK_ADDR_LEN; i++) - x ^= addr[i]; - - return x & (NAT25_HASH_SIZE - 1); - } -} - -static void __network_hash_link(struct adapter *priv, - struct nat25_network_db_entry *ent, int hash) -{ - /* Caller must spin_lock already! */ - ent->next_hash = priv->nethash[hash]; - if (ent->next_hash) - ent->next_hash->pprev_hash = &ent->next_hash; - priv->nethash[hash] = ent; - ent->pprev_hash = &priv->nethash[hash]; -} - -static void __network_hash_unlink(struct nat25_network_db_entry *ent) -{ - /* Caller must spin_lock already! */ - *ent->pprev_hash = ent->next_hash; - if (ent->next_hash) - ent->next_hash->pprev_hash = ent->pprev_hash; - ent->next_hash = NULL; - ent->pprev_hash = NULL; -} - -static void __nat25_db_network_insert(struct adapter *priv, - unsigned char *mac_addr, unsigned char *addr) -{ - struct nat25_network_db_entry *db; - int hash; - - spin_lock_bh(&priv->br_ext_lock); - hash = __nat25_network_hash(addr); - db = priv->nethash[hash]; - while (db) { - if (!memcmp(db->networkAddr, addr, MAX_NETWORK_ADDR_LEN)) { - memcpy(db->macAddr, mac_addr, ETH_ALEN); - db->ageing_timer = jiffies; - spin_unlock_bh(&priv->br_ext_lock); - return; - } - db = db->next_hash; - } - db = kmalloc(sizeof(*db), GFP_ATOMIC); - if (!db) { - spin_unlock_bh(&priv->br_ext_lock); - return; - } - memcpy(db->networkAddr, addr, MAX_NETWORK_ADDR_LEN); - memcpy(db->macAddr, mac_addr, ETH_ALEN); - atomic_set(&db->use_count, 1); - db->ageing_timer = jiffies; - - __network_hash_link(priv, db, hash); - - spin_unlock_bh(&priv->br_ext_lock); -} - -/* - * NAT2.5 interface - */ - -void nat25_db_cleanup(struct adapter *priv) -{ - int i; - - spin_lock_bh(&priv->br_ext_lock); - - for (i = 0; i < NAT25_HASH_SIZE; i++) { - struct nat25_network_db_entry *f; - - f = priv->nethash[i]; - while (f) { - struct nat25_network_db_entry *g; - - g = f->next_hash; - if (priv->scdb_entry == f) { - memset(priv->scdb_mac, 0, ETH_ALEN); - memset(priv->scdb_ip, 0, 4); - priv->scdb_entry = NULL; - } - __network_hash_unlink(f); - kfree(f); - f = g; - } - } - spin_unlock_bh(&priv->br_ext_lock); -} - -void nat25_db_expire(struct adapter *priv) -{ - int i; - - spin_lock_bh(&priv->br_ext_lock); - - for (i = 0; i < NAT25_HASH_SIZE; i++) { - struct nat25_network_db_entry *f; - - f = priv->nethash[i]; - while (f) { - struct nat25_network_db_entry *g; - - g = f->next_hash; - if (__nat25_has_expired(f)) { - if (atomic_dec_and_test(&f->use_count)) { - if (priv->scdb_entry == f) { - memset(priv->scdb_mac, 0, ETH_ALEN); - memset(priv->scdb_ip, 0, 4); - priv->scdb_entry = NULL; - } - __network_hash_unlink(f); - kfree(f); - } - } - f = g; - } - } - spin_unlock_bh(&priv->br_ext_lock); -} - -int nat25_db_handle(struct adapter *priv, struct sk_buff *skb, int method) -{ - unsigned short protocol; - unsigned char addr[MAX_NETWORK_ADDR_LEN]; - unsigned int tmp; - - if (!skb) - return -1; - - if ((method <= NAT25_MIN) || (method >= NAT25_MAX)) - return -1; - - protocol = be16_to_cpu(*((__be16 *)(skb->data + 2 * ETH_ALEN))); - - /*---------------------------------------------------*/ - /* Handle IP frame */ - /*---------------------------------------------------*/ - if (protocol == ETH_P_IP) { - struct iphdr *iph = (struct iphdr *)(skb->data + ETH_HLEN); - - if (((unsigned char *)(iph) + (iph->ihl << 2)) >= (skb->data + ETH_HLEN + skb->len)) - return -1; - - switch (method) { - case NAT25_CHECK: - return -1; - case NAT25_INSERT: - /* some multicast with source IP is all zero, maybe other case is illegal */ - /* in class A, B, C, host address is all zero or all one is illegal */ - if (iph->saddr == 0) - return 0; - tmp = be32_to_cpu(iph->saddr); - __nat25_generate_ipv4_network_addr(addr, &tmp); - /* record source IP address and , source mac address into db */ - __nat25_db_network_insert(priv, skb->data + ETH_ALEN, addr); - return 0; - default: - return -1; - } - } else if (protocol == ETH_P_ARP) { - /*---------------------------------------------------*/ - /* Handle ARP frame */ - /*---------------------------------------------------*/ - struct arphdr *arp = (struct arphdr *)(skb->data + ETH_HLEN); - unsigned char *arp_ptr = (unsigned char *)(arp + 1); - unsigned int *sender; - - if (arp->ar_pro != htons(ETH_P_IP)) - return -1; - - switch (method) { - case NAT25_CHECK: - return 0; /* skb_copy for all ARP frame */ - case NAT25_INSERT: - /* change to ARP sender mac address to wlan STA address */ - memcpy(arp_ptr, GET_MY_HWADDR(priv), ETH_ALEN); - arp_ptr += arp->ar_hln; - sender = (unsigned int *)arp_ptr; - __nat25_generate_ipv4_network_addr(addr, sender); - __nat25_db_network_insert(priv, skb->data + ETH_ALEN, addr); - return 0; - default: - return -1; - } - } else if ((protocol == ETH_P_PPP_DISC) || - (protocol == ETH_P_PPP_SES)) { - /*---------------------------------------------------*/ - /* Handle PPPoE frame */ - /*---------------------------------------------------*/ - struct pppoe_hdr *ph = (struct pppoe_hdr *)(skb->data + ETH_HLEN); - __be16 *pMagic; - - switch (method) { - case NAT25_CHECK: - if (ph->sid == 0) - return 0; - return 1; - case NAT25_INSERT: - if (ph->sid == 0) { /* Discovery phase according to tag */ - if (ph->code == PADI_CODE || ph->code == PADR_CODE) { - if (priv->ethBrExtInfo.addPPPoETag) { - struct pppoe_tag *tag, *pOldTag; - unsigned char tag_buf[40]; - int old_tag_len = 0; - - tag = (struct pppoe_tag *)tag_buf; - pOldTag = (struct pppoe_tag *)__nat25_find_pppoe_tag(ph, ntohs(PTT_RELAY_SID)); - if (pOldTag) { /* if SID existed, copy old value and delete it */ - old_tag_len = ntohs(pOldTag->tag_len); - if (old_tag_len + - TAG_HDR_LEN + - MAGIC_CODE_LEN + - RTL_RELAY_TAG_LEN > - sizeof(tag_buf)) - return -1; - - memcpy(tag->tag_data + MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN, - pOldTag->tag_data, old_tag_len); - - if (skb_pull_and_merge(skb, (unsigned char *)pOldTag, TAG_HDR_LEN + old_tag_len) < 0) - return -1; - - ph->length = htons(ntohs(ph->length) - TAG_HDR_LEN - old_tag_len); - } - - tag->tag_type = PTT_RELAY_SID; - tag->tag_len = htons(MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN + old_tag_len); - - /* insert the magic_code+client mac in relay tag */ - pMagic = (__be16 *)tag->tag_data; - *pMagic = htons(MAGIC_CODE); - memcpy(tag->tag_data + MAGIC_CODE_LEN, skb->data + ETH_ALEN, ETH_ALEN); - - /* Add relay tag */ - if (__nat25_add_pppoe_tag(skb, tag) < 0) - return -1; - } else { /* not add relay tag */ - if (priv->pppoe_connection_in_progress && - memcmp(skb->data + ETH_ALEN, - priv->pppoe_addr, - ETH_ALEN)) - return -2; - - if (priv->pppoe_connection_in_progress == 0) - memcpy(priv->pppoe_addr, skb->data + ETH_ALEN, ETH_ALEN); - - priv->pppoe_connection_in_progress = WAIT_TIME_PPPOE; - } - } else { - return -1; - } - } else { /* session phase */ - __nat25_generate_pppoe_network_addr(addr, skb->data, &ph->sid); - - __nat25_db_network_insert(priv, skb->data + ETH_ALEN, addr); - - if (!priv->ethBrExtInfo.addPPPoETag && - priv->pppoe_connection_in_progress && - !memcmp(skb->data + ETH_ALEN, priv->pppoe_addr, ETH_ALEN)) - priv->pppoe_connection_in_progress = 0; - } - return 0; - default: - return -1; - } - } else if (protocol == 0x888e) { - /*---------------------------------------------------*/ - /* Handle EAP frame */ - /*---------------------------------------------------*/ - switch (method) { - case NAT25_CHECK: - return -1; - case NAT25_INSERT: - return 0; - default: - return -1; - } - } else if ((protocol == 0xe2ae) || (protocol == 0xe2af)) { - /*---------------------------------------------------*/ - /* Handle C-Media proprietary frame */ - /*---------------------------------------------------*/ - switch (method) { - case NAT25_CHECK: - return -1; - case NAT25_INSERT: - return 0; - default: - return -1; - } - } else if (protocol == ETH_P_IPV6) { - /*------------------------------------------------*/ - /* Handle IPV6 frame */ - /*------------------------------------------------*/ - struct ipv6hdr *iph = (struct ipv6hdr *)(skb->data + ETH_HLEN); - - if (sizeof(*iph) >= (skb->len - ETH_HLEN)) - return -1; - - switch (method) { - case NAT25_CHECK: - if (skb->data[0] & 1) - return 0; - return -1; - case NAT25_INSERT: - if (memcmp(&iph->saddr, "\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0", 16)) { - __nat25_generate_ipv6_network_addr(addr, (unsigned int *)&iph->saddr); - __nat25_db_network_insert(priv, skb->data + ETH_ALEN, addr); - - if (iph->nexthdr == IPPROTO_ICMPV6 && - skb->len > (ETH_HLEN + sizeof(*iph) + 4)) { - if (update_nd_link_layer_addr(skb->data + ETH_HLEN + sizeof(*iph), - skb->len - ETH_HLEN - sizeof(*iph), GET_MY_HWADDR(priv))) { - struct icmp6hdr *hdr = (struct icmp6hdr *)(skb->data + ETH_HLEN + sizeof(*iph)); - hdr->icmp6_cksum = 0; - hdr->icmp6_cksum = csum_ipv6_magic(&iph->saddr, &iph->daddr, - be16_to_cpu(iph->payload_len), - IPPROTO_ICMPV6, - csum_partial((__u8 *)hdr, - be16_to_cpu(iph->payload_len), - 0)); - } - } - } - return 0; - default: - return -1; - } - } - return -1; -} - -#define SERVER_PORT 67 -#define CLIENT_PORT 68 -#define DHCP_MAGIC 0x63825363 -#define BROADCAST_FLAG 0x8000 - -struct dhcpMessage { - u_int8_t op; - u_int8_t htype; - u_int8_t hlen; - u_int8_t hops; - u_int32_t xid; - __be16 secs; - __be16 flags; - __be32 ciaddr; - __be32 yiaddr; - __be32 siaddr; - __be32 giaddr; - u_int8_t chaddr[16]; - u_int8_t sname[64]; - u_int8_t file[128]; - __be32 cookie; - u_int8_t options[308]; /* 312 - cookie */ -}; - -void dhcp_flag_bcast(struct adapter *priv, struct sk_buff *skb) -{ - if (!skb) - return; - - if (!priv->ethBrExtInfo.dhcp_bcst_disable) { - __be16 protocol = *((__be16 *)(skb->data + 2 * ETH_ALEN)); - - if (protocol == htons(ETH_P_IP)) { /* IP */ - struct iphdr *iph = (struct iphdr *)(skb->data + ETH_HLEN); - - if (iph->protocol == IPPROTO_UDP) { /* UDP */ - struct udphdr *udph = (void *)iph + (iph->ihl << 2); - - if ((udph->source == htons(CLIENT_PORT)) && - (udph->dest == htons(SERVER_PORT))) { /* DHCP request */ - struct dhcpMessage *dhcph = (void *)udph + sizeof(struct udphdr); - u32 cookie = be32_to_cpu(dhcph->cookie); - - if (cookie == DHCP_MAGIC) { /* match magic word */ - if (!(dhcph->flags & htons(BROADCAST_FLAG))) { - /* if not broadcast */ - register int sum = 0; - - /* or BROADCAST flag */ - dhcph->flags |= htons(BROADCAST_FLAG); - /* recalculate checksum */ - sum = ~(udph->check) & 0xffff; - sum += be16_to_cpu(dhcph->flags); - while (sum >> 16) - sum = (sum & 0xffff) + (sum >> 16); - udph->check = ~sum; - } - } - } - } - } - } -} - -void *scdb_findEntry(struct adapter *priv, unsigned char *ip_addr) -{ - unsigned char addr[MAX_NETWORK_ADDR_LEN]; - struct nat25_network_db_entry *db; - int hash; - - __nat25_generate_ipv4_network_addr(addr, (unsigned int *)ip_addr); - hash = __nat25_network_hash(addr); - db = priv->nethash[hash]; - while (db) { - if (!memcmp(db->networkAddr, addr, MAX_NETWORK_ADDR_LEN)) - return (void *)db; - - db = db->next_hash; - } - - return NULL; -} diff --git a/drivers/staging/r8188eu/core/rtw_cmd.c b/drivers/staging/r8188eu/core/rtw_cmd.c deleted file mode 100644 index ca9e3d4ee7f4..000000000000 --- a/drivers/staging/r8188eu/core/rtw_cmd.c +++ /dev/null @@ -1,1529 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2007 - 2012 Realtek Corporation. */ - -#define _RTW_CMD_C_ - -#include "../include/osdep_service.h" -#include "../include/drv_types.h" -#include "../include/rtw_br_ext.h" -#include "../include/rtw_mlme_ext.h" -#include "../include/rtl8188e_dm.h" - -/* Caller and the rtw_cmd_thread can protect cmd_q by spin_lock. - * No irqsave is necessary. - */ - -static void c2h_wk_callback(struct work_struct *work); - -void rtw_free_evt_priv(struct evt_priv *pevtpriv) -{ - cancel_work_sync(&pevtpriv->c2h_wk); - while (pevtpriv->c2h_wk_alive) - msleep(10); - - while (!rtw_cbuf_empty(pevtpriv->c2h_queue)) { - void *c2h = rtw_cbuf_pop(pevtpriv->c2h_queue); - if (c2h && c2h != (void *)pevtpriv) - kfree(c2h); - } -} - -int rtw_init_cmd_priv(struct cmd_priv *pcmdpriv) -{ - init_completion(&pcmdpriv->enqueue_cmd); - /* sema_init(&(pcmdpriv->cmd_done_sema), 0); */ - init_completion(&pcmdpriv->start_cmd_thread); - init_completion(&pcmdpriv->stop_cmd_thread); - - rtw_init_queue(&pcmdpriv->cmd_queue); - - /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */ - - pcmdpriv->cmd_allocated_buf = kzalloc(MAX_CMDSZ + CMDBUFF_ALIGN_SZ, - GFP_KERNEL); - - if (!pcmdpriv->cmd_allocated_buf) - return -ENOMEM; - - pcmdpriv->cmd_buf = pcmdpriv->cmd_allocated_buf + CMDBUFF_ALIGN_SZ - ((size_t)(pcmdpriv->cmd_allocated_buf) & (CMDBUFF_ALIGN_SZ - 1)); - - pcmdpriv->rsp_allocated_buf = kzalloc(MAX_RSPSZ + 4, GFP_KERNEL); - - if (!pcmdpriv->rsp_allocated_buf) { - kfree(pcmdpriv->cmd_allocated_buf); - return -ENOMEM; - } - - pcmdpriv->rsp_buf = pcmdpriv->rsp_allocated_buf + 4 - ((size_t)(pcmdpriv->rsp_allocated_buf) & 3); - - pcmdpriv->cmd_done_cnt = 0; - pcmdpriv->rsp_cnt = 0; - - return 0; -} - -int rtw_init_evt_priv(struct evt_priv *pevtpriv) -{ - /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */ - atomic_set(&pevtpriv->event_seq, 0); - - INIT_WORK(&pevtpriv->c2h_wk, c2h_wk_callback); - pevtpriv->c2h_wk_alive = false; - pevtpriv->c2h_queue = rtw_cbuf_alloc(C2H_QUEUE_MAX_LEN + 1); - if (!pevtpriv->c2h_queue) - return -ENOMEM; - - return 0; -} - -void rtw_free_cmd_priv(struct cmd_priv *pcmdpriv) -{ - if (pcmdpriv) { - kfree(pcmdpriv->cmd_allocated_buf); - kfree(pcmdpriv->rsp_allocated_buf); - } -} - -static int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj) -{ - u8 bAllow = false; /* set to true to allow enqueuing cmd when hw_init_completed is false */ - - if (cmd_obj->cmdcode == GEN_CMD_CODE(_SetChannelPlan)) - bAllow = true; - - if ((!pcmdpriv->padapter->hw_init_completed && !bAllow) || - !pcmdpriv->cmdthd_running) /* com_thread not running */ - return _FAIL; - return _SUCCESS; -} - -u32 rtw_enqueue_cmd(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj) -{ - unsigned long flags; - struct adapter *padapter = pcmdpriv->padapter; - - if (!cmd_obj) - return _FAIL; - - cmd_obj->padapter = padapter; - - if (rtw_cmd_filter(pcmdpriv, cmd_obj) == _FAIL) { - rtw_free_cmd_obj(cmd_obj); - return _FAIL; - } - - spin_lock_irqsave(&pcmdpriv->cmd_queue.lock, flags); - list_add_tail(&cmd_obj->list, &pcmdpriv->cmd_queue.queue); - spin_unlock_irqrestore(&pcmdpriv->cmd_queue.lock, flags); - - complete(&pcmdpriv->enqueue_cmd); - return _SUCCESS; -} - -struct cmd_obj *rtw_dequeue_cmd(struct cmd_priv *pcmdpriv) -{ - struct cmd_obj *obj; - struct __queue *queue = &pcmdpriv->cmd_queue; - unsigned long flags; - - spin_lock_irqsave(&queue->lock, flags); - if (list_empty(&queue->queue)) { - obj = NULL; - } else { - obj = container_of((&queue->queue)->next, struct cmd_obj, list); - list_del_init(&obj->list); - } - - spin_unlock_irqrestore(&queue->lock, flags); - - return obj; -} - -void rtw_free_cmd_obj(struct cmd_obj *pcmd) -{ - - if ((pcmd->cmdcode != _JoinBss_CMD_) && (pcmd->cmdcode != _CreateBss_CMD_)) { - /* free parmbuf in cmd_obj */ - kfree(pcmd->parmbuf); - } - - if (pcmd->rsp) { - if (pcmd->rspsz != 0) { - /* free rsp in cmd_obj */ - kfree(pcmd->rsp); - } - } - - /* free cmd_obj */ - kfree(pcmd); - -} - -int rtw_cmd_thread(void *context) -{ - u8 ret; - struct cmd_obj *pcmd; - u8 *pcmdbuf; - u8 (*cmd_hdl)(struct adapter *padapter, u8 *pbuf); - void (*pcmd_callback)(struct adapter *dev, struct cmd_obj *pcmd); - struct adapter *padapter = (struct adapter *)context; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - - pcmdbuf = pcmdpriv->cmd_buf; - - pcmdpriv->cmdthd_running = true; - complete(&pcmdpriv->start_cmd_thread); - - while (1) { - wait_for_completion(&pcmdpriv->enqueue_cmd); - -_next: - if (padapter->bDriverStopped || - padapter->bSurpriseRemoved) - break; - - pcmd = rtw_dequeue_cmd(pcmdpriv); - if (!pcmd) - continue; - - if (rtw_cmd_filter(pcmdpriv, pcmd) == _FAIL) { - pcmd->res = H2C_DROPPED; - goto post_process; - } - - pcmd->cmdsz = round_up(pcmd->cmdsz, 4); - - memcpy(pcmdbuf, pcmd->parmbuf, pcmd->cmdsz); - - if (pcmd->cmdcode < ARRAY_SIZE(wlancmds)) { - cmd_hdl = wlancmds[pcmd->cmdcode].h2cfuns; - - if (cmd_hdl) { - ret = cmd_hdl(pcmd->padapter, pcmdbuf); - pcmd->res = ret; - } - } else { - pcmd->res = H2C_PARAMETERS_ERROR; - } - - cmd_hdl = NULL; - -post_process: - - /* call callback function for post-processed */ - if (pcmd->cmdcode < ARRAY_SIZE(rtw_cmd_callback)) { - pcmd_callback = rtw_cmd_callback[pcmd->cmdcode].callback; - if (!pcmd_callback) - rtw_free_cmd_obj(pcmd); - else - /* todo: !!! fill rsp_buf to pcmd->rsp if (pcmd->rsp!= NULL) */ - pcmd_callback(pcmd->padapter, pcmd);/* need consider that free cmd_obj in rtw_cmd_callback */ - } else { - rtw_free_cmd_obj(pcmd); - } - - flush_signals_thread(); - - goto _next; - } - pcmdpriv->cmdthd_running = false; - - /* free all cmd_obj resources */ - do { - pcmd = rtw_dequeue_cmd(pcmdpriv); - if (!pcmd) - break; - - rtw_free_cmd_obj(pcmd); - } while (1); - - complete(&pcmdpriv->stop_cmd_thread); - - return 0; -} - -/* rtw_sitesurvey_cmd(~) - * ### NOTE:#### (!!!!) - * MUST TAKE CARE THAT BEFORE CALLING THIS FUNC, YOU SHOULD HAVE LOCKED pmlmepriv->lock - */ -u8 rtw_sitesurvey_cmd(struct adapter *padapter, struct ndis_802_11_ssid *ssid, int ssid_num) -{ - u8 res = _FAIL; - struct cmd_obj *ph2c; - struct sitesurvey_parm *psurveyPara; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - if (check_fwstate(pmlmepriv, _FW_LINKED)) - rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_SCAN, 1); - - if (check_fwstate(pmlmepriv, _FW_LINKED)) - p2p_ps_wk_cmd(padapter, P2P_PS_SCAN, 1); - - ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC); - if (!ph2c) - return _FAIL; - - psurveyPara = kzalloc(sizeof(*psurveyPara), GFP_ATOMIC); - if (!psurveyPara) { - kfree(ph2c); - return _FAIL; - } - - rtw_free_network_queue(padapter, false); - - init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, GEN_CMD_CODE(_SiteSurvey)); - - /* psurveyPara->bsslimit = 48; */ - psurveyPara->scan_mode = pmlmepriv->scan_mode; - - /* prepare ssid list */ - if (ssid) { - int i; - for (i = 0; i < ssid_num && i < RTW_SSID_SCAN_AMOUNT; i++) { - if (ssid[i].SsidLength) { - memcpy(&psurveyPara->ssid[i], &ssid[i], sizeof(struct ndis_802_11_ssid)); - psurveyPara->ssid_num++; - } - } - } - - set_fwstate(pmlmepriv, _FW_UNDER_SURVEY); - - res = rtw_enqueue_cmd(pcmdpriv, ph2c); - - if (res == _SUCCESS) { - pmlmepriv->scan_start_time = jiffies; - - _set_timer(&pmlmepriv->scan_to_timer, SCANNING_TIMEOUT); - - rtw_led_control(padapter, LED_CTL_SITE_SURVEY); - - pmlmepriv->scan_interval = SCAN_INTERVAL;/* 30*2 sec = 60sec */ - } else { - _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY); - } - - return res; -} - -int rtw_setdatarate_cmd(struct adapter *padapter, u8 *rateset) -{ - struct cmd_obj *ph2c; - struct setdatarate_parm *pbsetdataratepara; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - - ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC); - if (!ph2c) - return -ENOMEM; - - pbsetdataratepara = kzalloc(sizeof(*pbsetdataratepara), GFP_ATOMIC); - if (!pbsetdataratepara) { - kfree(ph2c); - return -ENOMEM; - } - - init_h2fwcmd_w_parm_no_rsp(ph2c, pbsetdataratepara, GEN_CMD_CODE(_SetDataRate)); - pbsetdataratepara->mac_id = 5; - memcpy(pbsetdataratepara->datarates, rateset, NumRates); - if (rtw_enqueue_cmd(pcmdpriv, ph2c) == _FAIL) - return -EPERM; - - return 0; -} - -void rtw_getbbrfreg_cmdrsp_callback(struct adapter *padapter, struct cmd_obj *pcmd) -{ - - - kfree(pcmd->parmbuf); - kfree(pcmd); -} - -u8 rtw_createbss_cmd(struct adapter *padapter) -{ - struct cmd_obj *pcmd; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - struct wlan_bssid_ex *pdev_network = &padapter->registrypriv.dev_network; - u8 res = _SUCCESS; - - rtw_led_control(padapter, LED_CTL_START_TO_LINK); - - pcmd = kzalloc(sizeof(*pcmd), GFP_ATOMIC); - if (!pcmd) { - res = _FAIL; - goto exit; - } - - INIT_LIST_HEAD(&pcmd->list); - pcmd->cmdcode = _CreateBss_CMD_; - pcmd->parmbuf = (unsigned char *)pdev_network; - pcmd->cmdsz = get_wlan_bssid_ex_sz((struct wlan_bssid_ex *)pdev_network); - pcmd->rsp = NULL; - pcmd->rspsz = 0; - pdev_network->Length = pcmd->cmdsz; - res = rtw_enqueue_cmd(pcmdpriv, pcmd); -exit: - - return res; -} - -u8 rtw_joinbss_cmd(struct adapter *padapter, struct wlan_network *pnetwork) -{ - u8 res = _SUCCESS; - uint t_len = 0; - struct wlan_bssid_ex *psecnetwork; - struct cmd_obj *pcmd; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct qos_priv *pqospriv = &pmlmepriv->qospriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct registry_priv *pregistrypriv = &padapter->registrypriv; - struct ht_priv *phtpriv = &pmlmepriv->htpriv; - enum ndis_802_11_network_infra ndis_network_mode = pnetwork->network.InfrastructureMode; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - rtw_led_control(padapter, LED_CTL_START_TO_LINK); - - pcmd = kzalloc(sizeof(*pcmd), GFP_ATOMIC); - if (!pcmd) { - res = _FAIL; - goto exit; - } - /* for IEs is fix buf size */ - t_len = sizeof(struct wlan_bssid_ex); - - /* for hidden ap to set fw_state here */ - if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_ADHOC_STATE)) { - switch (ndis_network_mode) { - case Ndis802_11IBSS: - set_fwstate(pmlmepriv, WIFI_ADHOC_STATE); - break; - case Ndis802_11Infrastructure: - set_fwstate(pmlmepriv, WIFI_STATION_STATE); - break; - case Ndis802_11APMode: - case Ndis802_11AutoUnknown: - case Ndis802_11InfrastructureMax: - break; - } - } - - psecnetwork = (struct wlan_bssid_ex *)&psecuritypriv->sec_bss; - if (!psecnetwork) { - kfree(pcmd); - res = _FAIL; - goto exit; - } - - memset(psecnetwork, 0, t_len); - - memcpy(psecnetwork, &pnetwork->network, get_wlan_bssid_ex_sz(&pnetwork->network)); - - psecuritypriv->authenticator_ie[0] = (unsigned char)psecnetwork->IELength; - - if (psecnetwork->IELength - 12 < 255) - memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->IEs[12], psecnetwork->IELength - 12); - else - memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->IEs[12], 255); - - psecnetwork->IELength = 0; - /* Added by Albert 2009/02/18 */ - /* If the driver wants to use the bssid to create the connection. */ - /* If not, we have to copy the connecting AP's MAC address to it so that */ - /* the driver just has the bssid information for PMKIDList searching. */ - - if (!pmlmepriv->assoc_by_bssid) - memcpy(&pmlmepriv->assoc_bssid[0], &pnetwork->network.MacAddress[0], ETH_ALEN); - - psecnetwork->IELength = rtw_restruct_sec_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0], pnetwork->network.IELength); - - pqospriv->qos_option = 0; - - if (pregistrypriv->wmm_enable) { - u32 tmp_len; - - tmp_len = rtw_restruct_wmm_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0], pnetwork->network.IELength, psecnetwork->IELength); - - if (psecnetwork->IELength != tmp_len) { - psecnetwork->IELength = tmp_len; - pqospriv->qos_option = 1; /* There is WMM IE in this corresp. beacon */ - } else { - pqospriv->qos_option = 0;/* There is no WMM IE in this corresp. beacon */ - } - } - - phtpriv->ht_option = false; - if (pregistrypriv->ht_enable) { - /* Added by Albert 2010/06/23 */ - /* For the WEP mode, we will use the bg mode to do the connection to avoid some IOT issue. */ - /* Especially for Realtek 8192u SoftAP. */ - if ((padapter->securitypriv.dot11PrivacyAlgrthm != _WEP40_) && - (padapter->securitypriv.dot11PrivacyAlgrthm != _WEP104_) && - (padapter->securitypriv.dot11PrivacyAlgrthm != _TKIP_)) { - /* rtw_restructure_ht_ie */ - rtw_restructure_ht_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0], - pnetwork->network.IELength, &psecnetwork->IELength); - } - } - - pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pnetwork->network.IEs, pnetwork->network.IELength); - - if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_TENDA) - padapter->pwrctrlpriv.smart_ps = 0; - else - padapter->pwrctrlpriv.smart_ps = padapter->registrypriv.smart_ps; - - pcmd->cmdsz = get_wlan_bssid_ex_sz(psecnetwork);/* get cmdsz before endian conversion */ - - INIT_LIST_HEAD(&pcmd->list); - pcmd->cmdcode = _JoinBss_CMD_;/* GEN_CMD_CODE(_JoinBss) */ - pcmd->parmbuf = (unsigned char *)psecnetwork; - pcmd->rsp = NULL; - pcmd->rspsz = 0; - - res = rtw_enqueue_cmd(pcmdpriv, pcmd); - -exit: - - return res; -} - -u8 rtw_disassoc_cmd(struct adapter *padapter, u32 deauth_timeout_ms, bool enqueue) /* for sta_mode */ -{ - struct cmd_obj *cmdobj = NULL; - struct disconnect_parm *param = NULL; - struct cmd_priv *cmdpriv = &padapter->cmdpriv; - u8 res = _SUCCESS; - - /* prepare cmd parameter */ - param = kzalloc(sizeof(*param), GFP_ATOMIC); - if (!param) { - res = _FAIL; - goto exit; - } - param->deauth_timeout_ms = deauth_timeout_ms; - - if (enqueue) { - /* need enqueue, prepare cmd_obj and enqueue */ - cmdobj = kzalloc(sizeof(*cmdobj), GFP_ATOMIC); - if (!cmdobj) { - res = _FAIL; - kfree(param); - goto exit; - } - init_h2fwcmd_w_parm_no_rsp(cmdobj, param, _DisConnect_CMD_); - res = rtw_enqueue_cmd(cmdpriv, cmdobj); - } else { - /* no need to enqueue, do the cmd hdl directly and free cmd parameter */ - if (disconnect_hdl(padapter, (u8 *)param) != H2C_SUCCESS) - res = _FAIL; - kfree(param); - } - -exit: - - return res; -} - -u8 rtw_setopmode_cmd(struct adapter *padapter, enum ndis_802_11_network_infra networktype) -{ - struct cmd_obj *ph2c; - struct setopmode_parm *psetop; - - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - u8 res = _SUCCESS; - - ph2c = kzalloc(sizeof(*ph2c), GFP_KERNEL); - if (!ph2c) { - res = false; - goto exit; - } - psetop = kzalloc(sizeof(*psetop), GFP_KERNEL); - - if (!psetop) { - kfree(ph2c); - res = false; - goto exit; - } - - init_h2fwcmd_w_parm_no_rsp(ph2c, psetop, _SetOpMode_CMD_); - psetop->mode = (u8)networktype; - - res = rtw_enqueue_cmd(pcmdpriv, ph2c); - -exit: - - return res; -} - -u8 rtw_setstakey_cmd(struct adapter *padapter, u8 *psta, u8 unicast_key) -{ - struct cmd_obj *ph2c; - struct set_stakey_parm *psetstakey_para; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - struct set_stakey_rsp *psetstakey_rsp = NULL; - - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct sta_info *sta = (struct sta_info *)psta; - u8 res = _SUCCESS; - - ph2c = kzalloc(sizeof(*ph2c), GFP_KERNEL); - if (!ph2c) { - res = _FAIL; - goto exit; - } - - psetstakey_para = kzalloc(sizeof(*psetstakey_para), GFP_KERNEL); - if (!psetstakey_para) { - kfree(ph2c); - res = _FAIL; - goto exit; - } - - psetstakey_rsp = kzalloc(sizeof(*psetstakey_rsp), GFP_KERNEL); - if (!psetstakey_rsp) { - kfree(ph2c); - kfree(psetstakey_para); - res = _FAIL; - goto exit; - } - - init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_); - ph2c->rsp = (u8 *)psetstakey_rsp; - ph2c->rspsz = sizeof(struct set_stakey_rsp); - - memcpy(psetstakey_para->addr, sta->hwaddr, ETH_ALEN); - - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) - psetstakey_para->algorithm = (unsigned char)psecuritypriv->dot11PrivacyAlgrthm; - else - GET_ENCRY_ALGO(psecuritypriv, sta, psetstakey_para->algorithm, false); - - if (unicast_key) - memcpy(&psetstakey_para->key, &sta->dot118021x_UncstKey, 16); - else - memcpy(&psetstakey_para->key, &psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey, 16); - - /* jeff: set this because at least sw key is ready */ - padapter->securitypriv.busetkipkey = true; - - res = rtw_enqueue_cmd(pcmdpriv, ph2c); - -exit: - - return res; -} - -u8 rtw_clearstakey_cmd(struct adapter *padapter, u8 *psta, u8 entry, u8 enqueue) -{ - struct cmd_obj *ph2c; - struct set_stakey_parm *psetstakey_para; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - struct set_stakey_rsp *psetstakey_rsp = NULL; - struct sta_info *sta = (struct sta_info *)psta; - u8 res = _SUCCESS; - - if (!enqueue) { - clear_cam_entry(padapter, entry); - } else { - ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC); - if (!ph2c) { - res = _FAIL; - goto exit; - } - - psetstakey_para = kzalloc(sizeof(*psetstakey_para), - GFP_ATOMIC); - if (!psetstakey_para) { - kfree(ph2c); - res = _FAIL; - goto exit; - } - - psetstakey_rsp = kzalloc(sizeof(*psetstakey_rsp), - GFP_ATOMIC); - if (!psetstakey_rsp) { - kfree(ph2c); - kfree(psetstakey_para); - res = _FAIL; - goto exit; - } - - init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_); - ph2c->rsp = (u8 *)psetstakey_rsp; - ph2c->rspsz = sizeof(struct set_stakey_rsp); - - memcpy(psetstakey_para->addr, sta->hwaddr, ETH_ALEN); - - psetstakey_para->algorithm = _NO_PRIVACY_; - - psetstakey_para->id = entry; - - res = rtw_enqueue_cmd(pcmdpriv, ph2c); - } -exit: - - return res; -} - -u8 rtw_addbareq_cmd(struct adapter *padapter, u8 tid, u8 *addr) -{ - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - struct cmd_obj *ph2c; - struct addBaReq_parm *paddbareq_parm; - u8 res = _SUCCESS; - - ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC); - if (!ph2c) { - res = _FAIL; - goto exit; - } - - paddbareq_parm = kzalloc(sizeof(*paddbareq_parm), GFP_ATOMIC); - if (!paddbareq_parm) { - kfree(ph2c); - res = _FAIL; - goto exit; - } - - paddbareq_parm->tid = tid; - memcpy(paddbareq_parm->addr, addr, ETH_ALEN); - - init_h2fwcmd_w_parm_no_rsp(ph2c, paddbareq_parm, GEN_CMD_CODE(_AddBAReq)); - - /* rtw_enqueue_cmd(pcmdpriv, ph2c); */ - res = rtw_enqueue_cmd(pcmdpriv, ph2c); - -exit: - - return res; -} - -u8 rtw_dynamic_chk_wk_cmd(struct adapter *padapter) -{ - struct cmd_obj *ph2c; - struct drvextra_cmd_parm *pdrvextra_cmd_parm; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - u8 res = _SUCCESS; - - ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC); - if (!ph2c) { - res = _FAIL; - goto exit; - } - - pdrvextra_cmd_parm = kzalloc(sizeof(*pdrvextra_cmd_parm), GFP_ATOMIC); - if (!pdrvextra_cmd_parm) { - kfree(ph2c); - res = _FAIL; - goto exit; - } - - pdrvextra_cmd_parm->ec_id = DYNAMIC_CHK_WK_CID; - pdrvextra_cmd_parm->type_size = 0; - pdrvextra_cmd_parm->pbuf = (u8 *)padapter; - - init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); - - /* rtw_enqueue_cmd(pcmdpriv, ph2c); */ - res = rtw_enqueue_cmd(pcmdpriv, ph2c); -exit: - - return res; -} - -u8 rtw_set_chplan_cmd(struct adapter *padapter, u8 chplan) -{ - struct cmd_obj *pcmdobj; - struct SetChannelPlan_param *setChannelPlan_param; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - - u8 res = _SUCCESS; - - /* check input parameter */ - if (!rtw_is_channel_plan_valid(chplan)) { - res = _FAIL; - goto exit; - } - - /* prepare cmd parameter */ - setChannelPlan_param = kzalloc(sizeof(*setChannelPlan_param), - GFP_KERNEL); - if (!setChannelPlan_param) { - res = _FAIL; - goto exit; - } - setChannelPlan_param->channel_plan = chplan; - - /* need enqueue, prepare cmd_obj and enqueue */ - pcmdobj = kzalloc(sizeof(*pcmdobj), GFP_KERNEL); - if (!pcmdobj) { - kfree(setChannelPlan_param); - res = _FAIL; - goto exit; - } - - init_h2fwcmd_w_parm_no_rsp(pcmdobj, setChannelPlan_param, GEN_CMD_CODE(_SetChannelPlan)); - res = rtw_enqueue_cmd(pcmdpriv, pcmdobj); - - /* do something based on res... */ - if (res == _SUCCESS) - padapter->mlmepriv.ChannelPlan = chplan; - -exit: - - return res; -} - -static void traffic_status_watchdog(struct adapter *padapter) -{ - u8 bEnterPS; - u8 bBusyTraffic = false, bTxBusyTraffic = false, bRxBusyTraffic = false; - u8 bHigherBusyTraffic = false, bHigherBusyRxTraffic = false, bHigherBusyTxTraffic = false; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - /* */ - /* Determine if our traffic is busy now */ - /* */ - if (check_fwstate(pmlmepriv, _FW_LINKED)) { - if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > 100 || - pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > 100) { - bBusyTraffic = true; - - if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > pmlmepriv->LinkDetectInfo.NumTxOkInPeriod) - bRxBusyTraffic = true; - else - bTxBusyTraffic = true; - } - - /* Higher Tx/Rx data. */ - if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > 4000 || - pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > 4000) { - bHigherBusyTraffic = true; - - if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > pmlmepriv->LinkDetectInfo.NumTxOkInPeriod) - bHigherBusyRxTraffic = true; - else - bHigherBusyTxTraffic = true; - } - - /* check traffic for powersaving. */ - if (((pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod + pmlmepriv->LinkDetectInfo.NumTxOkInPeriod) > 8) || - (pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod > 2)) - bEnterPS = false; - else - bEnterPS = true; - - /* LeisurePS only work in infra mode. */ - if (bEnterPS) - LPS_Enter(padapter); - else - LPS_Leave(padapter); - } else { - LPS_Leave(padapter); - } - - pmlmepriv->LinkDetectInfo.NumRxOkInPeriod = 0; - pmlmepriv->LinkDetectInfo.NumTxOkInPeriod = 0; - pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod = 0; - pmlmepriv->LinkDetectInfo.bBusyTraffic = bBusyTraffic; - pmlmepriv->LinkDetectInfo.bTxBusyTraffic = bTxBusyTraffic; - pmlmepriv->LinkDetectInfo.bRxBusyTraffic = bRxBusyTraffic; - pmlmepriv->LinkDetectInfo.bHigherBusyTraffic = bHigherBusyTraffic; - pmlmepriv->LinkDetectInfo.bHigherBusyRxTraffic = bHigherBusyRxTraffic; - pmlmepriv->LinkDetectInfo.bHigherBusyTxTraffic = bHigherBusyTxTraffic; -} - -static void rtl8188e_sreset_xmit_status_check(struct adapter *padapter) -{ - u32 txdma_status; - int res; - - res = rtw_read32(padapter, REG_TXDMA_STATUS, &txdma_status); - if (res) - return; - - if (txdma_status != 0x00) - rtw_write32(padapter, REG_TXDMA_STATUS, txdma_status); - /* total xmit irp = 4 */ -} - -static void dynamic_chk_wk_hdl(struct adapter *padapter, u8 *pbuf) -{ - struct mlme_priv *pmlmepriv; - - padapter = (struct adapter *)pbuf; - pmlmepriv = &padapter->mlmepriv; - - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) - expire_timeout_chk(padapter); - - rtl8188e_sreset_xmit_status_check(padapter); - - linked_status_chk(padapter); - traffic_status_watchdog(padapter); - - rtl8188e_HalDmWatchDog(padapter); -} - -static void lps_ctrl_wk_hdl(struct adapter *padapter, u8 lps_ctrl_type) -{ - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - u8 mstatus; - - if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) || - check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) - return; - - switch (lps_ctrl_type) { - case LPS_CTRL_SCAN: - if (check_fwstate(pmlmepriv, _FW_LINKED)) { - /* connect */ - LPS_Leave(padapter); - } - break; - case LPS_CTRL_JOINBSS: - LPS_Leave(padapter); - break; - case LPS_CTRL_CONNECT: - mstatus = 1;/* connect */ - /* Reset LPS Setting */ - padapter->pwrctrlpriv.LpsIdleCount = 0; - rtl8188e_set_FwJoinBssReport_cmd(padapter, mstatus); - break; - case LPS_CTRL_DISCONNECT: - mstatus = 0;/* disconnect */ - LPS_Leave(padapter); - rtl8188e_set_FwJoinBssReport_cmd(padapter, mstatus); - break; - case LPS_CTRL_SPECIAL_PACKET: - pwrpriv->DelayLPSLastTimeStamp = jiffies; - LPS_Leave(padapter); - break; - case LPS_CTRL_LEAVE: - LPS_Leave(padapter); - break; - default: - break; - } - -} - -u8 rtw_lps_ctrl_wk_cmd(struct adapter *padapter, u8 lps_ctrl_type, u8 enqueue) -{ - struct cmd_obj *ph2c; - struct drvextra_cmd_parm *pdrvextra_cmd_parm; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - /* struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv; */ - u8 res = _SUCCESS; - - /* if (!pwrctrlpriv->bLeisurePs) */ - /* return res; */ - - if (enqueue) { - ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC); - if (!ph2c) { - res = _FAIL; - goto exit; - } - - pdrvextra_cmd_parm = kzalloc(sizeof(*pdrvextra_cmd_parm), - GFP_ATOMIC); - if (!pdrvextra_cmd_parm) { - kfree(ph2c); - res = _FAIL; - goto exit; - } - - pdrvextra_cmd_parm->ec_id = LPS_CTRL_WK_CID; - pdrvextra_cmd_parm->type_size = lps_ctrl_type; - pdrvextra_cmd_parm->pbuf = NULL; - - init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); - - res = rtw_enqueue_cmd(pcmdpriv, ph2c); - } else { - lps_ctrl_wk_hdl(padapter, lps_ctrl_type); - } - -exit: - - return res; -} - -static void rpt_timer_setting_wk_hdl(struct adapter *padapter, u16 min_time) -{ - struct hal_data_8188e *haldata = &padapter->haldata; - struct odm_dm_struct *odmpriv = &haldata->odmpriv; - - ODM_RA_Set_TxRPT_Time(odmpriv, min_time); -} - -u8 rtw_rpt_timer_cfg_cmd(struct adapter *padapter, u16 min_time) -{ - struct cmd_obj *ph2c; - struct drvextra_cmd_parm *pdrvextra_cmd_parm; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - - u8 res = _SUCCESS; - - ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC); - if (!ph2c) { - res = _FAIL; - goto exit; - } - - pdrvextra_cmd_parm = kzalloc(sizeof(*pdrvextra_cmd_parm), - GFP_ATOMIC); - if (!pdrvextra_cmd_parm) { - kfree(ph2c); - res = _FAIL; - goto exit; - } - - pdrvextra_cmd_parm->ec_id = RTP_TIMER_CFG_WK_CID; - pdrvextra_cmd_parm->type_size = min_time; - pdrvextra_cmd_parm->pbuf = NULL; - init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); - res = rtw_enqueue_cmd(pcmdpriv, ph2c); -exit: - - return res; -} - -static void antenna_select_wk_hdl(struct adapter *padapter, u8 antenna) -{ - struct hal_data_8188e *haldata = &padapter->haldata; - - /* switch current antenna to optimum antenna */ - if (haldata->CurAntenna != antenna) { - ODM_UpdateRxIdleAnt_88E(&haldata->odmpriv, antenna == 2 ? MAIN_ANT : AUX_ANT); - haldata->CurAntenna = antenna; - } -} - -static bool rtw_antenna_diversity(struct adapter *adapter) -{ - struct hal_data_8188e *haldata = &adapter->haldata; - - return haldata->AntDivCfg != 0; -} - -u8 rtw_antenna_select_cmd(struct adapter *padapter, u8 antenna, u8 enqueue) -{ - struct cmd_obj *ph2c; - struct drvextra_cmd_parm *pdrvextra_cmd_parm; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - u8 res = _SUCCESS; - - if (!rtw_antenna_diversity(padapter)) - return res; - - if (enqueue) { - ph2c = kzalloc(sizeof(*ph2c), GFP_KERNEL); - if (!ph2c) { - res = _FAIL; - goto exit; - } - - pdrvextra_cmd_parm = kzalloc(sizeof(*pdrvextra_cmd_parm), - GFP_KERNEL); - if (!pdrvextra_cmd_parm) { - kfree(ph2c); - res = _FAIL; - goto exit; - } - - pdrvextra_cmd_parm->ec_id = ANT_SELECT_WK_CID; - pdrvextra_cmd_parm->type_size = antenna; - pdrvextra_cmd_parm->pbuf = NULL; - init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); - - res = rtw_enqueue_cmd(pcmdpriv, ph2c); - } else { - antenna_select_wk_hdl(padapter, antenna); - } -exit: - - return res; -} - -u8 p2p_protocol_wk_cmd(struct adapter *padapter, int intCmdType) -{ - struct cmd_obj *ph2c; - struct drvextra_cmd_parm *pdrvextra_cmd_parm; - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - u8 res = _SUCCESS; - - if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) - return res; - - ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC); - if (!ph2c) { - res = _FAIL; - goto exit; - } - - pdrvextra_cmd_parm = kzalloc(sizeof(*pdrvextra_cmd_parm), GFP_ATOMIC); - if (!pdrvextra_cmd_parm) { - kfree(ph2c); - res = _FAIL; - goto exit; - } - - pdrvextra_cmd_parm->ec_id = P2P_PROTO_WK_CID; - pdrvextra_cmd_parm->type_size = intCmdType; /* As the command type. */ - pdrvextra_cmd_parm->pbuf = NULL; /* Must be NULL here */ - - init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); - - res = rtw_enqueue_cmd(pcmdpriv, ph2c); - -exit: - - return res; -} - -u8 rtw_ps_cmd(struct adapter *padapter) -{ - struct cmd_obj *ppscmd; - struct drvextra_cmd_parm *pdrvextra_cmd_parm; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - - u8 res = _SUCCESS; - - ppscmd = kzalloc(sizeof(*ppscmd), GFP_ATOMIC); - if (!ppscmd) { - res = _FAIL; - goto exit; - } - - pdrvextra_cmd_parm = kzalloc(sizeof(*pdrvextra_cmd_parm), GFP_ATOMIC); - if (!pdrvextra_cmd_parm) { - kfree(ppscmd); - res = _FAIL; - goto exit; - } - - pdrvextra_cmd_parm->ec_id = POWER_SAVING_CTRL_WK_CID; - pdrvextra_cmd_parm->pbuf = NULL; - init_h2fwcmd_w_parm_no_rsp(ppscmd, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); - - res = rtw_enqueue_cmd(pcmdpriv, ppscmd); - -exit: - - return res; -} - -static bool rtw_is_hi_queue_empty(struct adapter *adapter) -{ - int res; - u32 reg; - - res = rtw_read32(adapter, REG_HGQ_INFORMATION, ®); - if (res) - return false; - - return (reg & 0x0000ff00) == 0; -} - -static void rtw_chk_hi_queue_hdl(struct adapter *padapter) -{ - int cnt = 0; - struct sta_info *psta_bmc; - struct sta_priv *pstapriv = &padapter->stapriv; - - psta_bmc = rtw_get_bcmc_stainfo(padapter); - if (!psta_bmc) - return; - - if (psta_bmc->sleepq_len == 0) { - bool val = rtw_is_hi_queue_empty(padapter); - - while (!val) { - msleep(100); - - cnt++; - - if (cnt > 10) - break; - - val = rtw_is_hi_queue_empty(padapter); - } - - if (cnt <= 10) { - pstapriv->tim_bitmap &= ~BIT(0); - pstapriv->sta_dz_bitmap &= ~BIT(0); - - update_beacon(padapter, _TIM_IE_, NULL, false); - } else { /* re check again */ - rtw_chk_hi_queue_cmd(padapter); - } - } -} - -void rtw_chk_hi_queue_cmd(struct adapter *padapter) -{ - struct cmd_obj *ph2c; - struct drvextra_cmd_parm *pdrvextra_cmd_parm; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - - ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC); - if (!ph2c) - return; - - pdrvextra_cmd_parm = kzalloc(sizeof(*pdrvextra_cmd_parm), GFP_ATOMIC); - if (!pdrvextra_cmd_parm) { - kfree(ph2c); - return; - } - - pdrvextra_cmd_parm->ec_id = CHECK_HIQ_WK_CID; - pdrvextra_cmd_parm->type_size = 0; - pdrvextra_cmd_parm->pbuf = NULL; - - init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); - - rtw_enqueue_cmd(pcmdpriv, ph2c); -} - -u8 rtw_c2h_wk_cmd(struct adapter *padapter, u8 *c2h_evt) -{ - struct cmd_obj *ph2c; - struct drvextra_cmd_parm *pdrvextra_cmd_parm; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - u8 res = _SUCCESS; - - ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC); - if (!ph2c) { - res = _FAIL; - goto exit; - } - - pdrvextra_cmd_parm = kzalloc(sizeof(*pdrvextra_cmd_parm), GFP_ATOMIC); - if (!pdrvextra_cmd_parm) { - kfree(ph2c); - res = _FAIL; - goto exit; - } - - pdrvextra_cmd_parm->ec_id = C2H_WK_CID; - pdrvextra_cmd_parm->type_size = c2h_evt ? 16 : 0; - pdrvextra_cmd_parm->pbuf = c2h_evt; - - init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); - - res = rtw_enqueue_cmd(pcmdpriv, ph2c); - -exit: - - return res; -} - -/* C2H event format: - * Field TRIGGER CONTENT CMD_SEQ CMD_LEN CMD_ID - * BITS [127:120] [119:16] [15:8] [7:4] [3:0] - */ -static s32 c2h_evt_read(struct adapter *adapter, u8 *buf) -{ - s32 ret = _FAIL; - struct c2h_evt_hdr *c2h_evt; - int i; - u8 trigger; - - if (!buf) - goto exit; - - ret = rtw_read8(adapter, REG_C2HEVT_CLEAR, &trigger); - if (ret) - return _FAIL; - - if (trigger == C2H_EVT_HOST_CLOSE) - goto exit; /* Not ready */ - else if (trigger != C2H_EVT_FW_CLOSE) - goto clear_evt; /* Not a valid value */ - - c2h_evt = (struct c2h_evt_hdr *)buf; - - memset(c2h_evt, 0, 16); - - ret = rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL, buf); - if (ret) { - ret = _FAIL; - goto clear_evt; - } - - ret = rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL + 1, buf + 1); - if (ret) { - ret = _FAIL; - goto clear_evt; - } - /* Read the content */ - for (i = 0; i < c2h_evt->plen; i++) { - ret = rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL + - sizeof(*c2h_evt) + i, c2h_evt->payload + i); - if (ret) { - ret = _FAIL; - goto clear_evt; - } - } - - ret = _SUCCESS; - -clear_evt: - /* Clear event to notify FW we have read the command. - * If this field isn't clear, the FW won't update the next - * command message. - */ - rtw_write8(adapter, REG_C2HEVT_CLEAR, C2H_EVT_HOST_CLOSE); -exit: - return ret; -} - -static void c2h_evt_hdl(struct adapter *adapter, struct c2h_evt_hdr *c2h_evt, c2h_id_filter filter) -{ - u8 buf[16]; - - if (!c2h_evt) - c2h_evt_read(adapter, buf); -} - -static void c2h_wk_callback(struct work_struct *work) -{ - struct evt_priv *evtpriv = container_of(work, struct evt_priv, c2h_wk); - struct adapter *adapter = container_of(evtpriv, struct adapter, evtpriv); - struct c2h_evt_hdr *c2h_evt; - - evtpriv->c2h_wk_alive = true; - - while (!rtw_cbuf_empty(evtpriv->c2h_queue)) { - c2h_evt = (struct c2h_evt_hdr *)rtw_cbuf_pop(evtpriv->c2h_queue); - if (c2h_evt) { - /* This C2H event is read, clear it */ - rtw_write8(adapter, REG_C2HEVT_CLEAR, C2H_EVT_HOST_CLOSE); - } else { - c2h_evt = kmalloc(16, GFP_KERNEL); - if (c2h_evt) { - /* This C2H event is not read, read & clear now */ - if (c2h_evt_read(adapter, (u8 *)c2h_evt) != _SUCCESS) { - kfree(c2h_evt); - continue; - } - } else { - return; - } - } - - /* Special pointer to trigger c2h_evt_clear only */ - if ((void *)c2h_evt == (void *)evtpriv) - continue; - - if (!c2h_evt_exist(c2h_evt)) { - kfree(c2h_evt); - continue; - } - - /* Enqueue into cmd_thread for others */ - rtw_c2h_wk_cmd(adapter, (u8 *)c2h_evt); - } - - evtpriv->c2h_wk_alive = false; -} - -u8 rtw_drvextra_cmd_hdl(struct adapter *padapter, unsigned char *pbuf) -{ - struct drvextra_cmd_parm *pdrvextra_cmd; - - if (!pbuf) - return H2C_PARAMETERS_ERROR; - - pdrvextra_cmd = (struct drvextra_cmd_parm *)pbuf; - - switch (pdrvextra_cmd->ec_id) { - case DYNAMIC_CHK_WK_CID: - dynamic_chk_wk_hdl(padapter, pdrvextra_cmd->pbuf); - break; - case POWER_SAVING_CTRL_WK_CID: - rtw_ps_processor(padapter); - break; - case LPS_CTRL_WK_CID: - lps_ctrl_wk_hdl(padapter, (u8)pdrvextra_cmd->type_size); - break; - case RTP_TIMER_CFG_WK_CID: - rpt_timer_setting_wk_hdl(padapter, pdrvextra_cmd->type_size); - break; - case ANT_SELECT_WK_CID: - antenna_select_wk_hdl(padapter, pdrvextra_cmd->type_size); - break; - case P2P_PS_WK_CID: - p2p_ps_wk_hdl(padapter, pdrvextra_cmd->type_size); - break; - case P2P_PROTO_WK_CID: - /* Commented by Albert 2011/07/01 */ - /* I used the type_size as the type command */ - p2p_protocol_wk_hdl(padapter, pdrvextra_cmd->type_size); - break; - case CHECK_HIQ_WK_CID: - rtw_chk_hi_queue_hdl(padapter); - break; - case C2H_WK_CID: - c2h_evt_hdl(padapter, (struct c2h_evt_hdr *)pdrvextra_cmd->pbuf, NULL); - break; - default: - break; - } - - if (pdrvextra_cmd->pbuf && pdrvextra_cmd->type_size > 0) - kfree(pdrvextra_cmd->pbuf); - - return H2C_SUCCESS; -} - -void rtw_survey_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - if (pcmd->res != H2C_SUCCESS) { - /* TODO: cancel timer and do timeout handler directly... */ - _set_timer(&pmlmepriv->scan_to_timer, 1); - } - - /* free cmd */ - rtw_free_cmd_obj(pcmd); - -} - -void rtw_disassoc_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - if (pcmd->res != H2C_SUCCESS) { - spin_lock_bh(&pmlmepriv->lock); - set_fwstate(pmlmepriv, _FW_LINKED); - spin_unlock_bh(&pmlmepriv->lock); - - return; - } - - /* clear bridge database */ - nat25_db_cleanup(padapter); - - /* free cmd */ - rtw_free_cmd_obj(pcmd); -} - -void rtw_joinbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - if (pcmd->res != H2C_SUCCESS) { - /* TODO: cancel timer and do timeout handler directly... */ - _set_timer(&pmlmepriv->assoc_timer, 1); - } - - rtw_free_cmd_obj(pcmd); -} - -void rtw_createbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd) -{ - struct sta_info *psta = NULL; - struct wlan_network *pwlan = NULL; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)pcmd->parmbuf; - struct wlan_network *tgt_network = &pmlmepriv->cur_network; - - if (pcmd->res != H2C_SUCCESS) - _set_timer(&pmlmepriv->assoc_timer, 1); - - del_timer_sync(&pmlmepriv->assoc_timer); - - spin_lock_bh(&pmlmepriv->lock); - - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - psta = rtw_get_stainfo(&padapter->stapriv, pnetwork->MacAddress); - if (!psta) { - psta = rtw_alloc_stainfo(&padapter->stapriv, pnetwork->MacAddress); - if (!psta) - goto createbss_cmd_fail; - } - - rtw_indicate_connect(padapter); - } else { - - pwlan = rtw_alloc_network(pmlmepriv); - spin_lock_bh(&pmlmepriv->scanned_queue.lock); - if (!pwlan) { - pwlan = rtw_get_oldest_wlan_network(&pmlmepriv->scanned_queue); - if (!pwlan) { - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - goto createbss_cmd_fail; - } - pwlan->last_scanned = jiffies; - } else { - list_add_tail(&pwlan->list, &pmlmepriv->scanned_queue.queue); - } - - pnetwork->Length = get_wlan_bssid_ex_sz(pnetwork); - memcpy(&pwlan->network, pnetwork, pnetwork->Length); - - memcpy(&tgt_network->network, pnetwork, (get_wlan_bssid_ex_sz(pnetwork))); - - _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); - - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - /* we will set _FW_LINKED when there is one more sat to join us (rtw_stassoc_event_callback) */ - } - -createbss_cmd_fail: - - spin_unlock_bh(&pmlmepriv->lock); - - rtw_free_cmd_obj(pcmd); - -} - -void rtw_setstaKey_cmdrsp_callback(struct adapter *padapter, struct cmd_obj *pcmd) -{ - struct sta_priv *pstapriv = &padapter->stapriv; - struct set_stakey_rsp *psetstakey_rsp = (struct set_stakey_rsp *)(pcmd->rsp); - struct sta_info *psta = rtw_get_stainfo(pstapriv, psetstakey_rsp->addr); - - if (!psta) - goto exit; -exit: - rtw_free_cmd_obj(pcmd); - -} - -void rtw_setassocsta_cmdrsp_callback(struct adapter *padapter, struct cmd_obj *pcmd) -{ - struct sta_priv *pstapriv = &padapter->stapriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct set_assocsta_parm *passocsta_parm = (struct set_assocsta_parm *)(pcmd->parmbuf); - struct set_assocsta_rsp *passocsta_rsp = (struct set_assocsta_rsp *)(pcmd->rsp); - struct sta_info *psta = rtw_get_stainfo(pstapriv, passocsta_parm->addr); - - if (!psta) - goto exit; - - psta->aid = passocsta_rsp->cam_id; - psta->mac_id = passocsta_rsp->cam_id; - - spin_lock_bh(&pmlmepriv->lock); - - if (check_fwstate(pmlmepriv, WIFI_MP_STATE) && check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) - _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); - - set_fwstate(pmlmepriv, _FW_LINKED); - spin_unlock_bh(&pmlmepriv->lock); - -exit: - rtw_free_cmd_obj(pcmd); - -} diff --git a/drivers/staging/r8188eu/core/rtw_efuse.c b/drivers/staging/r8188eu/core/rtw_efuse.c deleted file mode 100644 index df9534dd25cb..000000000000 --- a/drivers/staging/r8188eu/core/rtw_efuse.c +++ /dev/null @@ -1,74 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#define _RTW_EFUSE_C_ - -#include "../include/osdep_service.h" -#include "../include/drv_types.h" -#include "../include/rtw_efuse.h" -#include "../include/rtl8188e_hal.h" - -/* */ -/* Description: */ -/* Execute E-Fuse read byte operation. */ -/* Referred from SD1 Richard. */ -/* */ -/* Assumption: */ -/* 1. Boot from E-Fuse and successfully auto-load. */ -/* 2. PASSIVE_LEVEL (USB interface) */ -/* */ -/* Created by Roger, 2008.10.21. */ -/* */ -void -ReadEFuseByte( - struct adapter *Adapter, - u16 _offset, - u8 *pbuf) -{ - u32 value32; - u8 readbyte; - u16 retry; - int res; - - /* Write Address */ - rtw_write8(Adapter, EFUSE_CTRL + 1, (_offset & 0xff)); - res = rtw_read8(Adapter, EFUSE_CTRL + 2, &readbyte); - if (res) - return; - - rtw_write8(Adapter, EFUSE_CTRL + 2, ((_offset >> 8) & 0x03) | (readbyte & 0xfc)); - - /* Write bit 32 0 */ - res = rtw_read8(Adapter, EFUSE_CTRL + 3, &readbyte); - if (res) - return; - - rtw_write8(Adapter, EFUSE_CTRL + 3, (readbyte & 0x7f)); - - /* Check bit 32 read-ready */ - res = rtw_read32(Adapter, EFUSE_CTRL, &value32); - if (res) - return; - - for (retry = 0; retry < 10000; retry++) { - res = rtw_read32(Adapter, EFUSE_CTRL, &value32); - if (res) - continue; - - if (((value32 >> 24) & 0xff) & 0x80) - break; - } - - /* 20100205 Joseph: Add delay suggested by SD1 Victor. */ - /* This fix the problem that Efuse read error in high temperature condition. */ - /* Designer says that there shall be some delay after ready bit is set, or the */ - /* result will always stay on last data we read. */ - udelay(50); - res = rtw_read32(Adapter, EFUSE_CTRL, &value32); - if (res) - return; - - *pbuf = (u8)(value32 & 0xff); - - /* FIXME: return an error to caller */ -} diff --git a/drivers/staging/r8188eu/core/rtw_fw.c b/drivers/staging/r8188eu/core/rtw_fw.c deleted file mode 100644 index 1e4baf74ecd5..000000000000 --- a/drivers/staging/r8188eu/core/rtw_fw.c +++ /dev/null @@ -1,335 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#include -#include "../include/rtw_fw.h" - -#define MAX_REG_BLOCK_SIZE 196 -#define FW_8188E_START_ADDRESS 0x1000 -#define MAX_PAGE_SIZE 4096 - -#define IS_FW_HEADER_EXIST(_fwhdr) \ - ((le16_to_cpu(_fwhdr->signature) & 0xFFF0) == 0x92C0 || \ - (le16_to_cpu(_fwhdr->signature) & 0xFFF0) == 0x88C0 || \ - (le16_to_cpu(_fwhdr->signature) & 0xFFF0) == 0x2300 || \ - (le16_to_cpu(_fwhdr->signature) & 0xFFF0) == 0x88E0) - -struct rt_firmware_hdr { - __le16 signature; /* 92C0: test chip; 92C, - * 88C0: test chip; 88C1: MP A-cut; - * 92C1: MP A-cut */ - u8 category; /* AP/NIC and USB/PCI */ - u8 function; /* Reserved for different FW function - * indcation, for further use when - * driver needs to download different - * FW for different conditions */ - __le16 version; /* FW Version */ - u8 subversion; /* FW Subversion, default 0x00 */ - u8 rsvd1; - u8 month; /* Release time Month field */ - u8 date; /* Release time Date field */ - u8 hour; /* Release time Hour field */ - u8 minute; /* Release time Minute field */ - __le16 ramcodesize; /* The size of RAM code */ - u8 foundry; - u8 rsvd2; - __le32 svnidx; /* The SVN entry index */ - __le32 rsvd3; - __le32 rsvd4; - __le32 rsvd5; -}; - -static_assert(sizeof(struct rt_firmware_hdr) == 32); - -static void fw_download_enable(struct adapter *padapter, bool enable) -{ - u8 tmp; - int res; - - if (enable) { - /* MCU firmware download enable. */ - res = rtw_read8(padapter, REG_MCUFWDL, &tmp); - if (res) - return; - - rtw_write8(padapter, REG_MCUFWDL, tmp | 0x01); - - /* 8051 reset */ - res = rtw_read8(padapter, REG_MCUFWDL + 2, &tmp); - if (res) - return; - - rtw_write8(padapter, REG_MCUFWDL + 2, tmp & 0xf7); - } else { - /* MCU firmware download disable. */ - res = rtw_read8(padapter, REG_MCUFWDL, &tmp); - if (res) - return; - - rtw_write8(padapter, REG_MCUFWDL, tmp & 0xfe); - - /* Reserved for fw extension. */ - rtw_write8(padapter, REG_MCUFWDL + 1, 0x00); - } -} - -static int block_write(struct adapter *padapter, u8 *buffer, u32 size) -{ - int ret = _SUCCESS; - u32 blocks, block_size, remain; - u32 i, offset, addr; - u8 *data; - - block_size = MAX_REG_BLOCK_SIZE; - - blocks = size / block_size; - remain = size % block_size; - - for (i = 0; i < blocks; i++) { - addr = FW_8188E_START_ADDRESS + i * block_size; - data = buffer + i * block_size; - - if (rtw_writeN(padapter, addr, block_size, data)) - return _FAIL; - } - - if (remain) { - offset = blocks * block_size; - block_size = 8; - - blocks = remain / block_size; - remain = remain % block_size; - - for (i = 0; i < blocks; i++) { - addr = FW_8188E_START_ADDRESS + offset + i * block_size; - data = buffer + offset + i * block_size; - - if (rtw_writeN(padapter, addr, block_size, data)) - return _FAIL; - } - } - - if (remain) { - offset += blocks * block_size; - - /* block size 1 */ - blocks = remain; - - for (i = 0; i < blocks; i++) { - addr = FW_8188E_START_ADDRESS + offset + i; - data = buffer + offset + i; - - ret = rtw_write8(padapter, addr, *data); - if (ret == _FAIL) - goto exit; - } - } - -exit: - return ret; -} - -static int page_write(struct adapter *padapter, u32 page, u8 *buffer, u32 size) -{ - u8 value8; - u8 u8Page = (u8)(page & 0x07); - int res; - - res = rtw_read8(padapter, REG_MCUFWDL + 2, &value8); - if (res) - return _FAIL; - - value8 = (value8 & 0xF8) | u8Page; - rtw_write8(padapter, REG_MCUFWDL + 2, value8); - - return block_write(padapter, buffer, size); -} - -static int write_fw(struct adapter *padapter, u8 *buffer, u32 size) -{ - /* Since we need dynamic decide method of dwonload fw, so we call this function to get chip version. */ - /* We can remove _ReadChipVersion from ReadpadapterInfo8192C later. */ - int ret = _SUCCESS; - u32 pageNums, remainSize; - u32 page, offset; - - pageNums = size / MAX_PAGE_SIZE; - remainSize = size % MAX_PAGE_SIZE; - - for (page = 0; page < pageNums; page++) { - offset = page * MAX_PAGE_SIZE; - ret = page_write(padapter, page, buffer + offset, MAX_PAGE_SIZE); - - if (ret == _FAIL) - goto exit; - } - if (remainSize) { - offset = pageNums * MAX_PAGE_SIZE; - page = pageNums; - ret = page_write(padapter, page, buffer + offset, remainSize); - - if (ret == _FAIL) - goto exit; - } -exit: - return ret; -} - -void rtw_reset_8051(struct adapter *padapter) -{ - u8 val8; - int res; - - res = rtw_read8(padapter, REG_SYS_FUNC_EN + 1, &val8); - if (res) - return; - - rtw_write8(padapter, REG_SYS_FUNC_EN + 1, val8 & (~BIT(2))); - rtw_write8(padapter, REG_SYS_FUNC_EN + 1, val8 | (BIT(2))); -} - -static int fw_free_to_go(struct adapter *padapter) -{ - u32 counter = 0; - u32 value32; - int res; - - /* polling CheckSum report */ - do { - res = rtw_read32(padapter, REG_MCUFWDL, &value32); - if (res) - continue; - - if (value32 & FWDL_CHKSUM_RPT) - break; - } while (counter++ < POLLING_READY_TIMEOUT_COUNT); - - if (counter >= POLLING_READY_TIMEOUT_COUNT) - return _FAIL; - - res = rtw_read32(padapter, REG_MCUFWDL, &value32); - if (res) - return _FAIL; - - value32 |= MCUFWDL_RDY; - value32 &= ~WINTINI_RDY; - rtw_write32(padapter, REG_MCUFWDL, value32); - - rtw_reset_8051(padapter); - - /* polling for FW ready */ - counter = 0; - do { - res = rtw_read32(padapter, REG_MCUFWDL, &value32); - if (!res && value32 & WINTINI_RDY) - return _SUCCESS; - - udelay(5); - } while (counter++ < POLLING_READY_TIMEOUT_COUNT); - - return _FAIL; -} - -static int load_firmware(struct rt_firmware *rtfw, struct device *device) -{ - int ret = _SUCCESS; - const struct firmware *fw; - const char *fw_name = FW_RTL8188EU; - int err = request_firmware(&fw, fw_name, device); - - if (err) { - pr_err("Request firmware failed with error 0x%x\n", err); - ret = _FAIL; - goto exit; - } - if (!fw) { - pr_err("Firmware %s not available\n", fw_name); - ret = _FAIL; - goto exit; - } - - rtfw->data = kmemdup(fw->data, fw->size, GFP_KERNEL); - if (!rtfw->data) { - pr_err("Failed to allocate rtfw->data\n"); - ret = _FAIL; - goto exit; - } - rtfw->size = fw->size; - -exit: - release_firmware(fw); - return ret; -} - -int rtl8188e_firmware_download(struct adapter *padapter) -{ - int ret = _SUCCESS; - u8 reg; - unsigned long fwdl_timeout; - struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); - struct device *device = dvobj_to_dev(dvobj); - struct rt_firmware_hdr *fwhdr = NULL; - u8 *fw_data; - u32 fw_size; - - if (!dvobj->firmware.data) - ret = load_firmware(&dvobj->firmware, device); - if (ret == _FAIL) { - dvobj->firmware.data = NULL; - goto exit; - } - fw_data = dvobj->firmware.data; - fw_size = dvobj->firmware.size; - - fwhdr = (struct rt_firmware_hdr *)dvobj->firmware.data; - - if (IS_FW_HEADER_EXIST(fwhdr)) { - dev_info_once(device, "Firmware Version %d, SubVersion %d, Signature 0x%x\n", - le16_to_cpu(fwhdr->version), fwhdr->subversion, - le16_to_cpu(fwhdr->signature)); - - fw_data = fw_data + sizeof(struct rt_firmware_hdr); - fw_size = fw_size - sizeof(struct rt_firmware_hdr); - } - - /* Suggested by Filen. If 8051 is running in RAM code, driver should inform Fw to reset by itself, */ - /* or it will cause download Fw fail. 2010.02.01. by tynli. */ - ret = rtw_read8(padapter, REG_MCUFWDL, ®); - if (ret) { - ret = _FAIL; - goto exit; - } - - if (reg & RAM_DL_SEL) { /* 8051 RAM code */ - rtw_write8(padapter, REG_MCUFWDL, 0x00); - rtw_reset_8051(padapter); - } - - fw_download_enable(padapter, true); - fwdl_timeout = jiffies + msecs_to_jiffies(500); - do { - /* reset the FWDL chksum */ - ret = rtw_read8(padapter, REG_MCUFWDL, ®); - if (ret) { - ret = _FAIL; - continue; - } - - rtw_write8(padapter, REG_MCUFWDL, reg | FWDL_CHKSUM_RPT); - - ret = write_fw(padapter, fw_data, fw_size); - if (ret == _SUCCESS) - break; - } while (!time_after(jiffies, fwdl_timeout)); - - fw_download_enable(padapter, false); - if (ret != _SUCCESS) - goto exit; - - ret = fw_free_to_go(padapter); - if (ret != _SUCCESS) - goto exit; - -exit: - return ret; -} diff --git a/drivers/staging/r8188eu/core/rtw_ieee80211.c b/drivers/staging/r8188eu/core/rtw_ieee80211.c deleted file mode 100644 index bc8543ea2e66..000000000000 --- a/drivers/staging/r8188eu/core/rtw_ieee80211.c +++ /dev/null @@ -1,1150 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#define _IEEE80211_C - -#include "../include/drv_types.h" -#include "../include/ieee80211.h" -#include "../include/wifi.h" -#include "../include/osdep_service.h" -#include "../include/wlan_bssdef.h" -#include "../include/usb_osintf.h" - -u8 RTW_WPA_OUI_TYPE[] = { 0x00, 0x50, 0xf2, 1 }; -u16 RTW_WPA_VERSION = 1; -u8 WPA_AUTH_KEY_MGMT_NONE[] = { 0x00, 0x50, 0xf2, 0 }; -u8 WPA_AUTH_KEY_MGMT_UNSPEC_802_1X[] = { 0x00, 0x50, 0xf2, 1 }; -u8 WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X[] = { 0x00, 0x50, 0xf2, 2 }; -u8 WPA_CIPHER_SUITE_NONE[] = { 0x00, 0x50, 0xf2, 0 }; -u8 WPA_CIPHER_SUITE_WEP40[] = { 0x00, 0x50, 0xf2, 1 }; -u8 WPA_CIPHER_SUITE_TKIP[] = { 0x00, 0x50, 0xf2, 2 }; -u8 WPA_CIPHER_SUITE_WRAP[] = { 0x00, 0x50, 0xf2, 3 }; -u8 WPA_CIPHER_SUITE_CCMP[] = { 0x00, 0x50, 0xf2, 4 }; -u8 WPA_CIPHER_SUITE_WEP104[] = { 0x00, 0x50, 0xf2, 5 }; - -u16 RSN_VERSION_BSD = 1; -u8 RSN_AUTH_KEY_MGMT_UNSPEC_802_1X[] = { 0x00, 0x0f, 0xac, 1 }; -u8 RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X[] = { 0x00, 0x0f, 0xac, 2 }; -u8 RSN_CIPHER_SUITE_NONE[] = { 0x00, 0x0f, 0xac, 0 }; -u8 RSN_CIPHER_SUITE_WEP40[] = { 0x00, 0x0f, 0xac, 1 }; -u8 RSN_CIPHER_SUITE_TKIP[] = { 0x00, 0x0f, 0xac, 2 }; -u8 RSN_CIPHER_SUITE_WRAP[] = { 0x00, 0x0f, 0xac, 3 }; -u8 RSN_CIPHER_SUITE_CCMP[] = { 0x00, 0x0f, 0xac, 4 }; -u8 RSN_CIPHER_SUITE_WEP104[] = { 0x00, 0x0f, 0xac, 5 }; -/* */ -/* for adhoc-master to generate ie and provide supported-rate to fw */ -/* */ - -static u8 WIFI_CCKRATES[] = { - (IEEE80211_CCK_RATE_1MB | IEEE80211_BASIC_RATE_MASK), - (IEEE80211_CCK_RATE_2MB | IEEE80211_BASIC_RATE_MASK), - (IEEE80211_CCK_RATE_5MB | IEEE80211_BASIC_RATE_MASK), - (IEEE80211_CCK_RATE_11MB | IEEE80211_BASIC_RATE_MASK) - }; - -static u8 WIFI_OFDMRATES[] = { - (IEEE80211_OFDM_RATE_6MB), - (IEEE80211_OFDM_RATE_9MB), - (IEEE80211_OFDM_RATE_12MB), - (IEEE80211_OFDM_RATE_18MB), - (IEEE80211_OFDM_RATE_24MB), - IEEE80211_OFDM_RATE_36MB, - IEEE80211_OFDM_RATE_48MB, - IEEE80211_OFDM_RATE_54MB - }; - -int rtw_get_bit_value_from_ieee_value(u8 val) -{ - unsigned char dot11_rate_table[] = { - 2, 4, 11, 22, 12, 18, 24, 36, 48, - 72, 96, 108, 0}; /* last element must be zero!! */ - - int i = 0; - while (dot11_rate_table[i] != 0) { - if (dot11_rate_table[i] == val) - return BIT(i); - i++; - } - return 0; -} - -bool rtw_is_cckrates_included(u8 *rate) -{ - u32 i = 0; - - while (rate[i] != 0) { - if ((((rate[i]) & 0x7f) == 2) || (((rate[i]) & 0x7f) == 4) || - (((rate[i]) & 0x7f) == 11) || (((rate[i]) & 0x7f) == 22)) - return true; - i++; - } - return false; -} - -bool rtw_is_cckratesonly_included(u8 *rate) -{ - u32 i = 0; - - while (rate[i] != 0) { - if ((((rate[i]) & 0x7f) != 2) && (((rate[i]) & 0x7f) != 4) && - (((rate[i]) & 0x7f) != 11) && (((rate[i]) & 0x7f) != 22)) - return false; - i++; - } - - return true; -} - -int rtw_check_network_type(unsigned char *rate, int ratelen, int channel) -{ - if (channel > 14) - return WIRELESS_INVALID; - /* could be pure B, pure G, or B/G */ - if (rtw_is_cckratesonly_included(rate)) - return WIRELESS_11B; - else if (rtw_is_cckrates_included(rate)) - return WIRELESS_11BG; - else - return WIRELESS_11G; -} - -u8 *rtw_set_fixed_ie(unsigned char *pbuf, unsigned int len, unsigned char *source, - unsigned int *frlen) -{ - memcpy((void *)pbuf, (void *)source, len); - *frlen = *frlen + len; - return pbuf + len; -} - -/* rtw_set_ie will update frame length */ -u8 *rtw_set_ie -( - u8 *pbuf, - int index, - uint len, - u8 *source, - uint *frlen /* frame length */ -) -{ - - *pbuf = (u8)index; - - *(pbuf + 1) = (u8)len; - - if (len > 0) - memcpy((void *)(pbuf + 2), (void *)source, len); - - *frlen = *frlen + (len + 2); - - return pbuf + len + 2; -} - -/*---------------------------------------------------------------------------- -index: the information element id index, limit is the limit for search ------------------------------------------------------------------------------*/ -u8 *rtw_get_ie(u8 *pbuf, int index, int *len, int limit) -{ - int tmp, i; - u8 *p; - - if (limit < 1) { - - return NULL; - } - - p = pbuf; - i = 0; - *len = 0; - while (1) { - if (*p == index) { - *len = *(p + 1); - return p; - } - tmp = *(p + 1); - p += (tmp + 2); - i += (tmp + 2); - if (i >= limit) - break; - } - - return NULL; -} - -void rtw_set_supported_rate(u8 *SupportedRates, uint mode) -{ - - memset(SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX); - - switch (mode) { - case WIRELESS_11B: - memcpy(SupportedRates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN); - break; - case WIRELESS_11G: - memcpy(SupportedRates, WIFI_OFDMRATES, IEEE80211_NUM_OFDM_RATESLEN); - break; - case WIRELESS_11BG: - case WIRELESS_11G_24N: - case WIRELESS_11_24N: - case WIRELESS_11BG_24N: - memcpy(SupportedRates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN); - memcpy(SupportedRates + IEEE80211_CCK_RATE_LEN, WIFI_OFDMRATES, IEEE80211_NUM_OFDM_RATESLEN); - break; - } - -} - -uint rtw_get_rateset_len(u8 *rateset) -{ - uint i = 0; - - while (1) { - if ((rateset[i]) == 0) - break; - if (i > 12) - break; - i++; - } - - return i; -} - -int rtw_generate_ie(struct registry_priv *pregistrypriv) -{ - u8 wireless_mode; - int sz = 0, rateLen; - struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network; - u8 *ie = pdev_network->IEs; - - /* timestamp will be inserted by hardware */ - sz += 8; - ie += sz; - - /* beacon interval : 2bytes */ - *(__le16 *)ie = cpu_to_le16((u16)pdev_network->Configuration.BeaconPeriod);/* BCN_INTERVAL; */ - sz += 2; - ie += 2; - - /* capability info */ - *(u16 *)ie = 0; - - *(__le16 *)ie |= cpu_to_le16(cap_IBSS); - - if (pregistrypriv->preamble == PREAMBLE_SHORT) - *(__le16 *)ie |= cpu_to_le16(cap_ShortPremble); - - if (pdev_network->Privacy) - *(__le16 *)ie |= cpu_to_le16(cap_Privacy); - - sz += 2; - ie += 2; - - /* SSID */ - ie = rtw_set_ie(ie, _SSID_IE_, pdev_network->Ssid.SsidLength, pdev_network->Ssid.Ssid, &sz); - - /* supported rates */ - wireless_mode = pregistrypriv->wireless_mode; - - rtw_set_supported_rate(pdev_network->SupportedRates, wireless_mode); - - rateLen = rtw_get_rateset_len(pdev_network->SupportedRates); - - if (rateLen > 8) { - ie = rtw_set_ie(ie, _SUPPORTEDRATES_IE_, 8, pdev_network->SupportedRates, &sz); - /* ie = rtw_set_ie(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8), (pdev_network->SupportedRates + 8), &sz); */ - } else { - ie = rtw_set_ie(ie, _SUPPORTEDRATES_IE_, rateLen, pdev_network->SupportedRates, &sz); - } - - /* DS parameter set */ - ie = rtw_set_ie(ie, _DSSET_IE_, 1, (u8 *)&pdev_network->Configuration.DSConfig, &sz); - - /* IBSS Parameter Set */ - - ie = rtw_set_ie(ie, _IBSS_PARA_IE_, 2, (u8 *)&pdev_network->Configuration.ATIMWindow, &sz); - - if (rateLen > 8) - ie = rtw_set_ie(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8), (pdev_network->SupportedRates + 8), &sz); - - return sz; -} - -unsigned char *rtw_get_wpa_ie(unsigned char *pie, int *wpa_ie_len, int limit) -{ - int len; - u16 val16; - __le16 le_tmp; - unsigned char wpa_oui_type[] = {0x00, 0x50, 0xf2, 0x01}; - u8 *pbuf = pie; - int limit_new = limit; - - while (1) { - pbuf = rtw_get_ie(pbuf, _WPA_IE_ID_, &len, limit_new); - - if (pbuf) { - /* check if oui matches... */ - if (memcmp((pbuf + 2), wpa_oui_type, sizeof(wpa_oui_type))) - goto check_next_ie; - - /* check version... */ - memcpy((u8 *)&le_tmp, (pbuf + 6), sizeof(val16)); - - val16 = le16_to_cpu(le_tmp); - if (val16 != 0x0001) - goto check_next_ie; - *wpa_ie_len = *(pbuf + 1); - return pbuf; - } - *wpa_ie_len = 0; - return NULL; - -check_next_ie: - limit_new = limit - (pbuf - pie) - 2 - len; - if (limit_new <= 0) - break; - pbuf += (2 + len); - } - *wpa_ie_len = 0; - return NULL; -} - -unsigned char *rtw_get_wpa2_ie(unsigned char *pie, int *rsn_ie_len, int limit) -{ - - return rtw_get_ie(pie, _WPA2_IE_ID_, rsn_ie_len, limit); -} - -int rtw_get_wpa_cipher_suite(u8 *s) -{ - if (!memcmp(s, WPA_CIPHER_SUITE_NONE, WPA_SELECTOR_LEN)) - return WPA_CIPHER_NONE; - if (!memcmp(s, WPA_CIPHER_SUITE_WEP40, WPA_SELECTOR_LEN)) - return WPA_CIPHER_WEP40; - if (!memcmp(s, WPA_CIPHER_SUITE_TKIP, WPA_SELECTOR_LEN)) - return WPA_CIPHER_TKIP; - if (!memcmp(s, WPA_CIPHER_SUITE_CCMP, WPA_SELECTOR_LEN)) - return WPA_CIPHER_CCMP; - if (!memcmp(s, WPA_CIPHER_SUITE_WEP104, WPA_SELECTOR_LEN)) - return WPA_CIPHER_WEP104; - - return 0; -} - -int rtw_get_wpa2_cipher_suite(u8 *s) -{ - if (!memcmp(s, RSN_CIPHER_SUITE_NONE, RSN_SELECTOR_LEN)) - return WPA_CIPHER_NONE; - if (!memcmp(s, RSN_CIPHER_SUITE_WEP40, RSN_SELECTOR_LEN)) - return WPA_CIPHER_WEP40; - if (!memcmp(s, RSN_CIPHER_SUITE_TKIP, RSN_SELECTOR_LEN)) - return WPA_CIPHER_TKIP; - if (!memcmp(s, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN)) - return WPA_CIPHER_CCMP; - if (!memcmp(s, RSN_CIPHER_SUITE_WEP104, RSN_SELECTOR_LEN)) - return WPA_CIPHER_WEP104; - - return 0; -} - -int rtw_parse_wpa_ie(u8 *wpa_ie, int wpa_ie_len, int *group_cipher, int *pairwise_cipher, int *is_8021x) -{ - int i, ret = _SUCCESS; - int left, count; - u8 *pos; - u8 SUITE_1X[4] = {0x00, 0x50, 0xf2, 1}; - - if (wpa_ie_len <= 0) { - /* No WPA IE - fail silently */ - return _FAIL; - } - - if ((*wpa_ie != _WPA_IE_ID_) || (*(wpa_ie + 1) != (u8)(wpa_ie_len - 2)) || - (memcmp(wpa_ie + 2, RTW_WPA_OUI_TYPE, WPA_SELECTOR_LEN))) - return _FAIL; - - pos = wpa_ie; - - pos += 8; - left = wpa_ie_len - 8; - - /* group_cipher */ - if (left >= WPA_SELECTOR_LEN) { - *group_cipher = rtw_get_wpa_cipher_suite(pos); - pos += WPA_SELECTOR_LEN; - left -= WPA_SELECTOR_LEN; - } else if (left > 0) { - return _FAIL; - } - - /* pairwise_cipher */ - if (left >= 2) { - count = get_unaligned_le16(pos); - pos += 2; - left -= 2; - - if (count == 0 || left < count * WPA_SELECTOR_LEN) - return _FAIL; - - for (i = 0; i < count; i++) { - *pairwise_cipher |= rtw_get_wpa_cipher_suite(pos); - - pos += WPA_SELECTOR_LEN; - left -= WPA_SELECTOR_LEN; - } - } else if (left == 1) { - return _FAIL; - } - - if (is_8021x) { - if (left >= 6) { - pos += 2; - if (!memcmp(pos, SUITE_1X, 4)) - *is_8021x = 1; - } - } - - return ret; -} - -int rtw_parse_wpa2_ie(u8 *rsn_ie, int rsn_ie_len, int *group_cipher, int *pairwise_cipher, int *is_8021x) -{ - int i, ret = _SUCCESS; - int left, count; - u8 *pos; - u8 SUITE_1X[4] = {0x00, 0x0f, 0xac, 0x01}; - - if (rsn_ie_len <= 0) { - /* No RSN IE - fail silently */ - return _FAIL; - } - - if ((*rsn_ie != _WPA2_IE_ID_) || (*(rsn_ie + 1) != (u8)(rsn_ie_len - 2))) - return _FAIL; - - pos = rsn_ie; - pos += 4; - left = rsn_ie_len - 4; - - /* group_cipher */ - if (left >= RSN_SELECTOR_LEN) { - *group_cipher = rtw_get_wpa2_cipher_suite(pos); - - pos += RSN_SELECTOR_LEN; - left -= RSN_SELECTOR_LEN; - - } else if (left > 0) { - return _FAIL; - } - - /* pairwise_cipher */ - if (left >= 2) { - count = get_unaligned_le16(pos); - pos += 2; - left -= 2; - - if (count == 0 || left < count * RSN_SELECTOR_LEN) - return _FAIL; - - for (i = 0; i < count; i++) { - *pairwise_cipher |= rtw_get_wpa2_cipher_suite(pos); - - pos += RSN_SELECTOR_LEN; - left -= RSN_SELECTOR_LEN; - } - - } else if (left == 1) { - return _FAIL; - } - - if (is_8021x) { - if (left >= 6) { - pos += 2; - if (!memcmp(pos, SUITE_1X, 4)) - *is_8021x = 1; - } - } - return ret; -} - -int rtw_get_sec_ie(u8 *in_ie, uint in_len, u8 *rsn_ie, u16 *rsn_len, u8 *wpa_ie, u16 *wpa_len) -{ - u8 authmode; - u8 wpa_oui[4] = {0x0, 0x50, 0xf2, 0x01}; - uint cnt; - - /* Search required WPA or WPA2 IE and copy to sec_ie[] */ - - cnt = (_TIMESTAMP_ + _BEACON_ITERVAL_ + _CAPABILITY_); - - while (cnt < in_len) { - authmode = in_ie[cnt]; - - if ((authmode == _WPA_IE_ID_) && (!memcmp(&in_ie[cnt + 2], &wpa_oui[0], 4))) { - if (wpa_ie) - memcpy(wpa_ie, &in_ie[cnt], in_ie[cnt + 1] + 2); - - *wpa_len = in_ie[cnt + 1] + 2; - cnt += in_ie[cnt + 1] + 2; /* get next */ - } else { - if (authmode == _WPA2_IE_ID_) { - if (rsn_ie) - memcpy(rsn_ie, &in_ie[cnt], in_ie[cnt + 1] + 2); - - *rsn_len = in_ie[cnt + 1] + 2; - cnt += in_ie[cnt + 1] + 2; /* get next */ - } else { - cnt += in_ie[cnt + 1] + 2; /* get next */ - } - } - } - - return *rsn_len + *wpa_len; -} - -u8 rtw_is_wps_ie(u8 *ie_ptr, uint *wps_ielen) -{ - u8 match = false; - u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04}; - - if (!ie_ptr) - return match; - - eid = ie_ptr[0]; - - if ((eid == _WPA_IE_ID_) && (!memcmp(&ie_ptr[2], wps_oui, 4))) { - *wps_ielen = ie_ptr[1] + 2; - match = true; - } - return match; -} - -/** - * rtw_get_wps_ie - Search WPS IE from a series of IEs - * @in_ie: Address of IEs to search - * @in_len: Length limit from in_ie - * @wps_ie: If not NULL and WPS IE is found, WPS IE will be copied to the buf starting from wps_ie - * @wps_ielen: If not NULL and WPS IE is found, will set to the length of the entire WPS IE - * - * Returns: The address of the WPS IE found, or NULL - */ -u8 *rtw_get_wps_ie(u8 *in_ie, uint in_len, u8 *wps_ie, uint *wps_ielen) -{ - uint cnt; - u8 *wpsie_ptr = NULL; - u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04}; - - if (wps_ielen) - *wps_ielen = 0; - - if (!in_ie || in_len <= 0) - return wpsie_ptr; - - cnt = 0; - - while (cnt < in_len) { - eid = in_ie[cnt]; - - if ((eid == _WPA_IE_ID_) && (!memcmp(&in_ie[cnt + 2], wps_oui, 4))) { - wpsie_ptr = &in_ie[cnt]; - - if (wps_ie) - memcpy(wps_ie, &in_ie[cnt], in_ie[cnt + 1] + 2); - - if (wps_ielen) - *wps_ielen = in_ie[cnt + 1] + 2; - - cnt += in_ie[cnt + 1] + 2; - - break; - } - cnt += in_ie[cnt + 1] + 2; /* goto next */ - } - return wpsie_ptr; -} - -/** - * rtw_get_wps_attr - Search a specific WPS attribute from a given WPS IE - * @wps_ie: Address of WPS IE to search - * @wps_ielen: Length limit from wps_ie - * @target_attr_id: The attribute ID of WPS attribute to search - * @buf_attr: If not NULL and the WPS attribute is found, WPS attribute will be copied to the buf starting from buf_attr - * @len_attr: If not NULL and the WPS attribute is found, will set to the length of the entire WPS attribute - * - * Returns: the address of the specific WPS attribute found, or NULL - */ -u8 *rtw_get_wps_attr(u8 *wps_ie, uint wps_ielen, u16 target_attr_id, u8 *buf_attr, u32 *len_attr) -{ - u8 *attr_ptr = NULL; - u8 *target_attr_ptr = NULL; - u8 wps_oui[4] = {0x00, 0x50, 0xF2, 0x04}; - - if (len_attr) - *len_attr = 0; - - if ((wps_ie[0] != _VENDOR_SPECIFIC_IE_) || - (memcmp(wps_ie + 2, wps_oui, 4))) - return attr_ptr; - - /* 6 = 1(Element ID) + 1(Length) + 4(WPS OUI) */ - attr_ptr = wps_ie + 6; /* goto first attr */ - - while (attr_ptr - wps_ie < wps_ielen) { - /* 4 = 2(Attribute ID) + 2(Length) */ - u16 attr_id = RTW_GET_BE16(attr_ptr); - u16 attr_data_len = RTW_GET_BE16(attr_ptr + 2); - u16 attr_len = attr_data_len + 4; - - if (attr_id == target_attr_id) { - target_attr_ptr = attr_ptr; - if (buf_attr) - memcpy(buf_attr, attr_ptr, attr_len); - if (len_attr) - *len_attr = attr_len; - break; - } - attr_ptr += attr_len; /* goto next */ - } - return target_attr_ptr; -} - -/** - * rtw_get_wps_attr_content - Search a specific WPS attribute content from a given WPS IE - * @wps_ie: Address of WPS IE to search - * @wps_ielen: Length limit from wps_ie - * @target_attr_id: The attribute ID of WPS attribute to search - * @buf_content: If not NULL and the WPS attribute is found, WPS attribute content will be copied to the buf starting from buf_content - * @len_content: If not NULL and the WPS attribute is found, will set to the length of the WPS attribute content - * - * Returns: the address of the specific WPS attribute content found, or NULL - */ -u8 *rtw_get_wps_attr_content(u8 *wps_ie, uint wps_ielen, u16 target_attr_id, u8 *buf_content, uint *len_content) -{ - u8 *attr_ptr; - u32 attr_len; - - if (len_content) - *len_content = 0; - - attr_ptr = rtw_get_wps_attr(wps_ie, wps_ielen, target_attr_id, NULL, &attr_len); - - if (attr_ptr && attr_len) { - if (buf_content) - memcpy(buf_content, attr_ptr + 4, attr_len - 4); - - if (len_content) - *len_content = attr_len - 4; - - return attr_ptr + 4; - } - - return NULL; -} - -static int rtw_ieee802_11_parse_vendor_specific(u8 *pos, uint elen, - struct rtw_ieee802_11_elems *elems, - int show_errors) -{ - unsigned int oui; - - /* first 3 bytes in vendor specific information element are the IEEE - * OUI of the vendor. The following byte is used a vendor specific - * sub-type. */ - if (elen < 4) - return -1; - - oui = RTW_GET_BE24(pos); - switch (oui) { - case OUI_MICROSOFT: - /* Microsoft/Wi-Fi information elements are further typed and - * subtyped */ - switch (pos[3]) { - case 1: - /* Microsoft OUI (00:50:F2) with OUI Type 1: - * real WPA information element */ - elems->wpa_ie = pos; - elems->wpa_ie_len = elen; - break; - case WME_OUI_TYPE: /* this is a Wi-Fi WME info. element */ - if (elen < 5) - return -1; - switch (pos[4]) { - case WME_OUI_SUBTYPE_INFORMATION_ELEMENT: - case WME_OUI_SUBTYPE_PARAMETER_ELEMENT: - elems->wme = pos; - elems->wme_len = elen; - break; - case WME_OUI_SUBTYPE_TSPEC_ELEMENT: - elems->wme_tspec = pos; - elems->wme_tspec_len = elen; - break; - default: - return -1; - } - break; - case 4: - /* Wi-Fi Protected Setup (WPS) IE */ - elems->wps_ie = pos; - elems->wps_ie_len = elen; - break; - default: - return -1; - } - break; - - case OUI_BROADCOM: - switch (pos[3]) { - case VENDOR_HT_CAPAB_OUI_TYPE: - elems->vendor_ht_cap = pos; - elems->vendor_ht_cap_len = elen; - break; - default: - return -1; - } - break; - default: - return -1; - } - return 0; -} - -/** - * ieee802_11_parse_elems - Parse information elements in management frames - * @start: Pointer to the start of IEs - * @len: Length of IE buffer in octets - * @elems: Data structure for parsed elements - * @show_errors: Whether to show parsing errors in debug log - * Returns: Parsing result - */ -enum parse_res rtw_ieee802_11_parse_elems(u8 *start, uint len, - struct rtw_ieee802_11_elems *elems, - int show_errors) -{ - uint left = len; - u8 *pos = start; - int unknown = 0; - - memset(elems, 0, sizeof(*elems)); - - while (left >= 2) { - u8 id, elen; - - id = *pos++; - elen = *pos++; - left -= 2; - - if (elen > left) - return ParseFailed; - - switch (id) { - case WLAN_EID_SSID: - elems->ssid = pos; - elems->ssid_len = elen; - break; - case WLAN_EID_SUPP_RATES: - elems->supp_rates = pos; - elems->supp_rates_len = elen; - break; - case WLAN_EID_FH_PARAMS: - elems->fh_params = pos; - elems->fh_params_len = elen; - break; - case WLAN_EID_DS_PARAMS: - elems->ds_params = pos; - elems->ds_params_len = elen; - break; - case WLAN_EID_CF_PARAMS: - elems->cf_params = pos; - elems->cf_params_len = elen; - break; - case WLAN_EID_TIM: - elems->tim = pos; - elems->tim_len = elen; - break; - case WLAN_EID_IBSS_PARAMS: - elems->ibss_params = pos; - elems->ibss_params_len = elen; - break; - case WLAN_EID_CHALLENGE: - elems->challenge = pos; - elems->challenge_len = elen; - break; - case WLAN_EID_ERP_INFO: - elems->erp_info = pos; - elems->erp_info_len = elen; - break; - case WLAN_EID_EXT_SUPP_RATES: - elems->ext_supp_rates = pos; - elems->ext_supp_rates_len = elen; - break; - case WLAN_EID_VENDOR_SPECIFIC: - if (rtw_ieee802_11_parse_vendor_specific(pos, elen, elems, show_errors)) - unknown++; - break; - case WLAN_EID_RSN: - elems->rsn_ie = pos; - elems->rsn_ie_len = elen; - break; - case WLAN_EID_PWR_CAPABILITY: - elems->power_cap = pos; - elems->power_cap_len = elen; - break; - case WLAN_EID_SUPPORTED_CHANNELS: - elems->supp_channels = pos; - elems->supp_channels_len = elen; - break; - case WLAN_EID_MOBILITY_DOMAIN: - elems->mdie = pos; - elems->mdie_len = elen; - break; - case WLAN_EID_FAST_BSS_TRANSITION: - elems->ftie = pos; - elems->ftie_len = elen; - break; - case WLAN_EID_TIMEOUT_INTERVAL: - elems->timeout_int = pos; - elems->timeout_int_len = elen; - break; - case WLAN_EID_HT_CAP: - elems->ht_capabilities = pos; - elems->ht_capabilities_len = elen; - break; - case WLAN_EID_HT_OPERATION: - elems->ht_operation = pos; - elems->ht_operation_len = elen; - break; - default: - unknown++; - break; - } - left -= elen; - pos += elen; - } - if (left) - return ParseFailed; - return unknown ? ParseUnknown : ParseOK; -} - -u8 key_char2num(u8 ch) -{ - if ((ch >= '0') && (ch <= '9')) - return ch - '0'; - else if ((ch >= 'a') && (ch <= 'f')) - return ch - 'a' + 10; - else if ((ch >= 'A') && (ch <= 'F')) - return ch - 'A' + 10; - else - return 0xff; -} - -u8 str_2char2num(u8 hch, u8 lch) -{ - return (key_char2num(hch) * 10) + key_char2num(lch); -} - -u8 key_2char2num(u8 hch, u8 lch) -{ - return (key_char2num(hch) << 4) | key_char2num(lch); -} - -void rtw_macaddr_cfg(u8 *mac_addr) -{ - u8 mac[ETH_ALEN]; - - if (!mac_addr) - return; - - if (rtw_initmac && mac_pton(rtw_initmac, mac)) { - /* Users specify the mac address */ - ether_addr_copy(mac_addr, mac); - } else { - /* Use the mac address stored in the Efuse */ - ether_addr_copy(mac, mac_addr); - } - - if (is_broadcast_ether_addr(mac) || is_zero_ether_addr(mac)) - eth_random_addr(mac_addr); -} - -/** - * rtw_get_p2p_ie - Search P2P IE from a series of IEs - * @in_ie: Address of IEs to search - * @in_len: Length limit from in_ie - * @p2p_ie: If not NULL and P2P IE is found, P2P IE will be copied to the buf starting from p2p_ie - * @p2p_ielen: If not NULL and P2P IE is found, will set to the length of the entire P2P IE - * - * Returns: The address of the P2P IE found, or NULL - */ -u8 *rtw_get_p2p_ie(u8 *in_ie, int in_len, u8 *p2p_ie, uint *p2p_ielen) -{ - uint cnt = 0; - u8 *p2p_ie_ptr; - u8 eid, p2p_oui[4] = {0x50, 0x6F, 0x9A, 0x09}; - - if (p2p_ielen) - *p2p_ielen = 0; - - while (cnt < in_len) { - eid = in_ie[cnt]; - if ((in_len < 0) || (cnt > MAX_IE_SZ)) { - dump_stack(); - return NULL; - } - if ((eid == _VENDOR_SPECIFIC_IE_) && !memcmp(&in_ie[cnt + 2], p2p_oui, 4)) { - p2p_ie_ptr = in_ie + cnt; - - if (p2p_ie) - memcpy(p2p_ie, &in_ie[cnt], in_ie[cnt + 1] + 2); - if (p2p_ielen) - *p2p_ielen = in_ie[cnt + 1] + 2; - return p2p_ie_ptr; - } - cnt += in_ie[cnt + 1] + 2; /* goto next */ - } - return NULL; -} - -/** - * rtw_get_p2p_attr - Search a specific P2P attribute from a given P2P IE - * @p2p_ie: Address of P2P IE to search - * @p2p_ielen: Length limit from p2p_ie - * @target_attr_id: The attribute ID of P2P attribute to search - * @buf_attr: If not NULL and the P2P attribute is found, P2P attribute will be copied to the buf starting from buf_attr - * @len_attr: If not NULL and the P2P attribute is found, will set to the length of the entire P2P attribute - * - * Returns: the address of the specific WPS attribute found, or NULL - */ -u8 *rtw_get_p2p_attr(u8 *p2p_ie, uint p2p_ielen, u8 target_attr_id, u8 *buf_attr, u32 *len_attr) -{ - u8 *attr_ptr = NULL; - u8 *target_attr_ptr = NULL; - u8 p2p_oui[4] = {0x50, 0x6F, 0x9A, 0x09}; - - if (len_attr) - *len_attr = 0; - - if (!p2p_ie || (p2p_ie[0] != _VENDOR_SPECIFIC_IE_) || - memcmp(p2p_ie + 2, p2p_oui, 4)) - return attr_ptr; - - /* 6 = 1(Element ID) + 1(Length) + 3 (OUI) + 1(OUI Type) */ - attr_ptr = p2p_ie + 6; /* goto first attr */ - - while (attr_ptr - p2p_ie < p2p_ielen) { - /* 3 = 1(Attribute ID) + 2(Length) */ - u8 attr_id = *attr_ptr; - u16 attr_data_len = get_unaligned_le16(attr_ptr + 1); - u16 attr_len = attr_data_len + 3; - - if (attr_id == target_attr_id) { - target_attr_ptr = attr_ptr; - - if (buf_attr) - memcpy(buf_attr, attr_ptr, attr_len); - if (len_attr) - *len_attr = attr_len; - break; - } - attr_ptr += attr_len; /* goto next */ - } - return target_attr_ptr; -} - -/** - * rtw_get_p2p_attr_content - Search a specific P2P attribute content from a given P2P IE - * @p2p_ie: Address of P2P IE to search - * @p2p_ielen: Length limit from p2p_ie - * @target_attr_id: The attribute ID of P2P attribute to search - * @buf_content: If not NULL and the P2P attribute is found, P2P attribute content will be copied to the buf starting from buf_content - * @len_content: If not NULL and the P2P attribute is found, will set to the length of the P2P attribute content - * - * Returns: the address of the specific P2P attribute content found, or NULL - */ -u8 *rtw_get_p2p_attr_content(u8 *p2p_ie, uint p2p_ielen, u8 target_attr_id, u8 *buf_content, uint *len_content) -{ - u8 *attr_ptr; - u32 attr_len; - - if (len_content) - *len_content = 0; - - attr_ptr = rtw_get_p2p_attr(p2p_ie, p2p_ielen, target_attr_id, NULL, &attr_len); - - if (attr_ptr && attr_len) { - if (buf_content) - memcpy(buf_content, attr_ptr + 3, attr_len - 3); - - if (len_content) - *len_content = attr_len - 3; - - return attr_ptr + 3; - } - - return NULL; -} - -u32 rtw_set_p2p_attr_content(u8 *pbuf, u8 attr_id, u16 attr_len, u8 *pdata_attr) -{ - u32 a_len; - - *pbuf = attr_id; - - /* u16*)(pbuf + 1) = cpu_to_le16(attr_len); */ - RTW_PUT_LE16(pbuf + 1, attr_len); - - if (pdata_attr) - memcpy(pbuf + 3, pdata_attr, attr_len); - - a_len = attr_len + 3; - - return a_len; -} - -static uint rtw_p2p_attr_remove(u8 *ie, uint ielen_ori, u8 attr_id) -{ - u8 *target_attr; - u32 target_attr_len; - uint ielen = ielen_ori; - - while (1) { - target_attr = rtw_get_p2p_attr(ie, ielen, attr_id, NULL, &target_attr_len); - if (target_attr && target_attr_len) { - u8 *next_attr = target_attr + target_attr_len; - uint remain_len = ielen - (next_attr - ie); - - memset(target_attr, 0, target_attr_len); - memcpy(target_attr, next_attr, remain_len); - memset(target_attr + remain_len, 0, target_attr_len); - *(ie + 1) -= target_attr_len; - ielen -= target_attr_len; - } else { - break; - } - } - return ielen; -} - -void rtw_wlan_bssid_ex_remove_p2p_attr(struct wlan_bssid_ex *bss_ex, u8 attr_id) -{ - u8 *p2p_ie; - uint p2p_ielen, p2p_ielen_ori; - - p2p_ie = rtw_get_p2p_ie(bss_ex->IEs + _FIXED_IE_LENGTH_, bss_ex->IELength - _FIXED_IE_LENGTH_, NULL, &p2p_ielen_ori); - if (p2p_ie) { - p2p_ielen = rtw_p2p_attr_remove(p2p_ie, p2p_ielen_ori, attr_id); - if (p2p_ielen != p2p_ielen_ori) { - u8 *next_ie_ori = p2p_ie + p2p_ielen_ori; - u8 *next_ie = p2p_ie + p2p_ielen; - uint remain_len = bss_ex->IELength - (next_ie_ori - bss_ex->IEs); - - memcpy(next_ie, next_ie_ori, remain_len); - memset(next_ie + remain_len, 0, p2p_ielen_ori - p2p_ielen); - bss_ex->IELength -= p2p_ielen_ori - p2p_ielen; - } - } -} - -static int rtw_get_cipher_info(struct wlan_network *pnetwork) -{ - u32 wpa_ielen; - unsigned char *pbuf; - int group_cipher = 0, pairwise_cipher = 0, is8021x = 0; - int ret = _FAIL; - - pbuf = rtw_get_wpa_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength - 12); - - if (pbuf && (wpa_ielen > 0)) { - if (rtw_parse_wpa_ie(pbuf, wpa_ielen + 2, &group_cipher, &pairwise_cipher, &is8021x) == _SUCCESS) { - pnetwork->BcnInfo.pairwise_cipher = pairwise_cipher; - pnetwork->BcnInfo.group_cipher = group_cipher; - pnetwork->BcnInfo.is_8021x = is8021x; - ret = _SUCCESS; - } - } else { - pbuf = rtw_get_wpa2_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength - 12); - - if (pbuf && (wpa_ielen > 0)) { - if (rtw_parse_wpa2_ie(pbuf, wpa_ielen + 2, &group_cipher, &pairwise_cipher, &is8021x) == _SUCCESS) { - pnetwork->BcnInfo.pairwise_cipher = pairwise_cipher; - pnetwork->BcnInfo.group_cipher = group_cipher; - pnetwork->BcnInfo.is_8021x = is8021x; - ret = _SUCCESS; - } - } - } - - return ret; -} - -void rtw_get_bcn_info(struct wlan_network *pnetwork) -{ - unsigned short cap = 0; - u8 bencrypt = 0; - __le16 le_tmp; - u16 wpa_len = 0, rsn_len = 0; - struct HT_info_element *pht_info = NULL; - struct ieee80211_ht_cap *pht_cap = NULL; - unsigned int len; - unsigned char *p; - - memcpy(&le_tmp, rtw_get_capability_from_ie(pnetwork->network.IEs), 2); - cap = le16_to_cpu(le_tmp); - if (cap & WLAN_CAPABILITY_PRIVACY) { - bencrypt = 1; - pnetwork->network.Privacy = 1; - } else { - pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_OPENSYS; - } - rtw_get_sec_ie(pnetwork->network.IEs, pnetwork->network.IELength, NULL, &rsn_len, NULL, &wpa_len); - - if (rsn_len > 0) { - pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WPA2; - } else if (wpa_len > 0) { - pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WPA; - } else { - if (bencrypt) - pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WEP; - } - rtw_get_cipher_info(pnetwork); - - /* get bwmode and ch_offset */ - /* parsing HT_CAP_IE */ - p = rtw_get_ie(pnetwork->network.IEs + _FIXED_IE_LENGTH_, _HT_CAPABILITY_IE_, &len, pnetwork->network.IELength - _FIXED_IE_LENGTH_); - if (p && len > 0) { - pht_cap = (struct ieee80211_ht_cap *)(p + 2); - pnetwork->BcnInfo.ht_cap_info = le16_to_cpu(pht_cap->cap_info); - } else { - pnetwork->BcnInfo.ht_cap_info = 0; - } - /* parsing HT_INFO_IE */ - p = rtw_get_ie(pnetwork->network.IEs + _FIXED_IE_LENGTH_, _HT_ADD_INFO_IE_, &len, pnetwork->network.IELength - _FIXED_IE_LENGTH_); - if (p && len > 0) { - pht_info = (struct HT_info_element *)(p + 2); - pnetwork->BcnInfo.ht_info_infos_0 = pht_info->infos[0]; - } else { - pnetwork->BcnInfo.ht_info_infos_0 = 0; - } -} - -/* show MCS rate, unit: 100Kbps */ -u16 rtw_mcs_rate(u8 bw_40MHz, u8 short_GI_20, u8 short_GI_40, unsigned char *MCS_rate) -{ - u16 max_rate = 0; - - if (MCS_rate[0] & BIT(7)) - max_rate = (bw_40MHz) ? ((short_GI_40) ? 1500 : 1350) : ((short_GI_20) ? 722 : 650); - else if (MCS_rate[0] & BIT(6)) - max_rate = (bw_40MHz) ? ((short_GI_40) ? 1350 : 1215) : ((short_GI_20) ? 650 : 585); - else if (MCS_rate[0] & BIT(5)) - max_rate = (bw_40MHz) ? ((short_GI_40) ? 1200 : 1080) : ((short_GI_20) ? 578 : 520); - else if (MCS_rate[0] & BIT(4)) - max_rate = (bw_40MHz) ? ((short_GI_40) ? 900 : 810) : ((short_GI_20) ? 433 : 390); - else if (MCS_rate[0] & BIT(3)) - max_rate = (bw_40MHz) ? ((short_GI_40) ? 600 : 540) : ((short_GI_20) ? 289 : 260); - else if (MCS_rate[0] & BIT(2)) - max_rate = (bw_40MHz) ? ((short_GI_40) ? 450 : 405) : ((short_GI_20) ? 217 : 195); - else if (MCS_rate[0] & BIT(1)) - max_rate = (bw_40MHz) ? ((short_GI_40) ? 300 : 270) : ((short_GI_20) ? 144 : 130); - else if (MCS_rate[0] & BIT(0)) - max_rate = (bw_40MHz) ? ((short_GI_40) ? 150 : 135) : ((short_GI_20) ? 72 : 65); - - return max_rate; -} diff --git a/drivers/staging/r8188eu/core/rtw_ioctl_set.c b/drivers/staging/r8188eu/core/rtw_ioctl_set.c deleted file mode 100644 index 785c0dba508f..000000000000 --- a/drivers/staging/r8188eu/core/rtw_ioctl_set.c +++ /dev/null @@ -1,479 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2007 - 2012 Realtek Corporation. */ - -#define _RTW_IOCTL_SET_C_ - -#include "../include/osdep_service.h" -#include "../include/drv_types.h" -#include "../include/rtw_ioctl_set.h" -#include "../include/hal_intf.h" - -#include "../include/usb_osintf.h" -#include "../include/usb_ops.h" - -u8 rtw_do_join(struct adapter *padapter) -{ - struct list_head *plist, *phead; - u8 *pibss = NULL; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct __queue *queue = &pmlmepriv->scanned_queue; - u8 ret = _SUCCESS; - - spin_lock_bh(&pmlmepriv->scanned_queue.lock); - phead = get_list_head(queue); - plist = phead->next; - - pmlmepriv->cur_network.join_res = -2; - - set_fwstate(pmlmepriv, _FW_UNDER_LINKING); - - pmlmepriv->pscanned = plist; - - pmlmepriv->to_join = true; - - if (list_empty(&queue->queue)) { - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); - - /* when set_ssid/set_bssid for rtw_do_join(), but scanning queue is empty */ - /* we try to issue sitesurvey firstly */ - - if (!pmlmepriv->LinkDetectInfo.bBusyTraffic || - pmlmepriv->to_roaming > 0) { - /* submit site_survey_cmd */ - ret = rtw_sitesurvey_cmd(padapter, &pmlmepriv->assoc_ssid, 1); - if (ret != _SUCCESS) - pmlmepriv->to_join = false; - } else { - pmlmepriv->to_join = false; - ret = _FAIL; - } - - return ret; - } else { - int select_ret; - - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - select_ret = rtw_select_and_join_from_scanned_queue(pmlmepriv); - if (select_ret == _SUCCESS) { - pmlmepriv->to_join = false; - _set_timer(&pmlmepriv->assoc_timer, MAX_JOIN_TIMEOUT); - } else { - if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) { - /* submit createbss_cmd to change to a ADHOC_MASTER */ - - /* pmlmepriv->lock has been acquired by caller... */ - struct wlan_bssid_ex *pdev_network = &padapter->registrypriv.dev_network; - - pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE; - - pibss = padapter->registrypriv.dev_network.MacAddress; - - memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid)); - - rtw_update_registrypriv_dev_network(padapter); - - rtw_generate_random_ibss(pibss); - - if (rtw_createbss_cmd(padapter) != _SUCCESS) - return false; - - pmlmepriv->to_join = false; - } else { - /* can't associate ; reset under-linking */ - _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); - - /* when set_ssid/set_bssid for rtw_do_join(), but there are no desired bss in scanning queue */ - /* we try to issue sitesurvey firstly */ - if (!pmlmepriv->LinkDetectInfo.bBusyTraffic || - pmlmepriv->to_roaming > 0) { - ret = rtw_sitesurvey_cmd(padapter, &pmlmepriv->assoc_ssid, 1); - if (ret != _SUCCESS) - pmlmepriv->to_join = false; - } else { - ret = _FAIL; - pmlmepriv->to_join = false; - } - } - } - } - - return ret; -} - -u8 rtw_set_802_11_bssid(struct adapter *padapter, u8 *bssid) -{ - u8 status = _SUCCESS; - u32 cur_time = 0; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - if ((bssid[0] == 0x00 && bssid[1] == 0x00 && bssid[2] == 0x00 && - bssid[3] == 0x00 && bssid[4] == 0x00 && bssid[5] == 0x00) || - (bssid[0] == 0xFF && bssid[1] == 0xFF && bssid[2] == 0xFF && - bssid[3] == 0xFF && bssid[4] == 0xFF && bssid[5] == 0xFF)) { - status = _FAIL; - goto exit; - } - - spin_lock_bh(&pmlmepriv->lock); - - if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) - goto handle_tkip_countermeasure; - else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) - goto release_mlme_lock; - - if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE)) { - if (!memcmp(&pmlmepriv->cur_network.network.MacAddress, bssid, ETH_ALEN)) { - if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE)) - goto release_mlme_lock;/* it means driver is in WIFI_ADHOC_MASTER_STATE, we needn't create bss again. */ - } else { - rtw_disassoc_cmd(padapter, 0, true); - - if (check_fwstate(pmlmepriv, _FW_LINKED)) - rtw_indicate_disconnect(padapter); - - rtw_free_assoc_resources(padapter, 1); - - if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) { - _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE); - set_fwstate(pmlmepriv, WIFI_ADHOC_STATE); - } - } - } - -handle_tkip_countermeasure: - /* should we add something here...? */ - - if (padapter->securitypriv.btkip_countermeasure) { - cur_time = jiffies; - - if ((cur_time - padapter->securitypriv.btkip_countermeasure_time) > 60 * HZ) { - padapter->securitypriv.btkip_countermeasure = false; - padapter->securitypriv.btkip_countermeasure_time = 0; - } else { - status = _FAIL; - goto release_mlme_lock; - } - } - - memcpy(&pmlmepriv->assoc_bssid, bssid, ETH_ALEN); - pmlmepriv->assoc_by_bssid = true; - - if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) - pmlmepriv->to_join = true; - else - status = rtw_do_join(padapter); - -release_mlme_lock: - spin_unlock_bh(&pmlmepriv->lock); - -exit: - return status; -} - -u8 rtw_set_802_11_ssid(struct adapter *padapter, struct ndis_802_11_ssid *ssid) -{ - u8 status = _SUCCESS; - u32 cur_time = 0; - - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wlan_network *pnetwork = &pmlmepriv->cur_network; - - if (!padapter->hw_init_completed) { - status = _FAIL; - goto exit; - } - - spin_lock_bh(&pmlmepriv->lock); - - if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) { - goto handle_tkip_countermeasure; - } else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) { - goto release_mlme_lock; - } - - if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE)) { - if ((pmlmepriv->assoc_ssid.SsidLength == ssid->SsidLength) && - (!memcmp(&pmlmepriv->assoc_ssid.Ssid, ssid->Ssid, ssid->SsidLength))) { - if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { - if (!rtw_is_same_ibss(padapter, pnetwork)) { - /* if in WIFI_ADHOC_MASTER_STATE | WIFI_ADHOC_STATE, create bss or rejoin again */ - rtw_disassoc_cmd(padapter, 0, true); - - if (check_fwstate(pmlmepriv, _FW_LINKED)) - rtw_indicate_disconnect(padapter); - - rtw_free_assoc_resources(padapter, 1); - - if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) { - _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE); - set_fwstate(pmlmepriv, WIFI_ADHOC_STATE); - } - } else { - goto release_mlme_lock;/* it means driver is in WIFI_ADHOC_MASTER_STATE, we needn't create bss again. */ - } - } else { - rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_JOINBSS, 1); - } - } else { - rtw_disassoc_cmd(padapter, 0, true); - - if (check_fwstate(pmlmepriv, _FW_LINKED)) - rtw_indicate_disconnect(padapter); - - rtw_free_assoc_resources(padapter, 1); - - if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) { - _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE); - set_fwstate(pmlmepriv, WIFI_ADHOC_STATE); - } - } - } - -handle_tkip_countermeasure: - - if (padapter->securitypriv.btkip_countermeasure) { - cur_time = jiffies; - - if ((cur_time - padapter->securitypriv.btkip_countermeasure_time) > 60 * HZ) { - padapter->securitypriv.btkip_countermeasure = false; - padapter->securitypriv.btkip_countermeasure_time = 0; - } else { - status = _FAIL; - goto release_mlme_lock; - } - } - - memcpy(&pmlmepriv->assoc_ssid, ssid, sizeof(struct ndis_802_11_ssid)); - pmlmepriv->assoc_by_bssid = false; - - if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) { - pmlmepriv->to_join = true; - } else { - status = rtw_do_join(padapter); - } - -release_mlme_lock: - spin_unlock_bh(&pmlmepriv->lock); - -exit: - return status; -} - -u8 rtw_set_802_11_infrastructure_mode(struct adapter *padapter, - enum ndis_802_11_network_infra networktype) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wlan_network *cur_network = &pmlmepriv->cur_network; - enum ndis_802_11_network_infra *pold_state = &cur_network->network.InfrastructureMode; - - if (*pold_state != networktype) { - spin_lock_bh(&pmlmepriv->lock); - - if (*pold_state == Ndis802_11APMode) { - /* change to other mode from Ndis802_11APMode */ - cur_network->join_res = -1; - - stop_ap_mode(padapter); - } - - if ((check_fwstate(pmlmepriv, _FW_LINKED)) || - (*pold_state == Ndis802_11IBSS)) - rtw_disassoc_cmd(padapter, 0, true); - - if ((check_fwstate(pmlmepriv, _FW_LINKED)) || - (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))) - rtw_free_assoc_resources(padapter, 1); - - if ((*pold_state == Ndis802_11Infrastructure) || (*pold_state == Ndis802_11IBSS)) { - if (check_fwstate(pmlmepriv, _FW_LINKED)) - rtw_indicate_disconnect(padapter); /* will clr Linked_state; before this function, we must have checked whether issue dis-assoc_cmd or not */ - } - - *pold_state = networktype; - - _clr_fwstate_(pmlmepriv, ~WIFI_NULL_STATE); - - switch (networktype) { - case Ndis802_11IBSS: - set_fwstate(pmlmepriv, WIFI_ADHOC_STATE); - break; - case Ndis802_11Infrastructure: - set_fwstate(pmlmepriv, WIFI_STATION_STATE); - break; - case Ndis802_11APMode: - set_fwstate(pmlmepriv, WIFI_AP_STATE); - break; - case Ndis802_11AutoUnknown: - case Ndis802_11InfrastructureMax: - break; - } - spin_unlock_bh(&pmlmepriv->lock); - } - - return true; -} - -void rtw_set_802_11_disassociate(struct adapter *padapter) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - spin_lock_bh(&pmlmepriv->lock); - - if (check_fwstate(pmlmepriv, _FW_LINKED)) { - rtw_disassoc_cmd(padapter, 0, true); - rtw_indicate_disconnect(padapter); - rtw_free_assoc_resources(padapter, 1); - rtw_pwr_wakeup(padapter); - } - - spin_unlock_bh(&pmlmepriv->lock); -} - -u8 rtw_set_802_11_bssid_list_scan(struct adapter *padapter, struct ndis_802_11_ssid *pssid, int ssid_max_num) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - u8 res = true; - - if (!padapter) { - res = false; - goto exit; - } - if (!padapter->hw_init_completed) { - res = false; - goto exit; - } - - if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING)) || - (pmlmepriv->LinkDetectInfo.bBusyTraffic)) { - /* Scan or linking is in progress, do nothing. */ - res = true; - } else { - spin_lock_bh(&pmlmepriv->lock); - - res = rtw_sitesurvey_cmd(padapter, pssid, ssid_max_num); - - spin_unlock_bh(&pmlmepriv->lock); - } -exit: - - return res; -} - -u8 rtw_set_802_11_authentication_mode(struct adapter *padapter, enum ndis_802_11_auth_mode authmode) -{ - struct security_priv *psecuritypriv = &padapter->securitypriv; - int res; - u8 ret; - - psecuritypriv->ndisauthtype = authmode; - - if (psecuritypriv->ndisauthtype > 3) - psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; - - res = rtw_set_auth(padapter, psecuritypriv); - - if (res == _SUCCESS) - ret = true; - else - ret = false; - - return ret; -} - -u8 rtw_set_802_11_add_wep(struct adapter *padapter, struct ndis_802_11_wep *wep) -{ - int keyid, res; - struct security_priv *psecuritypriv = &padapter->securitypriv; - u8 ret = _SUCCESS; - - keyid = wep->KeyIndex & 0x3fffffff; - - if (keyid >= 4) { - ret = false; - goto exit; - } - - switch (wep->KeyLength) { - case 5: - psecuritypriv->dot11PrivacyAlgrthm = _WEP40_; - break; - case 13: - psecuritypriv->dot11PrivacyAlgrthm = _WEP104_; - break; - default: - psecuritypriv->dot11PrivacyAlgrthm = _NO_PRIVACY_; - break; - } - - memcpy(&psecuritypriv->dot11DefKey[keyid].skey[0], &wep->KeyMaterial, wep->KeyLength); - - psecuritypriv->dot11DefKeylen[keyid] = wep->KeyLength; - - psecuritypriv->dot11PrivacyKeyIndex = keyid; - - res = rtw_set_key(padapter, psecuritypriv, keyid, 1); - - if (res == _FAIL) - ret = false; -exit: - - return ret; -} - -/* -* rtw_get_cur_max_rate - -* @adapter: pointer to struct adapter structure -* -* Return 0 or 100Kbps -*/ -u16 rtw_get_cur_max_rate(struct adapter *adapter) -{ - int i = 0; - u8 *p; - u16 rate = 0, max_rate = 0; - struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct registry_priv *pregistrypriv = &adapter->registrypriv; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network; - struct ieee80211_ht_cap *pht_capie; - u8 bw_40MHz = 0, short_GI_20 = 0, short_GI_40 = 0; - u16 mcs_rate = 0; - u32 ht_ielen = 0; - - if ((!check_fwstate(pmlmepriv, _FW_LINKED)) && - (!check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))) - return 0; - - if (pmlmeext->cur_wireless_mode & (WIRELESS_11_24N)) { - p = rtw_get_ie(&pcur_bss->IEs[12], _HT_CAPABILITY_IE_, &ht_ielen, pcur_bss->IELength - 12); - if (p && ht_ielen > 0) { - pht_capie = (struct ieee80211_ht_cap *)(p + 2); - - memcpy(&mcs_rate, pht_capie->mcs.rx_mask, 2); - - /* cur_bwmod is updated by beacon, pmlmeinfo is updated by association response */ - bw_40MHz = (pmlmeext->cur_bwmode && (HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH & pmlmeinfo->HT_info.infos[0])) ? 1 : 0; - - short_GI_20 = (le16_to_cpu(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info) & IEEE80211_HT_CAP_SGI_20) ? 1 : 0; - short_GI_40 = (le16_to_cpu(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info) & IEEE80211_HT_CAP_SGI_40) ? 1 : 0; - - max_rate = rtw_mcs_rate(bw_40MHz & (pregistrypriv->cbw40_enable), - short_GI_20, - short_GI_40, - pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate); - } - } else { - while ((pcur_bss->SupportedRates[i] != 0) && (pcur_bss->SupportedRates[i] != 0xFF)) { - rate = pcur_bss->SupportedRates[i] & 0x7F; - if (rate > max_rate) - max_rate = rate; - i++; - } - - max_rate *= 5; - } - - return max_rate; -} diff --git a/drivers/staging/r8188eu/core/rtw_iol.c b/drivers/staging/r8188eu/core/rtw_iol.c deleted file mode 100644 index 31e196ccd899..000000000000 --- a/drivers/staging/r8188eu/core/rtw_iol.c +++ /dev/null @@ -1,160 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#include "../include/rtw_iol.h" - -struct xmit_frame *rtw_IOL_accquire_xmit_frame(struct adapter *adapter) -{ - struct xmit_frame *xmit_frame; - struct xmit_buf *xmitbuf; - struct pkt_attrib *pattrib; - struct xmit_priv *pxmitpriv = &adapter->xmitpriv; - - xmit_frame = rtw_alloc_xmitframe(pxmitpriv); - if (!xmit_frame) - return NULL; - - xmitbuf = rtw_alloc_xmitbuf(pxmitpriv); - if (!xmitbuf) { - rtw_free_xmitframe(pxmitpriv, xmit_frame); - return NULL; - } - - xmit_frame->frame_tag = MGNT_FRAMETAG; - xmit_frame->pxmitbuf = xmitbuf; - xmit_frame->buf_addr = xmitbuf->pbuf; - xmitbuf->priv_data = xmit_frame; - - pattrib = &xmit_frame->attrib; - update_mgntframe_attrib(adapter, pattrib); - pattrib->qsel = 0x10;/* Beacon */ - pattrib->subtype = WIFI_BEACON; - pattrib->pktlen = 0; - pattrib->last_txcmdsz = 0; - - return xmit_frame; -} - -int rtw_IOL_append_cmds(struct xmit_frame *xmit_frame, u8 *IOL_cmds, u32 cmd_len) -{ - struct pkt_attrib *pattrib = &xmit_frame->attrib; - u16 buf_offset; - u32 ori_len; - - buf_offset = TXDESC_OFFSET; - ori_len = buf_offset + pattrib->pktlen; - - /* check if the io_buf can accommodate new cmds */ - if (ori_len + cmd_len + 8 > MAX_XMITBUF_SZ) - return _FAIL; - - memcpy(xmit_frame->buf_addr + buf_offset + pattrib->pktlen, IOL_cmds, cmd_len); - pattrib->pktlen += cmd_len; - pattrib->last_txcmdsz += cmd_len; - - return _SUCCESS; -} - -bool rtw_IOL_applied(struct adapter *adapter) -{ - if (adapter->registrypriv.fw_iol == 1) - return true; - - if ((adapter->registrypriv.fw_iol == 2) && - (adapter_to_dvobj(adapter)->pusbdev->speed != USB_SPEED_HIGH)) - return true; - - return false; -} - -int rtw_IOL_append_WB_cmd(struct xmit_frame *xmit_frame, u16 addr, u8 value, u8 mask) -{ - struct ioreg_cfg cmd = {8, IOREG_CMD_WB_REG, 0x0, 0x0, 0x0}; - - cmd.address = cpu_to_le16(addr); - cmd.data = cpu_to_le32(value); - - if (mask != 0xFF) { - cmd.length = 12; - cmd.mask = cpu_to_le32(mask); - } - return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, cmd.length); -} - -int rtw_IOL_append_WW_cmd(struct xmit_frame *xmit_frame, u16 addr, u16 value, u16 mask) -{ - struct ioreg_cfg cmd = {8, IOREG_CMD_WW_REG, 0x0, 0x0, 0x0}; - - cmd.address = cpu_to_le16(addr); - cmd.data = cpu_to_le32(value); - - if (mask != 0xFFFF) { - cmd.length = 12; - cmd.mask = cpu_to_le32(mask); - } - return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, cmd.length); -} - -int rtw_IOL_append_WD_cmd(struct xmit_frame *xmit_frame, u16 addr, u32 value, u32 mask) -{ - struct ioreg_cfg cmd = {8, IOREG_CMD_WD_REG, 0x0, 0x0, 0x0}; - - cmd.address = cpu_to_le16(addr); - cmd.data = cpu_to_le32(value); - - if (mask != 0xFFFFFFFF) { - cmd.length = 12; - cmd.mask = cpu_to_le32(mask); - } - return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, cmd.length); -} - -int rtw_IOL_append_WRF_cmd(struct xmit_frame *xmit_frame, u8 rf_path, u16 addr, u32 value, u32 mask) -{ - struct ioreg_cfg cmd = {8, IOREG_CMD_W_RF, 0x0, 0x0, 0x0}; - - cmd.address = cpu_to_le16((rf_path << 8) | ((addr) & 0xFF)); - cmd.data = cpu_to_le32(value); - - if (mask != 0x000FFFFF) { - cmd.length = 12; - cmd.mask = cpu_to_le32(mask); - } - return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, cmd.length); -} - -int rtw_IOL_append_DELAY_US_cmd(struct xmit_frame *xmit_frame, u16 us) -{ - struct ioreg_cfg cmd = {4, IOREG_CMD_DELAY_US, 0x0, 0x0, 0x0}; - cmd.address = cpu_to_le16(us); - - return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, 4); -} - -int rtw_IOL_append_DELAY_MS_cmd(struct xmit_frame *xmit_frame, u16 ms) -{ - struct ioreg_cfg cmd = {4, IOREG_CMD_DELAY_US, 0x0, 0x0, 0x0}; - - cmd.address = cpu_to_le16(ms); - return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, 4); -} - -int rtw_IOL_append_END_cmd(struct xmit_frame *xmit_frame) -{ - struct ioreg_cfg cmd = {4, IOREG_CMD_END, cpu_to_le16(0xFFFF), cpu_to_le32(0xFF), 0x0}; - - return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, 4); -} - -u8 rtw_IOL_cmd_boundary_handle(struct xmit_frame *pxmit_frame) -{ - u8 is_cmd_bndy = false; - if (((pxmit_frame->attrib.pktlen + 32) % 256) + 8 >= 256) { - rtw_IOL_append_END_cmd(pxmit_frame); - pxmit_frame->attrib.pktlen = ((((pxmit_frame->attrib.pktlen + 32) / 256) + 1) * 256); - - pxmit_frame->attrib.last_txcmdsz = pxmit_frame->attrib.pktlen; - is_cmd_bndy = true; - } - return is_cmd_bndy; -} diff --git a/drivers/staging/r8188eu/core/rtw_led.c b/drivers/staging/r8188eu/core/rtw_led.c deleted file mode 100644 index 48725ce9d369..000000000000 --- a/drivers/staging/r8188eu/core/rtw_led.c +++ /dev/null @@ -1,255 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2007 - 2012 Realtek Corporation. */ - -#include "../include/drv_types.h" -#include "../include/rtw_led.h" -#include "../include/rtl8188e_spec.h" - -#define LED_BLINK_NO_LINK_INTVL msecs_to_jiffies(1000) -#define LED_BLINK_LINK_INTVL msecs_to_jiffies(500) -#define LED_BLINK_SCAN_INTVL msecs_to_jiffies(180) -#define LED_BLINK_FASTER_INTVL msecs_to_jiffies(50) -#define LED_BLINK_WPS_SUCESS_INTVL msecs_to_jiffies(5000) - -#define IS_LED_WPS_BLINKING(l) \ - ((l)->CurrLedState == LED_BLINK_WPS || \ - (l)->CurrLedState == LED_BLINK_WPS_STOP || \ - (l)->bLedWPSBlinkInProgress) - -static void ResetLedStatus(struct led_priv *pLed) -{ - pLed->CurrLedState = RTW_LED_OFF; /* Current LED state. */ - pLed->bLedOn = false; /* true if LED is ON, false if LED is OFF. */ - - pLed->bLedBlinkInProgress = false; /* true if it is blinking, false o.w.. */ - pLed->bLedWPSBlinkInProgress = false; - - pLed->BlinkTimes = 0; /* Number of times to toggle led state for blinking. */ - - pLed->bLedScanBlinkInProgress = false; -} - -static void SwLedOn(struct led_priv *pLed) -{ - struct adapter *padapter = container_of(pLed, struct adapter, ledpriv); - - if (padapter->bDriverStopped) - return; - - if (rtw_write8(padapter, REG_LEDCFG2, BIT(5)) != _SUCCESS) - return; - - pLed->bLedOn = true; -} - -static void SwLedOff(struct led_priv *pLed) -{ - struct adapter *padapter = container_of(pLed, struct adapter, ledpriv); - - if (padapter->bDriverStopped) - return; - - if (rtw_write8(padapter, REG_LEDCFG2, BIT(5) | BIT(3)) != _SUCCESS) - return; - - pLed->bLedOn = false; -} - -static void blink_work(struct work_struct *work) -{ - struct delayed_work *dwork = to_delayed_work(work); - struct led_priv *pLed = container_of(dwork, struct led_priv, blink_work); - struct adapter *padapter = container_of(pLed, struct adapter, ledpriv); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - if (padapter->pwrctrlpriv.rf_pwrstate != rf_on) { - SwLedOff(pLed); - ResetLedStatus(pLed); - return; - } - - if (pLed->bLedOn) - SwLedOff(pLed); - else - SwLedOn(pLed); - - switch (pLed->CurrLedState) { - case LED_BLINK_SLOWLY: - schedule_delayed_work(&pLed->blink_work, LED_BLINK_NO_LINK_INTVL); - break; - case LED_BLINK_NORMAL: - schedule_delayed_work(&pLed->blink_work, LED_BLINK_LINK_INTVL); - break; - case LED_BLINK_SCAN: - case LED_BLINK_TXRX: - pLed->BlinkTimes--; - if (pLed->BlinkTimes == 0) { - if (check_fwstate(pmlmepriv, _FW_LINKED)) { - pLed->CurrLedState = LED_BLINK_NORMAL; - schedule_delayed_work(&pLed->blink_work, LED_BLINK_LINK_INTVL); - } else { - pLed->CurrLedState = LED_BLINK_SLOWLY; - schedule_delayed_work(&pLed->blink_work, LED_BLINK_NO_LINK_INTVL); - } - pLed->bLedBlinkInProgress = false; - pLed->bLedScanBlinkInProgress = false; - } else { - schedule_delayed_work(&pLed->blink_work, - pLed->CurrLedState == LED_BLINK_SCAN ? - LED_BLINK_SCAN_INTVL : LED_BLINK_FASTER_INTVL); - } - break; - case LED_BLINK_WPS: - schedule_delayed_work(&pLed->blink_work, LED_BLINK_SCAN_INTVL); - break; - case LED_BLINK_WPS_STOP: /* WPS success */ - if (!pLed->bLedOn) { - pLed->CurrLedState = LED_BLINK_NORMAL; - schedule_delayed_work(&pLed->blink_work, LED_BLINK_LINK_INTVL); - - pLed->bLedWPSBlinkInProgress = false; - } else { - schedule_delayed_work(&pLed->blink_work, LED_BLINK_WPS_SUCESS_INTVL); - } - break; - default: - break; - } -} - -void rtl8188eu_InitSwLeds(struct adapter *padapter) -{ - struct led_priv *pledpriv = &padapter->ledpriv; - - ResetLedStatus(pledpriv); - INIT_DELAYED_WORK(&pledpriv->blink_work, blink_work); -} - -void rtl8188eu_DeInitSwLeds(struct adapter *padapter) -{ - struct led_priv *ledpriv = &padapter->ledpriv; - - cancel_delayed_work_sync(&ledpriv->blink_work); - ResetLedStatus(ledpriv); - SwLedOff(ledpriv); -} - -void rtw_led_control(struct adapter *padapter, enum LED_CTL_MODE LedAction) -{ - struct led_priv *pLed = &padapter->ledpriv; - struct registry_priv *registry_par; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - if (!padapter->hw_init_completed) - return; - - if (!pLed->bRegUseLed) - return; - - registry_par = &padapter->registrypriv; - if (!registry_par->led_enable) - return; - - switch (LedAction) { - case LED_CTL_START_TO_LINK: - case LED_CTL_NO_LINK: - if (pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed)) - return; - - cancel_delayed_work(&pLed->blink_work); - - pLed->bLedBlinkInProgress = false; - - pLed->CurrLedState = LED_BLINK_SLOWLY; - schedule_delayed_work(&pLed->blink_work, LED_BLINK_NO_LINK_INTVL); - break; - case LED_CTL_LINK: - if (pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed)) - return; - - cancel_delayed_work(&pLed->blink_work); - - pLed->bLedBlinkInProgress = false; - - pLed->CurrLedState = LED_BLINK_NORMAL; - schedule_delayed_work(&pLed->blink_work, LED_BLINK_LINK_INTVL); - break; - case LED_CTL_SITE_SURVEY: - if ((pmlmepriv->LinkDetectInfo.bBusyTraffic) && (check_fwstate(pmlmepriv, _FW_LINKED))) - return; - - if (pLed->bLedScanBlinkInProgress) - return; - - if (IS_LED_WPS_BLINKING(pLed)) - return; - - cancel_delayed_work(&pLed->blink_work); - - pLed->bLedBlinkInProgress = false; - pLed->bLedScanBlinkInProgress = true; - - pLed->CurrLedState = LED_BLINK_SCAN; - pLed->BlinkTimes = 24; - schedule_delayed_work(&pLed->blink_work, LED_BLINK_SCAN_INTVL); - break; - case LED_CTL_TX: - case LED_CTL_RX: - if (pLed->bLedBlinkInProgress) - return; - - if (pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed)) - return; - - cancel_delayed_work(&pLed->blink_work); - - pLed->bLedBlinkInProgress = true; - - pLed->CurrLedState = LED_BLINK_TXRX; - pLed->BlinkTimes = 2; - schedule_delayed_work(&pLed->blink_work, LED_BLINK_FASTER_INTVL); - break; - case LED_CTL_START_WPS: /* wait until xinpin finish */ - if (pLed->bLedWPSBlinkInProgress) - return; - - cancel_delayed_work(&pLed->blink_work); - - pLed->bLedBlinkInProgress = false; - pLed->bLedScanBlinkInProgress = false; - pLed->bLedWPSBlinkInProgress = true; - pLed->CurrLedState = LED_BLINK_WPS; - schedule_delayed_work(&pLed->blink_work, LED_BLINK_SCAN_INTVL); - break; - case LED_CTL_STOP_WPS: - cancel_delayed_work(&pLed->blink_work); - - pLed->bLedBlinkInProgress = false; - pLed->bLedScanBlinkInProgress = false; - pLed->bLedWPSBlinkInProgress = true; - - pLed->CurrLedState = LED_BLINK_WPS_STOP; - if (pLed->bLedOn) { - schedule_delayed_work(&pLed->blink_work, LED_BLINK_WPS_SUCESS_INTVL); - } else { - schedule_delayed_work(&pLed->blink_work, 0); - } - break; - case LED_CTL_STOP_WPS_FAIL: - cancel_delayed_work(&pLed->blink_work); - pLed->bLedWPSBlinkInProgress = false; - pLed->CurrLedState = LED_BLINK_SLOWLY; - schedule_delayed_work(&pLed->blink_work, LED_BLINK_NO_LINK_INTVL); - break; - case LED_CTL_POWER_OFF: - pLed->CurrLedState = RTW_LED_OFF; - pLed->bLedBlinkInProgress = false; - pLed->bLedWPSBlinkInProgress = false; - pLed->bLedScanBlinkInProgress = false; - cancel_delayed_work(&pLed->blink_work); - SwLedOff(pLed); - break; - default: - break; - } -} diff --git a/drivers/staging/r8188eu/core/rtw_mlme.c b/drivers/staging/r8188eu/core/rtw_mlme.c deleted file mode 100644 index fb7d0e161fdd..000000000000 --- a/drivers/staging/r8188eu/core/rtw_mlme.c +++ /dev/null @@ -1,2067 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#define _RTW_MLME_C_ - -#include "../include/osdep_service.h" -#include "../include/drv_types.h" -#include "../include/hal_intf.h" -#include "../include/sta_info.h" -#include "../include/wifi.h" -#include "../include/wlan_bssdef.h" -#include "../include/rtw_ioctl_set.h" -#include "../include/usb_osintf.h" -#include "../include/rtl8188e_dm.h" - -extern unsigned char MCS_rate_1R[16]; - -void rtw_set_roaming(struct adapter *adapter, u8 to_roaming) -{ - if (to_roaming == 0) - adapter->mlmepriv.to_join = false; - adapter->mlmepriv.to_roaming = to_roaming; -} - -u8 rtw_to_roaming(struct adapter *adapter) -{ - return adapter->mlmepriv.to_roaming; -} - -static void rtw_free_mlme_ie_data(u8 **ppie, u32 *plen) -{ - kfree(*ppie); - *plen = 0; - *ppie = NULL; -} - -void rtw_free_mlme_priv_ie_data(struct mlme_priv *pmlmepriv) -{ - kfree(pmlmepriv->assoc_req); - rtw_free_mlme_ie_data(&pmlmepriv->wps_beacon_ie, &pmlmepriv->wps_beacon_ie_len); - rtw_free_mlme_ie_data(&pmlmepriv->wps_probe_req_ie, &pmlmepriv->wps_probe_req_ie_len); - rtw_free_mlme_ie_data(&pmlmepriv->wps_probe_resp_ie, &pmlmepriv->wps_probe_resp_ie_len); - rtw_free_mlme_ie_data(&pmlmepriv->wps_assoc_resp_ie, &pmlmepriv->wps_assoc_resp_ie_len); - - rtw_free_mlme_ie_data(&pmlmepriv->p2p_beacon_ie, &pmlmepriv->p2p_beacon_ie_len); - rtw_free_mlme_ie_data(&pmlmepriv->p2p_probe_req_ie, &pmlmepriv->p2p_probe_req_ie_len); - rtw_free_mlme_ie_data(&pmlmepriv->p2p_probe_resp_ie, &pmlmepriv->p2p_probe_resp_ie_len); - rtw_free_mlme_ie_data(&pmlmepriv->p2p_go_probe_resp_ie, &pmlmepriv->p2p_go_probe_resp_ie_len); - rtw_free_mlme_ie_data(&pmlmepriv->p2p_assoc_req_ie, &pmlmepriv->p2p_assoc_req_ie_len); -} - -void _rtw_free_network(struct mlme_priv *pmlmepriv, struct wlan_network *pnetwork, u8 isfreeall) -{ - u32 curr_time, delta_time; - u32 lifetime = SCANQUEUE_LIFETIME; - struct __queue *free_queue = &pmlmepriv->free_bss_pool; - - if (!pnetwork) - return; - - if (pnetwork->fixed) - return; - curr_time = jiffies; - if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) || - (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE))) - lifetime = 1; - if (!isfreeall) { - delta_time = (curr_time - pnetwork->last_scanned) / HZ; - if (delta_time < lifetime)/* unit:sec */ - return; - } - spin_lock_bh(&free_queue->lock); - list_del_init(&pnetwork->list); - list_add_tail(&pnetwork->list, &free_queue->queue); - pmlmepriv->num_of_scanned--; - spin_unlock_bh(&free_queue->lock); -} - -/* - return the wlan_network with the matching addr - - Shall be called under atomic context... to avoid possible racing condition... -*/ -struct wlan_network *_rtw_find_network(struct __queue *scanned_queue, u8 *addr) -{ - struct list_head *phead, *plist; - struct wlan_network *pnetwork = NULL; - u8 zero_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0}; - - if (!memcmp(zero_addr, addr, ETH_ALEN)) { - pnetwork = NULL; - goto exit; - } - phead = get_list_head(scanned_queue); - plist = phead->next; - - while (plist != phead) { - pnetwork = container_of(plist, struct wlan_network, list); - if (!memcmp(addr, pnetwork->network.MacAddress, ETH_ALEN)) - break; - plist = plist->next; - } - if (plist == phead) - pnetwork = NULL; -exit: - - return pnetwork; -} - -void _rtw_free_network_queue(struct adapter *padapter, u8 isfreeall) -{ - struct list_head *phead, *plist; - struct wlan_network *pnetwork; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct __queue *scanned_queue = &pmlmepriv->scanned_queue; - - spin_lock_bh(&scanned_queue->lock); - - phead = get_list_head(scanned_queue); - plist = phead->next; - - while (phead != plist) { - pnetwork = container_of(plist, struct wlan_network, list); - - plist = plist->next; - - _rtw_free_network(pmlmepriv, pnetwork, isfreeall); - } - spin_unlock_bh(&scanned_queue->lock); - -} - -int rtw_if_up(struct adapter *padapter) -{ - int res; - - if (padapter->bDriverStopped || padapter->bSurpriseRemoved || - !check_fwstate(&padapter->mlmepriv, _FW_LINKED)) - res = false; - else - res = true; - - return res; -} - -void rtw_generate_random_ibss(u8 *pibss) -{ - u32 curtime = jiffies; - - pibss[0] = 0x02; /* in ad-hoc mode bit1 must set to 1 */ - pibss[1] = 0x11; - pibss[2] = 0x87; - pibss[3] = (u8)(curtime & 0xff);/* p[0]; */ - pibss[4] = (u8)((curtime >> 8) & 0xff);/* p[1]; */ - pibss[5] = (u8)((curtime >> 16) & 0xff);/* p[2]; */ -} - -u8 *rtw_get_capability_from_ie(u8 *ie) -{ - return ie + 8 + 2; -} - -u16 rtw_get_capability(struct wlan_bssid_ex *bss) -{ - __le16 val; - - memcpy((u8 *)&val, rtw_get_capability_from_ie(bss->IEs), 2); - - return le16_to_cpu(val); -} - -u8 *rtw_get_beacon_interval_from_ie(u8 *ie) -{ - return ie + 8; -} - -static void rtw_join_timeout_handler(struct timer_list *t) -{ - struct adapter *adapter = from_timer(adapter, t, mlmepriv.assoc_timer); - - _rtw_join_timeout_handler(adapter); -} - -static void _rtw_scan_timeout_handler(struct timer_list *t) -{ - struct adapter *adapter = from_timer(adapter, t, mlmepriv.scan_to_timer); - - rtw_scan_timeout_handler(adapter); -} - -static void _dynamic_check_timer_handlder(struct timer_list *t) -{ - struct adapter *adapter = from_timer(adapter, t, mlmepriv.dynamic_chk_timer); - - rtw_dynamic_check_timer_handlder(adapter); - _set_timer(&adapter->mlmepriv.dynamic_chk_timer, 2000); -} - -static void rtw_init_mlme_timer(struct adapter *padapter) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - timer_setup(&pmlmepriv->assoc_timer, rtw_join_timeout_handler, 0); - timer_setup(&pmlmepriv->scan_to_timer, _rtw_scan_timeout_handler, 0); - timer_setup(&pmlmepriv->dynamic_chk_timer, _dynamic_check_timer_handlder, 0); -} - -int rtw_init_mlme_priv(struct adapter *padapter)/* struct mlme_priv *pmlmepriv) */ -{ - int i; - u8 *pbuf; - struct wlan_network *pnetwork; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - /* We don't need to memset padapter->XXX to zero, because adapter is allocated by vzalloc(). */ - - pmlmepriv->nic_hdl = (u8 *)padapter; - - pmlmepriv->pscanned = NULL; - pmlmepriv->fw_state = 0; - pmlmepriv->cur_network.network.InfrastructureMode = Ndis802_11AutoUnknown; - pmlmepriv->scan_mode = SCAN_ACTIVE;/* 1: active, 0: pasive. Maybe someday we should rename this varable to "active_mode" (Jeff) */ - - spin_lock_init(&pmlmepriv->lock); - rtw_init_queue(&pmlmepriv->free_bss_pool); - rtw_init_queue(&pmlmepriv->scanned_queue); - - set_scanned_network_val(pmlmepriv, 0); - - memset(&pmlmepriv->assoc_ssid, 0, sizeof(struct ndis_802_11_ssid)); - - pbuf = vzalloc(MAX_BSS_CNT * (sizeof(struct wlan_network))); - - if (!pbuf) - return -ENOMEM; - - pmlmepriv->free_bss_buf = pbuf; - - pnetwork = (struct wlan_network *)pbuf; - - for (i = 0; i < MAX_BSS_CNT; i++) { - INIT_LIST_HEAD(&pnetwork->list); - - list_add_tail(&pnetwork->list, &pmlmepriv->free_bss_pool.queue); - - pnetwork++; - } - - /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */ - - rtw_init_mlme_timer(padapter); - - return 0; -} - -void rtw_free_mlme_priv(struct mlme_priv *pmlmepriv) -{ - rtw_free_mlme_priv_ie_data(pmlmepriv); - vfree(pmlmepriv->free_bss_buf); -} - -struct wlan_network *rtw_alloc_network(struct mlme_priv *pmlmepriv) -{ - struct wlan_network *pnetwork; - struct __queue *free_queue = &pmlmepriv->free_bss_pool; - struct list_head *plist = NULL; - - spin_lock_bh(&free_queue->lock); - - if (list_empty(&free_queue->queue)) { - pnetwork = NULL; - goto exit; - } - plist = (&free_queue->queue)->next; - - pnetwork = container_of(plist, struct wlan_network, list); - - list_del_init(&pnetwork->list); - - pnetwork->network_type = 0; - pnetwork->fixed = false; - pnetwork->last_scanned = jiffies; - pnetwork->aid = 0; - pnetwork->join_res = 0; - - pmlmepriv->num_of_scanned++; - -exit: - spin_unlock_bh(&free_queue->lock); - - return pnetwork; -} - -static void rtw_free_network_nolock(struct mlme_priv *pmlmepriv, - struct wlan_network *pnetwork) -{ - struct __queue *free_queue = &pmlmepriv->free_bss_pool; - - if (!pnetwork) - return; - if (pnetwork->fixed) - return; - list_del_init(&pnetwork->list); - list_add_tail(&pnetwork->list, get_list_head(free_queue)); - pmlmepriv->num_of_scanned--; -} - -void rtw_free_network_queue(struct adapter *dev, u8 isfreeall) -{ - - _rtw_free_network_queue(dev, isfreeall); - -} - -/* - return the wlan_network with the matching addr - - Shall be called under atomic context... to avoid possible racing condition... -*/ -struct wlan_network *rtw_find_network(struct __queue *scanned_queue, u8 *addr) -{ - struct wlan_network *pnetwork = _rtw_find_network(scanned_queue, addr); - - return pnetwork; -} - -int rtw_is_same_ibss(struct adapter *adapter, struct wlan_network *pnetwork) -{ - int ret = true; - struct security_priv *psecuritypriv = &adapter->securitypriv; - - if ((psecuritypriv->dot11PrivacyAlgrthm != _NO_PRIVACY_) && - (pnetwork->network.Privacy == 0)) - ret = false; - else if ((psecuritypriv->dot11PrivacyAlgrthm == _NO_PRIVACY_) && - (pnetwork->network.Privacy == 1)) - ret = false; - else - ret = true; - return ret; -} - -static int is_same_ess(struct wlan_bssid_ex *a, struct wlan_bssid_ex *b) -{ - return (a->Ssid.SsidLength == b->Ssid.SsidLength) && - !memcmp(a->Ssid.Ssid, b->Ssid.Ssid, a->Ssid.SsidLength); -} - -int is_same_network(struct wlan_bssid_ex *src, struct wlan_bssid_ex *dst) -{ - u16 s_cap, d_cap; - __le16 le_scap, le_dcap; - - memcpy((u8 *)&le_scap, rtw_get_capability_from_ie(src->IEs), 2); - memcpy((u8 *)&le_dcap, rtw_get_capability_from_ie(dst->IEs), 2); - - s_cap = le16_to_cpu(le_scap); - d_cap = le16_to_cpu(le_dcap); - - return ((src->Ssid.SsidLength == dst->Ssid.SsidLength) && - ((!memcmp(src->MacAddress, dst->MacAddress, ETH_ALEN))) && - ((!memcmp(src->Ssid.Ssid, dst->Ssid.Ssid, src->Ssid.SsidLength))) && - ((s_cap & WLAN_CAPABILITY_IBSS) == - (d_cap & WLAN_CAPABILITY_IBSS)) && - ((s_cap & WLAN_CAPABILITY_BSS) == - (d_cap & WLAN_CAPABILITY_BSS))); -} - -struct wlan_network *rtw_get_oldest_wlan_network(struct __queue *scanned_queue) -{ - struct list_head *plist, *phead; - struct wlan_network *pwlan = NULL; - struct wlan_network *oldest = NULL; - - phead = get_list_head(scanned_queue); - - plist = phead->next; - - while (1) { - if (phead == plist) - break; - - pwlan = container_of(plist, struct wlan_network, list); - - if (!pwlan->fixed) { - if (!oldest || time_after(oldest->last_scanned, pwlan->last_scanned)) - oldest = pwlan; - } - - plist = plist->next; - } - - return oldest; -} - -void update_network(struct wlan_bssid_ex *dst, struct wlan_bssid_ex *src, - struct adapter *padapter, bool update_ie) -{ - long rssi_ori = dst->Rssi; - u8 sq_smp = src->PhyInfo.SignalQuality; - u8 ss_final; - u8 sq_final; - long rssi_final; - - AntDivCompare8188E(padapter, dst, src); /* this will update src.Rssi, need consider again */ - - /* The rule below is 1/5 for sample value, 4/5 for history value */ - if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) && is_same_network(&padapter->mlmepriv.cur_network.network, src)) { - /* Take the recvpriv's value for the connected AP*/ - ss_final = padapter->recvpriv.signal_strength; - sq_final = padapter->recvpriv.signal_qual; - /* the rssi value here is undecorated, and will be used for antenna diversity */ - if (sq_smp != 101) /* from the right channel */ - rssi_final = dst->Rssi; //(src->Rssi+dst->Rssi*4)/5; - else - rssi_final = rssi_ori; - } else { -// if (sq_smp != 101) { /* from the right channel */ - ss_final = (u32)dst->PhyInfo.SignalStrength; //((u32)(src->PhyInfo.SignalStrength)+(u32)(dst->PhyInfo.SignalStrength)*4)/5; - sq_final = (u32)dst->PhyInfo.SignalQuality; //((u32)(src->PhyInfo.SignalQuality)+(u32)(dst->PhyInfo.SignalQuality)*4)/5; - rssi_final = dst->Rssi; //(src->Rssi+dst->Rssi*4)/5; -// } else { -// /* bss info not receiving from the right channel, use the original RX signal infos */ -// ss_final = dst->PhyInfo.SignalStrength; -// sq_final = dst->PhyInfo.SignalQuality; -// rssi_final = dst->Rssi; -// } - } - if (update_ie) { - dst->Reserved[0] = src->Reserved[0]; - dst->Reserved[1] = src->Reserved[1]; - memcpy((u8 *)dst, (u8 *)src, get_wlan_bssid_ex_sz(src)); - } - dst->PhyInfo.SignalStrength = ss_final; - dst->PhyInfo.SignalQuality = sq_final; - dst->Rssi = rssi_final; - -} - -static void update_current_network(struct adapter *adapter, struct wlan_bssid_ex *pnetwork) -{ - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - - if (check_fwstate(pmlmepriv, _FW_LINKED) && - is_same_network(&pmlmepriv->cur_network.network, pnetwork)) { - update_network(&pmlmepriv->cur_network.network, pnetwork, adapter, true); - } - -} - -u8 rtw_current_antenna(struct adapter *adapter) -{ - struct hal_data_8188e *haldata = &adapter->haldata; - - return haldata->CurAntenna; -} - -/* -Caller must hold pmlmepriv->lock first. -*/ -void rtw_update_scanned_network(struct adapter *adapter, struct wlan_bssid_ex *target) -{ - struct list_head *plist, *phead; - u32 bssid_ex_sz; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - struct __queue *queue = &pmlmepriv->scanned_queue; - struct wlan_network *pnetwork = NULL; - struct wlan_network *oldest = NULL; - - spin_lock_bh(&queue->lock); - phead = get_list_head(queue); - plist = phead->next; - - while (phead != plist) { - pnetwork = container_of(plist, struct wlan_network, list); - - if (is_same_network(&pnetwork->network, target)) - break; - if ((oldest == ((struct wlan_network *)0)) || - time_after(oldest->last_scanned, pnetwork->last_scanned)) - oldest = pnetwork; - plist = plist->next; - } - /* If we didn't find a match, then get a new network slot to initialize - * with this beacon's information */ - if (phead == plist) { - if (list_empty(&pmlmepriv->free_bss_pool.queue)) { - /* If there are no more slots, expire the oldest */ - pnetwork = oldest; - - target->PhyInfo.Optimum_antenna = rtw_current_antenna(adapter); - - memcpy(&pnetwork->network, target, get_wlan_bssid_ex_sz(target)); - /* variable initialize */ - pnetwork->fixed = false; - pnetwork->last_scanned = jiffies; - - pnetwork->network_type = 0; - pnetwork->aid = 0; - pnetwork->join_res = 0; - - /* bss info not receiving from the right channel */ - if (pnetwork->network.PhyInfo.SignalQuality == 101) - pnetwork->network.PhyInfo.SignalQuality = 0; - } else { - /* Otherwise just pull from the free list */ - - pnetwork = rtw_alloc_network(pmlmepriv); /* will update scan_time */ - - if (!pnetwork) - goto exit; - - bssid_ex_sz = get_wlan_bssid_ex_sz(target); - target->Length = bssid_ex_sz; - target->PhyInfo.Optimum_antenna = rtw_current_antenna(adapter); - memcpy(&pnetwork->network, target, bssid_ex_sz); - - pnetwork->last_scanned = jiffies; - - /* bss info not receiving from the right channel */ - if (pnetwork->network.PhyInfo.SignalQuality == 101) - pnetwork->network.PhyInfo.SignalQuality = 0; - list_add_tail(&pnetwork->list, &queue->queue); - } - } else { - /* we have an entry and we are going to update it. But this entry may - * be already expired. In this case we do the same as we found a new - * net and call the new_net handler - */ - bool update_ie = true; - - pnetwork->last_scanned = jiffies; - - /* target.Reserved[0]== 1, means that scanned network is a bcn frame. */ - /* probe resp(3) > beacon(1) > probe req(2) */ - if ((target->Reserved[0] != 2) && - (target->Reserved[0] >= pnetwork->network.Reserved[0])) - update_ie = true; - else - update_ie = false; - update_network(&pnetwork->network, target, adapter, update_ie); - } - -exit: - spin_unlock_bh(&queue->lock); - -} - -static void rtw_add_network(struct adapter *adapter, - struct wlan_bssid_ex *pnetwork) -{ - - rtw_wlan_bssid_ex_remove_p2p_attr(pnetwork, P2P_ATTR_GROUP_INFO); - update_current_network(adapter, pnetwork); - rtw_update_scanned_network(adapter, pnetwork); - -} - -/* select the desired network based on the capability of the (i)bss. */ -/* check items: (1) security */ -/* (2) network_type */ -/* (3) WMM */ -/* (4) HT */ -/* (5) others */ -static bool rtw_is_desired_network(struct adapter *adapter, struct wlan_network *pnetwork) -{ - struct security_priv *psecuritypriv = &adapter->securitypriv; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - u32 desired_encmode; - u32 privacy; - - /* u8 wps_ie[512]; */ - uint wps_ielen; - - int bselected = true; - - desired_encmode = psecuritypriv->ndisencryptstatus; - privacy = pnetwork->network.Privacy; - - if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS)) { - if (rtw_get_wps_ie(pnetwork->network.IEs + _FIXED_IE_LENGTH_, pnetwork->network.IELength - _FIXED_IE_LENGTH_, NULL, &wps_ielen)) - return true; - else - return false; - } - if (adapter->registrypriv.wifi_spec == 1) { /* for correct flow of 8021X to do.... */ - u8 *p = NULL; - uint ie_len = 0; - - if ((desired_encmode == Ndis802_11EncryptionDisabled) && (privacy != 0)) - bselected = false; - if (psecuritypriv->ndisauthtype == Ndis802_11AuthModeWPA2PSK) { - p = rtw_get_ie(pnetwork->network.IEs + _BEACON_IE_OFFSET_, - _RSN_IE_2_, &ie_len, - (pnetwork->network.IELength - - _BEACON_IE_OFFSET_)); - if (p && ie_len > 0) - bselected = true; - else - bselected = false; - } - } - - if ((desired_encmode != Ndis802_11EncryptionDisabled) && (privacy == 0)) - bselected = false; - - if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) { - if (pnetwork->network.InfrastructureMode != pmlmepriv->cur_network.network.InfrastructureMode) - bselected = false; - } - - return bselected; -} - -void rtw_survey_event_callback(struct adapter *adapter, u8 *pbuf) -{ - u32 len; - struct wlan_bssid_ex *pnetwork; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - - pnetwork = (struct wlan_bssid_ex *)pbuf; - - len = get_wlan_bssid_ex_sz(pnetwork); - if (len > (sizeof(struct wlan_bssid_ex))) - return; - spin_lock_bh(&pmlmepriv->lock); - - /* update IBSS_network 's timestamp */ - if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) { - if (!memcmp(&pmlmepriv->cur_network.network.MacAddress, pnetwork->MacAddress, ETH_ALEN)) { - struct wlan_network *ibss_wlan = NULL; - - memcpy(pmlmepriv->cur_network.network.IEs, pnetwork->IEs, 8); - spin_lock_bh(&pmlmepriv->scanned_queue.lock); - ibss_wlan = rtw_find_network(&pmlmepriv->scanned_queue, pnetwork->MacAddress); - if (ibss_wlan) { - memcpy(ibss_wlan->network.IEs, pnetwork->IEs, 8); - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - goto exit; - } - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - } - } - - /* lock pmlmepriv->lock when you accessing network_q */ - if (!check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) { - if (pnetwork->Ssid.Ssid[0] == 0) - pnetwork->Ssid.SsidLength = 0; - rtw_add_network(adapter, pnetwork); - } - -exit: - - spin_unlock_bh(&pmlmepriv->lock); -} - -static void rtw_xmit_schedule(struct adapter *padapter) -{ - struct xmit_priv *pxmitpriv; - - if (!padapter) - return; - - pxmitpriv = &padapter->xmitpriv; - - spin_lock_bh(&pxmitpriv->lock); - - if (rtw_txframes_pending(padapter)) - tasklet_hi_schedule(&pxmitpriv->xmit_tasklet); - - spin_unlock_bh(&pxmitpriv->lock); -} - -void rtw_surveydone_event_callback(struct adapter *adapter, u8 *pbuf) -{ - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - - spin_lock_bh(&pmlmepriv->lock); - - if (pmlmepriv->wps_probe_req_ie) { - pmlmepriv->wps_probe_req_ie_len = 0; - kfree(pmlmepriv->wps_probe_req_ie); - pmlmepriv->wps_probe_req_ie = NULL; - } - - if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) - _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY); - - spin_unlock_bh(&pmlmepriv->lock); - - del_timer_sync(&pmlmepriv->scan_to_timer); - - spin_lock_bh(&pmlmepriv->lock); - rtw_set_signal_stat_timer(&adapter->recvpriv); - - if (pmlmepriv->to_join) { - if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) { - if (!check_fwstate(pmlmepriv, _FW_LINKED)) { - set_fwstate(pmlmepriv, _FW_UNDER_LINKING); - - if (rtw_select_and_join_from_scanned_queue(pmlmepriv) == _SUCCESS) { - _set_timer(&pmlmepriv->assoc_timer, MAX_JOIN_TIMEOUT); - } else { - struct wlan_bssid_ex *pdev_network = &adapter->registrypriv.dev_network; - u8 *pibss = adapter->registrypriv.dev_network.MacAddress; - - _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY); - - memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid)); - - rtw_update_registrypriv_dev_network(adapter); - rtw_generate_random_ibss(pibss); - - pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE; - - rtw_createbss_cmd(adapter); - pmlmepriv->to_join = false; - } - } - } else { - int s_ret; - set_fwstate(pmlmepriv, _FW_UNDER_LINKING); - pmlmepriv->to_join = false; - s_ret = rtw_select_and_join_from_scanned_queue(pmlmepriv); - if (s_ret == _SUCCESS) { - _set_timer(&pmlmepriv->assoc_timer, MAX_JOIN_TIMEOUT); - } else { - if (rtw_to_roaming(adapter) != 0) { - if (--pmlmepriv->to_roaming == 0 || - rtw_sitesurvey_cmd(adapter, &pmlmepriv->assoc_ssid, 1) != _SUCCESS) { - rtw_set_roaming(adapter, 0); - rtw_free_assoc_resources(adapter, 1); - rtw_indicate_disconnect(adapter); - } else { - pmlmepriv->to_join = true; - } - } else { - rtw_indicate_disconnect(adapter); - } - _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); - } - } - } - - indicate_wx_scan_complete_event(adapter); - - spin_unlock_bh(&pmlmepriv->lock); - - if (check_fwstate(pmlmepriv, _FW_LINKED)) - p2p_ps_wk_cmd(adapter, P2P_PS_SCAN_DONE, 0); - - rtw_xmit_schedule(adapter); -} - -static void free_scanqueue(struct mlme_priv *pmlmepriv) -{ - struct __queue *free_queue = &pmlmepriv->free_bss_pool; - struct __queue *scan_queue = &pmlmepriv->scanned_queue; - struct list_head *plist, *phead, *ptemp; - - spin_lock_bh(&scan_queue->lock); - spin_lock_bh(&free_queue->lock); - - phead = get_list_head(scan_queue); - plist = phead->next; - - while (plist != phead) { - ptemp = plist->next; - list_del_init(plist); - list_add_tail(plist, &free_queue->queue); - plist = ptemp; - pmlmepriv->num_of_scanned--; - } - - spin_unlock_bh(&free_queue->lock); - spin_unlock_bh(&scan_queue->lock); -} - -/* -*rtw_free_assoc_resources: the caller has to lock pmlmepriv->lock -*/ -void rtw_free_assoc_resources(struct adapter *adapter, int lock_scanned_queue) -{ - struct wlan_network *pwlan = NULL; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - struct sta_priv *pstapriv = &adapter->stapriv; - struct wlan_network *tgt_network = &pmlmepriv->cur_network; - - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_AP_STATE)) { - struct sta_info *psta; - - psta = rtw_get_stainfo(&adapter->stapriv, tgt_network->network.MacAddress); - - spin_lock_bh(&pstapriv->sta_hash_lock); - rtw_free_stainfo(adapter, psta); - spin_unlock_bh(&pstapriv->sta_hash_lock); - } - - if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE | WIFI_AP_STATE)) { - struct sta_info *psta; - - rtw_free_all_stainfo(adapter); - - psta = rtw_get_bcmc_stainfo(adapter); - spin_lock_bh(&pstapriv->sta_hash_lock); - rtw_free_stainfo(adapter, psta); - spin_unlock_bh(&pstapriv->sta_hash_lock); - - rtw_init_bcmc_stainfo(adapter); - } - - if (lock_scanned_queue) - spin_lock_bh(&pmlmepriv->scanned_queue.lock); - - pwlan = rtw_find_network(&pmlmepriv->scanned_queue, tgt_network->network.MacAddress); - if (pwlan) - pwlan->fixed = false; - - if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) && (adapter->stapriv.asoc_sta_count == 1))) - rtw_free_network_nolock(pmlmepriv, pwlan); - - if (lock_scanned_queue) - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - pmlmepriv->key_mask = 0; - -} - -static struct rt_pmkid_list backup_pmkid[NUM_PMKID_CACHE]; - -static void rtw_reset_securitypriv(struct adapter *adapter) -{ - u8 backup_index; - u8 backup_counter; - u32 backup_time; - - if (adapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) { - /* 802.1x */ - /* We have to backup the PMK information for WiFi PMK Caching test item. */ - /* Backup the btkip_countermeasure information. */ - /* When the countermeasure is trigger, the driver have to disconnect with AP for 60 seconds. */ - memcpy(&backup_pmkid[0], &adapter->securitypriv.PMKIDList[0], sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE); - backup_index = adapter->securitypriv.PMKIDIndex; - backup_counter = adapter->securitypriv.btkip_countermeasure; - backup_time = adapter->securitypriv.btkip_countermeasure_time; - memset((unsigned char *)&adapter->securitypriv, 0, sizeof(struct security_priv)); - - /* Restore the PMK information to securitypriv structure for the following connection. */ - memcpy(&adapter->securitypriv.PMKIDList[0], - &backup_pmkid[0], - sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE); - adapter->securitypriv.PMKIDIndex = backup_index; - adapter->securitypriv.btkip_countermeasure = backup_counter; - adapter->securitypriv.btkip_countermeasure_time = backup_time; - adapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen; - adapter->securitypriv.ndisencryptstatus = Ndis802_11WEPDisabled; - } else { - /* reset values in securitypriv */ - struct security_priv *psec_priv = &adapter->securitypriv; - - psec_priv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */ - psec_priv->dot11PrivacyAlgrthm = _NO_PRIVACY_; - psec_priv->dot11PrivacyKeyIndex = 0; - psec_priv->dot118021XGrpPrivacy = _NO_PRIVACY_; - psec_priv->dot118021XGrpKeyid = 1; - psec_priv->ndisauthtype = Ndis802_11AuthModeOpen; - psec_priv->ndisencryptstatus = Ndis802_11WEPDisabled; - } -} - -/* -*rtw_indicate_connect: the caller has to lock pmlmepriv->lock -*/ -void rtw_indicate_connect(struct adapter *padapter) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - pmlmepriv->to_join = false; - - if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED)) { - set_fwstate(pmlmepriv, _FW_LINKED); - - rtw_led_control(padapter, LED_CTL_LINK); - - rtw_indicate_wx_assoc_event(padapter); - netif_carrier_on(padapter->pnetdev); - if (padapter->pid[2] != 0) - rtw_signal_process(padapter->pid[2], SIGALRM); - } - - pmlmepriv->to_roaming = 0; -} - -/* -*rtw_indicate_disconnect: the caller has to lock pmlmepriv->lock -*/ -void rtw_indicate_disconnect(struct adapter *padapter) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING | WIFI_UNDER_WPS); - - if (pmlmepriv->to_roaming > 0) - _clr_fwstate_(pmlmepriv, _FW_LINKED); - - if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) || - (pmlmepriv->to_roaming <= 0)) { - /* Do it first for tx broadcast pkt after disconnection issue! */ - netif_carrier_off(padapter->pnetdev); - - rtw_indicate_wx_disassoc_event(padapter); - rtw_reset_securitypriv(padapter); - - _clr_fwstate_(pmlmepriv, _FW_LINKED); - rtw_led_control(padapter, LED_CTL_NO_LINK); - } - p2p_ps_wk_cmd(padapter, P2P_PS_DISABLE, 1); - - rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_DISCONNECT, 1); - -} - -inline void rtw_indicate_scan_done(struct adapter *padapter) -{ - indicate_wx_scan_complete_event(padapter); -} - -static struct sta_info *rtw_joinbss_update_stainfo(struct adapter *padapter, struct wlan_network *pnetwork) -{ - int i; - struct sta_info *bmc_sta, *psta = NULL; - struct recv_reorder_ctrl *preorder_ctrl; - struct sta_priv *pstapriv = &padapter->stapriv; - - psta = rtw_get_stainfo(pstapriv, pnetwork->network.MacAddress); - if (!psta) - psta = rtw_alloc_stainfo(pstapriv, pnetwork->network.MacAddress); - - if (psta) { /* update ptarget_sta */ - psta->aid = pnetwork->join_res; - psta->mac_id = 0; - /* sta mode */ - rtl8188e_SetHalODMVar(padapter, psta, true); - /* security related */ - if (padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) { - padapter->securitypriv.binstallGrpkey = false; - padapter->securitypriv.busetkipkey = false; - padapter->securitypriv.bgrpkey_handshake = false; - psta->ieee8021x_blocked = true; - psta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm; - memset((u8 *)&psta->dot118021x_UncstKey, 0, sizeof(union Keytype)); - memset((u8 *)&psta->dot11tkiprxmickey, 0, sizeof(union Keytype)); - memset((u8 *)&psta->dot11tkiptxmickey, 0, sizeof(union Keytype)); - memset((u8 *)&psta->dot11txpn, 0, sizeof(union pn48)); - memset((u8 *)&psta->dot11rxpn, 0, sizeof(union pn48)); - } - /* When doing the WPS, the wps_ie_len won't equal to 0 */ - /* And the Wi-Fi driver shouldn't allow the data packet to be transmitted. */ - if (padapter->securitypriv.wps_ie_len != 0) { - psta->ieee8021x_blocked = true; - padapter->securitypriv.wps_ie_len = 0; - } - /* for A-MPDU Rx reordering buffer control for bmc_sta & sta_info */ - /* if A-MPDU Rx is enabled, resetting rx_ordering_ctrl wstart_b(indicate_seq) to default value = 0xffff */ - /* todo: check if AP can send A-MPDU packets */ - for (i = 0; i < 16; i++) { - /* preorder_ctrl = &precvpriv->recvreorder_ctrl[i]; */ - preorder_ctrl = &psta->recvreorder_ctrl[i]; - preorder_ctrl->enable = false; - preorder_ctrl->indicate_seq = 0xffff; - preorder_ctrl->wend_b = 0xffff; - preorder_ctrl->wsize_b = 64;/* max_ampdu_sz; ex. 32(kbytes) -> wsize_b = 32 */ - } - bmc_sta = rtw_get_bcmc_stainfo(padapter); - if (bmc_sta) { - for (i = 0; i < 16; i++) { - /* preorder_ctrl = &precvpriv->recvreorder_ctrl[i]; */ - preorder_ctrl = &bmc_sta->recvreorder_ctrl[i]; - preorder_ctrl->enable = false; - preorder_ctrl->indicate_seq = 0xffff; - preorder_ctrl->wend_b = 0xffff; - preorder_ctrl->wsize_b = 64;/* max_ampdu_sz; ex. 32(kbytes) -> wsize_b = 32 */ - } - } - /* misc. */ - update_sta_info(padapter, psta); - } - return psta; -} - -/* pnetwork: returns from rtw_joinbss_event_callback */ -/* ptarget_wlan: found from scanned_queue */ -static void rtw_joinbss_update_network(struct adapter *padapter, struct wlan_network *ptarget_wlan, struct wlan_network *pnetwork) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wlan_network *cur_network = &pmlmepriv->cur_network; - - /* why not use ptarget_wlan?? */ - memcpy(&cur_network->network, &pnetwork->network, pnetwork->network.Length); - /* some IEs in pnetwork is wrong, so we should use ptarget_wlan IEs */ - cur_network->network.IELength = ptarget_wlan->network.IELength; - memcpy(&cur_network->network.IEs[0], &ptarget_wlan->network.IEs[0], MAX_IE_SZ); - - cur_network->aid = pnetwork->join_res; - - rtw_set_signal_stat_timer(&padapter->recvpriv); - padapter->recvpriv.signal_strength = ptarget_wlan->network.PhyInfo.SignalStrength; - padapter->recvpriv.signal_qual = ptarget_wlan->network.PhyInfo.SignalQuality; - /* the ptarget_wlan->network.Rssi is raw data, we use ptarget_wlan->network.PhyInfo.SignalStrength instead (has scaled) */ - padapter->recvpriv.rssi = translate_percentage_to_dbm(ptarget_wlan->network.PhyInfo.SignalStrength); - rtw_set_signal_stat_timer(&padapter->recvpriv); - - /* update fw_state will clr _FW_UNDER_LINKING here indirectly */ - switch (pnetwork->network.InfrastructureMode) { - case Ndis802_11Infrastructure: - if (pmlmepriv->fw_state & WIFI_UNDER_WPS) - pmlmepriv->fw_state = WIFI_STATION_STATE | WIFI_UNDER_WPS; - else - pmlmepriv->fw_state = WIFI_STATION_STATE; - break; - case Ndis802_11IBSS: - pmlmepriv->fw_state = WIFI_ADHOC_STATE; - break; - default: - pmlmepriv->fw_state = WIFI_NULL_STATE; - break; - } - - rtw_update_ht_cap(padapter, cur_network->network.IEs, cur_network->network.IELength); -} - -/* Notes: the function could be > passive_level (the same context as Rx tasklet) */ -/* pnetwork: returns from rtw_joinbss_event_callback */ -/* ptarget_wlan: found from scanned_queue */ -/* if join_res > 0, for (fw_state == WIFI_STATION_STATE), we check if "ptarget_sta" & "ptarget_wlan" exist. */ -/* if join_res > 0, for (fw_state == WIFI_ADHOC_STATE), we only check if "ptarget_wlan" exist. */ -/* if join_res > 0, update "cur_network->network" from "pnetwork->network" if (ptarget_wlan != NULL). */ - -void rtw_joinbss_event_prehandle(struct adapter *adapter, u8 *pbuf) -{ - struct sta_info *ptarget_sta = NULL, *pcur_sta = NULL; - struct sta_priv *pstapriv = &adapter->stapriv; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - struct wlan_network *pnetwork = (struct wlan_network *)pbuf; - struct wlan_network *cur_network = &pmlmepriv->cur_network; - struct wlan_network *pcur_wlan = NULL, *ptarget_wlan = NULL; - unsigned int the_same_macaddr = false; - - the_same_macaddr = !memcmp(pnetwork->network.MacAddress, cur_network->network.MacAddress, ETH_ALEN); - - pnetwork->network.Length = get_wlan_bssid_ex_sz(&pnetwork->network); - if (pnetwork->network.Length > sizeof(struct wlan_bssid_ex)) - return; - - spin_lock_bh(&pmlmepriv->lock); - - if (pnetwork->join_res > 0) { - spin_lock_bh(&pmlmepriv->scanned_queue.lock); - if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) { - /* s1. find ptarget_wlan */ - if (check_fwstate(pmlmepriv, _FW_LINKED)) { - if (the_same_macaddr) { - ptarget_wlan = rtw_find_network(&pmlmepriv->scanned_queue, cur_network->network.MacAddress); - } else { - pcur_wlan = rtw_find_network(&pmlmepriv->scanned_queue, cur_network->network.MacAddress); - if (pcur_wlan) - pcur_wlan->fixed = false; - - pcur_sta = rtw_get_stainfo(pstapriv, cur_network->network.MacAddress); - if (pcur_sta) { - spin_lock_bh(&pstapriv->sta_hash_lock); - rtw_free_stainfo(adapter, pcur_sta); - spin_unlock_bh(&pstapriv->sta_hash_lock); - } - - ptarget_wlan = rtw_find_network(&pmlmepriv->scanned_queue, pnetwork->network.MacAddress); - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { - if (ptarget_wlan) - ptarget_wlan->fixed = true; - } - } - } else { - ptarget_wlan = rtw_find_network(&pmlmepriv->scanned_queue, pnetwork->network.MacAddress); - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { - if (ptarget_wlan) - ptarget_wlan->fixed = true; - } - } - - /* s2. update cur_network */ - if (ptarget_wlan) { - rtw_joinbss_update_network(adapter, ptarget_wlan, pnetwork); - } else { - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - goto ignore_joinbss_callback; - } - - /* s3. find ptarget_sta & update ptarget_sta after update cur_network only for station mode */ - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { - ptarget_sta = rtw_joinbss_update_stainfo(adapter, pnetwork); - if (!ptarget_sta) { - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - goto ignore_joinbss_callback; - } - } - - /* s4. indicate connect */ - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { - pmlmepriv->cur_network_scanned = ptarget_wlan; - rtw_indicate_connect(adapter); - } - - spin_unlock_bh(&pmlmepriv->lock); - /* s5. Cancel assoc_timer */ - del_timer_sync(&pmlmepriv->assoc_timer); - spin_lock_bh(&pmlmepriv->lock); - } else { - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - goto ignore_joinbss_callback; - } - - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - - } else if (pnetwork->join_res == -4) { - rtw_reset_securitypriv(adapter); - _set_timer(&pmlmepriv->assoc_timer, 1); - - if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) - _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); - } else { /* if join_res < 0 (join fails), then try again */ - _set_timer(&pmlmepriv->assoc_timer, 1); - _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); - } - -ignore_joinbss_callback: - spin_unlock_bh(&pmlmepriv->lock); -} - -void rtw_joinbss_event_callback(struct adapter *adapter, u8 *pbuf) -{ - struct wlan_network *pnetwork = (struct wlan_network *)pbuf; - - mlmeext_joinbss_event_callback(adapter, pnetwork->join_res); - - rtw_xmit_schedule(adapter); -} - -void rtw_set_max_rpt_macid(struct adapter *adapter, u8 macid) -{ - rtw_write8(adapter, REG_TX_RPT_CTRL + 1, macid + 1); -} - -static u8 search_max_mac_id(struct adapter *padapter) -{ - u8 mac_id; - u8 aid; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct sta_priv *pstapriv = &padapter->stapriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - for (aid = (pstapriv->max_num_sta); aid > 0; aid--) { - if (pstapriv->sta_aid[aid - 1]) - break; - } - mac_id = aid + 1; - } else { - /* adhoc id = 31~2 */ - for (mac_id = (NUM_STA - 1); mac_id >= IBSS_START_MAC_ID; mac_id--) { - if (pmlmeinfo->FW_sta_info[mac_id].status == 1) - break; - } - } - return mac_id; -} - -/* FOR AP , AD-HOC mode */ -void rtw_sta_media_status_rpt(struct adapter *adapter, struct sta_info *psta, - u32 mstatus) -{ - u16 media_status_rpt; - u8 macid; - - if (!psta) - return; - - macid = search_max_mac_id(adapter); - rtw_set_max_rpt_macid(adapter, macid); - - /* MACID|OPMODE:1 connect */ - media_status_rpt = (u16)((psta->mac_id << 8) | mstatus); - rtl8188e_set_FwMediaStatus_cmd(adapter, media_status_rpt); -} - -void rtw_stassoc_event_callback(struct adapter *adapter, u8 *pbuf) -{ - struct sta_info *psta; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - struct stassoc_event *pstassoc = (struct stassoc_event *)pbuf; - struct wlan_network *cur_network = &pmlmepriv->cur_network; - struct wlan_network *ptarget_wlan = NULL; - - if (!rtw_access_ctrl(adapter, pstassoc->macaddr)) - return; - - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - psta = rtw_get_stainfo(&adapter->stapriv, pstassoc->macaddr); - if (psta) - rtw_indicate_sta_assoc_event(adapter, psta); - return; - } - /* for AD-HOC mode */ - psta = rtw_get_stainfo(&adapter->stapriv, pstassoc->macaddr); - if (psta) - /* the sta have been in sta_info_queue => do nothing */ - return; /* between drv has received this event before and fw have not yet to set key to CAM_ENTRY) */ - psta = rtw_alloc_stainfo(&adapter->stapriv, pstassoc->macaddr); - if (!psta) - return; - /* to do: init sta_info variable */ - psta->qos_option = 0; - psta->mac_id = (uint)pstassoc->cam_id; - - /* for ad-hoc mode */ - rtl8188e_SetHalODMVar(adapter, psta, true); - rtw_sta_media_status_rpt(adapter, psta, 1); - if (adapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) - psta->dot118021XPrivacy = adapter->securitypriv.dot11PrivacyAlgrthm; - psta->ieee8021x_blocked = false; - spin_lock_bh(&pmlmepriv->lock); - if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) || - (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE))) { - if (adapter->stapriv.asoc_sta_count == 2) { - spin_lock_bh(&pmlmepriv->scanned_queue.lock); - ptarget_wlan = rtw_find_network(&pmlmepriv->scanned_queue, cur_network->network.MacAddress); - pmlmepriv->cur_network_scanned = ptarget_wlan; - if (ptarget_wlan) - ptarget_wlan->fixed = true; - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - /* a sta + bc/mc_stainfo (not Ibss_stainfo) */ - rtw_indicate_connect(adapter); - } - } - spin_unlock_bh(&pmlmepriv->lock); - mlmeext_sta_add_event_callback(adapter, psta); -} - -void rtw_stadel_event_callback(struct adapter *adapter, u8 *pbuf) -{ - int mac_id = -1; - struct sta_info *psta; - struct wlan_network *pwlan = NULL; - struct wlan_bssid_ex *pdev_network = NULL; - u8 *pibss = NULL; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - struct stadel_event *pstadel = (struct stadel_event *)pbuf; - struct sta_priv *pstapriv = &adapter->stapriv; - struct wlan_network *tgt_network = &pmlmepriv->cur_network; - - psta = rtw_get_stainfo(&adapter->stapriv, pstadel->macaddr); - if (psta) - mac_id = psta->mac_id; - else - mac_id = pstadel->mac_id; - - if (mac_id >= 0) { - u16 media_status; - media_status = (mac_id << 8) | 0; /* MACID|OPMODE:0 means disconnect */ - /* for STA, AP, ADHOC mode, report disconnect stauts to FW */ - rtl8188e_set_FwMediaStatus_cmd(adapter, media_status); - } - - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) - return; - - mlmeext_sta_del_event_callback(adapter); - - spin_lock_bh(&pmlmepriv->lock); - - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { - if (adapter->registrypriv.wifi_spec == 1) - rtw_set_roaming(adapter, 0); /* don't roam */ - else if (rtw_to_roaming(adapter) > 0) - pmlmepriv->to_roaming--; /* this stadel_event is caused by roaming, decrease to_roaming */ - else if (rtw_to_roaming(adapter) == 0) - rtw_set_roaming(adapter, - adapter->registrypriv.max_roaming_times); - - if (*((unsigned short *)(pstadel->rsvd)) != WLAN_REASON_EXPIRATION_CHK) - rtw_set_roaming(adapter, 0); /* don't roam */ - - rtw_free_uc_swdec_pending_queue(adapter); - - rtw_free_assoc_resources(adapter, 1); - rtw_indicate_disconnect(adapter); - spin_lock_bh(&pmlmepriv->scanned_queue.lock); - /* remove the network entry in scanned_queue */ - pwlan = rtw_find_network(&pmlmepriv->scanned_queue, tgt_network->network.MacAddress); - if (pwlan) { - pwlan->fixed = false; - rtw_free_network_nolock(pmlmepriv, pwlan); - } - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - _rtw_roaming(adapter, tgt_network); - } - if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) || - check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) { - spin_lock_bh(&pstapriv->sta_hash_lock); - rtw_free_stainfo(adapter, psta); - spin_unlock_bh(&pstapriv->sta_hash_lock); - - if (adapter->stapriv.asoc_sta_count == 1) { /* a sta + bc/mc_stainfo (not Ibss_stainfo) */ - spin_lock_bh(&pmlmepriv->scanned_queue.lock); - /* free old ibss network */ - pwlan = rtw_find_network(&pmlmepriv->scanned_queue, tgt_network->network.MacAddress); - if (pwlan) { - pwlan->fixed = false; - rtw_free_network_nolock(pmlmepriv, pwlan); - } - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - /* re-create ibss */ - pdev_network = &adapter->registrypriv.dev_network; - pibss = adapter->registrypriv.dev_network.MacAddress; - - memcpy(pdev_network, &tgt_network->network, get_wlan_bssid_ex_sz(&tgt_network->network)); - - memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid)); - - rtw_update_registrypriv_dev_network(adapter); - - rtw_generate_random_ibss(pibss); - - if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) { - set_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE); - _clr_fwstate_(pmlmepriv, WIFI_ADHOC_STATE); - } - - rtw_createbss_cmd(adapter); - } - } - spin_unlock_bh(&pmlmepriv->lock); - -} - -/* -* _rtw_join_timeout_handler - Timeout/failure handler for CMD JoinBss -* @adapter: pointer to struct adapter structure -*/ -void _rtw_join_timeout_handler (struct adapter *adapter) -{ - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - int do_join_r; - - if (adapter->bDriverStopped || adapter->bSurpriseRemoved) - return; - - spin_lock_irq(&pmlmepriv->lock); - - if (rtw_to_roaming(adapter) > 0) { /* join timeout caused by roaming */ - while (1) { - pmlmepriv->to_roaming--; - if (rtw_to_roaming(adapter) != 0) { /* try another */ - do_join_r = rtw_do_join(adapter); - if (do_join_r != _SUCCESS) - continue; - break; - } else { - rtw_indicate_disconnect(adapter); - break; - } - } - } else { - rtw_indicate_disconnect(adapter); - free_scanqueue(pmlmepriv);/* */ - } - spin_unlock_irq(&pmlmepriv->lock); - -} - -/* -* rtw_scan_timeout_handler - Timeout/Failure handler for CMD SiteSurvey -* @adapter: pointer to struct adapter structure -*/ -void rtw_scan_timeout_handler (struct adapter *adapter) -{ - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - - spin_lock_bh(&pmlmepriv->lock); - _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY); - spin_unlock_bh(&pmlmepriv->lock); - rtw_indicate_scan_done(adapter); -} - -static void rtw_auto_scan_handler(struct adapter *padapter) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - /* auto site survey per 60sec */ - if (pmlmepriv->scan_interval > 0) { - pmlmepriv->scan_interval--; - if (pmlmepriv->scan_interval == 0) { - rtw_set_802_11_bssid_list_scan(padapter, NULL, 0); - pmlmepriv->scan_interval = SCAN_INTERVAL;/* 30*2 sec = 60sec */ - } - } -} - -void rtw_dynamic_check_timer_handlder(struct adapter *adapter) -{ - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - struct registry_priv *pregistrypriv = &adapter->registrypriv; - - if (!adapter) - return; - if (!adapter->hw_init_completed) - return; - if ((adapter->bDriverStopped) || (adapter->bSurpriseRemoved)) - return; - if (adapter->net_closed) - return; - rtw_dynamic_chk_wk_cmd(adapter); - - if (pregistrypriv->wifi_spec == 1) { - struct wifidirect_info *pwdinfo = &adapter->wdinfo; - if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) { - /* auto site survey */ - rtw_auto_scan_handler(adapter); - } - } - - rcu_read_lock(); - - if (rcu_dereference(adapter->pnetdev->rx_handler_data) && - check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_ADHOC_STATE)) { - /* expire NAT2.5 entry */ - nat25_db_expire(adapter); - - if (adapter->pppoe_connection_in_progress > 0) - adapter->pppoe_connection_in_progress--; - - /* due to rtw_dynamic_check_timer_handlder() is called every 2 seconds */ - if (adapter->pppoe_connection_in_progress > 0) - adapter->pppoe_connection_in_progress--; - } - - rcu_read_unlock(); -} - -#define RTW_SCAN_RESULT_EXPIRE 2000 - -/* -* Select a new join candidate from the original @param candidate and @param competitor -* @return true: candidate is updated -* @return false: candidate is not updated -*/ -static int rtw_check_join_candidate(struct mlme_priv *pmlmepriv - , struct wlan_network **candidate, struct wlan_network *competitor) -{ - int updated = false; - struct adapter *adapter = container_of(pmlmepriv, struct adapter, mlmepriv); - unsigned long scan_res_expire; - - /* check bssid, if needed */ - if (pmlmepriv->assoc_by_bssid) { - if (memcmp(competitor->network.MacAddress, pmlmepriv->assoc_bssid, ETH_ALEN)) - goto exit; - } - - /* check ssid, if needed */ - if (pmlmepriv->assoc_ssid.SsidLength) { - if (competitor->network.Ssid.SsidLength != pmlmepriv->assoc_ssid.SsidLength || - memcmp(competitor->network.Ssid.Ssid, pmlmepriv->assoc_ssid.Ssid, pmlmepriv->assoc_ssid.SsidLength)) - goto exit; - } - - if (!rtw_is_desired_network(adapter, competitor)) - goto exit; - - scan_res_expire = competitor->last_scanned + msecs_to_jiffies(RTW_SCAN_RESULT_EXPIRE); - if (rtw_to_roaming(adapter) > 0) { - if (time_after(jiffies, scan_res_expire) || - !is_same_ess(&competitor->network, &pmlmepriv->cur_network.network)) - goto exit; - } - - if (!*candidate || (*candidate)->network.Rssi < competitor->network.Rssi) { - *candidate = competitor; - updated = true; - } - -exit: - return updated; -} - -/* -Calling context: -The caller of the sub-routine will be in critical section... -The caller must hold the following spinlock -pmlmepriv->lock -*/ - -int rtw_select_and_join_from_scanned_queue(struct mlme_priv *pmlmepriv) -{ - int ret; - struct list_head *phead; - struct adapter *adapter; - struct __queue *queue = &pmlmepriv->scanned_queue; - struct wlan_network *pnetwork = NULL; - struct wlan_network *candidate = NULL; - - spin_lock_bh(&pmlmepriv->scanned_queue.lock); - phead = get_list_head(queue); - adapter = (struct adapter *)pmlmepriv->nic_hdl; - pmlmepriv->pscanned = phead->next; - while (phead != pmlmepriv->pscanned) { - pnetwork = container_of(pmlmepriv->pscanned, struct wlan_network, list); - pmlmepriv->pscanned = pmlmepriv->pscanned->next; - rtw_check_join_candidate(pmlmepriv, &candidate, pnetwork); - } - if (!candidate) { - ret = _FAIL; - goto exit; - } - - /* check for situation of _FW_LINKED */ - if (check_fwstate(pmlmepriv, _FW_LINKED)) { - rtw_disassoc_cmd(adapter, 0, true); - rtw_indicate_disconnect(adapter); - rtw_free_assoc_resources(adapter, 0); - } - - ret = rtw_joinbss_cmd(adapter, candidate); - -exit: - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - - return ret; -} - -int rtw_set_auth(struct adapter *adapter, struct security_priv *psecuritypriv) -{ - struct cmd_obj *pcmd; - struct setauth_parm *psetauthparm; - struct cmd_priv *pcmdpriv = &adapter->cmdpriv; - int res = _SUCCESS; - - pcmd = kzalloc(sizeof(*pcmd), GFP_KERNEL); - if (!pcmd) { - res = _FAIL; /* try again */ - goto exit; - } - - psetauthparm = kzalloc(sizeof(*psetauthparm), GFP_KERNEL); - if (!psetauthparm) { - kfree(pcmd); - res = _FAIL; - goto exit; - } - psetauthparm->mode = (unsigned char)psecuritypriv->dot11AuthAlgrthm; - pcmd->cmdcode = _SetAuth_CMD_; - pcmd->parmbuf = (unsigned char *)psetauthparm; - pcmd->cmdsz = (sizeof(struct setauth_parm)); - pcmd->rsp = NULL; - pcmd->rspsz = 0; - INIT_LIST_HEAD(&pcmd->list); - res = rtw_enqueue_cmd(pcmdpriv, pcmd); -exit: - - return res; -} - -int rtw_set_key(struct adapter *adapter, struct security_priv *psecuritypriv, int keyid, u8 set_tx) -{ - u8 keylen; - struct cmd_obj *pcmd; - struct setkey_parm *psetkeyparm; - struct cmd_priv *pcmdpriv = &adapter->cmdpriv; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - int res = _SUCCESS; - - pcmd = kzalloc(sizeof(*pcmd), GFP_KERNEL); - if (!pcmd) { - res = _FAIL; /* try again */ - goto exit; - } - psetkeyparm = kzalloc(sizeof(*psetkeyparm), GFP_KERNEL); - if (!psetkeyparm) { - kfree(pcmd); - res = _FAIL; - goto exit; - } - - if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) - psetkeyparm->algorithm = (unsigned char)psecuritypriv->dot118021XGrpPrivacy; - else - psetkeyparm->algorithm = (u8)psecuritypriv->dot11PrivacyAlgrthm; - psetkeyparm->keyid = (u8)keyid;/* 0~3 */ - psetkeyparm->set_tx = set_tx; - pmlmepriv->key_mask |= BIT(psetkeyparm->keyid); - - switch (psetkeyparm->algorithm) { - case _WEP40_: - keylen = 5; - memcpy(&psetkeyparm->key[0], &psecuritypriv->dot11DefKey[keyid].skey[0], keylen); - break; - case _WEP104_: - keylen = 13; - memcpy(&psetkeyparm->key[0], &psecuritypriv->dot11DefKey[keyid].skey[0], keylen); - break; - case _TKIP_: - keylen = 16; - memcpy(&psetkeyparm->key, &psecuritypriv->dot118021XGrpKey[keyid], keylen); - psetkeyparm->grpkey = 1; - break; - case _AES_: - keylen = 16; - memcpy(&psetkeyparm->key, &psecuritypriv->dot118021XGrpKey[keyid], keylen); - psetkeyparm->grpkey = 1; - break; - default: - kfree(psetkeyparm); - kfree(pcmd); - res = _FAIL; - goto exit; - } - pcmd->cmdcode = _SetKey_CMD_; - pcmd->parmbuf = (u8 *)psetkeyparm; - pcmd->cmdsz = (sizeof(struct setkey_parm)); - pcmd->rsp = NULL; - pcmd->rspsz = 0; - INIT_LIST_HEAD(&pcmd->list); - res = rtw_enqueue_cmd(pcmdpriv, pcmd); -exit: - return res; -} - -/* adjust IEs for rtw_joinbss_cmd in WMM */ -int rtw_restruct_wmm_ie(struct adapter *adapter, u8 *in_ie, u8 *out_ie, uint in_len, uint initial_out_len) -{ - unsigned int ielength = 0; - unsigned int i, j; - - i = 12; /* after the fixed IE */ - while (i < in_len) { - ielength = initial_out_len; - - if (in_ie[i] == 0xDD && in_ie[i + 2] == 0x00 && in_ie[i + 3] == 0x50 && in_ie[i + 4] == 0xF2 && in_ie[i + 5] == 0x02 && i + 5 < in_len) { - /* WMM element ID and OUI */ - /* Append WMM IE to the last index of out_ie */ - - for (j = i; j < i + 9; j++) { - out_ie[ielength] = in_ie[j]; - ielength++; - } - out_ie[initial_out_len + 1] = 0x07; - out_ie[initial_out_len + 6] = 0x00; - out_ie[initial_out_len + 8] = 0x00; - break; - } - i += (in_ie[i + 1] + 2); /* to the next IE element */ - } - return ielength; -} - -/* */ -/* Search by BSSID, */ -/* Return Value: */ -/* -1 :if there is no pre-auth key in the table */ -/* >= 0 :if there is pre-auth key, and return the entry id */ -/* */ -/* */ - -static int SecIsInPMKIDList(struct adapter *Adapter, u8 *bssid) -{ - struct security_priv *p = &Adapter->securitypriv; - int i; - - for (i = 0; i < NUM_PMKID_CACHE; i++) - if (p->PMKIDList[i].bUsed && !memcmp(p->PMKIDList[i].Bssid, bssid, ETH_ALEN)) - return i; - return -1; -} - -/* */ -/* Check the RSN IE length */ -/* If the RSN IE length <= 20, the RSN IE didn't include the PMKID information */ -/* 0-11th element in the array are the fixed IE */ -/* 12th element in the array is the IE */ -/* 13th element in the array is the IE length */ -/* */ - -static int rtw_append_pmkid(struct adapter *Adapter, int iEntry, u8 *ie, uint ie_len) -{ - struct security_priv *psecuritypriv = &Adapter->securitypriv; - - if (ie[13] <= 20) { - /* The RSN IE didn't include the PMK ID, append the PMK information */ - ie[ie_len] = 1; - ie_len++; - ie[ie_len] = 0; /* PMKID count = 0x0100 */ - ie_len++; - memcpy(&ie[ie_len], &psecuritypriv->PMKIDList[iEntry].PMKID, 16); - - ie_len += 16; - ie[13] += 18;/* PMKID length = 2+16 */ - } - return ie_len; -} - -static void rtw_report_sec_ie(struct adapter *adapter, u8 authmode, u8 *sec_ie) -{ - uint len; - u8 *buff, *p, i; - union iwreq_data wrqu; - - buff = NULL; - if (authmode == _WPA_IE_ID_) { - buff = kzalloc(IW_CUSTOM_MAX, GFP_ATOMIC); - if (!buff) - return; - p = buff; - p += sprintf(p, "ASSOCINFO(ReqIEs ="); - len = sec_ie[1] + 2; - len = (len < IW_CUSTOM_MAX) ? len : IW_CUSTOM_MAX; - for (i = 0; i < len; i++) - p += sprintf(p, "%02x", sec_ie[i]); - p += sprintf(p, ")"); - memset(&wrqu, 0, sizeof(wrqu)); - wrqu.data.length = p - buff; - wrqu.data.length = (wrqu.data.length < IW_CUSTOM_MAX) ? - wrqu.data.length : IW_CUSTOM_MAX; - wireless_send_event(adapter->pnetdev, IWEVCUSTOM, &wrqu, buff); - kfree(buff); - } -} - -int rtw_restruct_sec_ie(struct adapter *adapter, u8 *in_ie, u8 *out_ie, uint in_len) -{ - u8 authmode = 0; - uint ielength; - int iEntry; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - struct security_priv *psecuritypriv = &adapter->securitypriv; - uint ndisauthmode = psecuritypriv->ndisauthtype; - - /* copy fixed ie only */ - memcpy(out_ie, in_ie, 12); - ielength = 12; - if ((ndisauthmode == Ndis802_11AuthModeWPA) || - (ndisauthmode == Ndis802_11AuthModeWPAPSK)) - authmode = _WPA_IE_ID_; - if ((ndisauthmode == Ndis802_11AuthModeWPA2) || - (ndisauthmode == Ndis802_11AuthModeWPA2PSK)) - authmode = _WPA2_IE_ID_; - - if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS)) { - memcpy(out_ie + ielength, psecuritypriv->wps_ie, psecuritypriv->wps_ie_len); - - ielength += psecuritypriv->wps_ie_len; - } else if ((authmode == _WPA_IE_ID_) || (authmode == _WPA2_IE_ID_)) { - /* copy RSN or SSN */ - memcpy(&out_ie[ielength], &psecuritypriv->supplicant_ie[0], psecuritypriv->supplicant_ie[1] + 2); - ielength += psecuritypriv->supplicant_ie[1] + 2; - rtw_report_sec_ie(adapter, authmode, psecuritypriv->supplicant_ie); - } - - iEntry = SecIsInPMKIDList(adapter, pmlmepriv->assoc_bssid); - if (iEntry < 0) { - return ielength; - } else { - if (authmode == _WPA2_IE_ID_) - ielength = rtw_append_pmkid(adapter, iEntry, out_ie, ielength); - } - - return ielength; -} - -void rtw_init_registrypriv_dev_network(struct adapter *adapter) -{ - struct registry_priv *pregistrypriv = &adapter->registrypriv; - struct eeprom_priv *peepriv = &adapter->eeprompriv; - struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network; - u8 *myhwaddr = myid(peepriv); - - memcpy(pdev_network->MacAddress, myhwaddr, ETH_ALEN); - - memcpy(&pdev_network->Ssid, &pregistrypriv->ssid, sizeof(struct ndis_802_11_ssid)); - - pdev_network->Configuration.Length = sizeof(struct ndis_802_11_config); - pdev_network->Configuration.BeaconPeriod = 100; - pdev_network->Configuration.FHConfig.Length = 0; - pdev_network->Configuration.FHConfig.HopPattern = 0; - pdev_network->Configuration.FHConfig.HopSet = 0; - pdev_network->Configuration.FHConfig.DwellTime = 0; - -} - -void rtw_update_registrypriv_dev_network(struct adapter *adapter) -{ - int sz = 0; - struct registry_priv *pregistrypriv = &adapter->registrypriv; - struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network; - struct security_priv *psecuritypriv = &adapter->securitypriv; - struct wlan_network *cur_network = &adapter->mlmepriv.cur_network; - - pdev_network->Privacy = (psecuritypriv->dot11PrivacyAlgrthm > 0 ? 1 : 0); /* adhoc no 802.1x */ - - pdev_network->Rssi = 0; - - pdev_network->Configuration.DSConfig = (pregistrypriv->channel); - - if (cur_network->network.InfrastructureMode == Ndis802_11IBSS) - pdev_network->Configuration.ATIMWindow = (0); - - pdev_network->InfrastructureMode = (cur_network->network.InfrastructureMode); - - /* 1. Supported rates */ - /* 2. IE */ - - sz = rtw_generate_ie(pregistrypriv); - pdev_network->IELength = sz; - pdev_network->Length = get_wlan_bssid_ex_sz((struct wlan_bssid_ex *)pdev_network); - - /* notes: translate IELength & Length after assign the Length to cmdsz in createbss_cmd(); */ - /* pdev_network->IELength = cpu_to_le32(sz); */ - -} - -static void rtw_set_threshold(struct adapter *adapter) -{ - struct mlme_priv *mlmepriv = &adapter->mlmepriv; - struct ht_priv *htpriv = &mlmepriv->htpriv; - - if (htpriv->ht_option && adapter->registrypriv.wifi_spec != 1) { - /* validate usb rx aggregation, use init value. */ - rtw_write8(adapter, REG_RXDMA_AGG_PG_TH, USB_RXAGG_PAGE_COUNT); - } else { - /* invalidate usb rx aggregation */ - rtw_write8(adapter, REG_RXDMA_AGG_PG_TH, 1); - } -} - -/* the function is at passive_level */ -void rtw_joinbss_reset(struct adapter *padapter) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct ht_priv *phtpriv = &pmlmepriv->htpriv; - - /* todo: if you want to do something io/reg/hw setting before join_bss, please add code here */ - pmlmepriv->num_FortyMHzIntolerant = 0; - - pmlmepriv->num_sta_no_ht = 0; - - phtpriv->ampdu_enable = false;/* reset to disabled */ - - rtw_set_threshold(padapter); -} - -/* the function is >= passive_level */ -unsigned int rtw_restructure_ht_ie(struct adapter *padapter, u8 *in_ie, u8 *out_ie, uint in_len, uint *pout_len) -{ - u32 ielen, out_len; - unsigned char *p; - struct ieee80211_ht_cap ht_capie; - unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00}; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct qos_priv *pqospriv = &pmlmepriv->qospriv; - struct ht_priv *phtpriv = &pmlmepriv->htpriv; - - phtpriv->ht_option = false; - - p = rtw_get_ie(in_ie + 12, _HT_CAPABILITY_IE_, &ielen, in_len - 12); - - if (p && ielen > 0) { - if (pqospriv->qos_option == 0) { - out_len = *pout_len; - rtw_set_ie(out_ie + out_len, _VENDOR_SPECIFIC_IE_, - _WMM_IE_Length_, WMM_IE, pout_len); - - pqospriv->qos_option = 1; - } - - out_len = *pout_len; - - memset(&ht_capie, 0, sizeof(struct ieee80211_ht_cap)); - - ht_capie.cap_info = cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40 | - IEEE80211_HT_CAP_SGI_20 | - IEEE80211_HT_CAP_SGI_40 | - IEEE80211_HT_CAP_TX_STBC | - IEEE80211_HT_CAP_DSSSCCK40); - - /* - AMPDU_para [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k - AMPDU_para [4:2]:Min MPDU Start Spacing - */ - - ht_capie.ampdu_params_info = (MAX_AMPDU_FACTOR_64K & 0x03); - - if (padapter->securitypriv.dot11PrivacyAlgrthm == _AES_) - ht_capie.ampdu_params_info |= (IEEE80211_HT_AMPDU_PARM_DENSITY & (0x07 << 2)); - else - ht_capie.ampdu_params_info |= (IEEE80211_HT_AMPDU_PARM_DENSITY & 0x00); - - rtw_set_ie(out_ie + out_len, _HT_CAPABILITY_IE_, - sizeof(struct ieee80211_ht_cap), (unsigned char *)&ht_capie, pout_len); - - phtpriv->ht_option = true; - - p = rtw_get_ie(in_ie + 12, _HT_ADD_INFO_IE_, &ielen, in_len - 12); - if (p && (ielen == sizeof(struct ieee80211_ht_addt_info))) { - out_len = *pout_len; - rtw_set_ie(out_ie + out_len, _HT_ADD_INFO_IE_, ielen, p + 2, pout_len); - } - } - return phtpriv->ht_option; -} - -/* the function is > passive_level (in critical_section) */ -void rtw_update_ht_cap(struct adapter *padapter, u8 *pie, uint ie_len) -{ - u8 *p, max_ampdu_sz; - int len; - struct ieee80211_ht_cap *pht_capie; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct ht_priv *phtpriv = &pmlmepriv->htpriv; - struct registry_priv *pregistrypriv = &padapter->registrypriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - if (!phtpriv->ht_option) - return; - - if ((!pmlmeinfo->HT_info_enable) || (!pmlmeinfo->HT_caps_enable)) - return; - - /* maybe needs check if ap supports rx ampdu. */ - if ((!phtpriv->ampdu_enable) && (pregistrypriv->ampdu_enable == 1)) { - if (pregistrypriv->wifi_spec == 1) - phtpriv->ampdu_enable = false; - else - phtpriv->ampdu_enable = true; - } else if (pregistrypriv->ampdu_enable == 2) { - phtpriv->ampdu_enable = true; - } - - /* check Max Rx A-MPDU Size */ - len = 0; - p = rtw_get_ie(pie + sizeof(struct ndis_802_11_fixed_ie), _HT_CAPABILITY_IE_, &len, ie_len - sizeof(struct ndis_802_11_fixed_ie)); - if (p && len > 0) { - pht_capie = (struct ieee80211_ht_cap *)(p + 2); - max_ampdu_sz = (pht_capie->ampdu_params_info & IEEE80211_HT_AMPDU_PARM_FACTOR); - max_ampdu_sz = 1 << (max_ampdu_sz + 3); /* max_ampdu_sz (kbytes); */ - phtpriv->rx_ampdu_maxlen = max_ampdu_sz; - } - len = 0; - p = rtw_get_ie(pie + sizeof(struct ndis_802_11_fixed_ie), _HT_ADD_INFO_IE_, &len, ie_len - sizeof(struct ndis_802_11_fixed_ie)); - - /* update cur_bwmode & cur_ch_offset */ - if ((pregistrypriv->cbw40_enable) && - (le16_to_cpu(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info) & BIT(1)) && - (pmlmeinfo->HT_info.infos[0] & BIT(2))) { - int i; - - /* update the MCS rates */ - for (i = 0; i < 16; i++) - pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate[i] &= MCS_rate_1R[i]; - - /* switch to the 40M Hz mode according to the AP */ - pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40; - switch ((pmlmeinfo->HT_info.infos[0] & 0x3)) { - case HT_EXTCHNL_OFFSET_UPPER: - pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER; - break; - case HT_EXTCHNL_OFFSET_LOWER: - pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER; - break; - default: - pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - break; - } - } - - /* Config SM Power Save setting */ - pmlmeinfo->SM_PS = (le16_to_cpu(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info) & 0x0C) >> 2; - - /* Config current HT Protection mode. */ - pmlmeinfo->HT_protection = pmlmeinfo->HT_info.infos[1] & 0x3; -} - -void rtw_issue_addbareq_cmd(struct adapter *padapter, struct xmit_frame *pxmitframe) -{ - u8 issued; - int priority; - struct sta_info *psta = NULL; - struct ht_priv *phtpriv; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - - if (is_multicast_ether_addr(pattrib->ra) || - padapter->mlmepriv.LinkDetectInfo.NumTxOkInPeriod < 100) - return; - - priority = pattrib->priority; - - if (pattrib->psta) - psta = pattrib->psta; - else - psta = rtw_get_stainfo(&padapter->stapriv, pattrib->ra); - - if (!psta) - return; - - phtpriv = &psta->htpriv; - - if ((phtpriv->ht_option) && (phtpriv->ampdu_enable)) { - issued = (phtpriv->agg_enable_bitmap >> priority) & 0x1; - issued |= (phtpriv->candidate_tid_bitmap >> priority) & 0x1; - - if (issued == 0) { - psta->htpriv.candidate_tid_bitmap |= BIT((u8)priority); - rtw_addbareq_cmd(padapter, (u8)priority, pattrib->ra); - } - } -} - -void rtw_roaming(struct adapter *padapter, struct wlan_network *tgt_network) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - spin_lock_bh(&pmlmepriv->lock); - _rtw_roaming(padapter, tgt_network); - spin_unlock_bh(&pmlmepriv->lock); -} -void _rtw_roaming(struct adapter *padapter, struct wlan_network *tgt_network) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - int do_join_r; - - struct wlan_network *pnetwork; - - if (tgt_network) - pnetwork = tgt_network; - else - pnetwork = &pmlmepriv->cur_network; - - if (rtw_to_roaming(padapter) > 0) { - memcpy(&pmlmepriv->assoc_ssid, &pnetwork->network.Ssid, sizeof(struct ndis_802_11_ssid)); - - pmlmepriv->assoc_by_bssid = false; - - while (1) { - do_join_r = rtw_do_join(padapter); - if (do_join_r == _SUCCESS) { - break; - } else { - pmlmepriv->to_roaming--; - - if (pmlmepriv->to_roaming > 0) { - continue; - } else { - rtw_indicate_disconnect(padapter); - break; - } - } - } - } -} diff --git a/drivers/staging/r8188eu/core/rtw_mlme_ext.c b/drivers/staging/r8188eu/core/rtw_mlme_ext.c deleted file mode 100644 index dc181e491b34..000000000000 --- a/drivers/staging/r8188eu/core/rtw_mlme_ext.c +++ /dev/null @@ -1,7817 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2007 - 2012 Realtek Corporation. */ - -#define _RTW_MLME_EXT_C_ - -#include -#include "../include/osdep_service.h" -#include "../include/drv_types.h" -#include "../include/wifi.h" -#include "../include/rtw_mlme_ext.h" -#include "../include/wlan_bssdef.h" -#include "../include/rtl8188e_xmit.h" -#include "../include/rtl8188e_dm.h" - -static u8 null_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0}; - -/************************************************** -OUI definitions for the vendor specific IE -***************************************************/ -unsigned char RTW_WPA_OUI[] = {0x00, 0x50, 0xf2, 0x01}; -unsigned char WMM_OUI[] = {0x00, 0x50, 0xf2, 0x02}; -unsigned char WPS_OUI[] = {0x00, 0x50, 0xf2, 0x04}; -unsigned char P2P_OUI[] = {0x50, 0x6F, 0x9A, 0x09}; -unsigned char WFD_OUI[] = {0x50, 0x6F, 0x9A, 0x0A}; - -unsigned char WMM_INFO_OUI[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01}; -unsigned char WMM_PARA_OUI[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01}; - -unsigned char WPA_TKIP_CIPHER[4] = {0x00, 0x50, 0xf2, 0x02}; -unsigned char RSN_TKIP_CIPHER[4] = {0x00, 0x0f, 0xac, 0x02}; - -extern unsigned char REALTEK_96B_IE[]; - -/******************************************************** -MCS rate definitions -*********************************************************/ -unsigned char MCS_rate_1R[16] = {0xff, 0x00, 0x0, 0x0, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; - -/******************************************************** -ChannelPlan definitions -*********************************************************/ -static struct rt_channel_plan RTW_ChannelPlan2G[RT_CHANNEL_DOMAIN_2G_MAX] = { - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}, /* 0x00, RT_CHANNEL_DOMAIN_2G_WORLD , Passive scan CH 12, 13 */ - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}, /* 0x01, RT_CHANNEL_DOMAIN_2G_ETSI1 */ - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11}, /* 0x02, RT_CHANNEL_DOMAIN_2G_FCC1 */ - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14}, /* 0x03, RT_CHANNEL_DOMAIN_2G_MIKK1 */ - {{10, 11, 12, 13}, 4}, /* 0x04, RT_CHANNEL_DOMAIN_2G_ETSI2 */ - {{}, 0}, /* 0x05, RT_CHANNEL_DOMAIN_2G_NULL */ -}; - -static struct rt_channel_plan_map RTW_ChannelPlanMap[RT_CHANNEL_DOMAIN_MAX] = { - /* 0x00 ~ 0x1F , Old Define ===== */ - {0x02}, /* 0x00, RT_CHANNEL_DOMAIN_FCC */ - {0x02}, /* 0x01, RT_CHANNEL_DOMAIN_IC */ - {0x01}, /* 0x02, RT_CHANNEL_DOMAIN_ETSI */ - {0x01}, /* 0x03, RT_CHANNEL_DOMAIN_SPAIN */ - {0x01}, /* 0x04, RT_CHANNEL_DOMAIN_FRANCE */ - {0x03}, /* 0x05, RT_CHANNEL_DOMAIN_MKK */ - {0x03}, /* 0x06, RT_CHANNEL_DOMAIN_MKK1 */ - {0x01}, /* 0x07, RT_CHANNEL_DOMAIN_ISRAEL */ - {0x03}, /* 0x08, RT_CHANNEL_DOMAIN_TELEC */ - {0x03}, /* 0x09, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN */ - {0x00}, /* 0x0A, RT_CHANNEL_DOMAIN_WORLD_WIDE_13 */ - {0x02}, /* 0x0B, RT_CHANNEL_DOMAIN_TAIWAN */ - {0x01}, /* 0x0C, RT_CHANNEL_DOMAIN_CHINA */ - {0x02}, /* 0x0D, RT_CHANNEL_DOMAIN_SINGAPORE_INDIA_MEXICO */ - {0x02}, /* 0x0E, RT_CHANNEL_DOMAIN_KOREA */ - {0x02}, /* 0x0F, RT_CHANNEL_DOMAIN_TURKEY */ - {0x01}, /* 0x10, RT_CHANNEL_DOMAIN_JAPAN */ - {0x02}, /* 0x11, RT_CHANNEL_DOMAIN_FCC_NO_DFS */ - {0x01}, /* 0x12, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */ - {0x00}, /* 0x13 */ - {0x02}, /* 0x14, RT_CHANNEL_DOMAIN_TAIWAN_NO_DFS */ - {0x00}, /* 0x15, RT_CHANNEL_DOMAIN_ETSI_NO_DFS */ - {0x00}, /* 0x16, RT_CHANNEL_DOMAIN_KOREA_NO_DFS */ - {0x03}, /* 0x17, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */ - {0x05}, /* 0x18, RT_CHANNEL_DOMAIN_PAKISTAN_NO_DFS */ - {0x02}, /* 0x19, RT_CHANNEL_DOMAIN_TAIWAN2_NO_DFS */ - {0x00}, /* 0x1A, */ - {0x00}, /* 0x1B, */ - {0x00}, /* 0x1C, */ - {0x00}, /* 0x1D, */ - {0x00}, /* 0x1E, */ - {0x00}, /* 0x1F, */ - /* 0x20 ~ 0x7F , New Define ===== */ - {0x00}, /* 0x20, RT_CHANNEL_DOMAIN_WORLD_NULL */ - {0x01}, /* 0x21, RT_CHANNEL_DOMAIN_ETSI1_NULL */ - {0x02}, /* 0x22, RT_CHANNEL_DOMAIN_FCC1_NULL */ - {0x03}, /* 0x23, RT_CHANNEL_DOMAIN_MKK1_NULL */ - {0x04}, /* 0x24, RT_CHANNEL_DOMAIN_ETSI2_NULL */ - {0x02}, /* 0x25, RT_CHANNEL_DOMAIN_FCC1_FCC1 */ - {0x00}, /* 0x26, RT_CHANNEL_DOMAIN_WORLD_ETSI1 */ - {0x03}, /* 0x27, RT_CHANNEL_DOMAIN_MKK1_MKK1 */ - {0x00}, /* 0x28, RT_CHANNEL_DOMAIN_WORLD_KCC1 */ - {0x00}, /* 0x29, RT_CHANNEL_DOMAIN_WORLD_FCC2 */ - {0x00}, /* 0x2A, */ - {0x00}, /* 0x2B, */ - {0x00}, /* 0x2C, */ - {0x00}, /* 0x2D, */ - {0x00}, /* 0x2E, */ - {0x00}, /* 0x2F, */ - {0x00}, /* 0x30, RT_CHANNEL_DOMAIN_WORLD_FCC3 */ - {0x00}, /* 0x31, RT_CHANNEL_DOMAIN_WORLD_FCC4 */ - {0x00}, /* 0x32, RT_CHANNEL_DOMAIN_WORLD_FCC5 */ - {0x00}, /* 0x33, RT_CHANNEL_DOMAIN_WORLD_FCC6 */ - {0x02}, /* 0x34, RT_CHANNEL_DOMAIN_FCC1_FCC7 */ - {0x00}, /* 0x35, RT_CHANNEL_DOMAIN_WORLD_ETSI2 */ - {0x00}, /* 0x36, RT_CHANNEL_DOMAIN_WORLD_ETSI3 */ - {0x03}, /* 0x37, RT_CHANNEL_DOMAIN_MKK1_MKK2 */ - {0x03}, /* 0x38, RT_CHANNEL_DOMAIN_MKK1_MKK3 */ - {0x02}, /* 0x39, RT_CHANNEL_DOMAIN_FCC1_NCC1 */ - {0x00}, /* 0x3A, */ - {0x00}, /* 0x3B, */ - {0x00}, /* 0x3C, */ - {0x00}, /* 0x3D, */ - {0x00}, /* 0x3E, */ - {0x00}, /* 0x3F, */ - {0x02}, /* 0x40, RT_CHANNEL_DOMAIN_FCC1_NCC2 */ - {0x03}, /* 0x41, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G */ -}; - -static struct rt_channel_plan_map RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE = {0x03}; /* use the combination for max channel numbers */ - -/* - * Search the @param channel_num in given @param channel_set - * @ch_set: the given channel set - * @ch: the given channel number - * - * return the index of channel_num in channel_set, -1 if not found - */ -int rtw_ch_set_search_ch(struct rt_channel_info *ch_set, const u32 ch) -{ - int i; - for (i = 0; ch_set[i].ChannelNum != 0; i++) { - if (ch == ch_set[i].ChannelNum) - break; - } - - if (i >= ch_set[i].ChannelNum) - return -1; - return i; -} - -/**************************************************************************** - -Following are the initialization functions for WiFi MLME - -*****************************************************************************/ - -int init_hw_mlme_ext(struct adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); - return _SUCCESS; -} - -static void init_mlme_ext_priv_value(struct adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - unsigned char mixed_datarate[NumRates] = { - _1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_, - _9M_RATE_, _12M_RATE_, _18M_RATE_, _24M_RATE_, _36M_RATE_, - _48M_RATE_, _54M_RATE_, 0xff - }; - unsigned char mixed_basicrate[NumRates] = { - _1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_, - _12M_RATE_, _24M_RATE_, 0xff, - }; - - atomic_set(&pmlmeext->event_seq, 0); - pmlmeext->mgnt_seq = 0;/* reset to zero when disconnect at client mode */ - - pmlmeext->cur_channel = padapter->registrypriv.channel; - pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20; - pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - pmlmeext->retry = 0; - - pmlmeext->cur_wireless_mode = padapter->registrypriv.wireless_mode; - - memcpy(pmlmeext->datarate, mixed_datarate, NumRates); - memcpy(pmlmeext->basicrate, mixed_basicrate, NumRates); - - pmlmeext->tx_rate = IEEE80211_CCK_RATE_1MB; - - pmlmeext->sitesurvey_res.state = SCAN_DISABLE; - pmlmeext->sitesurvey_res.channel_idx = 0; - pmlmeext->sitesurvey_res.bss_cnt = 0; - pmlmeext->scan_abort = false; - - pmlmeinfo->state = WIFI_FW_NULL_STATE; - pmlmeinfo->reauth_count = 0; - pmlmeinfo->reassoc_count = 0; - pmlmeinfo->link_count = 0; - pmlmeinfo->auth_seq = 0; - pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open; - pmlmeinfo->key_index = 0; - pmlmeinfo->iv = 0; - - pmlmeinfo->enc_algo = _NO_PRIVACY_; - pmlmeinfo->authModeToggle = 0; - - memset(pmlmeinfo->chg_txt, 0, 128); - - pmlmeinfo->slotTime = SHORT_SLOT_TIME; - pmlmeinfo->preamble_mode = PREAMBLE_AUTO; - - pmlmeinfo->dialogToken = 0; - - pmlmeext->action_public_rxseq = 0xffff; - pmlmeext->action_public_dialog_token = 0xff; -} - -static int has_channel(struct rt_channel_info *channel_set, - u8 chanset_size, - u8 chan) -{ - int i; - - for (i = 0; i < chanset_size; i++) { - if (channel_set[i].ChannelNum == chan) - return 1; - } - return 0; -} - -static void init_channel_list(struct adapter *padapter, struct rt_channel_info *channel_set, - u8 chanset_size, - struct p2p_channels *channel_list) -{ - struct p2p_oper_class_map op_class[] = { - { IEEE80211G, 81, 1, 13, 1, BW20 }, - { IEEE80211G, 82, 14, 14, 1, BW20 }, - { -1, 0, 0, 0, 0, BW20 } - }; - - int cla, op; - - cla = 0; - - for (op = 0; op_class[op].op_class; op++) { - u8 ch; - struct p2p_oper_class_map *o = &op_class[op]; - struct p2p_reg_class *reg = NULL; - - for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) { - if (!has_channel(channel_set, chanset_size, ch)) { - continue; - } - - if ((padapter->registrypriv.ht_enable == 0) && (o->inc == 8)) - continue; - - if (((padapter->registrypriv.cbw40_enable & BIT(1)) == 0) && - ((o->bw == BW40MINUS) || (o->bw == BW40PLUS))) - continue; - - if (!reg) { - reg = &channel_list->reg_class[cla]; - cla++; - reg->reg_class = o->op_class; - reg->channels = 0; - } - reg->channel[reg->channels] = ch; - reg->channels++; - } - } - channel_list->reg_classes = cla; -} - -static u8 init_channel_set(struct adapter *padapter, u8 ChannelPlan, struct rt_channel_info *channel_set) -{ - u8 index, chanset_size = 0; - u8 b2_4GBand = false; - u8 Index2G = 0; - - memset(channel_set, 0, sizeof(struct rt_channel_info) * MAX_CHANNEL_NUM); - - if (ChannelPlan >= RT_CHANNEL_DOMAIN_MAX && ChannelPlan != RT_CHANNEL_DOMAIN_REALTEK_DEFINE) - return chanset_size; - - if (padapter->registrypriv.wireless_mode & WIRELESS_11G) { - b2_4GBand = true; - if (ChannelPlan == RT_CHANNEL_DOMAIN_REALTEK_DEFINE) - Index2G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index2G; - else - Index2G = RTW_ChannelPlanMap[ChannelPlan].Index2G; - } - - if (b2_4GBand) { - for (index = 0; index < RTW_ChannelPlan2G[Index2G].Len; index++) { - channel_set[chanset_size].ChannelNum = RTW_ChannelPlan2G[Index2G].Channel[index]; - - if ((ChannelPlan == RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN) ||/* Channel 1~11 is active, and 12~14 is passive */ - (ChannelPlan == RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G)) { - if (channel_set[chanset_size].ChannelNum >= 1 && channel_set[chanset_size].ChannelNum <= 11) - channel_set[chanset_size].ScanType = SCAN_ACTIVE; - else if ((channel_set[chanset_size].ChannelNum >= 12 && channel_set[chanset_size].ChannelNum <= 14)) - channel_set[chanset_size].ScanType = SCAN_PASSIVE; - } else if (ChannelPlan == RT_CHANNEL_DOMAIN_WORLD_WIDE_13 || - Index2G == RT_CHANNEL_DOMAIN_2G_WORLD) {/* channel 12~13, passive scan */ - if (channel_set[chanset_size].ChannelNum <= 11) - channel_set[chanset_size].ScanType = SCAN_ACTIVE; - else - channel_set[chanset_size].ScanType = SCAN_PASSIVE; - } else { - channel_set[chanset_size].ScanType = SCAN_ACTIVE; - } - - chanset_size++; - } - } - return chanset_size; -} - -static void _survey_timer_hdl(struct timer_list *t) -{ - struct adapter *padapter = from_timer(padapter, t, mlmeextpriv.survey_timer); - - survey_timer_hdl(padapter); -} - -static void _link_timer_hdl(struct timer_list *t) -{ - struct adapter *padapter = from_timer(padapter, t, mlmeextpriv.link_timer); - - link_timer_hdl(padapter); -} - -static void init_mlme_ext_timer(struct adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - timer_setup(&pmlmeext->survey_timer, _survey_timer_hdl, 0); - timer_setup(&pmlmeext->link_timer, _link_timer_hdl, 0); -} - -void init_mlme_ext_priv(struct adapter *padapter) -{ - struct registry_priv *pregistrypriv = &padapter->registrypriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - pmlmeext->padapter = padapter; - - init_mlme_ext_priv_value(padapter); - pmlmeinfo->bAcceptAddbaReq = pregistrypriv->bAcceptAddbaReq; - - init_mlme_ext_timer(padapter); - - init_mlme_ap_info(padapter); - - pmlmeext->max_chan_nums = init_channel_set(padapter, pmlmepriv->ChannelPlan, pmlmeext->channel_set); - init_channel_list(padapter, pmlmeext->channel_set, pmlmeext->max_chan_nums, &pmlmeext->channel_list); - - pmlmeext->chan_scan_time = SURVEY_TO; - pmlmeext->mlmeext_init = true; - - pmlmeext->active_keep_alive_check = true; -} - -void free_mlme_ext_priv(struct mlme_ext_priv *pmlmeext) -{ - struct adapter *padapter = pmlmeext->padapter; - - if (!padapter) - return; - - if (padapter->bDriverStopped) { - _cancel_timer_ex(&pmlmeext->survey_timer); - _cancel_timer_ex(&pmlmeext->link_timer); - /* _cancel_timer_ex(&pmlmeext->ADDBA_timer); */ - } -} - -static u32 p2p_listen_state_process(struct adapter *padapter, unsigned char *da) -{ - bool response = true; - - /* do nothing if the device name is empty */ - if (!padapter->wdinfo.device_name_len) - response = false; - - if (response) - issue_probersp_p2p(padapter, da); - - return _SUCCESS; -} - -static void correct_TSF(struct adapter *padapter) -{ - u8 reg; - int res; - u64 tsf; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - tsf = pmlmeext->TSFValue - do_div(pmlmeext->TSFValue, - pmlmeinfo->bcn_interval * 1024) - 1024; /* us */ - - if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) || - ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) - rtw_stop_tx_beacon(padapter); - - /* disable related TSF function */ - res = rtw_read8(padapter, REG_BCN_CTRL, ®); - if (res) - return; - - rtw_write8(padapter, REG_BCN_CTRL, reg & (~BIT(3))); - - rtw_write32(padapter, REG_TSFTR, tsf); - rtw_write32(padapter, REG_TSFTR + 4, tsf >> 32); - - /* enable related TSF function */ - res = rtw_read8(padapter, REG_BCN_CTRL, ®); - if (res) - return; - - rtw_write8(padapter, REG_BCN_CTRL, reg | BIT(3)); - - if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) || - ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) - rtw_resume_tx_beacon(padapter); -} - -/**************************************************************************** - -Following are the callback functions for each subtype of the management frames - -*****************************************************************************/ - -static void OnProbeReq(struct adapter *padapter, struct recv_frame *precv_frame) -{ - unsigned int ielen; - unsigned char *p; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *cur = &pmlmeinfo->network; - u8 *pframe = precv_frame->rx_data; - uint len = precv_frame->len; - u8 is_valid_p2p_probereq = false; - - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - - if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) && - !rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE) && - !rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT) && - !rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH) && - !rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN)) { - /* mcs_rate = 0 -> CCK 1M rate */ - /* mcs_rate = 1 -> CCK 2M rate */ - /* mcs_rate = 2 -> CCK 5.5M rate */ - /* mcs_rate = 3 -> CCK 11M rate */ - /* In the P2P mode, the driver should not support the CCK rate */ - - /* Commented by Kurt 2012/10/16 */ - /* IOT issue: Google Nexus7 use 1M rate to send p2p_probe_req after GO nego completed and Nexus7 is client */ - is_valid_p2p_probereq = process_probe_req_p2p_ie(pwdinfo, pframe, len); - if (is_valid_p2p_probereq) { - if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE)) { - /* FIXME */ - report_survey_event(padapter, precv_frame); - p2p_listen_state_process(padapter, get_sa(pframe)); - - return; - } - } - } - - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) - return; - - if (!check_fwstate(pmlmepriv, _FW_LINKED) && - !check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE | WIFI_AP_STATE)) - return; - - p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _SSID_IE_, (int *)&ielen, - len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_); - - /* check (wildcard) SSID */ - if (p) { - if (is_valid_p2p_probereq) - goto _issue_probersp; - - if ((ielen != 0 && memcmp((void *)(p + 2), (void *)cur->Ssid.Ssid, cur->Ssid.SsidLength)) || - (ielen == 0 && pmlmeinfo->hidden_ssid_mode)) - return; - -_issue_probersp: - - if (check_fwstate(pmlmepriv, _FW_LINKED) && - (pmlmepriv->cur_network.join_res || - check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))) - issue_probersp(padapter, get_sa(pframe), is_valid_p2p_probereq); - } -} - -static void OnProbeRsp(struct adapter *padapter, struct recv_frame *precv_frame) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - u8 *pframe = precv_frame->rx_data; - - if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ)) { - if (pwdinfo->tx_prov_disc_info.benable) { - if (!memcmp(pwdinfo->tx_prov_disc_info.peerIFAddr, GetAddr2Ptr(pframe), ETH_ALEN)) { - if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) { - pwdinfo->tx_prov_disc_info.benable = false; - issue_p2p_provision_request(padapter, - pwdinfo->tx_prov_disc_info.ssid.Ssid, - pwdinfo->tx_prov_disc_info.ssid.SsidLength, - pwdinfo->tx_prov_disc_info.peerDevAddr); - } else if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE) || rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) { - pwdinfo->tx_prov_disc_info.benable = false; - issue_p2p_provision_request(padapter, NULL, 0, - pwdinfo->tx_prov_disc_info.peerDevAddr); - } - } - } - return; - } else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING)) { - if (pwdinfo->nego_req_info.benable) { - if (!memcmp(pwdinfo->nego_req_info.peerDevAddr, GetAddr2Ptr(pframe), ETH_ALEN)) { - pwdinfo->nego_req_info.benable = false; - issue_p2p_GO_request(padapter, pwdinfo->nego_req_info.peerDevAddr); - } - } - } else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_INVITE_REQ)) { - if (pwdinfo->invitereq_info.benable) { - if (!memcmp(pwdinfo->invitereq_info.peer_macaddr, GetAddr2Ptr(pframe), ETH_ALEN)) { - pwdinfo->invitereq_info.benable = false; - issue_p2p_invitation_request(padapter, pwdinfo->invitereq_info.peer_macaddr); - } - } - } - if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) { - report_survey_event(padapter, precv_frame); - return; - } -} - -static void OnBeacon(struct adapter *padapter, struct recv_frame *precv_frame) -{ - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)precv_frame->rx_data; - int cam_idx; - struct sta_info *psta; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct sta_priv *pstapriv = &padapter->stapriv; - u8 *pframe = precv_frame->rx_data; - uint len = precv_frame->len; - struct wlan_bssid_ex *pbss; - u8 *ie_ptr; - u32 ie_len; - - ie_ptr = (u8 *)&mgmt->u.beacon.variable; - if (precv_frame->len < offsetof(struct ieee80211_mgmt, u.beacon.variable)) - return; - ie_len = precv_frame->len - offsetof(struct ieee80211_mgmt, u.beacon.variable); - - if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) { - report_survey_event(padapter, precv_frame); - return; - } - - if (memcmp(mgmt->bssid, get_my_bssid(&pmlmeinfo->network), ETH_ALEN)) - return; - - if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) { - /* we should update current network before auth, or some IE is wrong */ - pbss = kmalloc(sizeof(struct wlan_bssid_ex), GFP_ATOMIC); - if (!pbss) - return; - - if (collect_bss_info(padapter, precv_frame, pbss) == _SUCCESS) { - update_network(&pmlmepriv->cur_network.network, pbss, padapter, true); - rtw_get_bcn_info(&pmlmepriv->cur_network); - } - kfree(pbss); - - /* check the vendor of the assoc AP */ - pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pframe + sizeof(struct ieee80211_hdr_3addr), len - sizeof(struct ieee80211_hdr_3addr)); - - pmlmeext->TSFValue = le64_to_cpu(mgmt->u.beacon.timestamp); - - /* start auth */ - start_clnt_auth(padapter); - - return; - } - - if (((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE) && (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) { - psta = rtw_get_stainfo(pstapriv, mgmt->sa); - if (!psta) - return; - - if (rtw_check_bcn_info(padapter, pframe, len) != _SUCCESS) { - receive_disconnect(padapter, pmlmeinfo->network.MacAddress, 0); - return; - } - /* update WMM, ERP in the beacon */ - /* todo: the timer is used instead of the number of the beacon received */ - if ((sta_rx_pkts(psta) & 0xf) == 0) - update_beacon_info(padapter, ie_ptr, ie_len, psta); - process_p2p_ps_ie(padapter, ie_ptr, ie_len); - } else if ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) { - psta = rtw_get_stainfo(pstapriv, mgmt->sa); - if (psta) { - /* update WMM, ERP in the beacon */ - /* todo: the timer is used instead of the number of the beacon received */ - if ((sta_rx_pkts(psta) & 0xf) == 0) - update_beacon_info(padapter, ie_ptr, ie_len, psta); - } else { - /* allocate a new CAM entry for IBSS station */ - cam_idx = allocate_fw_sta_entry(padapter); - if (cam_idx == NUM_STA) - return; - - /* get supported rate */ - if (update_sta_support_rate(padapter, ie_ptr, ie_len, cam_idx) == _FAIL) { - pmlmeinfo->FW_sta_info[cam_idx].status = 0; - return; - } - - pmlmeext->TSFValue = le64_to_cpu(mgmt->u.beacon.timestamp); - - report_add_sta_event(padapter, mgmt->sa, cam_idx); - } - } -} - -static void OnAuth(struct adapter *padapter, struct recv_frame *precv_frame) -{ - unsigned int auth_mode, ie_len; - u16 seq; - unsigned char *sa, *p; - u16 algorithm; - int status; - static struct sta_info stat; - struct sta_info *pstat = NULL; - struct sta_priv *pstapriv = &padapter->stapriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - u8 *pframe = precv_frame->rx_data; - uint len = precv_frame->len; - - if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE) - return; - - sa = GetAddr2Ptr(pframe); - - auth_mode = psecuritypriv->dot11AuthAlgrthm; - seq = le16_to_cpu(*(__le16 *)((size_t)pframe + WLAN_HDR_A3_LEN + 2)); - algorithm = le16_to_cpu(*(__le16 *)((size_t)pframe + WLAN_HDR_A3_LEN)); - - if (auth_mode == 2 && psecuritypriv->dot11PrivacyAlgrthm != _WEP40_ && - psecuritypriv->dot11PrivacyAlgrthm != _WEP104_) - auth_mode = 0; - - if ((algorithm > 0 && auth_mode == 0) || /* rx a shared-key auth but shared not enabled */ - (algorithm == 0 && auth_mode == 1)) { /* rx a open-system auth but shared-key is enabled */ - - status = _STATS_NO_SUPP_ALG_; - - goto auth_fail; - } - - if (!rtw_access_ctrl(padapter, sa)) { - status = _STATS_UNABLE_HANDLE_STA_; - goto auth_fail; - } - - pstat = rtw_get_stainfo(pstapriv, sa); - if (!pstat) { - /* allocate a new one */ - pstat = rtw_alloc_stainfo(pstapriv, sa); - if (!pstat) { - status = _STATS_UNABLE_HANDLE_STA_; - goto auth_fail; - } - - pstat->state = WIFI_FW_AUTH_NULL; - pstat->auth_seq = 0; - } else { - spin_lock_bh(&pstapriv->asoc_list_lock); - if (!list_empty(&pstat->asoc_list)) { - list_del_init(&pstat->asoc_list); - pstapriv->asoc_list_cnt--; - } - spin_unlock_bh(&pstapriv->asoc_list_lock); - - if (seq == 1) { - /* TODO: STA re_auth and auth timeout */ - } - } - - spin_lock_bh(&pstapriv->auth_list_lock); - if (list_empty(&pstat->auth_list)) { - list_add_tail(&pstat->auth_list, &pstapriv->auth_list); - pstapriv->auth_list_cnt++; - } - spin_unlock_bh(&pstapriv->auth_list_lock); - - if (pstat->auth_seq == 0) - pstat->expire_to = pstapriv->auth_to; - - if ((pstat->auth_seq + 1) != seq) { - status = _STATS_OUT_OF_AUTH_SEQ_; - goto auth_fail; - } - - if (algorithm == 0 && (auth_mode == 0 || auth_mode == 2)) { - if (seq == 1) { - pstat->state &= ~WIFI_FW_AUTH_NULL; - pstat->state |= WIFI_FW_AUTH_SUCCESS; - pstat->expire_to = pstapriv->assoc_to; - pstat->authalg = algorithm; - } else { - status = _STATS_OUT_OF_AUTH_SEQ_; - goto auth_fail; - } - } else { /* shared system or auto authentication */ - if (seq == 1) { - /* prepare for the challenging txt... */ - - pstat->state &= ~WIFI_FW_AUTH_NULL; - pstat->state |= WIFI_FW_AUTH_STATE; - pstat->authalg = algorithm; - pstat->auth_seq = 2; - } else if (seq == 3) { - /* checking for challenging txt... */ - - p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + 4 + _AUTH_IE_OFFSET_, _CHLGETXT_IE_, (int *)&ie_len, - len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_ - 4); - - if (!p || ie_len <= 0) { - status = _STATS_CHALLENGE_FAIL_; - goto auth_fail; - } - - if (!memcmp((void *)(p + 2), pstat->chg_txt, 128)) { - pstat->state &= (~WIFI_FW_AUTH_STATE); - pstat->state |= WIFI_FW_AUTH_SUCCESS; - /* challenging txt is correct... */ - pstat->expire_to = pstapriv->assoc_to; - } else { - status = _STATS_CHALLENGE_FAIL_; - goto auth_fail; - } - } else { - status = _STATS_OUT_OF_AUTH_SEQ_; - goto auth_fail; - } - } - - /* Now, we are going to issue_auth... */ - pstat->auth_seq = seq + 1; - - issue_auth(padapter, pstat, (unsigned short)(_STATS_SUCCESSFUL_)); - - if (pstat->state & WIFI_FW_AUTH_SUCCESS) - pstat->auth_seq = 0; - - return; - -auth_fail: - - if (pstat) - rtw_free_stainfo(padapter, pstat); - - pstat = &stat; - memset((char *)pstat, '\0', sizeof(stat)); - pstat->auth_seq = 2; - memcpy(pstat->hwaddr, sa, 6); - - issue_auth(padapter, pstat, (unsigned short)status); -} - -static void OnAuthClient(struct adapter *padapter, struct recv_frame *precv_frame) -{ - unsigned int seq, len, status, offset; - unsigned char *p; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)precv_frame->rx_data; - u8 *pframe = precv_frame->rx_data; - uint pkt_len = precv_frame->len; - - /* check A1 matches or not */ - if (memcmp(myid(&padapter->eeprompriv), ieee80211_get_DA(hdr), ETH_ALEN)) - return; - - if (!(pmlmeinfo->state & WIFI_FW_AUTH_STATE)) - return; - - offset = ieee80211_has_protected(hdr->frame_control) ? 4 : 0; - - seq = le16_to_cpu(*(__le16 *)((size_t)pframe + WLAN_HDR_A3_LEN + offset + 2)); - status = le16_to_cpu(*(__le16 *)((size_t)pframe + WLAN_HDR_A3_LEN + offset + 4)); - - if (status != 0) { - if (status == 13) { /* pmlmeinfo->auth_algo == dot11AuthAlgrthm_Auto) */ - if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) - pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open; - else - pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared; - } - - set_link_timer(pmlmeext, 1); - return; - } - - if (seq == 2) { - if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) { - /* legendary shared system */ - p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _AUTH_IE_OFFSET_, _CHLGETXT_IE_, (int *)&len, - pkt_len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_); - - if (!p) - return; - - memcpy((void *)(pmlmeinfo->chg_txt), (void *)(p + 2), len); - pmlmeinfo->auth_seq = 3; - issue_auth(padapter, NULL, 0); - set_link_timer(pmlmeext, REAUTH_TO); - - return; - } else { - /* open system */ - start_clnt_assoc(padapter); - } - } else if (seq == 4) { - if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) - start_clnt_assoc(padapter); - } -} - -static void UpdateBrateTbl(u8 *mbrate) -{ - u8 i; - u8 rate; - - /* 1M, 2M, 5.5M, 11M, 6M, 12M, 24M are mandatory. */ - for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) { - rate = mbrate[i] & 0x7f; - switch (rate) { - case IEEE80211_CCK_RATE_1MB: - case IEEE80211_CCK_RATE_2MB: - case IEEE80211_CCK_RATE_5MB: - case IEEE80211_CCK_RATE_11MB: - case IEEE80211_OFDM_RATE_6MB: - case IEEE80211_OFDM_RATE_12MB: - case IEEE80211_OFDM_RATE_24MB: - mbrate[i] |= IEEE80211_BASIC_RATE_MASK; - break; - } - } -} - -static void UpdateBrateTblForSoftAP(u8 *bssrateset, u32 bssratelen) -{ - u8 i; - u8 rate; - - for (i = 0; i < bssratelen; i++) { - rate = bssrateset[i] & 0x7f; - switch (rate) { - case IEEE80211_CCK_RATE_1MB: - case IEEE80211_CCK_RATE_2MB: - case IEEE80211_CCK_RATE_5MB: - case IEEE80211_CCK_RATE_11MB: - bssrateset[i] |= IEEE80211_BASIC_RATE_MASK; - break; - } - } -} - -static void OnAssocReq(struct adapter *padapter, struct recv_frame *precv_frame) -{ - u16 capab_info; - struct rtw_ieee802_11_elems elems; - struct sta_info *pstat; - unsigned char *p, *pos, *wpa_ie; - unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01}; - int i, ie_len, wpa_ie_len, left; - unsigned char supportRate[16]; - int supportRateNum; - unsigned short status = _STATS_SUCCESSFUL_; - unsigned short frame_type, ie_offset = 0; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *cur = &pmlmeinfo->network; - struct sta_priv *pstapriv = &padapter->stapriv; - u8 *pframe = precv_frame->rx_data; - uint pkt_len = precv_frame->len; - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - u8 p2p_status_code = P2P_STATUS_SUCCESS; - u8 *p2pie; - u32 p2pielen = 0; - - if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE) - return; - - frame_type = GetFrameSubType(pframe); - if (frame_type == WIFI_ASSOCREQ) - ie_offset = _ASOCREQ_IE_OFFSET_; - else /* WIFI_REASSOCREQ */ - ie_offset = _REASOCREQ_IE_OFFSET_; - - if (pkt_len < IEEE80211_3ADDR_LEN + ie_offset) - return; - - pstat = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe)); - if (pstat == (struct sta_info *)NULL) { - status = _RSON_CLS2_; - goto asoc_class2_error; - } - - capab_info = get_unaligned_le16(pframe + WLAN_HDR_A3_LEN); - - left = pkt_len - (IEEE80211_3ADDR_LEN + ie_offset); - pos = pframe + (IEEE80211_3ADDR_LEN + ie_offset); - - /* check if this stat has been successfully authenticated/assocated */ - if (!((pstat->state) & WIFI_FW_AUTH_SUCCESS)) { - if (!((pstat->state) & WIFI_FW_ASSOC_SUCCESS)) { - status = _RSON_CLS2_; - goto asoc_class2_error; - } else { - pstat->state &= (~WIFI_FW_ASSOC_SUCCESS); - pstat->state |= WIFI_FW_ASSOC_STATE; - } - } else { - pstat->state &= (~WIFI_FW_AUTH_SUCCESS); - pstat->state |= WIFI_FW_ASSOC_STATE; - } - pstat->capability = capab_info; - /* now parse all ieee802_11 ie to point to elems */ - if (rtw_ieee802_11_parse_elems(pos, left, &elems, 1) == ParseFailed || - !elems.ssid) { - status = _STATS_FAILURE_; - goto OnAssocReqFail; - } - - /* now we should check all the fields... */ - /* checking SSID */ - p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _SSID_IE_, &ie_len, - pkt_len - WLAN_HDR_A3_LEN - ie_offset); - if (!p) - status = _STATS_FAILURE_; - - if (ie_len == 0) { /* broadcast ssid, however it is not allowed in assocreq */ - status = _STATS_FAILURE_; - } else { - /* check if ssid match */ - if (memcmp((void *)(p + 2), cur->Ssid.Ssid, cur->Ssid.SsidLength)) - status = _STATS_FAILURE_; - - if (ie_len != cur->Ssid.SsidLength) - status = _STATS_FAILURE_; - } - - if (status != _STATS_SUCCESSFUL_) - goto OnAssocReqFail; - - /* check if the supported rate is ok */ - p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _SUPPORTEDRATES_IE_, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset); - if (!p) { - /* use our own rate set as statoin used */ - /* memcpy(supportRate, AP_BSSRATE, AP_BSSRATE_LEN); */ - /* supportRateNum = AP_BSSRATE_LEN; */ - - status = _STATS_FAILURE_; - goto OnAssocReqFail; - } else { - memcpy(supportRate, p + 2, ie_len); - supportRateNum = ie_len; - - p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _EXT_SUPPORTEDRATES_IE_, &ie_len, - pkt_len - WLAN_HDR_A3_LEN - ie_offset); - if (p) { - if (supportRateNum <= sizeof(supportRate)) { - memcpy(supportRate + supportRateNum, p + 2, ie_len); - supportRateNum += ie_len; - } - } - } - - /* todo: mask supportRate between AP & STA -> move to update raid */ - /* get_matched_rate(pmlmeext, supportRate, &supportRateNum, 0); */ - - /* update station supportRate */ - pstat->bssratelen = supportRateNum; - memcpy(pstat->bssrateset, supportRate, supportRateNum); - UpdateBrateTblForSoftAP(pstat->bssrateset, pstat->bssratelen); - - /* check RSN/WPA/WPS */ - pstat->dot8021xalg = 0; - pstat->wpa_psk = 0; - pstat->wpa_group_cipher = 0; - pstat->wpa2_group_cipher = 0; - pstat->wpa_pairwise_cipher = 0; - pstat->wpa2_pairwise_cipher = 0; - memset(pstat->wpa_ie, 0, sizeof(pstat->wpa_ie)); - if ((psecuritypriv->wpa_psk & BIT(1)) && elems.rsn_ie) { - int group_cipher = 0, pairwise_cipher = 0; - - wpa_ie = elems.rsn_ie; - wpa_ie_len = elems.rsn_ie_len; - - if (rtw_parse_wpa2_ie(wpa_ie - 2, wpa_ie_len + 2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) { - pstat->dot8021xalg = 1;/* psk, todo:802.1x */ - pstat->wpa_psk |= BIT(1); - - pstat->wpa2_group_cipher = group_cipher & psecuritypriv->wpa2_group_cipher; - pstat->wpa2_pairwise_cipher = pairwise_cipher & psecuritypriv->wpa2_pairwise_cipher; - - if (!pstat->wpa2_group_cipher) - status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID; - - if (!pstat->wpa2_pairwise_cipher) - status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID; - } else { - status = WLAN_STATUS_INVALID_IE; - } - } else if ((psecuritypriv->wpa_psk & BIT(0)) && elems.wpa_ie) { - int group_cipher = 0, pairwise_cipher = 0; - - wpa_ie = elems.wpa_ie; - wpa_ie_len = elems.wpa_ie_len; - - if (rtw_parse_wpa_ie(wpa_ie - 2, wpa_ie_len + 2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) { - pstat->dot8021xalg = 1;/* psk, todo:802.1x */ - pstat->wpa_psk |= BIT(0); - - pstat->wpa_group_cipher = group_cipher & psecuritypriv->wpa_group_cipher; - pstat->wpa_pairwise_cipher = pairwise_cipher & psecuritypriv->wpa_pairwise_cipher; - - if (!pstat->wpa_group_cipher) - status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID; - - if (!pstat->wpa_pairwise_cipher) - status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID; - } else { - status = WLAN_STATUS_INVALID_IE; - } - } else { - wpa_ie = NULL; - wpa_ie_len = 0; - } - - if (status != _STATS_SUCCESSFUL_) - goto OnAssocReqFail; - - pstat->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS); - if (!wpa_ie) { - if (elems.wps_ie) - pstat->flags |= WLAN_STA_WPS; - /* wpabuf_free(sta->wps_ie); */ - /* sta->wps_ie = wpabuf_alloc_copy(elems.wps_ie + 4, */ - /* elems.wps_ie_len - 4); */ - else - pstat->flags |= WLAN_STA_MAYBE_WPS; - - /* AP support WPA/RSN, and sta is going to do WPS, but AP is not ready */ - /* that the selected registrar of AP is _FLASE */ - if ((psecuritypriv->wpa_psk > 0) && (pstat->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS))) { - if (pmlmepriv->wps_beacon_ie) { - u8 selected_registrar = 0; - - rtw_get_wps_attr_content(pmlmepriv->wps_beacon_ie, pmlmepriv->wps_beacon_ie_len, WPS_ATTR_SELECTED_REGISTRAR, &selected_registrar, NULL); - - if (!selected_registrar) { - - status = _STATS_UNABLE_HANDLE_STA_; - - goto OnAssocReqFail; - } - } - } - } else { - int copy_len; - - if (psecuritypriv->wpa_psk == 0) { - - status = WLAN_STATUS_INVALID_IE; - - goto OnAssocReqFail; - } - - if (elems.wps_ie) { - pstat->flags |= WLAN_STA_WPS; - copy_len = 0; - } else { - copy_len = ((wpa_ie_len + 2) > sizeof(pstat->wpa_ie)) ? (sizeof(pstat->wpa_ie)) : (wpa_ie_len + 2); - } - if (copy_len > 0) - memcpy(pstat->wpa_ie, wpa_ie - 2, copy_len); - } - /* check if there is WMM IE & support WWM-PS */ - pstat->flags &= ~WLAN_STA_WME; - pstat->qos_option = 0; - pstat->qos_info = 0; - pstat->has_legacy_ac = true; - pstat->uapsd_vo = 0; - pstat->uapsd_vi = 0; - pstat->uapsd_be = 0; - pstat->uapsd_bk = 0; - if (pmlmepriv->qospriv.qos_option) { - p = pframe + WLAN_HDR_A3_LEN + ie_offset; ie_len = 0; - for (;;) { - p = rtw_get_ie(p, _VENDOR_SPECIFIC_IE_, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset); - if (p) { - if (!memcmp(p + 2, WMM_IE, 6)) { - pstat->flags |= WLAN_STA_WME; - - pstat->qos_option = 1; - pstat->qos_info = *(p + 8); - - pstat->max_sp_len = (pstat->qos_info >> 5) & 0x3; - - if ((pstat->qos_info & 0xf) != 0xf) - pstat->has_legacy_ac = true; - else - pstat->has_legacy_ac = false; - - if (pstat->qos_info & 0xf) { - if (pstat->qos_info & BIT(0)) - pstat->uapsd_vo = BIT(0) | BIT(1); - else - pstat->uapsd_vo = 0; - - if (pstat->qos_info & BIT(1)) - pstat->uapsd_vi = BIT(0) | BIT(1); - else - pstat->uapsd_vi = 0; - - if (pstat->qos_info & BIT(2)) - pstat->uapsd_bk = BIT(0) | BIT(1); - else - pstat->uapsd_bk = 0; - - if (pstat->qos_info & BIT(3)) - pstat->uapsd_be = BIT(0) | BIT(1); - else - pstat->uapsd_be = 0; - } - break; - } - } else { - break; - } - p = p + ie_len + 2; - } - } - - /* save HT capabilities in the sta object */ - memset(&pstat->htpriv.ht_cap, 0, sizeof(struct ieee80211_ht_cap)); - if (elems.ht_capabilities && elems.ht_capabilities_len >= sizeof(struct ieee80211_ht_cap)) { - pstat->flags |= WLAN_STA_HT; - - pstat->flags |= WLAN_STA_WME; - - memcpy(&pstat->htpriv.ht_cap, elems.ht_capabilities, sizeof(struct ieee80211_ht_cap)); - } else { - pstat->flags &= ~WLAN_STA_HT; - } - if ((!pmlmepriv->htpriv.ht_option) && (pstat->flags & WLAN_STA_HT)) { - status = _STATS_FAILURE_; - goto OnAssocReqFail; - } - - pstat->flags |= WLAN_STA_NONERP; - for (i = 0; i < pstat->bssratelen; i++) { - if ((pstat->bssrateset[i] & 0x7f) > 22) { - pstat->flags &= ~WLAN_STA_NONERP; - break; - } - } - - if (pstat->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) - pstat->flags |= WLAN_STA_SHORT_PREAMBLE; - else - pstat->flags &= ~WLAN_STA_SHORT_PREAMBLE; - - if (status != _STATS_SUCCESSFUL_) - goto OnAssocReqFail; - - pstat->is_p2p_device = false; - if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) { - p2pie = rtw_get_p2p_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, pkt_len - WLAN_HDR_A3_LEN - ie_offset, NULL, &p2pielen); - if (p2pie) { - pstat->is_p2p_device = true; - p2p_status_code = (u8)process_assoc_req_p2p_ie(pwdinfo, pframe, pkt_len, pstat); - if (p2p_status_code > 0) { - pstat->p2p_status_code = p2p_status_code; - status = _STATS_CAP_FAIL_; - goto OnAssocReqFail; - } - } - } - pstat->p2p_status_code = p2p_status_code; - - /* TODO: identify_proprietary_vendor_ie(); */ - /* Realtek proprietary IE */ - /* identify if this is Broadcom sta */ - /* identify if this is ralink sta */ - /* Customer proprietary IE */ - - /* get a unique AID */ - if (pstat->aid == 0) { - for (pstat->aid = 1; pstat->aid <= NUM_STA; pstat->aid++) - if (!pstapriv->sta_aid[pstat->aid - 1]) - break; - - /* if (pstat->aid > NUM_STA) { */ - if (pstat->aid > pstapriv->max_num_sta) { - pstat->aid = 0; - - status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; - - goto OnAssocReqFail; - } else { - pstapriv->sta_aid[pstat->aid - 1] = pstat; - } - } - - pstat->state &= (~WIFI_FW_ASSOC_STATE); - pstat->state |= WIFI_FW_ASSOC_SUCCESS; - - spin_lock_bh(&pstapriv->auth_list_lock); - if (!list_empty(&pstat->auth_list)) { - list_del_init(&pstat->auth_list); - pstapriv->auth_list_cnt--; - } - spin_unlock_bh(&pstapriv->auth_list_lock); - - spin_lock_bh(&pstapriv->asoc_list_lock); - if (list_empty(&pstat->asoc_list)) { - pstat->expire_to = pstapriv->expire_to; - list_add_tail(&pstat->asoc_list, &pstapriv->asoc_list); - pstapriv->asoc_list_cnt++; - } - spin_unlock_bh(&pstapriv->asoc_list_lock); - - /* now the station is qualified to join our BSS... */ - if (pstat && (pstat->state & WIFI_FW_ASSOC_SUCCESS) && (status == _STATS_SUCCESSFUL_)) { - /* 1 bss_cap_update & sta_info_update */ - bss_cap_update_on_sta_join(padapter, pstat); - sta_info_update(padapter, pstat); - - /* issue assoc rsp before notify station join event. */ - if (frame_type == WIFI_ASSOCREQ) - issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP); - else - issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP); - - /* 2 - report to upper layer */ - rtw_indicate_sta_assoc_event(padapter, pstat); - - /* 3-(1) report sta add event */ - report_add_sta_event(padapter, pstat->hwaddr, pstat->aid); - } - - return; - -asoc_class2_error: - - issue_deauth(padapter, (void *)GetAddr2Ptr(pframe), status); - - return; - -OnAssocReqFail: - - pstat->aid = 0; - if (frame_type == WIFI_ASSOCREQ) - issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP); - else - issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP); - - return; -} - -static void OnAssocRsp(struct adapter *padapter, struct recv_frame *precv_frame) -{ - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)precv_frame->rx_data; - uint i; - int res; - struct ndis_802_11_var_ie *pIE; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - /* struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network); */ - u8 *pframe = precv_frame->rx_data; - uint pkt_len = precv_frame->len; - - /* check A1 matches or not */ - if (memcmp(myid(&padapter->eeprompriv), mgmt->da, ETH_ALEN)) - return; - - if (!(pmlmeinfo->state & (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE))) - return; - - if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) - return; - - _cancel_timer_ex(&pmlmeext->link_timer); - - if (le16_to_cpu(mgmt->u.assoc_resp.status_code) > 0) { - pmlmeinfo->state = WIFI_FW_NULL_STATE; - res = -4; - goto report_assoc_result; - } - - pmlmeinfo->capability = le16_to_cpu(mgmt->u.assoc_resp.capab_info); - - /* set slot time */ - pmlmeinfo->slotTime = (pmlmeinfo->capability & BIT(10)) ? 9 : 20; - - pmlmeinfo->aid = le16_to_cpu(mgmt->u.assoc_resp.aid) & 0x3fff; - res = pmlmeinfo->aid; - - /* following are moved to join event callback function */ - /* to handle HT, WMM, rate adaptive, update MAC reg */ - /* for not to handle the synchronous IO in the tasklet */ - for (i = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable); i < pkt_len;) { - pIE = (struct ndis_802_11_var_ie *)(pframe + i); - - switch (pIE->ElementID) { - case _VENDOR_SPECIFIC_IE_: - if (!memcmp(pIE->data, WMM_PARA_OUI, 6)) /* WMM */ - WMM_param_handler(padapter, pIE); - break; - case _HT_CAPABILITY_IE_: /* HT caps */ - HT_caps_handler(padapter, pIE); - break; - case _HT_EXTRA_INFO_IE_: /* HT info */ - HT_info_handler(padapter, pIE); - break; - case _ERPINFO_IE_: - ERP_IE_handler(padapter, pIE); - break; - default: - break; - } - - i += (pIE->Length + 2); - } - - pmlmeinfo->state &= (~WIFI_FW_ASSOC_STATE); - pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS; - - /* Update Basic Rate Table for spec, 2010-12-28 , by thomas */ - UpdateBrateTbl(pmlmeinfo->network.SupportedRates); - -report_assoc_result: - report_join_res(padapter, res); -} - -static void OnDeAuth(struct adapter *padapter, struct recv_frame *precv_frame) -{ - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)precv_frame->rx_data; - unsigned short reason; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - - if (memcmp(mgmt->bssid, get_my_bssid(&pmlmeinfo->network), ETH_ALEN)) - return; - - if (pwdinfo->rx_invitereq_info.scan_op_ch_only) { - _cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey); - _set_timer(&pwdinfo->reset_ch_sitesurvey, 10); - } - - reason = le16_to_cpu(mgmt->u.disassoc.reason_code); - - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - struct sta_info *psta; - struct sta_priv *pstapriv = &padapter->stapriv; - u8 updated = 0; - - psta = rtw_get_stainfo(pstapriv, mgmt->sa); - if (!psta) - return; - - spin_lock_bh(&pstapriv->asoc_list_lock); - if (!list_empty(&psta->asoc_list)) { - list_del_init(&psta->asoc_list); - pstapriv->asoc_list_cnt--; - updated = ap_free_sta(padapter, psta, false, reason); - } - spin_unlock_bh(&pstapriv->asoc_list_lock); - - associated_clients_update(padapter, updated); - } else { - bool ignore_received_deauth = false; - - /* Before sending the auth frame to start the STA/GC mode connection with AP/GO, - * we will send the deauth first. - * However, the Win8.1 with BRCM Wi-Fi will send the deauth with reason code 6 to us after receieving our deauth. - * Added the following code to avoid this case. - */ - if (pmlmeinfo->state & (WIFI_FW_AUTH_STATE | WIFI_FW_ASSOC_STATE)) { - if (reason == WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA) { - ignore_received_deauth = true; - } else if (reason == WLAN_REASON_PREV_AUTH_NOT_VALID) { - // TODO: 802.11r - ignore_received_deauth = true; - } - } - - if (!ignore_received_deauth) - receive_disconnect(padapter, mgmt->bssid, reason); - - pmlmepriv->LinkDetectInfo.bBusyTraffic = false; - } -} - -static void OnDisassoc(struct adapter *padapter, struct recv_frame *precv_frame) -{ - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)precv_frame->rx_data; - u16 reason; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - struct sta_info *psta; - struct sta_priv *pstapriv = &padapter->stapriv; - u8 updated = 0; - - if (memcmp(mgmt->bssid, get_my_bssid(&pmlmeinfo->network), ETH_ALEN)) - return; - - if (pwdinfo->rx_invitereq_info.scan_op_ch_only) { - _cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey); - _set_timer(&pwdinfo->reset_ch_sitesurvey, 10); - } - - reason = le16_to_cpu(mgmt->u.disassoc.reason_code); - - if (!check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - receive_disconnect(padapter, mgmt->bssid, reason); - pmlmepriv->LinkDetectInfo.bBusyTraffic = false; - return; - } - - psta = rtw_get_stainfo(pstapriv, mgmt->sa); - if (!psta) - return; - - spin_lock_bh(&pstapriv->asoc_list_lock); - if (!list_empty(&psta->asoc_list)) { - list_del_init(&psta->asoc_list); - pstapriv->asoc_list_cnt--; - updated = ap_free_sta(padapter, psta, false, reason); - } - spin_unlock_bh(&pstapriv->asoc_list_lock); - - associated_clients_update(padapter, updated); -} - -static void OnAction_back(struct adapter *padapter, struct recv_frame *precv_frame) -{ - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)precv_frame->rx_data; - struct sta_info *psta = NULL; - struct recv_reorder_ctrl *preorder_ctrl; - unsigned short tid; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct sta_priv *pstapriv = &padapter->stapriv; - - if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE) - if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) - return; - - psta = rtw_get_stainfo(pstapriv, mgmt->sa); - if (!psta) - return; - - if (!pmlmeinfo->HT_enable) - return; - /* All union members start with an action code, it's ok to use addba_req. */ - switch (mgmt->u.action.u.addba_req.action_code) { - case WLAN_ACTION_ADDBA_REQ: - tid = u16_get_bits(le16_to_cpu(mgmt->u.action.u.addba_req.capab), - IEEE80211_ADDBA_PARAM_TID_MASK); - preorder_ctrl = &psta->recvreorder_ctrl[tid]; - preorder_ctrl->indicate_seq = 0xffff; - preorder_ctrl->enable = pmlmeinfo->bAcceptAddbaReq; - issue_action_BA(padapter, mgmt->sa, WLAN_ACTION_ADDBA_RESP, - pmlmeinfo->bAcceptAddbaReq ? - WLAN_STATUS_SUCCESS : WLAN_STATUS_REQUEST_DECLINED, mgmt); - break; - case WLAN_ACTION_ADDBA_RESP: - tid = u16_get_bits(le16_to_cpu(mgmt->u.action.u.addba_resp.capab), - IEEE80211_ADDBA_PARAM_TID_MASK); - if (mgmt->u.action.u.addba_resp.status == 0) { /* successful */ - psta->htpriv.agg_enable_bitmap |= BIT(tid); - psta->htpriv.candidate_tid_bitmap &= ~BIT(tid); - } else { - psta->htpriv.agg_enable_bitmap &= ~BIT(tid); - } - break; - case WLAN_ACTION_DELBA: - tid = u16_get_bits(le16_to_cpu(mgmt->u.action.u.delba.params), - IEEE80211_DELBA_PARAM_TID_MASK); - if (u16_get_bits(le16_to_cpu(mgmt->u.action.u.delba.params), - IEEE80211_DELBA_PARAM_INITIATOR_MASK) == WLAN_BACK_RECIPIENT) { - psta->htpriv.agg_enable_bitmap &= ~BIT(tid); - psta->htpriv.candidate_tid_bitmap &= ~BIT(tid); - } else { - preorder_ctrl = &psta->recvreorder_ctrl[tid]; - preorder_ctrl->enable = false; - preorder_ctrl->indicate_seq = 0xffff; - } - /* todo: how to notify the host while receiving DELETE BA */ - break; - default: - break; - } -} - -static int get_reg_classes_full_count(struct p2p_channels *channel_list) -{ - int cnt = 0; - int i; - - for (i = 0; i < channel_list->reg_classes; i++) { - cnt += channel_list->reg_class[i].channels; - } - - return cnt; -} - -void issue_p2p_GO_request(struct adapter *padapter, u8 *raddr) -{ - unsigned char category = WLAN_CATEGORY_PUBLIC; - u8 action = P2P_PUB_ACTION_ACTION; - __be32 p2poui = cpu_to_be32(P2POUI); - u8 oui_subtype = P2P_GO_NEGO_REQ; - u8 wpsie[255] = { 0x00 }, p2pie[255] = { 0x00 }; - u8 wpsielen = 0, p2pielen = 0; - u16 len_channellist_attr = 0; - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct ieee80211_hdr *pwlanhdr; - __le16 *fctrl; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - - pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (!pmgntframe) - return; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib(padapter, pattrib); - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct ieee80211_hdr *)pframe; - - fctrl = &pwlanhdr->frame_control; - *(fctrl) = 0; - - memcpy(pwlanhdr->addr1, raddr, ETH_ALEN); - memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN); - memcpy(pwlanhdr->addr3, myid(&padapter->eeprompriv), ETH_ALEN); - - SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); - pmlmeext->mgnt_seq++; - SetFrameSubType(pframe, WIFI_ACTION); - - pframe += sizeof(struct ieee80211_hdr_3addr); - pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); - - pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen); - pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen); - pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&p2poui, &pattrib->pktlen); - pframe = rtw_set_fixed_ie(pframe, 1, &oui_subtype, &pattrib->pktlen); - pwdinfo->negotiation_dialog_token = 1; /* Initialize the dialog value */ - pframe = rtw_set_fixed_ie(pframe, 1, &pwdinfo->negotiation_dialog_token, &pattrib->pktlen); - - /* WPS Section */ - wpsielen = 0; - /* WPS OUI */ - *(__be32 *)(wpsie) = cpu_to_be32(WPSOUI); - wpsielen += 4; - - /* WPS version */ - /* Type: */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1); - wpsielen += 2; - - /* Length: */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001); - wpsielen += 2; - - /* Value: */ - wpsie[wpsielen++] = WPS_VERSION_1; /* Version 1.0 */ - - /* Device Password ID */ - /* Type: */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_PWID); - wpsielen += 2; - - /* Length: */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002); - wpsielen += 2; - - /* Value: */ - - if (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PEER_DISPLAY_PIN) - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_USER_SPEC); - else if (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_SELF_DISPLAY_PIN) - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_REGISTRAR_SPEC); - else if (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PBC) - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_PBC); - - wpsielen += 2; - - pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *)wpsie, &pattrib->pktlen); - - /* P2P IE Section. */ - - /* P2P OUI */ - p2pielen = 0; - p2pie[p2pielen++] = 0x50; - p2pie[p2pielen++] = 0x6F; - p2pie[p2pielen++] = 0x9A; - p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */ - - /* Commented by Albert 20110306 */ - /* According to the P2P Specification, the group negotiation request frame should contain 9 P2P attributes */ - /* 1. P2P Capability */ - /* 2. Group Owner Intent */ - /* 3. Configuration Timeout */ - /* 4. Listen Channel */ - /* 5. Extended Listen Timing */ - /* 6. Intended P2P Interface Address */ - /* 7. Channel List */ - /* 8. P2P Device Info */ - /* 9. Operating Channel */ - - /* P2P Capability */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_CAPABILITY; - - /* Length: */ - *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002); - p2pielen += 2; - - /* Value: */ - /* Device Capability Bitmap, 1 byte */ - p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT; - - /* Group Capability Bitmap, 1 byte */ - if (pwdinfo->persistent_supported) - p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN | P2P_GRPCAP_PERSISTENT_GROUP; - else - p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN; - - /* Group Owner Intent */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_GO_INTENT; - - /* Length: */ - *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001); - p2pielen += 2; - - /* Value: */ - /* Todo the tie breaker bit. */ - p2pie[p2pielen++] = ((pwdinfo->intent << 1) | BIT(0)); - - /* Configuration Timeout */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT; - - /* Length: */ - *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002); - p2pielen += 2; - - /* Value: */ - p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P GO */ - p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P Client */ - - /* Listen Channel */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_LISTEN_CH; - - /* Length: */ - *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005); - p2pielen += 2; - - /* Value: */ - /* Country String */ - p2pie[p2pielen++] = 'X'; - p2pie[p2pielen++] = 'X'; - - /* The third byte should be set to 0x04. */ - /* Described in the "Operating Channel Attribute" section. */ - p2pie[p2pielen++] = 0x04; - - /* Operating Class */ - p2pie[p2pielen++] = 0x51; /* Copy from SD7 */ - - /* Channel Number */ - p2pie[p2pielen++] = pwdinfo->listen_channel; /* listening channel number */ - - /* Extended Listen Timing ATTR */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_EX_LISTEN_TIMING; - - /* Length: */ - *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0004); - p2pielen += 2; - - /* Value: */ - /* Availability Period */ - *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF); - p2pielen += 2; - - /* Availability Interval */ - *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF); - p2pielen += 2; - - /* Intended P2P Interface Address */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_INTENTED_IF_ADDR; - - /* Length: */ - *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN); - p2pielen += 2; - - /* Value: */ - memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN); - p2pielen += ETH_ALEN; - - /* Channel List */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_CH_LIST; - - /* Length: */ - /* Country String(3) */ - /* + (Operating Class (1) + Number of Channels(1)) * Operation Classes (?) */ - /* + number of channels in all classes */ - len_channellist_attr = 3 - + (1 + 1) * (u16)(pmlmeext->channel_list.reg_classes) - + get_reg_classes_full_count(&pmlmeext->channel_list); - - *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr); - p2pielen += 2; - - /* Value: */ - /* Country String */ - p2pie[p2pielen++] = 'X'; - p2pie[p2pielen++] = 'X'; - - /* The third byte should be set to 0x04. */ - /* Described in the "Operating Channel Attribute" section. */ - p2pie[p2pielen++] = 0x04; - - /* Channel Entry List */ - - { - int i, j; - for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) { - /* Operating Class */ - p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class; - - /* Number of Channels */ - p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels; - - /* Channel List */ - for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) { - p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i]; - } - } - } - - /* Device Info */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO; - - /* Length: */ - /* 21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */ - /* + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */ - *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len); - p2pielen += 2; - - /* Value: */ - /* P2P Device Address */ - memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN); - p2pielen += ETH_ALEN; - - /* Config Method */ - /* This field should be big endian. Noted by P2P specification. */ - - *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->supported_wps_cm); - - p2pielen += 2; - - /* Primary Device Type */ - /* Category ID */ - *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA); - p2pielen += 2; - - /* OUI */ - *(__be32 *)(p2pie + p2pielen) = cpu_to_be32(WPSOUI); - p2pielen += 4; - - /* Sub Category ID */ - *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER); - p2pielen += 2; - - /* Number of Secondary Device Types */ - p2pie[p2pielen++] = 0x00; /* No Secondary Device Type List */ - - /* Device Name */ - /* Type: */ - *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME); - p2pielen += 2; - - /* Length: */ - *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len); - p2pielen += 2; - - /* Value: */ - memcpy(p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len); - p2pielen += pwdinfo->device_name_len; - - /* Operating Channel */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH; - - /* Length: */ - *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005); - p2pielen += 2; - - /* Value: */ - /* Country String */ - p2pie[p2pielen++] = 'X'; - p2pie[p2pielen++] = 'X'; - - /* The third byte should be set to 0x04. */ - /* Described in the "Operating Channel Attribute" section. */ - p2pie[p2pielen++] = 0x04; - - /* Operating Class */ - p2pie[p2pielen++] = 0x51; - - /* Channel Number */ - p2pie[p2pielen++] = pwdinfo->operating_channel; /* operating channel number */ - - pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &pattrib->pktlen); - - pattrib->last_txcmdsz = pattrib->pktlen; - - dump_mgntframe(padapter, pmgntframe); -} - -static void issue_p2p_GO_response(struct adapter *padapter, u8 *raddr, u8 *frame_body, uint len, u8 result) -{ - unsigned char category = WLAN_CATEGORY_PUBLIC; - u8 action = P2P_PUB_ACTION_ACTION; - __be32 p2poui = cpu_to_be32(P2POUI); - u8 oui_subtype = P2P_GO_NEGO_RESP; - u8 wpsie[255] = { 0x00 }, p2pie[255] = { 0x00 }; - u8 p2pielen = 0; - uint wpsielen = 0; - u16 wps_devicepassword_id = 0x0000; - __be16 be_tmp; - uint wps_devicepassword_id_len = 0; - u16 len_channellist_attr = 0; - - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct ieee80211_hdr *pwlanhdr; - __le16 *fctrl; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - - pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (!pmgntframe) - return; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib(padapter, pattrib); - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct ieee80211_hdr *)pframe; - - fctrl = &pwlanhdr->frame_control; - *(fctrl) = 0; - - memcpy(pwlanhdr->addr1, raddr, ETH_ALEN); - memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN); - memcpy(pwlanhdr->addr3, myid(&padapter->eeprompriv), ETH_ALEN); - - SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); - pmlmeext->mgnt_seq++; - SetFrameSubType(pframe, WIFI_ACTION); - - pframe += sizeof(struct ieee80211_hdr_3addr); - pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); - - pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen); - pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen); - pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&p2poui, &pattrib->pktlen); - pframe = rtw_set_fixed_ie(pframe, 1, &oui_subtype, &pattrib->pktlen); - pwdinfo->negotiation_dialog_token = frame_body[7]; /* The Dialog Token of provisioning discovery request frame. */ - pframe = rtw_set_fixed_ie(pframe, 1, &pwdinfo->negotiation_dialog_token, &pattrib->pktlen); - - /* Commented by Albert 20110328 */ - /* Try to get the device password ID from the WPS IE of group negotiation request frame */ - /* WiFi Direct test plan 5.1.15 */ - rtw_get_wps_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, wpsie, &wpsielen); - rtw_get_wps_attr_content(wpsie, wpsielen, WPS_ATTR_DEVICE_PWID, (u8 *)&be_tmp, &wps_devicepassword_id_len); - wps_devicepassword_id = be16_to_cpu(be_tmp); - - memset(wpsie, 0x00, 255); - wpsielen = 0; - - /* WPS Section */ - wpsielen = 0; - /* WPS OUI */ - *(__be32 *)(wpsie) = cpu_to_be32(WPSOUI); - wpsielen += 4; - - /* WPS version */ - /* Type: */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1); - wpsielen += 2; - - /* Length: */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001); - wpsielen += 2; - - /* Value: */ - wpsie[wpsielen++] = WPS_VERSION_1; /* Version 1.0 */ - - /* Device Password ID */ - /* Type: */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_PWID); - wpsielen += 2; - - /* Length: */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002); - wpsielen += 2; - - /* Value: */ - if (wps_devicepassword_id == WPS_DPID_USER_SPEC) - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_REGISTRAR_SPEC); - else if (wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC) - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_USER_SPEC); - else - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_PBC); - wpsielen += 2; - - /* Commented by Kurt 20120113 */ - /* If some device wants to do p2p handshake without sending prov_disc_req */ - /* We have to get peer_req_cm from here. */ - if (!memcmp(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "000", 3)) { - if (wps_devicepassword_id == WPS_DPID_USER_SPEC) - memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "dis", 3); - else if (wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC) - memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pad", 3); - else - memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pbc", 3); - } - - pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *)wpsie, &pattrib->pktlen); - - /* P2P IE Section. */ - - /* P2P OUI */ - p2pielen = 0; - p2pie[p2pielen++] = 0x50; - p2pie[p2pielen++] = 0x6F; - p2pie[p2pielen++] = 0x9A; - p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */ - - /* Commented by Albert 20100908 */ - /* According to the P2P Specification, the group negotiation response frame should contain 9 P2P attributes */ - /* 1. Status */ - /* 2. P2P Capability */ - /* 3. Group Owner Intent */ - /* 4. Configuration Timeout */ - /* 5. Operating Channel */ - /* 6. Intended P2P Interface Address */ - /* 7. Channel List */ - /* 8. Device Info */ - /* 9. Group ID (Only GO) */ - - /* ToDo: */ - - /* P2P Status */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_STATUS; - - /* Length: */ - *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001); - p2pielen += 2; - - /* Value: */ - p2pie[p2pielen++] = result; - - /* P2P Capability */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_CAPABILITY; - - /* Length: */ - *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002); - p2pielen += 2; - - /* Value: */ - /* Device Capability Bitmap, 1 byte */ - - if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) { - /* Commented by Albert 2011/03/08 */ - /* According to the P2P specification */ - /* if the sending device will be client, the P2P Capability should be reserved of group negotiation response frame */ - p2pie[p2pielen++] = 0; - } else { - /* Be group owner or meet the error case */ - p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT; - } - - /* Group Capability Bitmap, 1 byte */ - if (pwdinfo->persistent_supported) { - p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN | P2P_GRPCAP_PERSISTENT_GROUP; - } else { - p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN; - } - - /* Group Owner Intent */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_GO_INTENT; - - /* Length: */ - *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001); - p2pielen += 2; - - /* Value: */ - if (pwdinfo->peer_intent & 0x01) { - /* Peer's tie breaker bit is 1, our tie breaker bit should be 0 */ - p2pie[p2pielen++] = (pwdinfo->intent << 1); - } else { - /* Peer's tie breaker bit is 0, our tie breaker bit should be 1 */ - p2pie[p2pielen++] = ((pwdinfo->intent << 1) | BIT(0)); - } - - /* Configuration Timeout */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT; - - /* Length: */ - *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002); - p2pielen += 2; - - /* Value: */ - p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P GO */ - p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P Client */ - - /* Operating Channel */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH; - - /* Length: */ - *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005); - p2pielen += 2; - - /* Value: */ - /* Country String */ - p2pie[p2pielen++] = 'X'; - p2pie[p2pielen++] = 'X'; - - /* The third byte should be set to 0x04. */ - /* Described in the "Operating Channel Attribute" section. */ - p2pie[p2pielen++] = 0x04; - - /* Operating Class */ - p2pie[p2pielen++] = 0x51; - - /* Channel Number */ - p2pie[p2pielen++] = pwdinfo->operating_channel; /* operating channel number */ - - /* Intended P2P Interface Address */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_INTENTED_IF_ADDR; - - /* Length: */ - *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN); - p2pielen += 2; - - /* Value: */ - memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN); - p2pielen += ETH_ALEN; - - /* Channel List */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_CH_LIST; - - /* Country String(3) */ - /* + (Operating Class (1) + Number of Channels(1)) * Operation Classes (?) */ - /* + number of channels in all classes */ - len_channellist_attr = 3 - + (1 + 1) * (u16)pmlmeext->channel_list.reg_classes - + get_reg_classes_full_count(&pmlmeext->channel_list); - - *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr); - - p2pielen += 2; - - /* Value: */ - /* Country String */ - p2pie[p2pielen++] = 'X'; - p2pie[p2pielen++] = 'X'; - - /* The third byte should be set to 0x04. */ - /* Described in the "Operating Channel Attribute" section. */ - p2pie[p2pielen++] = 0x04; - - /* Channel Entry List */ - - { - int i, j; - for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) { - /* Operating Class */ - p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class; - - /* Number of Channels */ - p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels; - - /* Channel List */ - for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) { - p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i]; - } - } - } - - /* Device Info */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO; - - /* Length: */ - /* 21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */ - /* + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */ - *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len); - p2pielen += 2; - - /* Value: */ - /* P2P Device Address */ - memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN); - p2pielen += ETH_ALEN; - - /* Config Method */ - /* This field should be big endian. Noted by P2P specification. */ - - *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->supported_wps_cm); - - p2pielen += 2; - - /* Primary Device Type */ - /* Category ID */ - *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA); - p2pielen += 2; - - /* OUI */ - *(__be32 *)(p2pie + p2pielen) = cpu_to_be32(WPSOUI); - p2pielen += 4; - - /* Sub Category ID */ - *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER); - p2pielen += 2; - - /* Number of Secondary Device Types */ - p2pie[p2pielen++] = 0x00; /* No Secondary Device Type List */ - - /* Device Name */ - /* Type: */ - *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME); - p2pielen += 2; - - /* Length: */ - *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len); - p2pielen += 2; - - /* Value: */ - memcpy(p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len); - p2pielen += pwdinfo->device_name_len; - - if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) { - /* Group ID Attribute */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_GROUP_ID; - - /* Length: */ - *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN + pwdinfo->nego_ssidlen); - p2pielen += 2; - - /* Value: */ - /* p2P Device Address */ - memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN); - p2pielen += ETH_ALEN; - - /* SSID */ - memcpy(p2pie + p2pielen, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen); - p2pielen += pwdinfo->nego_ssidlen; - } - - pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &pattrib->pktlen); - - pattrib->last_txcmdsz = pattrib->pktlen; - - dump_mgntframe(padapter, pmgntframe); -} - -static void issue_p2p_GO_confirm(struct adapter *padapter, u8 *raddr, u8 result) -{ - unsigned char category = WLAN_CATEGORY_PUBLIC; - u8 action = P2P_PUB_ACTION_ACTION; - __be32 p2poui = cpu_to_be32(P2POUI); - u8 oui_subtype = P2P_GO_NEGO_CONF; - u8 p2pie[255] = { 0x00 }; - u8 p2pielen = 0; - - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct ieee80211_hdr *pwlanhdr; - __le16 *fctrl; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - - pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (!pmgntframe) - return; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib(padapter, pattrib); - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct ieee80211_hdr *)pframe; - - fctrl = &pwlanhdr->frame_control; - *(fctrl) = 0; - - memcpy(pwlanhdr->addr1, raddr, ETH_ALEN); - memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN); - memcpy(pwlanhdr->addr3, myid(&padapter->eeprompriv), ETH_ALEN); - - SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); - pmlmeext->mgnt_seq++; - SetFrameSubType(pframe, WIFI_ACTION); - - pframe += sizeof(struct ieee80211_hdr_3addr); - pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); - - pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen); - pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen); - pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&p2poui, &pattrib->pktlen); - pframe = rtw_set_fixed_ie(pframe, 1, &oui_subtype, &pattrib->pktlen); - pframe = rtw_set_fixed_ie(pframe, 1, &pwdinfo->negotiation_dialog_token, &pattrib->pktlen); - - /* P2P IE Section. */ - - /* P2P OUI */ - p2pielen = 0; - p2pie[p2pielen++] = 0x50; - p2pie[p2pielen++] = 0x6F; - p2pie[p2pielen++] = 0x9A; - p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */ - - /* Commented by Albert 20110306 */ - /* According to the P2P Specification, the group negotiation request frame should contain 5 P2P attributes */ - /* 1. Status */ - /* 2. P2P Capability */ - /* 3. Operating Channel */ - /* 4. Channel List */ - /* 5. Group ID (if this WiFi is GO) */ - - /* P2P Status */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_STATUS; - - /* Length: */ - *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001); - p2pielen += 2; - - /* Value: */ - p2pie[p2pielen++] = result; - - /* P2P Capability */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_CAPABILITY; - - /* Length: */ - *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002); - p2pielen += 2; - - /* Value: */ - /* Device Capability Bitmap, 1 byte */ - p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT; - - /* Group Capability Bitmap, 1 byte */ - if (pwdinfo->persistent_supported) - p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN | P2P_GRPCAP_PERSISTENT_GROUP; - else - p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN; - - /* Operating Channel */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH; - - /* Length: */ - *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005); - p2pielen += 2; - - /* Value: */ - /* Country String */ - p2pie[p2pielen++] = 'X'; - p2pie[p2pielen++] = 'X'; - - /* The third byte should be set to 0x04. */ - /* Described in the "Operating Channel Attribute" section. */ - p2pie[p2pielen++] = 0x04; - - if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) { - /* Operating Class */ - p2pie[p2pielen++] = 0x51; - p2pie[p2pielen++] = pwdinfo->peer_operating_ch; - } else { - /* Operating Class */ - p2pie[p2pielen++] = 0x51; - - /* Channel Number */ - p2pie[p2pielen++] = pwdinfo->operating_channel; /* Use the listen channel as the operating channel */ - } - - /* Channel List */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_CH_LIST; - - /* Length: */ - *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(pwdinfo->channel_list_attr_len); - p2pielen += 2; - - /* Value: */ - memcpy(p2pie + p2pielen, pwdinfo->channel_list_attr, pwdinfo->channel_list_attr_len); - p2pielen += pwdinfo->channel_list_attr_len; - - if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) { - /* Group ID Attribute */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_GROUP_ID; - - /* Length: */ - *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN + pwdinfo->nego_ssidlen); - p2pielen += 2; - - /* Value: */ - /* p2P Device Address */ - memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN); - p2pielen += ETH_ALEN; - - /* SSID */ - memcpy(p2pie + p2pielen, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen); - p2pielen += pwdinfo->nego_ssidlen; - } - pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &pattrib->pktlen); - pattrib->last_txcmdsz = pattrib->pktlen; - dump_mgntframe(padapter, pmgntframe); -} - -void issue_p2p_invitation_request(struct adapter *padapter, u8 *raddr) -{ - unsigned char category = WLAN_CATEGORY_PUBLIC; - u8 action = P2P_PUB_ACTION_ACTION; - __be32 p2poui = cpu_to_be32(P2POUI); - u8 oui_subtype = P2P_INVIT_REQ; - u8 p2pie[255] = { 0x00 }; - u8 p2pielen = 0; - u8 dialogToken = 3; - u16 len_channellist_attr = 0; - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct ieee80211_hdr *pwlanhdr; - __le16 *fctrl; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - - pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (!pmgntframe) - return; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib(padapter, pattrib); - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct ieee80211_hdr *)pframe; - - fctrl = &pwlanhdr->frame_control; - *(fctrl) = 0; - - memcpy(pwlanhdr->addr1, raddr, ETH_ALEN); - memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN); - memcpy(pwlanhdr->addr3, raddr, ETH_ALEN); - - SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); - pmlmeext->mgnt_seq++; - SetFrameSubType(pframe, WIFI_ACTION); - - pframe += sizeof(struct ieee80211_hdr_3addr); - pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); - - pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen); - pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen); - pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&p2poui, &pattrib->pktlen); - pframe = rtw_set_fixed_ie(pframe, 1, &oui_subtype, &pattrib->pktlen); - pframe = rtw_set_fixed_ie(pframe, 1, &dialogToken, &pattrib->pktlen); - - /* P2P IE Section. */ - - /* P2P OUI */ - p2pielen = 0; - p2pie[p2pielen++] = 0x50; - p2pie[p2pielen++] = 0x6F; - p2pie[p2pielen++] = 0x9A; - p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */ - - /* Commented by Albert 20101011 */ - /* According to the P2P Specification, the P2P Invitation request frame should contain 7 P2P attributes */ - /* 1. Configuration Timeout */ - /* 2. Invitation Flags */ - /* 3. Operating Channel (Only GO) */ - /* 4. P2P Group BSSID (Should be included if I am the GO) */ - /* 5. Channel List */ - /* 6. P2P Group ID */ - /* 7. P2P Device Info */ - - /* Configuration Timeout */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT; - - /* Length: */ - *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002); - p2pielen += 2; - - /* Value: */ - p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P GO */ - p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P Client */ - - /* Invitation Flags */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_INVITATION_FLAGS; - - /* Length: */ - *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001); - p2pielen += 2; - - /* Value: */ - p2pie[p2pielen++] = P2P_INVITATION_FLAGS_PERSISTENT; - - /* Operating Channel */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH; - - /* Length: */ - *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005); - p2pielen += 2; - - /* Value: */ - /* Country String */ - p2pie[p2pielen++] = 'X'; - p2pie[p2pielen++] = 'X'; - - /* The third byte should be set to 0x04. */ - /* Described in the "Operating Channel Attribute" section. */ - p2pie[p2pielen++] = 0x04; - - /* Operating Class */ - p2pie[p2pielen++] = 0x51; - - /* Channel Number */ - p2pie[p2pielen++] = pwdinfo->invitereq_info.operating_ch; /* operating channel number */ - - if (!memcmp(myid(&padapter->eeprompriv), pwdinfo->invitereq_info.go_bssid, ETH_ALEN)) { - /* P2P Group BSSID */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_GROUP_BSSID; - - /* Length: */ - *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN); - p2pielen += 2; - - /* Value: */ - /* P2P Device Address for GO */ - memcpy(p2pie + p2pielen, pwdinfo->invitereq_info.go_bssid, ETH_ALEN); - p2pielen += ETH_ALEN; - } - - /* Channel List */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_CH_LIST; - - /* Length: */ - /* Country String(3) */ - /* + (Operating Class (1) + Number of Channels(1)) * Operation Classes (?) */ - /* + number of channels in all classes */ - len_channellist_attr = 3 - + (1 + 1) * (u16)pmlmeext->channel_list.reg_classes - + get_reg_classes_full_count(&pmlmeext->channel_list); - - *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr); - - p2pielen += 2; - - /* Value: */ - /* Country String */ - p2pie[p2pielen++] = 'X'; - p2pie[p2pielen++] = 'X'; - - /* The third byte should be set to 0x04. */ - /* Described in the "Operating Channel Attribute" section. */ - p2pie[p2pielen++] = 0x04; - - /* Channel Entry List */ - { - int i, j; - for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) { - /* Operating Class */ - p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class; - - /* Number of Channels */ - p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels; - - /* Channel List */ - for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) { - p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i]; - } - } - } - - /* P2P Group ID */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_GROUP_ID; - - /* Length: */ - *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(6 + pwdinfo->invitereq_info.ssidlen); - p2pielen += 2; - - /* Value: */ - /* P2P Device Address for GO */ - memcpy(p2pie + p2pielen, pwdinfo->invitereq_info.go_bssid, ETH_ALEN); - p2pielen += ETH_ALEN; - - /* SSID */ - memcpy(p2pie + p2pielen, pwdinfo->invitereq_info.go_ssid, pwdinfo->invitereq_info.ssidlen); - p2pielen += pwdinfo->invitereq_info.ssidlen; - - /* Device Info */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO; - - /* Length: */ - /* 21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */ - /* + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */ - *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len); - p2pielen += 2; - - /* Value: */ - /* P2P Device Address */ - memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN); - p2pielen += ETH_ALEN; - - /* Config Method */ - /* This field should be big endian. Noted by P2P specification. */ - *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_CONFIG_METHOD_DISPLAY); - p2pielen += 2; - - /* Primary Device Type */ - /* Category ID */ - *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA); - p2pielen += 2; - - /* OUI */ - *(__be32 *)(p2pie + p2pielen) = cpu_to_be32(WPSOUI); - p2pielen += 4; - - /* Sub Category ID */ - *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER); - p2pielen += 2; - - /* Number of Secondary Device Types */ - p2pie[p2pielen++] = 0x00; /* No Secondary Device Type List */ - - /* Device Name */ - /* Type: */ - *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME); - p2pielen += 2; - - /* Length: */ - *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len); - p2pielen += 2; - - /* Value: */ - memcpy(p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len); - p2pielen += pwdinfo->device_name_len; - - pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &pattrib->pktlen); - - pattrib->last_txcmdsz = pattrib->pktlen; - - dump_mgntframe(padapter, pmgntframe); -} - -void issue_p2p_invitation_response(struct adapter *padapter, u8 *raddr, u8 dialogToken, u8 status_code) -{ - unsigned char category = WLAN_CATEGORY_PUBLIC; - u8 action = P2P_PUB_ACTION_ACTION; - __be32 p2poui = cpu_to_be32(P2POUI); - u8 oui_subtype = P2P_INVIT_RESP; - u8 p2pie[255] = { 0x00 }; - u8 p2pielen = 0; - u16 len_channellist_attr = 0; - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct ieee80211_hdr *pwlanhdr; - __le16 *fctrl; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - - pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (!pmgntframe) - return; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib(padapter, pattrib); - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct ieee80211_hdr *)pframe; - - fctrl = &pwlanhdr->frame_control; - *(fctrl) = 0; - - memcpy(pwlanhdr->addr1, raddr, ETH_ALEN); - memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN); - memcpy(pwlanhdr->addr3, raddr, ETH_ALEN); - - SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); - pmlmeext->mgnt_seq++; - SetFrameSubType(pframe, WIFI_ACTION); - - pframe += sizeof(struct ieee80211_hdr_3addr); - pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); - - pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen); - pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen); - pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&p2poui, &pattrib->pktlen); - pframe = rtw_set_fixed_ie(pframe, 1, &oui_subtype, &pattrib->pktlen); - pframe = rtw_set_fixed_ie(pframe, 1, &dialogToken, &pattrib->pktlen); - - /* P2P IE Section. */ - - /* P2P OUI */ - p2pielen = 0; - p2pie[p2pielen++] = 0x50; - p2pie[p2pielen++] = 0x6F; - p2pie[p2pielen++] = 0x9A; - p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */ - - /* Commented by Albert 20101005 */ - /* According to the P2P Specification, the P2P Invitation response frame should contain 5 P2P attributes */ - /* 1. Status */ - /* 2. Configuration Timeout */ - /* 3. Operating Channel (Only GO) */ - /* 4. P2P Group BSSID (Only GO) */ - /* 5. Channel List */ - - /* P2P Status */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_STATUS; - - /* Length: */ - *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001); - p2pielen += 2; - - /* Value: */ - /* When status code is P2P_STATUS_FAIL_INFO_UNAVAILABLE. */ - /* Sent the event receiving the P2P Invitation Req frame to DMP UI. */ - /* DMP had to compare the MAC address to find out the profile. */ - /* So, the WiFi driver will send the P2P_STATUS_FAIL_INFO_UNAVAILABLE to NB. */ - /* If the UI found the corresponding profile, the WiFi driver sends the P2P Invitation Req */ - /* to NB to rebuild the persistent group. */ - p2pie[p2pielen++] = status_code; - - /* Configuration Timeout */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT; - - /* Length: */ - *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002); - p2pielen += 2; - - /* Value: */ - p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P GO */ - p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P Client */ - - if (status_code == P2P_STATUS_SUCCESS) { - if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) { - /* The P2P Invitation request frame asks this Wi-Fi device to be the P2P GO */ - /* In this case, the P2P Invitation response frame should carry the two more P2P attributes. */ - /* First one is operating channel attribute. */ - /* Second one is P2P Group BSSID attribute. */ - - /* Operating Channel */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH; - - /* Length: */ - *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005); - p2pielen += 2; - - /* Value: */ - /* Country String */ - p2pie[p2pielen++] = 'X'; - p2pie[p2pielen++] = 'X'; - - /* The third byte should be set to 0x04. */ - /* Described in the "Operating Channel Attribute" section. */ - p2pie[p2pielen++] = 0x04; - - /* Operating Class */ - p2pie[p2pielen++] = 0x51; /* Copy from SD7 */ - - /* Channel Number */ - p2pie[p2pielen++] = pwdinfo->operating_channel; /* operating channel number */ - - /* P2P Group BSSID */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_GROUP_BSSID; - - /* Length: */ - *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN); - p2pielen += 2; - - /* Value: */ - /* P2P Device Address for GO */ - memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN); - p2pielen += ETH_ALEN; - } - - /* Channel List */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_CH_LIST; - - /* Length: */ - /* Country String(3) */ - /* + (Operating Class (1) + Number of Channels(1)) * Operation Classes (?) */ - /* + number of channels in all classes */ - len_channellist_attr = 3 - + (1 + 1) * (u16)pmlmeext->channel_list.reg_classes - + get_reg_classes_full_count(&pmlmeext->channel_list); - - *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr); - p2pielen += 2; - - /* Value: */ - /* Country String */ - p2pie[p2pielen++] = 'X'; - p2pie[p2pielen++] = 'X'; - - /* The third byte should be set to 0x04. */ - /* Described in the "Operating Channel Attribute" section. */ - p2pie[p2pielen++] = 0x04; - - /* Channel Entry List */ - { - int i, j; - for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) { - /* Operating Class */ - p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class; - - /* Number of Channels */ - p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels; - - /* Channel List */ - for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) { - p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i]; - } - } - } - } - - pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &pattrib->pktlen); - - pattrib->last_txcmdsz = pattrib->pktlen; - - dump_mgntframe(padapter, pmgntframe); -} - -void issue_p2p_provision_request(struct adapter *padapter, u8 *pssid, u8 ussidlen, u8 *pdev_raddr) -{ - unsigned char category = WLAN_CATEGORY_PUBLIC; - u8 action = P2P_PUB_ACTION_ACTION; - u8 dialogToken = 1; - u8 oui_subtype = P2P_PROVISION_DISC_REQ; - u8 wpsie[100] = { 0x00 }; - u8 wpsielen = 0; - __be32 p2poui = cpu_to_be32(P2POUI); - u32 p2pielen = 0; - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct ieee80211_hdr *pwlanhdr; - __le16 *fctrl; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - - pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (!pmgntframe) - return; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib(padapter, pattrib); - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct ieee80211_hdr *)pframe; - - fctrl = &pwlanhdr->frame_control; - *(fctrl) = 0; - - memcpy(pwlanhdr->addr1, pdev_raddr, ETH_ALEN); - memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN); - memcpy(pwlanhdr->addr3, pdev_raddr, ETH_ALEN); - - SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); - pmlmeext->mgnt_seq++; - SetFrameSubType(pframe, WIFI_ACTION); - - pframe += sizeof(struct ieee80211_hdr_3addr); - pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); - - pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen); - pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen); - pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&p2poui, &pattrib->pktlen); - pframe = rtw_set_fixed_ie(pframe, 1, &oui_subtype, &pattrib->pktlen); - pframe = rtw_set_fixed_ie(pframe, 1, &dialogToken, &pattrib->pktlen); - - p2pielen = build_prov_disc_request_p2p_ie(pwdinfo, pframe, pssid, ussidlen, pdev_raddr); - - pframe += p2pielen; - pattrib->pktlen += p2pielen; - - wpsielen = 0; - /* WPS OUI */ - *(__be32 *)(wpsie) = cpu_to_be32(WPSOUI); - wpsielen += 4; - - /* WPS version */ - /* Type: */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1); - wpsielen += 2; - - /* Length: */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001); - wpsielen += 2; - - /* Value: */ - wpsie[wpsielen++] = WPS_VERSION_1; /* Version 1.0 */ - - /* Config Method */ - /* Type: */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_CONF_METHOD); - wpsielen += 2; - - /* Length: */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002); - wpsielen += 2; - - /* Value: */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->tx_prov_disc_info.wps_config_method_request); - wpsielen += 2; - - pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *)wpsie, &pattrib->pktlen); - - pattrib->last_txcmdsz = pattrib->pktlen; - - dump_mgntframe(padapter, pmgntframe); -} - -static u8 is_matched_in_profilelist(u8 *peermacaddr, struct profile_info *profileinfo) -{ - u8 i, match_result = 0; - - for (i = 0; i < P2P_MAX_PERSISTENT_GROUP_NUM; i++, profileinfo++) { - if (!memcmp(peermacaddr, profileinfo->peermac, ETH_ALEN)) { - match_result = 1; - break; - } - } - return match_result; -} - -void issue_probersp_p2p(struct adapter *padapter, unsigned char *da) -{ - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct ieee80211_hdr *pwlanhdr; - __le16 *fctrl; - unsigned char *mac; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - u16 beacon_interval = 100; - u16 capInfo = 0; - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - u8 wpsie[255] = { 0x00 }; - u32 wpsielen = 0, p2pielen = 0; - - pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (!pmgntframe) - return; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib(padapter, pattrib); - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct ieee80211_hdr *)pframe; - - mac = myid(&padapter->eeprompriv); - - fctrl = &pwlanhdr->frame_control; - *(fctrl) = 0; - memcpy(pwlanhdr->addr1, da, ETH_ALEN); - memcpy(pwlanhdr->addr2, mac, ETH_ALEN); - - /* Use the device address for BSSID field. */ - memcpy(pwlanhdr->addr3, mac, ETH_ALEN); - - SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); - pmlmeext->mgnt_seq++; - SetFrameSubType(fctrl, WIFI_PROBERSP); - - pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr); - pattrib->pktlen = pattrib->hdrlen; - pframe += pattrib->hdrlen; - - /* timestamp will be inserted by hardware */ - pframe += 8; - pattrib->pktlen += 8; - - /* beacon interval: 2 bytes */ - memcpy(pframe, (unsigned char *)&beacon_interval, 2); - pframe += 2; - pattrib->pktlen += 2; - - /* capability info: 2 bytes */ - /* ESS and IBSS bits must be 0 (defined in the 3.1.2.1.1 of WiFi Direct Spec) */ - capInfo |= cap_ShortPremble; - capInfo |= cap_ShortSlot; - - memcpy(pframe, (unsigned char *)&capInfo, 2); - pframe += 2; - pattrib->pktlen += 2; - - /* SSID */ - pframe = rtw_set_ie(pframe, _SSID_IE_, 7, pwdinfo->p2p_wildcard_ssid, &pattrib->pktlen); - - /* supported rates... */ - /* Use the OFDM rate in the P2P probe response frame. (6(B), 9(B), 12, 18, 24, 36, 48, 54) */ - pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pwdinfo->support_rate, &pattrib->pktlen); - - /* DS parameter set */ - pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&pwdinfo->listen_channel, &pattrib->pktlen); - - /* Todo: WPS IE */ - /* Noted by Albert 20100907 */ - /* According to the WPS specification, all the WPS attribute is presented by Big Endian. */ - - wpsielen = 0; - /* WPS OUI */ - *(__be32 *)(wpsie) = cpu_to_be32(WPSOUI); - wpsielen += 4; - - /* WPS version */ - /* Type: */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1); - wpsielen += 2; - - /* Length: */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001); - wpsielen += 2; - - /* Value: */ - wpsie[wpsielen++] = WPS_VERSION_1; /* Version 1.0 */ - - /* WiFi Simple Config State */ - /* Type: */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_SIMPLE_CONF_STATE); - wpsielen += 2; - - /* Length: */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001); - wpsielen += 2; - - /* Value: */ - wpsie[wpsielen++] = WPS_WSC_STATE_NOT_CONFIG; /* Not Configured. */ - - /* Response Type */ - /* Type: */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_RESP_TYPE); - wpsielen += 2; - - /* Length: */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001); - wpsielen += 2; - - /* Value: */ - wpsie[wpsielen++] = WPS_RESPONSE_TYPE_8021X; - - /* UUID-E */ - /* Type: */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_UUID_E); - wpsielen += 2; - - /* Length: */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0010); - wpsielen += 2; - - /* Value: */ - memcpy(wpsie + wpsielen, myid(&padapter->eeprompriv), ETH_ALEN); - wpsielen += 0x10; - - /* Manufacturer */ - /* Type: */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_MANUFACTURER); - wpsielen += 2; - - /* Length: */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0007); - wpsielen += 2; - - /* Value: */ - memcpy(wpsie + wpsielen, "Realtek", 7); - wpsielen += 7; - - /* Model Name */ - /* Type: */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_MODEL_NAME); - wpsielen += 2; - - /* Length: */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0006); - wpsielen += 2; - - /* Value: */ - memcpy(wpsie + wpsielen, "8188EU", 6); - wpsielen += 6; - - /* Model Number */ - /* Type: */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_MODEL_NUMBER); - wpsielen += 2; - - /* Length: */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001); - wpsielen += 2; - - /* Value: */ - wpsie[wpsielen++] = 0x31; /* character 1 */ - - /* Serial Number */ - /* Type: */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_SERIAL_NUMBER); - wpsielen += 2; - - /* Length: */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(ETH_ALEN); - wpsielen += 2; - - /* Value: */ - memcpy(wpsie + wpsielen, "123456", ETH_ALEN); - wpsielen += ETH_ALEN; - - /* Primary Device Type */ - /* Type: */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_PRIMARY_DEV_TYPE); - wpsielen += 2; - - /* Length: */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0008); - wpsielen += 2; - - /* Value: */ - /* Category ID */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA); - wpsielen += 2; - - /* OUI */ - *(__be32 *)(wpsie + wpsielen) = cpu_to_be32(WPSOUI); - wpsielen += 4; - - /* Sub Category ID */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER); - wpsielen += 2; - - /* Device Name */ - /* Type: */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME); - wpsielen += 2; - - /* Length: */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->device_name_len); - wpsielen += 2; - - /* Value: */ - if (pwdinfo->device_name_len) { - memcpy(wpsie + wpsielen, pwdinfo->device_name, pwdinfo->device_name_len); - wpsielen += pwdinfo->device_name_len; - } - - /* Config Method */ - /* Type: */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_CONF_METHOD); - wpsielen += 2; - - /* Length: */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002); - wpsielen += 2; - - /* Value: */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->supported_wps_cm); - wpsielen += 2; - - pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *)wpsie, &pattrib->pktlen); - - p2pielen = build_probe_resp_p2p_ie(pwdinfo, pframe); - pframe += p2pielen; - pattrib->pktlen += p2pielen; - - pattrib->last_txcmdsz = pattrib->pktlen; - - dump_mgntframe(padapter, pmgntframe); -} - -inline void issue_probereq_p2p(struct adapter *padapter) -{ - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct ieee80211_hdr *pwlanhdr; - __le16 *fctrl; - unsigned char *mac; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - u8 wpsie[255] = { 0x00 }, p2pie[255] = { 0x00 }; - u16 wpsielen = 0, p2pielen = 0; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (!pmgntframe) - return; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib(padapter, pattrib); - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct ieee80211_hdr *)pframe; - - mac = myid(&padapter->eeprompriv); - - fctrl = &pwlanhdr->frame_control; - *(fctrl) = 0; - - if ((pwdinfo->p2p_info.scan_op_ch_only) || (pwdinfo->rx_invitereq_info.scan_op_ch_only)) { - /* This two flags will be set when this is only the P2P client mode. */ - memcpy(pwlanhdr->addr1, pwdinfo->p2p_peer_interface_addr, ETH_ALEN); - memcpy(pwlanhdr->addr3, pwdinfo->p2p_peer_interface_addr, ETH_ALEN); - } else { - /* broadcast probe request frame */ - eth_broadcast_addr(pwlanhdr->addr1); - eth_broadcast_addr(pwlanhdr->addr3); - } - - memcpy(pwlanhdr->addr2, mac, ETH_ALEN); - - SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); - pmlmeext->mgnt_seq++; - SetFrameSubType(pframe, WIFI_PROBEREQ); - - pframe += sizeof(struct ieee80211_hdr_3addr); - pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); - - if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ)) - pframe = rtw_set_ie(pframe, _SSID_IE_, pwdinfo->tx_prov_disc_info.ssid.SsidLength, pwdinfo->tx_prov_disc_info.ssid.Ssid, &pattrib->pktlen); - else - pframe = rtw_set_ie(pframe, _SSID_IE_, P2P_WILDCARD_SSID_LEN, pwdinfo->p2p_wildcard_ssid, &pattrib->pktlen); - - /* Use the OFDM rate in the P2P probe request frame. (6(B), 9(B), 12(B), 24(B), 36, 48, 54) */ - pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pwdinfo->support_rate, &pattrib->pktlen); - - /* WPS IE */ - /* Noted by Albert 20110221 */ - /* According to the WPS specification, all the WPS attribute is presented by Big Endian. */ - - wpsielen = 0; - /* WPS OUI */ - *(__be32 *)(wpsie) = cpu_to_be32(WPSOUI); - wpsielen += 4; - - /* WPS version */ - /* Type: */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1); - wpsielen += 2; - - /* Length: */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001); - wpsielen += 2; - - /* Value: */ - wpsie[wpsielen++] = WPS_VERSION_1; /* Version 1.0 */ - - if (!pmlmepriv->wps_probe_req_ie) { - /* UUID-E */ - /* Type: */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_UUID_E); - wpsielen += 2; - - /* Length: */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0010); - wpsielen += 2; - - /* Value: */ - memcpy(wpsie + wpsielen, myid(&padapter->eeprompriv), ETH_ALEN); - wpsielen += 0x10; - - /* Config Method */ - /* Type: */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_CONF_METHOD); - wpsielen += 2; - - /* Length: */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002); - wpsielen += 2; - - /* Value: */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->supported_wps_cm); - wpsielen += 2; - } - - /* Device Name */ - /* Type: */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME); - wpsielen += 2; - - /* Length: */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->device_name_len); - wpsielen += 2; - - /* Value: */ - memcpy(wpsie + wpsielen, pwdinfo->device_name, pwdinfo->device_name_len); - wpsielen += pwdinfo->device_name_len; - - /* Primary Device Type */ - /* Type: */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_PRIMARY_DEV_TYPE); - wpsielen += 2; - - /* Length: */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0008); - wpsielen += 2; - - /* Value: */ - /* Category ID */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_PDT_CID_RTK_WIDI); - wpsielen += 2; - - /* OUI */ - *(__be32 *)(wpsie + wpsielen) = cpu_to_be32(WPSOUI); - wpsielen += 4; - - /* Sub Category ID */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_PDT_SCID_RTK_DMP); - wpsielen += 2; - - /* Device Password ID */ - /* Type: */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_PWID); - wpsielen += 2; - - /* Length: */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002); - wpsielen += 2; - - /* Value: */ - *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_REGISTRAR_SPEC); /* Registrar-specified */ - wpsielen += 2; - - pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *)wpsie, &pattrib->pktlen); - - /* P2P OUI */ - p2pielen = 0; - p2pie[p2pielen++] = 0x50; - p2pie[p2pielen++] = 0x6F; - p2pie[p2pielen++] = 0x9A; - p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */ - - /* Commented by Albert 20110221 */ - /* According to the P2P Specification, the probe request frame should contain 5 P2P attributes */ - /* 1. P2P Capability */ - /* 2. P2P Device ID if this probe request wants to find the specific P2P device */ - /* 3. Listen Channel */ - /* 4. Extended Listen Timing */ - /* 5. Operating Channel if this WiFi is working as the group owner now */ - - /* P2P Capability */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_CAPABILITY; - - /* Length: */ - *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002); - p2pielen += 2; - - /* Value: */ - /* Device Capability Bitmap, 1 byte */ - p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT; - - /* Group Capability Bitmap, 1 byte */ - if (pwdinfo->persistent_supported) - p2pie[p2pielen++] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT; - else - p2pie[p2pielen++] = DMP_P2P_GRPCAP_SUPPORT; - - /* Listen Channel */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_LISTEN_CH; - - /* Length: */ - *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005); - p2pielen += 2; - - /* Value: */ - /* Country String */ - p2pie[p2pielen++] = 'X'; - p2pie[p2pielen++] = 'X'; - - /* The third byte should be set to 0x04. */ - /* Described in the "Operating Channel Attribute" section. */ - p2pie[p2pielen++] = 0x04; - - /* Operating Class */ - p2pie[p2pielen++] = 0x51; /* Copy from SD7 */ - - /* Channel Number */ - p2pie[p2pielen++] = pwdinfo->listen_channel; /* listen channel */ - - /* Extended Listen Timing */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_EX_LISTEN_TIMING; - - /* Length: */ - *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0004); - p2pielen += 2; - - /* Value: */ - /* Availability Period */ - *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF); - p2pielen += 2; - - /* Availability Interval */ - *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF); - p2pielen += 2; - - if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) { - /* Operating Channel (if this WiFi is working as the group owner now) */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH; - - /* Length: */ - *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005); - p2pielen += 2; - - /* Value: */ - /* Country String */ - p2pie[p2pielen++] = 'X'; - p2pie[p2pielen++] = 'X'; - - /* The third byte should be set to 0x04. */ - /* Described in the "Operating Channel Attribute" section. */ - p2pie[p2pielen++] = 0x04; - - /* Operating Class */ - p2pie[p2pielen++] = 0x51; /* Copy from SD7 */ - - /* Channel Number */ - p2pie[p2pielen++] = pwdinfo->operating_channel; /* operating channel number */ - } - - pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &pattrib->pktlen); - - if (pmlmepriv->wps_probe_req_ie) { - /* WPS IE */ - memcpy(pframe, pmlmepriv->wps_probe_req_ie, pmlmepriv->wps_probe_req_ie_len); - pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len; - pframe += pmlmepriv->wps_probe_req_ie_len; - } - - pattrib->last_txcmdsz = pattrib->pktlen; - - dump_mgntframe(padapter, pmgntframe); -} - -static s32 rtw_action_public_decache(struct recv_frame *recv_frame, u8 token) -{ - struct adapter *adapter = recv_frame->adapter; - struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv; - u8 *frame = recv_frame->rx_data; - u16 seq_ctrl = ((recv_frame->attrib.seq_num & 0xffff) << 4) | - (recv_frame->attrib.frag_num & 0xf); - - if (GetRetry(frame)) { - if ((seq_ctrl == mlmeext->action_public_rxseq) && - (token == mlmeext->action_public_dialog_token)) - return _FAIL; - } - - mlmeext->action_public_rxseq = seq_ctrl; - mlmeext->action_public_dialog_token = token; - return _SUCCESS; -} - -static unsigned int on_action_public_p2p(struct recv_frame *precv_frame) -{ - u8 *pframe = precv_frame->rx_data; - u8 *frame_body; - u8 dialogToken = 0; - struct adapter *padapter = precv_frame->adapter; - uint len = precv_frame->len; - u8 *p2p_ie; - u32 p2p_ielen; - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - u8 result = P2P_STATUS_SUCCESS; - u8 empty_addr[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - - frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr)); - - dialogToken = frame_body[7]; - - if (rtw_action_public_decache(precv_frame, dialogToken) == _FAIL) - return _FAIL; - - _cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey); - /* Do nothing if the driver doesn't enable the P2P function. */ - if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE)) - return _SUCCESS; - - len -= sizeof(struct ieee80211_hdr_3addr); - - switch (frame_body[6]) { /* OUI Subtype */ - case P2P_GO_NEGO_REQ: - memset(&pwdinfo->groupid_info, 0x00, sizeof(struct group_id_info)); - - if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ)) - rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo)); - - if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL)) { - /* Commented by Albert 20110526 */ - /* In this case, this means the previous nego fail doesn't be reset yet. */ - _cancel_timer_ex(&pwdinfo->restore_p2p_state_timer); - /* Restore the previous p2p state */ - rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo)); - } - - /* Commented by Kurt 20110902 */ - /* Add if statement to avoid receiving duplicate prov disc req. such that pre_p2p_state would be covered. */ - if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING)) - rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo)); - - /* Commented by Kurt 20120113 */ - /* Get peer_dev_addr here if peer doesn't issue prov_disc frame. */ - if (!memcmp(pwdinfo->rx_prov_disc_info.peerDevAddr, empty_addr, ETH_ALEN)) - memcpy(pwdinfo->rx_prov_disc_info.peerDevAddr, GetAddr2Ptr(pframe), ETH_ALEN); - - result = process_p2p_group_negotation_req(pwdinfo, frame_body, len); - issue_p2p_GO_response(padapter, GetAddr2Ptr(pframe), frame_body, len, result); - - /* Commented by Albert 20110718 */ - /* No matter negotiating or negotiation failure, the driver should set up the restore P2P state timer. */ - _set_timer(&pwdinfo->restore_p2p_state_timer, 5000); - break; - case P2P_GO_NEGO_RESP: - if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING)) { - /* Commented by Albert 20110425 */ - /* The restore timer is enabled when issuing the nego request frame of rtw_p2p_connect function. */ - _cancel_timer_ex(&pwdinfo->restore_p2p_state_timer); - pwdinfo->nego_req_info.benable = false; - result = process_p2p_group_negotation_resp(pwdinfo, frame_body, len); - issue_p2p_GO_confirm(pwdinfo->padapter, GetAddr2Ptr(pframe), result); - if (result == P2P_STATUS_SUCCESS) { - if (rtw_p2p_role(pwdinfo) == P2P_ROLE_CLIENT) { - pwdinfo->p2p_info.operation_ch[0] = pwdinfo->peer_operating_ch; - pwdinfo->p2p_info.scan_op_ch_only = 1; - _set_timer(&pwdinfo->reset_ch_sitesurvey2, P2P_RESET_SCAN_CH); - } - } - /* Reset the dialog token for group negotiation frames. */ - pwdinfo->negotiation_dialog_token = 1; - if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL)) - _set_timer(&pwdinfo->restore_p2p_state_timer, 5000); - } - break; - case P2P_GO_NEGO_CONF: - result = process_p2p_group_negotation_confirm(pwdinfo, frame_body, len); - if (result == P2P_STATUS_SUCCESS) { - if (rtw_p2p_role(pwdinfo) == P2P_ROLE_CLIENT) { - pwdinfo->p2p_info.operation_ch[0] = pwdinfo->peer_operating_ch; - pwdinfo->p2p_info.scan_op_ch_only = 1; - _set_timer(&pwdinfo->reset_ch_sitesurvey2, P2P_RESET_SCAN_CH); - } - } - break; - case P2P_INVIT_REQ: - /* Added by Albert 2010/10/05 */ - /* Received the P2P Invite Request frame. */ - - p2p_ie = rtw_get_p2p_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &p2p_ielen); - if (p2p_ie) { - /* Parse the necessary information from the P2P Invitation Request frame. */ - /* For example: The MAC address of sending this P2P Invitation Request frame. */ - u32 attr_contentlen = 0; - u8 status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE; - struct group_id_info group_id; - u8 invitation_flag = 0; - - rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_INVITATION_FLAGS, &invitation_flag, &attr_contentlen); - if (attr_contentlen) { - rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_BSSID, pwdinfo->p2p_peer_interface_addr, &attr_contentlen); - /* Commented by Albert 20120510 */ - /* Copy to the pwdinfo->p2p_peer_interface_addr. */ - /* So that the WFD UI (or Sigma) can get the peer interface address by using the following command. */ - /* #> iwpriv wlan0 p2p_get peer_ifa */ - /* After having the peer interface address, the sigma can find the correct conf file for wpa_supplicant. */ - - if (invitation_flag & P2P_INVITATION_FLAGS_PERSISTENT) { - /* Re-invoke the persistent group. */ - - memset(&group_id, 0x00, sizeof(struct group_id_info)); - rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, (u8 *)&group_id, &attr_contentlen); - if (attr_contentlen) { - if (!memcmp(group_id.go_device_addr, myid(&padapter->eeprompriv), ETH_ALEN)) { - /* The p2p device sending this p2p invitation request wants this Wi-Fi device to be the persistent GO. */ - rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_GO); - rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO); - status_code = P2P_STATUS_SUCCESS; - } else { - /* The p2p device sending this p2p invitation request wants to be the persistent GO. */ - if (is_matched_in_profilelist(pwdinfo->p2p_peer_interface_addr, &pwdinfo->profileinfo[0])) { - u8 operatingch_info[5] = { 0x00 }; - if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen)) { - if (rtw_ch_set_search_ch(padapter->mlmeextpriv.channel_set, (u32)operatingch_info[4])) { - /* The operating channel is acceptable for this device. */ - pwdinfo->rx_invitereq_info.operation_ch[0] = operatingch_info[4]; - pwdinfo->rx_invitereq_info.scan_op_ch_only = 1; - _set_timer(&pwdinfo->reset_ch_sitesurvey, P2P_RESET_SCAN_CH); - rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_MATCH); - rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT); - status_code = P2P_STATUS_SUCCESS; - } else { - /* The operating channel isn't supported by this device. */ - rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_DISMATCH); - rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE); - status_code = P2P_STATUS_FAIL_NO_COMMON_CH; - _set_timer(&pwdinfo->restore_p2p_state_timer, 3000); - } - } else { - /* Commented by Albert 20121130 */ - /* Intel will use the different P2P IE to store the operating channel information */ - /* Workaround for Intel WiDi 3.5 */ - rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_MATCH); - rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT); - status_code = P2P_STATUS_SUCCESS; - } - } else { - rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_DISMATCH); - status_code = P2P_STATUS_FAIL_UNKNOWN_P2PGROUP; - } - } - } else { - status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE; - } - } else { - /* Received the invitation to join a P2P group. */ - - memset(&group_id, 0x00, sizeof(struct group_id_info)); - rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, (u8 *)&group_id, &attr_contentlen); - if (attr_contentlen) { - if (!memcmp(group_id.go_device_addr, myid(&padapter->eeprompriv), ETH_ALEN)) { - /* In this case, the GO can't be myself. */ - rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_DISMATCH); - status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE; - } else { - /* The p2p device sending this p2p invitation request wants to join an existing P2P group */ - /* Commented by Albert 2012/06/28 */ - /* In this case, this Wi-Fi device should use the iwpriv command to get the peer device address. */ - /* The peer device address should be the destination address for the provisioning discovery request. */ - /* Then, this Wi-Fi device should use the iwpriv command to get the peer interface address. */ - /* The peer interface address should be the address for WPS mac address */ - memcpy(pwdinfo->p2p_peer_device_addr, group_id.go_device_addr, ETH_ALEN); - rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT); - rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_JOIN); - status_code = P2P_STATUS_SUCCESS; - } - } else { - status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE; - } - } - } else { - status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE; - } - - pwdinfo->inviteresp_info.token = frame_body[7]; - issue_p2p_invitation_response(padapter, GetAddr2Ptr(pframe), pwdinfo->inviteresp_info.token, status_code); - } - break; - case P2P_INVIT_RESP: { - u8 attr_content = 0x00; - u32 attr_contentlen = 0; - - _cancel_timer_ex(&pwdinfo->restore_p2p_state_timer); - p2p_ie = rtw_get_p2p_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &p2p_ielen); - if (p2p_ie) { - rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, &attr_content, &attr_contentlen); - - if (attr_contentlen == 1) { - pwdinfo->invitereq_info.benable = false; - - if (attr_content == P2P_STATUS_SUCCESS) { - if (!memcmp(pwdinfo->invitereq_info.go_bssid, myid(&padapter->eeprompriv), ETH_ALEN)) { - rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO); - } else { - rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT); - } - rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_OK); - } else { - rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE); - rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL); - } - } else { - rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE); - rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL); - } - } else { - rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE); - rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL); - } - - if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL)) - _set_timer(&pwdinfo->restore_p2p_state_timer, 5000); - break; - } - case P2P_DEVDISC_REQ: - process_p2p_devdisc_req(pwdinfo, pframe, len); - break; - case P2P_DEVDISC_RESP: - process_p2p_devdisc_resp(pwdinfo, pframe, len); - break; - case P2P_PROVISION_DISC_REQ: - process_p2p_provdisc_req(pwdinfo, pframe, len); - memcpy(pwdinfo->rx_prov_disc_info.peerDevAddr, GetAddr2Ptr(pframe), ETH_ALEN); - - /* 20110902 Kurt */ - /* Add the following statement to avoid receiving duplicate prov disc req. such that pre_p2p_state would be covered. */ - if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ)) - rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo)); - - rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ); - _set_timer(&pwdinfo->restore_p2p_state_timer, P2P_PROVISION_TIMEOUT); - break; - case P2P_PROVISION_DISC_RESP: - /* Commented by Albert 20110707 */ - /* Should we check the pwdinfo->tx_prov_disc_info.bsent flag here?? */ - /* Commented by Albert 20110426 */ - /* The restore timer is enabled when issuing the provisioing request frame in rtw_p2p_prov_disc function. */ - _cancel_timer_ex(&pwdinfo->restore_p2p_state_timer); - rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_RSP); - process_p2p_provdisc_resp(pwdinfo, pframe); - _set_timer(&pwdinfo->restore_p2p_state_timer, P2P_PROVISION_TIMEOUT); - break; - } - - return _SUCCESS; -} - -static void on_action_public(struct adapter *padapter, struct recv_frame *precv_frame) -{ - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)precv_frame->rx_data; - u8 *frame_body = (u8 *)&mgmt->u; - - /* All members of the action enum start with action_code. */ - if (mgmt->u.action.u.s1g.action_code == WLAN_PUB_ACTION_VENDOR_SPECIFIC) { - if (!memcmp(frame_body + 2, P2P_OUI, 4)) - on_action_public_p2p(precv_frame); - } else { - rtw_action_public_decache(precv_frame, frame_body[2]); - } -} - -static void OnAction_p2p(struct adapter *padapter, struct recv_frame *precv_frame) -{ - u8 *frame_body; - u8 OUI_Subtype; - u8 *pframe = precv_frame->rx_data; - uint len = precv_frame->len; - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - - frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr)); - - if (be32_to_cpu(*((__be32 *)(frame_body + 1))) != P2POUI) - return; - - len -= sizeof(struct ieee80211_hdr_3addr); - OUI_Subtype = frame_body[5]; - - if (OUI_Subtype == P2P_PRESENCE_REQUEST) - process_p2p_presence_req(pwdinfo, pframe, len); -} - -static void OnAction(struct adapter *padapter, struct recv_frame *precv_frame) -{ - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)precv_frame->rx_data; - - if (!ether_addr_equal(myid(&padapter->eeprompriv), mgmt->da)) - return; - - switch (mgmt->u.action.category) { - case WLAN_CATEGORY_BACK: - OnAction_back(padapter, precv_frame); - break; - case WLAN_CATEGORY_PUBLIC: - on_action_public(padapter, precv_frame); - break; - case RTW_WLAN_CATEGORY_P2P: - OnAction_p2p(padapter, precv_frame); - break; - } -} - -struct xmit_frame *alloc_mgtxmitframe(struct xmit_priv *pxmitpriv) -{ - struct xmit_frame *pmgntframe; - struct xmit_buf *pxmitbuf; - - pmgntframe = rtw_alloc_xmitframe(pxmitpriv); - if (!pmgntframe) - return NULL; - - pxmitbuf = rtw_alloc_xmitbuf_ext(pxmitpriv); - if (!pxmitbuf) { - rtw_free_xmitframe(pxmitpriv, pmgntframe); - return NULL; - } - pmgntframe->frame_tag = MGNT_FRAMETAG; - pmgntframe->pxmitbuf = pxmitbuf; - pmgntframe->buf_addr = pxmitbuf->pbuf; - pxmitbuf->priv_data = pmgntframe; - return pmgntframe; -} - -void mgt_dispatcher(struct adapter *padapter, struct recv_frame *precv_frame) -{ - mlme_handler mlme_sta_tbl[] = { - OnAssocReq, - OnAssocRsp, - OnAssocReq, - OnAssocRsp, - OnProbeReq, - OnProbeRsp, - NULL, - NULL, - OnBeacon, - NULL, - OnDisassoc, - OnAuthClient, - OnDeAuth, - OnAction, - }; - int index; - mlme_handler fct; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)precv_frame->rx_data; - struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, hdr->addr2); - - if (!ieee80211_is_mgmt(hdr->frame_control)) - return; - - /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */ - if (memcmp(hdr->addr1, myid(&padapter->eeprompriv), ETH_ALEN) && - !is_broadcast_ether_addr(hdr->addr1)) - return; - - index = (le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_STYPE) >> 4; - if (index >= ARRAY_SIZE(mlme_sta_tbl)) - return; - fct = mlme_sta_tbl[index]; - - if (psta) { - if (ieee80211_has_retry(hdr->frame_control)) { - if (precv_frame->attrib.seq_num == psta->RxMgmtFrameSeqNum) - /* drop the duplicate management frame */ - return; - } - psta->RxMgmtFrameSeqNum = precv_frame->attrib.seq_num; - } - - if (ieee80211_is_auth(hdr->frame_control)) { - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) - fct = OnAuth; - else - fct = OnAuthClient; - } - - if (fct) - fct(padapter, precv_frame); -} - -/**************************************************************************** - -Following are some TX functions for WiFi MLME - -*****************************************************************************/ - -void update_mgnt_tx_rate(struct adapter *padapter, u8 rate) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - pmlmeext->tx_rate = rate; -} - -void update_mgntframe_attrib(struct adapter *padapter, struct pkt_attrib *pattrib) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - memset((u8 *)(pattrib), 0, sizeof(struct pkt_attrib)); - - pattrib->hdrlen = 24; - pattrib->nr_frags = 1; - pattrib->priority = 7; - pattrib->mac_id = 0; - pattrib->qsel = 0x12; - - pattrib->pktlen = 0; - - if (pmlmeext->cur_wireless_mode & WIRELESS_11B) - pattrib->raid = 6;/* b mode */ - else - pattrib->raid = 5;/* a/g mode */ - - pattrib->encrypt = _NO_PRIVACY_; - pattrib->bswenc = false; - - pattrib->qos_en = false; - pattrib->ht_en = false; - pattrib->bwmode = HT_CHANNEL_WIDTH_20; - pattrib->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - pattrib->sgi = false; - - pattrib->seqnum = pmlmeext->mgnt_seq; - - pattrib->retry_ctrl = true; -} - -void dump_mgntframe(struct adapter *padapter, struct xmit_frame *pmgntframe) -{ - rtl8188eu_mgnt_xmit(padapter, pmgntframe); -} - -s32 dump_mgntframe_and_wait(struct adapter *padapter, struct xmit_frame *pmgntframe, int timeout_ms) -{ - s32 ret = _FAIL; - struct xmit_buf *pxmitbuf = pmgntframe->pxmitbuf; - struct submit_ctx sctx; - - if (padapter->bSurpriseRemoved || padapter->bDriverStopped) - return ret; - - rtw_sctx_init(&sctx, timeout_ms); - pxmitbuf->sctx = &sctx; - - ret = rtl8188eu_mgnt_xmit(padapter, pmgntframe); - - if (ret == _SUCCESS) - ret = rtw_sctx_wait(&sctx); - - return ret; -} - -s32 dump_mgntframe_and_wait_ack(struct adapter *padapter, struct xmit_frame *pmgntframe) -{ - s32 ret = _FAIL; - u32 timeout_ms = 500;/* 500ms */ - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - mutex_lock(&pxmitpriv->ack_tx_mutex); - pxmitpriv->ack_tx = true; - - pmgntframe->ack_report = 1; - if (rtl8188eu_mgnt_xmit(padapter, pmgntframe) == _SUCCESS) { - ret = rtw_ack_tx_wait(pxmitpriv, timeout_ms); - } - - pxmitpriv->ack_tx = false; - mutex_unlock(&pxmitpriv->ack_tx_mutex); - - return ret; -} - -static int update_hidden_ssid(u8 *ies, u32 ies_len, u8 hidden_ssid_mode) -{ - u8 *ssid_ie; - int ssid_len_ori; - int len_diff = 0; - - ssid_ie = rtw_get_ie(ies, WLAN_EID_SSID, &ssid_len_ori, ies_len); - - if (ssid_ie && ssid_len_ori > 0) { - switch (hidden_ssid_mode) { - case 1: { - u8 *next_ie = ssid_ie + 2 + ssid_len_ori; - u32 remain_len = 0; - - remain_len = ies_len - (next_ie - ies); - - ssid_ie[1] = 0; - memcpy(ssid_ie + 2, next_ie, remain_len); - len_diff -= ssid_len_ori; - - break; - } - case 2: - memset(&ssid_ie[2], 0, ssid_len_ori); - break; - default: - break; - } - } - - return len_diff; -} - -void issue_beacon(struct adapter *padapter, int timeout_ms) -{ - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct ieee80211_hdr *pwlanhdr; - __le16 *fctrl; - unsigned int rate_len; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *cur_network = &pmlmeinfo->network; - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - - pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (!pmgntframe) - return; - spin_lock_bh(&pmlmepriv->bcn_update_lock); - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib(padapter, pattrib); - pattrib->qsel = 0x10; - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct ieee80211_hdr *)pframe; - - fctrl = &pwlanhdr->frame_control; - *(fctrl) = 0; - - eth_broadcast_addr(pwlanhdr->addr1); - memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN); - memcpy(pwlanhdr->addr3, get_my_bssid(cur_network), ETH_ALEN); - - SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/); - /* pmlmeext->mgnt_seq++; */ - SetFrameSubType(pframe, WIFI_BEACON); - - pframe += sizeof(struct ieee80211_hdr_3addr); - pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); - - if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) { - /* for P2P : Primary Device Type & Device Name */ - u32 wpsielen = 0, insert_len = 0; - u8 *wpsie = NULL; - wpsie = rtw_get_wps_ie(cur_network->IEs + _FIXED_IE_LENGTH_, cur_network->IELength - _FIXED_IE_LENGTH_, NULL, &wpsielen); - - if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) && wpsie && wpsielen > 0) { - uint wps_offset, remainder_ielen; - u8 *premainder_ie, *pframe_wscie; - - wps_offset = (uint)(wpsie - cur_network->IEs); - premainder_ie = wpsie + wpsielen; - remainder_ielen = cur_network->IELength - wps_offset - wpsielen; - pframe_wscie = pframe + wps_offset; - memcpy(pframe, cur_network->IEs, wps_offset + wpsielen); - pframe += (wps_offset + wpsielen); - pattrib->pktlen += (wps_offset + wpsielen); - - /* now pframe is end of wsc ie, insert Primary Device Type & Device Name */ - /* Primary Device Type */ - /* Type: */ - *(__be16 *)(pframe + insert_len) = cpu_to_be16(WPS_ATTR_PRIMARY_DEV_TYPE); - insert_len += 2; - - /* Length: */ - *(__be16 *)(pframe + insert_len) = cpu_to_be16(0x0008); - insert_len += 2; - - /* Value: */ - /* Category ID */ - *(__be16 *)(pframe + insert_len) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA); - insert_len += 2; - - /* OUI */ - *(__be32 *)(pframe + insert_len) = cpu_to_be32(WPSOUI); - insert_len += 4; - - /* Sub Category ID */ - *(__be16 *)(pframe + insert_len) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER); - insert_len += 2; - - /* Device Name */ - /* Type: */ - *(__be16 *)(pframe + insert_len) = cpu_to_be16(WPS_ATTR_DEVICE_NAME); - insert_len += 2; - - /* Length: */ - *(__be16 *)(pframe + insert_len) = cpu_to_be16(pwdinfo->device_name_len); - insert_len += 2; - - /* Value: */ - memcpy(pframe + insert_len, pwdinfo->device_name, pwdinfo->device_name_len); - insert_len += pwdinfo->device_name_len; - - /* update wsc ie length */ - *(pframe_wscie + 1) = (wpsielen - 2) + insert_len; - - /* pframe move to end */ - pframe += insert_len; - pattrib->pktlen += insert_len; - - /* copy remainder_ie to pframe */ - memcpy(pframe, premainder_ie, remainder_ielen); - pframe += remainder_ielen; - pattrib->pktlen += remainder_ielen; - } else { - int len_diff; - memcpy(pframe, cur_network->IEs, cur_network->IELength); - len_diff = update_hidden_ssid( - pframe + _BEACON_IE_OFFSET_ - , cur_network->IELength - _BEACON_IE_OFFSET_ - , pmlmeinfo->hidden_ssid_mode - ); - pframe += (cur_network->IELength + len_diff); - pattrib->pktlen += (cur_network->IELength + len_diff); - } - - { - u8 *wps_ie; - uint wps_ielen; - u8 sr = 0; - wps_ie = rtw_get_wps_ie(pmgntframe->buf_addr + TXDESC_OFFSET + sizeof(struct ieee80211_hdr_3addr) + _BEACON_IE_OFFSET_, - pattrib->pktlen - sizeof(struct ieee80211_hdr_3addr) - _BEACON_IE_OFFSET_, NULL, &wps_ielen); - if (wps_ie && wps_ielen > 0) - rtw_get_wps_attr_content(wps_ie, wps_ielen, WPS_ATTR_SELECTED_REGISTRAR, (u8 *)(&sr), NULL); - if (sr != 0) - set_fwstate(pmlmepriv, WIFI_UNDER_WPS); - else - _clr_fwstate_(pmlmepriv, WIFI_UNDER_WPS); - } - - if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) { - u32 len; - len = build_beacon_p2p_ie(pwdinfo, pframe); - - pframe += len; - pattrib->pktlen += len; - } - - goto _issue_bcn; - } - - /* below for ad-hoc mode */ - - /* timestamp will be inserted by hardware */ - pframe += 8; - pattrib->pktlen += 8; - - /* beacon interval: 2 bytes */ - - memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2); - - pframe += 2; - pattrib->pktlen += 2; - - /* capability info: 2 bytes */ - - memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2); - - pframe += 2; - pattrib->pktlen += 2; - - /* SSID */ - pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pattrib->pktlen); - - /* supported rates... */ - rate_len = rtw_get_rateset_len(cur_network->SupportedRates); - pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pattrib->pktlen); - - /* DS parameter set */ - pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&cur_network->Configuration.DSConfig, &pattrib->pktlen); - - { - u8 erpinfo = 0; - u32 ATIMWindow; - /* IBSS Parameter Set... */ - ATIMWindow = 0; - pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen); - - /* ERP IE */ - pframe = rtw_set_ie(pframe, _ERPINFO_IE_, 1, &erpinfo, &pattrib->pktlen); - } - - /* EXTERNDED SUPPORTED RATE */ - if (rate_len > 8) - pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen); - /* todo:HT for adhoc */ -_issue_bcn: - - pmlmepriv->update_bcn = false; - - spin_unlock_bh(&pmlmepriv->bcn_update_lock); - - if ((pattrib->pktlen + TXDESC_SIZE) > 512) - return; - - pattrib->last_txcmdsz = pattrib->pktlen; - - if (timeout_ms > 0) - dump_mgntframe_and_wait(padapter, pmgntframe, timeout_ms); - else - dump_mgntframe(padapter, pmgntframe); -} - -void issue_probersp(struct adapter *padapter, unsigned char *da, u8 is_valid_p2p_probereq) -{ - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct ieee80211_hdr *pwlanhdr; - __le16 *fctrl; - unsigned char *mac, *bssid; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - u8 *pwps_ie; - uint wps_ielen; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *cur_network = &pmlmeinfo->network; - unsigned int rate_len; - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - - pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (!pmgntframe) - return; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib(padapter, pattrib); - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct ieee80211_hdr *)pframe; - - mac = myid(&padapter->eeprompriv); - bssid = cur_network->MacAddress; - - fctrl = &pwlanhdr->frame_control; - *(fctrl) = 0; - memcpy(pwlanhdr->addr1, da, ETH_ALEN); - memcpy(pwlanhdr->addr2, mac, ETH_ALEN); - memcpy(pwlanhdr->addr3, bssid, ETH_ALEN); - - SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); - pmlmeext->mgnt_seq++; - SetFrameSubType(fctrl, WIFI_PROBERSP); - - pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr); - pattrib->pktlen = pattrib->hdrlen; - pframe += pattrib->hdrlen; - - if (cur_network->IELength > MAX_IE_SZ) - return; - - if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) { - pwps_ie = rtw_get_wps_ie(cur_network->IEs + _FIXED_IE_LENGTH_, cur_network->IELength - _FIXED_IE_LENGTH_, NULL, &wps_ielen); - - /* inerset & update wps_probe_resp_ie */ - if (pmlmepriv->wps_probe_resp_ie && pwps_ie && wps_ielen > 0) { - uint wps_offset, remainder_ielen; - u8 *premainder_ie; - - wps_offset = (uint)(pwps_ie - cur_network->IEs); - - premainder_ie = pwps_ie + wps_ielen; - - remainder_ielen = cur_network->IELength - wps_offset - wps_ielen; - - memcpy(pframe, cur_network->IEs, wps_offset); - pframe += wps_offset; - pattrib->pktlen += wps_offset; - - wps_ielen = (uint)pmlmepriv->wps_probe_resp_ie[1];/* to get ie data len */ - if ((wps_offset + wps_ielen + 2) <= MAX_IE_SZ) { - memcpy(pframe, pmlmepriv->wps_probe_resp_ie, wps_ielen + 2); - pframe += wps_ielen + 2; - pattrib->pktlen += wps_ielen + 2; - } - - if ((wps_offset + wps_ielen + 2 + remainder_ielen) <= MAX_IE_SZ) { - memcpy(pframe, premainder_ie, remainder_ielen); - pframe += remainder_ielen; - pattrib->pktlen += remainder_ielen; - } - } else { - memcpy(pframe, cur_network->IEs, cur_network->IELength); - pframe += cur_network->IELength; - pattrib->pktlen += cur_network->IELength; - } - } else { - /* timestamp will be inserted by hardware */ - pframe += 8; - pattrib->pktlen += 8; - - /* beacon interval: 2 bytes */ - - memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2); - - pframe += 2; - pattrib->pktlen += 2; - - /* capability info: 2 bytes */ - - memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2); - - pframe += 2; - pattrib->pktlen += 2; - - /* below for ad-hoc mode */ - - /* SSID */ - pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pattrib->pktlen); - - /* supported rates... */ - rate_len = rtw_get_rateset_len(cur_network->SupportedRates); - pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pattrib->pktlen); - - /* DS parameter set */ - pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&cur_network->Configuration.DSConfig, &pattrib->pktlen); - - if ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) { - u8 erpinfo = 0; - u32 ATIMWindow; - /* IBSS Parameter Set... */ - /* ATIMWindow = cur->Configuration.ATIMWindow; */ - ATIMWindow = 0; - pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen); - - /* ERP IE */ - pframe = rtw_set_ie(pframe, _ERPINFO_IE_, 1, &erpinfo, &pattrib->pktlen); - } - - /* EXTERNDED SUPPORTED RATE */ - if (rate_len > 8) - pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen); - /* todo:HT for adhoc */ - } - - if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) && is_valid_p2p_probereq) { - u32 len; - len = build_probe_resp_p2p_ie(pwdinfo, pframe); - - pframe += len; - pattrib->pktlen += len; - } - - pattrib->last_txcmdsz = pattrib->pktlen; - - dump_mgntframe(padapter, pmgntframe); -} - -static int _issue_probereq(struct adapter *padapter, struct ndis_802_11_ssid *pssid, u8 *da, int wait_ack) -{ - int ret = _FAIL; - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct ieee80211_hdr *pwlanhdr; - __le16 *fctrl; - unsigned char *mac; - unsigned char bssrate[NumRates]; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - int bssrate_len = 0; - - pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (!pmgntframe) - goto exit; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib(padapter, pattrib); - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct ieee80211_hdr *)pframe; - - mac = myid(&padapter->eeprompriv); - - fctrl = &pwlanhdr->frame_control; - *(fctrl) = 0; - - if (da) { - /* unicast probe request frame */ - memcpy(pwlanhdr->addr1, da, ETH_ALEN); - memcpy(pwlanhdr->addr3, da, ETH_ALEN); - } else { - /* broadcast probe request frame */ - eth_broadcast_addr(pwlanhdr->addr1); - eth_broadcast_addr(pwlanhdr->addr3); - } - - memcpy(pwlanhdr->addr2, mac, ETH_ALEN); - - SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); - pmlmeext->mgnt_seq++; - SetFrameSubType(pframe, WIFI_PROBEREQ); - - pframe += sizeof(struct ieee80211_hdr_3addr); - pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); - - if (pssid) - pframe = rtw_set_ie(pframe, _SSID_IE_, pssid->SsidLength, pssid->Ssid, &pattrib->pktlen); - else - pframe = rtw_set_ie(pframe, _SSID_IE_, 0, NULL, &pattrib->pktlen); - - get_rate_set(padapter, bssrate, &bssrate_len); - - if (bssrate_len > 8) { - pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, bssrate, &pattrib->pktlen); - pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, bssrate_len - 8, bssrate + 8, &pattrib->pktlen); - } else { - pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, bssrate_len, bssrate, &pattrib->pktlen); - } - - /* add wps_ie for wps2.0 */ - if (pmlmepriv->wps_probe_req_ie_len > 0 && pmlmepriv->wps_probe_req_ie) { - memcpy(pframe, pmlmepriv->wps_probe_req_ie, pmlmepriv->wps_probe_req_ie_len); - pframe += pmlmepriv->wps_probe_req_ie_len; - pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len; - } - - pattrib->last_txcmdsz = pattrib->pktlen; - - if (wait_ack) { - ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe); - } else { - dump_mgntframe(padapter, pmgntframe); - ret = _SUCCESS; - } - -exit: - return ret; -} - -inline void issue_probereq(struct adapter *padapter, struct ndis_802_11_ssid *pssid, u8 *da) -{ - _issue_probereq(padapter, pssid, da, false); -} - -void issue_probereq_ex(struct adapter *padapter, struct ndis_802_11_ssid *pssid, u8 *da) -{ - int i; - - for (i = 0; i < 3; i++) { - if (_issue_probereq(padapter, pssid, da, true) == _FAIL) - msleep(1); - else - break; - } -} - -/* if psta == NULL, indicate we are station (client) now... */ -void issue_auth(struct adapter *padapter, struct sta_info *psta, unsigned short status) -{ - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct ieee80211_hdr *pwlanhdr; - __le16 *fctrl; - unsigned int val32; - u16 val16; - __le16 le_val16; - int use_shared_key = 0; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (!pmgntframe) - return; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib(padapter, pattrib); - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct ieee80211_hdr *)pframe; - - fctrl = &pwlanhdr->frame_control; - *(fctrl) = 0; - - SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); - pmlmeext->mgnt_seq++; - SetFrameSubType(pframe, WIFI_AUTH); - - pframe += sizeof(struct ieee80211_hdr_3addr); - pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); - - if (psta) {/* for AP mode */ - memcpy(pwlanhdr->addr1, psta->hwaddr, ETH_ALEN); - memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN); - memcpy(pwlanhdr->addr3, myid(&padapter->eeprompriv), ETH_ALEN); - - /* setting auth algo number */ - val16 = (u16)psta->authalg; - - if (status != _STATS_SUCCESSFUL_) - val16 = 0; - - if (val16) { - le_val16 = cpu_to_le16(val16); - use_shared_key = 1; - } else { - le_val16 = 0; - } - - pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, (unsigned char *)&le_val16, &pattrib->pktlen); - - /* setting auth seq number */ - val16 = (u16)psta->auth_seq; - le_val16 = cpu_to_le16(val16); - pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, (unsigned char *)&le_val16, &pattrib->pktlen); - - /* setting status code... */ - val16 = status; - le_val16 = cpu_to_le16(val16); - pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&le_val16, &pattrib->pktlen); - - /* added challenging text... */ - if ((psta->auth_seq == 2) && (psta->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) - pframe = rtw_set_ie(pframe, _CHLGETXT_IE_, 128, psta->chg_txt, &pattrib->pktlen); - } else { - __le32 le_tmp32; - __le16 le_tmp16; - memcpy(pwlanhdr->addr1, get_my_bssid(&pmlmeinfo->network), ETH_ALEN); - memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN); - memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN); - - /* setting auth algo number */ - val16 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) ? 1 : 0;/* 0:OPEN System, 1:Shared key */ - if (val16) - use_shared_key = 1; - - /* setting IV for auth seq #3 */ - if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) { - val32 = ((pmlmeinfo->iv++) | (pmlmeinfo->key_index << 30)); - le_tmp32 = cpu_to_le32(val32); - pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&le_tmp32, &pattrib->pktlen); - - pattrib->iv_len = 4; - } - - le_tmp16 = cpu_to_le16(val16); - pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, (unsigned char *)&le_tmp16, &pattrib->pktlen); - - /* setting auth seq number */ - val16 = pmlmeinfo->auth_seq; - le_tmp16 = cpu_to_le16(val16); - pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, (unsigned char *)&le_tmp16, &pattrib->pktlen); - - /* setting status code... */ - le_tmp16 = cpu_to_le16(status); - pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&le_tmp16, &pattrib->pktlen); - - /* then checking to see if sending challenging text... */ - if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) { - pframe = rtw_set_ie(pframe, _CHLGETXT_IE_, 128, pmlmeinfo->chg_txt, &pattrib->pktlen); - - SetPrivacy(fctrl); - - pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr); - - pattrib->encrypt = _WEP40_; - - pattrib->icv_len = 4; - - pattrib->pktlen += pattrib->icv_len; - } - } - - pattrib->last_txcmdsz = pattrib->pktlen; - - rtw_wep_encrypt(padapter, pmgntframe); - dump_mgntframe(padapter, pmgntframe); -} - -void issue_asocrsp(struct adapter *padapter, unsigned short status, struct sta_info *pstat, int pkt_type) -{ - struct xmit_frame *pmgntframe; - struct ieee80211_hdr *pwlanhdr; - struct pkt_attrib *pattrib; - unsigned char *pbuf, *pframe; - unsigned short val; - __le16 *fctrl; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network; - u8 *ie = pnetwork->IEs; - __le16 lestatus, leval; - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - - pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (!pmgntframe) - return; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib(padapter, pattrib); - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct ieee80211_hdr *)pframe; - - fctrl = &pwlanhdr->frame_control; - *(fctrl) = 0; - - memcpy((void *)GetAddr1Ptr(pwlanhdr), pstat->hwaddr, ETH_ALEN); - memcpy((void *)GetAddr2Ptr(pwlanhdr), myid(&padapter->eeprompriv), ETH_ALEN); - memcpy((void *)GetAddr3Ptr(pwlanhdr), get_my_bssid(&pmlmeinfo->network), ETH_ALEN); - - SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); - pmlmeext->mgnt_seq++; - if ((pkt_type == WIFI_ASSOCRSP) || (pkt_type == WIFI_REASSOCRSP)) - SetFrameSubType(pwlanhdr, pkt_type); - else - return; - - pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr); - pattrib->pktlen += pattrib->hdrlen; - pframe += pattrib->hdrlen; - - /* capability */ - val = *(unsigned short *)rtw_get_capability_from_ie(ie); - - pframe = rtw_set_fixed_ie(pframe, _CAPABILITY_, (unsigned char *)&val, &pattrib->pktlen); - - lestatus = cpu_to_le16(status); - pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&lestatus, &pattrib->pktlen); - - leval = cpu_to_le16(pstat->aid | BIT(14) | BIT(15)); - pframe = rtw_set_fixed_ie(pframe, _ASOC_ID_, (unsigned char *)&leval, &pattrib->pktlen); - - if (pstat->bssratelen <= 8) { - pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, pstat->bssratelen, pstat->bssrateset, &pattrib->pktlen); - } else { - pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pstat->bssrateset, &pattrib->pktlen); - pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, pstat->bssratelen - 8, pstat->bssrateset + 8, &pattrib->pktlen); - } - - if ((pstat->flags & WLAN_STA_HT) && (pmlmepriv->htpriv.ht_option)) { - uint ie_len = 0; - - /* FILL HT CAP INFO IE */ - pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_CAPABILITY_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_)); - if (pbuf && ie_len > 0) { - memcpy(pframe, pbuf, ie_len + 2); - pframe += (ie_len + 2); - pattrib->pktlen += (ie_len + 2); - } - - /* FILL HT ADD INFO IE */ - pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_ADD_INFO_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_)); - if (pbuf && ie_len > 0) { - memcpy(pframe, pbuf, ie_len + 2); - pframe += (ie_len + 2); - pattrib->pktlen += (ie_len + 2); - } - } - - /* FILL WMM IE */ - if ((pstat->flags & WLAN_STA_WME) && (pmlmepriv->qospriv.qos_option)) { - uint ie_len = 0; - unsigned char WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01}; - - for (pbuf = ie + _BEACON_IE_OFFSET_;; pbuf += (ie_len + 2)) { - pbuf = rtw_get_ie(pbuf, _VENDOR_SPECIFIC_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2))); - if (pbuf && !memcmp(pbuf + 2, WMM_PARA_IE, 6)) { - memcpy(pframe, pbuf, ie_len + 2); - pframe += (ie_len + 2); - pattrib->pktlen += (ie_len + 2); - break; - } - - if (!pbuf || ie_len == 0) - break; - } - } - - if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK) - pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 6, REALTEK_96B_IE, &pattrib->pktlen); - - /* add WPS IE ie for wps 2.0 */ - if (pmlmepriv->wps_assoc_resp_ie && pmlmepriv->wps_assoc_resp_ie_len > 0) { - memcpy(pframe, pmlmepriv->wps_assoc_resp_ie, pmlmepriv->wps_assoc_resp_ie_len); - - pframe += pmlmepriv->wps_assoc_resp_ie_len; - pattrib->pktlen += pmlmepriv->wps_assoc_resp_ie_len; - } - - if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) && (pstat->is_p2p_device)) { - u32 len; - - len = build_assoc_resp_p2p_ie(pwdinfo, pframe, pstat->p2p_status_code); - - pframe += len; - pattrib->pktlen += len; - } - pattrib->last_txcmdsz = pattrib->pktlen; - dump_mgntframe(padapter, pmgntframe); -} - -void issue_assocreq(struct adapter *padapter) -{ - int ret = _FAIL; - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe, *p; - struct ieee80211_hdr *pwlanhdr; - __le16 *fctrl; - __le16 le_tmp; - unsigned int i, j, ie_len, index = 0; - unsigned char bssrate[NumRates], sta_bssrate[NumRates]; - struct ndis_802_11_var_ie *pIE; - struct registry_priv *pregpriv = &padapter->registrypriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - int bssrate_len = 0, sta_bssrate_len = 0; - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - u8 p2pie[255] = { 0x00 }; - u16 p2pielen = 0; - - pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (!pmgntframe) - goto exit; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib(padapter, pattrib); - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct ieee80211_hdr *)pframe; - - fctrl = &pwlanhdr->frame_control; - *(fctrl) = 0; - memcpy(pwlanhdr->addr1, get_my_bssid(&pmlmeinfo->network), ETH_ALEN); - memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN); - memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN); - - SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); - pmlmeext->mgnt_seq++; - SetFrameSubType(pframe, WIFI_ASSOCREQ); - - pframe += sizeof(struct ieee80211_hdr_3addr); - pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); - - /* caps */ - - memcpy(pframe, rtw_get_capability_from_ie(pmlmeinfo->network.IEs), 2); - - pframe += 2; - pattrib->pktlen += 2; - - /* listen interval */ - /* todo: listen interval for power saving */ - le_tmp = cpu_to_le16(3); - memcpy(pframe, (unsigned char *)&le_tmp, 2); - pframe += 2; - pattrib->pktlen += 2; - - /* SSID */ - pframe = rtw_set_ie(pframe, _SSID_IE_, pmlmeinfo->network.Ssid.SsidLength, pmlmeinfo->network.Ssid.Ssid, &pattrib->pktlen); - - /* supported rate & extended supported rate */ - - /* Check if the AP's supported rates are also supported by STA. */ - get_rate_set(padapter, sta_bssrate, &sta_bssrate_len); - - if (pmlmeext->cur_channel == 14)/* for JAPAN, channel 14 can only uses B Mode(CCK) */ - sta_bssrate_len = 4; - - for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) { - if (pmlmeinfo->network.SupportedRates[i] == 0) - break; - - /* Check if the AP's supported rates are also supported by STA. */ - for (j = 0; j < sta_bssrate_len; j++) { - /* Avoid the proprietary data rate (22Mbps) of Handlink WSG-4000 AP */ - if ((pmlmeinfo->network.SupportedRates[i] | IEEE80211_BASIC_RATE_MASK) - == (sta_bssrate[j] | IEEE80211_BASIC_RATE_MASK)) - break; - } - - if (j != sta_bssrate_len) - /* the rate is supported by STA */ - bssrate[index++] = pmlmeinfo->network.SupportedRates[i]; - } - - bssrate_len = index; - - if (bssrate_len == 0) { - rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf); - rtw_free_xmitframe(pxmitpriv, pmgntframe); - goto exit; /* don't connect to AP if no joint supported rate */ - } - - if (bssrate_len > 8) { - pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, bssrate, &pattrib->pktlen); - pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, bssrate_len - 8, bssrate + 8, &pattrib->pktlen); - } else { - pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, bssrate_len, bssrate, &pattrib->pktlen); - } - - /* RSN */ - p = rtw_get_ie((pmlmeinfo->network.IEs + sizeof(struct ndis_802_11_fixed_ie)), _RSN_IE_2_, &ie_len, (pmlmeinfo->network.IELength - sizeof(struct ndis_802_11_fixed_ie))); - if (p) - pframe = rtw_set_ie(pframe, _RSN_IE_2_, ie_len, p + 2, &pattrib->pktlen); - - /* HT caps */ - if (padapter->mlmepriv.htpriv.ht_option) { - p = rtw_get_ie((pmlmeinfo->network.IEs + sizeof(struct ndis_802_11_fixed_ie)), _HT_CAPABILITY_IE_, &ie_len, (pmlmeinfo->network.IELength - sizeof(struct ndis_802_11_fixed_ie))); - if (p && !is_ap_in_tkip(padapter)) { - memcpy(&pmlmeinfo->HT_caps, p + 2, sizeof(struct HT_caps_element)); - - /* to disable 40M Hz support while gd_bw_40MHz_en = 0 */ - if (pregpriv->cbw40_enable == 0) - pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info &= cpu_to_le16(~(BIT(6) | BIT(1))); - else - pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= cpu_to_le16(BIT(1)); - - /* todo: disable SM power save mode */ - pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= cpu_to_le16(0x000c); - - if (pregpriv->rx_stbc) - pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= cpu_to_le16(0x0100);/* RX STBC One spatial stream */ - memcpy(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_rate_1R, 16); - - pframe = rtw_set_ie(pframe, _HT_CAPABILITY_IE_, ie_len, (u8 *)(&pmlmeinfo->HT_caps), &pattrib->pktlen); - } - } - - /* vendor specific IE, such as WPA, WMM, WPS */ - for (i = sizeof(struct ndis_802_11_fixed_ie); i < pmlmeinfo->network.IELength;) { - pIE = (struct ndis_802_11_var_ie *)(pmlmeinfo->network.IEs + i); - - switch (pIE->ElementID) { - case _VENDOR_SPECIFIC_IE_: - if ((!memcmp(pIE->data, RTW_WPA_OUI, 4)) || - (!memcmp(pIE->data, WMM_OUI, 4)) || - (!memcmp(pIE->data, WPS_OUI, 4))) { - if (!padapter->registrypriv.wifi_spec) { - /* Commented by Kurt 20110629 */ - /* In some older APs, WPS handshake */ - /* would be fail if we append vendor extension information to AP */ - if (!memcmp(pIE->data, WPS_OUI, 4)) - pIE->Length = 14; - } - pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, pIE->Length, pIE->data, &pattrib->pktlen); - } - break; - default: - break; - } - i += (pIE->Length + 2); - } - - if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK) - pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 6, REALTEK_96B_IE, &pattrib->pktlen); - - if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) && !rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE)) { - /* Should add the P2P IE in the association request frame. */ - /* P2P OUI */ - - p2pielen = 0; - p2pie[p2pielen++] = 0x50; - p2pie[p2pielen++] = 0x6F; - p2pie[p2pielen++] = 0x9A; - p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */ - - /* Commented by Albert 20101109 */ - /* According to the P2P Specification, the association request frame should contain 3 P2P attributes */ - /* 1. P2P Capability */ - /* 2. Extended Listen Timing */ - /* 3. Device Info */ - /* Commented by Albert 20110516 */ - /* 4. P2P Interface */ - - /* P2P Capability */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_CAPABILITY; - - /* Length: */ - *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002); - p2pielen += 2; - - /* Value: */ - /* Device Capability Bitmap, 1 byte */ - p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT; - - /* Group Capability Bitmap, 1 byte */ - if (pwdinfo->persistent_supported) - p2pie[p2pielen++] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT; - else - p2pie[p2pielen++] = DMP_P2P_GRPCAP_SUPPORT; - - /* Extended Listen Timing */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_EX_LISTEN_TIMING; - - /* Length: */ - *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0004); - p2pielen += 2; - - /* Value: */ - /* Availability Period */ - *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF); - p2pielen += 2; - - /* Availability Interval */ - *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF); - p2pielen += 2; - - /* Device Info */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO; - - /* Length: */ - /* 21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */ - /* + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */ - *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len); - p2pielen += 2; - - /* Value: */ - /* P2P Device Address */ - memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN); - p2pielen += ETH_ALEN; - - /* Config Method */ - /* This field should be big endian. Noted by P2P specification. */ - if ((pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PEER_DISPLAY_PIN) || - (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_SELF_DISPLAY_PIN)) - *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_CONFIG_METHOD_DISPLAY); - else - *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_CONFIG_METHOD_PBC); - - p2pielen += 2; - - /* Primary Device Type */ - /* Category ID */ - *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA); - p2pielen += 2; - - /* OUI */ - *(__be32 *)(p2pie + p2pielen) = cpu_to_be32(WPSOUI); - p2pielen += 4; - - /* Sub Category ID */ - *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER); - p2pielen += 2; - - /* Number of Secondary Device Types */ - p2pie[p2pielen++] = 0x00; /* No Secondary Device Type List */ - - /* Device Name */ - /* Type: */ - *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME); - p2pielen += 2; - - /* Length: */ - *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len); - p2pielen += 2; - - /* Value: */ - memcpy(p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len); - p2pielen += pwdinfo->device_name_len; - - /* P2P Interface */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_INTERFACE; - - /* Length: */ - *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x000D); - p2pielen += 2; - - /* Value: */ - memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN); /* P2P Device Address */ - p2pielen += ETH_ALEN; - - p2pie[p2pielen++] = 1; /* P2P Interface Address Count */ - - memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN); /* P2P Interface Address List */ - p2pielen += ETH_ALEN; - - pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &pattrib->pktlen); - } - - pattrib->last_txcmdsz = pattrib->pktlen; - dump_mgntframe(padapter, pmgntframe); - - ret = _SUCCESS; - -exit: - if (ret == _SUCCESS) - rtw_buf_update(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len, (u8 *)pwlanhdr, pattrib->pktlen); - else - kfree(pmlmepriv->assoc_req); -} - -/* when wait_ack is true, this function should be called at process context */ -static int _issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned int power_mode, int wait_ack) -{ - int ret = _FAIL; - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct ieee80211_hdr *pwlanhdr; - __le16 *fctrl; - struct xmit_priv *pxmitpriv; - struct mlme_ext_priv *pmlmeext; - struct mlme_ext_info *pmlmeinfo; - - if (!padapter) - goto exit; - - pxmitpriv = &padapter->xmitpriv; - pmlmeext = &padapter->mlmeextpriv; - pmlmeinfo = &pmlmeext->mlmext_info; - - pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (!pmgntframe) - goto exit; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib(padapter, pattrib); - pattrib->retry_ctrl = false; - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct ieee80211_hdr *)pframe; - - fctrl = &pwlanhdr->frame_control; - *(fctrl) = 0; - - if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) - SetFrDs(fctrl); - else if ((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE) - SetToDs(fctrl); - - if (power_mode) - SetPwrMgt(fctrl); - - memcpy(pwlanhdr->addr1, da, ETH_ALEN); - memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN); - memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN); - - SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); - pmlmeext->mgnt_seq++; - SetFrameSubType(pframe, WIFI_DATA_NULL); - - pframe += sizeof(struct ieee80211_hdr_3addr); - pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); - - pattrib->last_txcmdsz = pattrib->pktlen; - - if (wait_ack) { - ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe); - } else { - dump_mgntframe(padapter, pmgntframe); - ret = _SUCCESS; - } - -exit: - return ret; -} - -/* when wait_ms > 0, this function should be called at process context */ -/* da == NULL for station mode */ -int issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned int power_mode, int try_cnt, int wait_ms) -{ - int ret; - int i = 0; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - /* da == NULL, assume it's null data for sta to ap*/ - if (!da) - da = get_my_bssid(&pmlmeinfo->network); - - do { - ret = _issue_nulldata(padapter, da, power_mode, wait_ms > 0); - - i++; - - if (padapter->bDriverStopped || padapter->bSurpriseRemoved) - break; - - if (i < try_cnt && wait_ms > 0 && ret == _FAIL) - msleep(wait_ms); - } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0))); - - if (ret != _FAIL) { - ret = _SUCCESS; - goto exit; - } -exit: - return ret; -} - -/* when wait_ack is true, this function should be called at process context */ -static int _issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 tid, int wait_ack) -{ - int ret = _FAIL; - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct ieee80211_hdr *pwlanhdr; - __le16 *fctrl; - unsigned short *qc; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (!pmgntframe) - goto exit; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib(padapter, pattrib); - - pattrib->hdrlen += 2; - pattrib->qos_en = true; - pattrib->eosp = 1; - pattrib->ack_policy = 0; - pattrib->mdata = 0; - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct ieee80211_hdr *)pframe; - - fctrl = &pwlanhdr->frame_control; - *(fctrl) = 0; - - if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) - SetFrDs(fctrl); - else if ((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE) - SetToDs(fctrl); - - qc = (unsigned short *)(pframe + pattrib->hdrlen - 2); - - SetPriority(qc, tid); - - SetEOSP(qc, pattrib->eosp); - - SetAckpolicy(qc, pattrib->ack_policy); - - memcpy(pwlanhdr->addr1, da, ETH_ALEN); - memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN); - memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN); - - SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); - pmlmeext->mgnt_seq++; - SetFrameSubType(pframe, WIFI_QOS_DATA_NULL); - - pframe += sizeof(struct ieee80211_qos_hdr); - pattrib->pktlen = sizeof(struct ieee80211_qos_hdr); - - pattrib->last_txcmdsz = pattrib->pktlen; - - if (wait_ack) { - ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe); - } else { - dump_mgntframe(padapter, pmgntframe); - ret = _SUCCESS; - } - -exit: - return ret; -} - -/* when wait_ms > 0 , this function should be called at process context */ -/* da == NULL for station mode */ -int issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 tid, int try_cnt, int wait_ms) -{ - int ret; - int i = 0; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - /* da == NULL, assume it's null data for sta to ap*/ - if (!da) - da = get_my_bssid(&pmlmeinfo->network); - - do { - ret = _issue_qos_nulldata(padapter, da, tid, wait_ms > 0); - - i++; - - if (padapter->bDriverStopped || padapter->bSurpriseRemoved) - break; - - if (i < try_cnt && wait_ms > 0 && ret == _FAIL) - msleep(wait_ms); - } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0))); - - if (ret != _FAIL) { - ret = _SUCCESS; - goto exit; - } -exit: - return ret; -} - -static int _issue_deauth(struct adapter *padapter, unsigned char *da, unsigned short reason, u8 wait_ack) -{ - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct ieee80211_hdr *pwlanhdr; - __le16 *fctrl; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - int ret = _FAIL; - __le16 le_tmp; - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - - if (!(rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) && (pwdinfo->rx_invitereq_info.scan_op_ch_only)) { - _cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey); - _set_timer(&pwdinfo->reset_ch_sitesurvey, 10); - } - - pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (!pmgntframe) - goto exit; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib(padapter, pattrib); - pattrib->retry_ctrl = false; - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct ieee80211_hdr *)pframe; - - fctrl = &pwlanhdr->frame_control; - *(fctrl) = 0; - - memcpy(pwlanhdr->addr1, da, ETH_ALEN); - memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN); - memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN); - - SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); - pmlmeext->mgnt_seq++; - SetFrameSubType(pframe, WIFI_DEAUTH); - - pframe += sizeof(struct ieee80211_hdr_3addr); - pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); - - le_tmp = cpu_to_le16(reason); - pframe = rtw_set_fixed_ie(pframe, _RSON_CODE_, (unsigned char *)&le_tmp, &pattrib->pktlen); - - pattrib->last_txcmdsz = pattrib->pktlen; - - if (wait_ack) { - ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe); - } else { - dump_mgntframe(padapter, pmgntframe); - ret = _SUCCESS; - } - -exit: - return ret; -} - -int issue_deauth(struct adapter *padapter, unsigned char *da, unsigned short reason) -{ - return _issue_deauth(padapter, da, reason, false); -} - -int issue_deauth_ex(struct adapter *padapter, u8 *da, unsigned short reason, int try_cnt, - int wait_ms) -{ - int ret; - int i = 0; - - do { - ret = _issue_deauth(padapter, da, reason, wait_ms > 0); - - i++; - - if (padapter->bDriverStopped || padapter->bSurpriseRemoved) - break; - - if (i < try_cnt && wait_ms > 0 && ret == _FAIL) - msleep(wait_ms); - } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0))); - - if (ret != _FAIL) { - ret = _SUCCESS; - goto exit; - } -exit: - return ret; -} - -void issue_action_BA(struct adapter *padapter, unsigned char *raddr, u8 action, - u16 status, struct ieee80211_mgmt *mgmt_req) -{ - u16 start_seq; - u16 BA_starting_seqctrl = 0; - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct sta_info *psta; - struct sta_priv *pstapriv = &padapter->stapriv; - struct registry_priv *pregpriv = &padapter->registrypriv; - struct ieee80211_mgmt *mgmt; - u16 capab, params; - - pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (!pmgntframe) - return; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib(padapter, pattrib); - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - mgmt = (struct ieee80211_mgmt *)(pmgntframe->buf_addr + TXDESC_OFFSET); - - mgmt->frame_control = cpu_to_le16(IEEE80211_STYPE_ACTION | IEEE80211_FTYPE_MGMT); - - memcpy(mgmt->da, raddr, ETH_ALEN); - memcpy(mgmt->sa, myid(&padapter->eeprompriv), ETH_ALEN); - memcpy(mgmt->bssid, get_my_bssid(&pmlmeinfo->network), ETH_ALEN); - - mgmt->seq_ctrl = cpu_to_le16(pmlmeext->mgnt_seq); - pmlmeext->mgnt_seq++; - - mgmt->u.action.category = WLAN_CATEGORY_BACK; - - switch (action) { - case WLAN_ACTION_ADDBA_REQ: - mgmt->u.action.u.addba_req.action_code = WLAN_ACTION_ADDBA_REQ; - do { - pmlmeinfo->dialogToken++; - } while (pmlmeinfo->dialogToken == 0); - mgmt->u.action.u.addba_req.dialog_token = pmlmeinfo->dialogToken; - - /* immediate ack & 64 buffer size */ - capab = u16_encode_bits(64, IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK); - capab |= u16_encode_bits(1, IEEE80211_ADDBA_PARAM_POLICY_MASK); - capab |= u16_encode_bits(status, IEEE80211_ADDBA_PARAM_TID_MASK); - mgmt->u.action.u.addba_req.capab = cpu_to_le16(capab); - - mgmt->u.action.u.addba_req.timeout = cpu_to_le16(5000); /* 5 ms */ - - psta = rtw_get_stainfo(pstapriv, raddr); - if (psta) { - start_seq = (psta->sta_xmitpriv.txseq_tid[status & 0x07] & 0xfff) + 1; - - psta->BA_starting_seqctrl[status & 0x07] = start_seq; - - BA_starting_seqctrl = start_seq << 4; - } - mgmt->u.action.u.addba_req.start_seq_num = cpu_to_le16(BA_starting_seqctrl); - - pattrib->pktlen = offsetofend(struct ieee80211_mgmt, - u.action.u.addba_req.start_seq_num); - break; - case WLAN_ACTION_ADDBA_RESP: - mgmt->u.action.u.addba_resp.action_code = WLAN_ACTION_ADDBA_RESP; - mgmt->u.action.u.addba_resp.dialog_token = mgmt_req->u.action.u.addba_req.dialog_token; - mgmt->u.action.u.addba_resp.status = cpu_to_le16(status); - capab = le16_to_cpu(mgmt_req->u.action.u.addba_req.capab) & 0x3f; - capab |= u16_encode_bits(64, IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK); - capab |= u16_encode_bits(pregpriv->ampdu_amsdu, IEEE80211_ADDBA_PARAM_AMSDU_MASK); - mgmt->u.action.u.addba_req.capab = cpu_to_le16(capab); - mgmt->u.action.u.addba_resp.timeout = mgmt_req->u.action.u.addba_req.timeout; - pattrib->pktlen = offsetofend(struct ieee80211_mgmt, u.action.u.addba_resp.timeout); - break; - case WLAN_ACTION_DELBA: - mgmt->u.action.u.delba.action_code = WLAN_ACTION_DELBA; - mgmt->u.action.u.delba.params = cpu_to_le16((status & 0x1F) << 3); - params = u16_encode_bits((status & 0x1), IEEE80211_DELBA_PARAM_INITIATOR_MASK); - params |= u16_encode_bits((status >> 1) & 0xF, IEEE80211_DELBA_PARAM_TID_MASK); - mgmt->u.action.u.delba.params = cpu_to_le16(params); - mgmt->u.action.u.delba.reason_code = cpu_to_le16(WLAN_STATUS_REQUEST_DECLINED); - pattrib->pktlen = offsetofend(struct ieee80211_mgmt, u.action.u.delba.reason_code); - break; - default: - break; - } - - pattrib->last_txcmdsz = pattrib->pktlen; - - dump_mgntframe(padapter, pmgntframe); -} - -static void issue_action_BSSCoexistPacket(struct adapter *padapter) -{ - struct list_head *plist, *phead; - unsigned char category, action; - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct ieee80211_hdr *pwlanhdr; - __le16 *fctrl; - struct wlan_network *pnetwork = NULL; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct __queue *queue = &pmlmepriv->scanned_queue; - u8 InfoContent[16] = {0}; - u8 ICS[8][15]; - if ((pmlmepriv->num_FortyMHzIntolerant == 0) || (pmlmepriv->num_sta_no_ht == 0)) - return; - - if (pmlmeinfo->bwmode_updated) - return; - - category = WLAN_CATEGORY_PUBLIC; - action = ACT_PUBLIC_BSSCOEXIST; - - pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (!pmgntframe) - return; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib(padapter, pattrib); - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct ieee80211_hdr *)pframe; - - fctrl = &pwlanhdr->frame_control; - *(fctrl) = 0; - - memcpy(pwlanhdr->addr1, get_my_bssid(&pmlmeinfo->network), ETH_ALEN); - memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN); - memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN); - - SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); - pmlmeext->mgnt_seq++; - SetFrameSubType(pframe, WIFI_ACTION); - - pframe += sizeof(struct ieee80211_hdr_3addr); - pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); - - pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen); - pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen); - - /* */ - if (pmlmepriv->num_FortyMHzIntolerant > 0) { - u8 iedata = 0; - - iedata |= BIT(2);/* 20 MHz BSS Width Request */ - - pframe = rtw_set_ie(pframe, EID_BSSCoexistence, 1, &iedata, &pattrib->pktlen); - } - - /* */ - memset(ICS, 0, sizeof(ICS)); - if (pmlmepriv->num_sta_no_ht > 0) { - int i; - - spin_lock_bh(&pmlmepriv->scanned_queue.lock); - - phead = get_list_head(queue); - plist = phead->next; - - while (phead != plist) { - int len; - u8 *p; - struct wlan_bssid_ex *pbss_network; - - pnetwork = container_of(plist, struct wlan_network, list); - - plist = plist->next; - - pbss_network = (struct wlan_bssid_ex *)&pnetwork->network; - - p = rtw_get_ie(pbss_network->IEs + _FIXED_IE_LENGTH_, _HT_CAPABILITY_IE_, &len, pbss_network->IELength - _FIXED_IE_LENGTH_); - if (!p || len == 0) { /* non-HT */ - if ((pbss_network->Configuration.DSConfig <= 0) || (pbss_network->Configuration.DSConfig > 14)) - continue; - - ICS[0][pbss_network->Configuration.DSConfig] = 1; - - if (ICS[0][0] == 0) - ICS[0][0] = 1; - } - } - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - - for (i = 0; i < 8; i++) { - if (ICS[i][0] == 1) { - int j, k = 0; - - InfoContent[k] = i; - /* SET_BSS_INTOLERANT_ELE_REG_CLASS(InfoContent, i); */ - k++; - - for (j = 1; j <= 14; j++) { - if (ICS[i][j] == 1) { - if (k < 16) { - InfoContent[k] = j; /* channel number */ - /* SET_BSS_INTOLERANT_ELE_CHANNEL(InfoContent+k, j); */ - k++; - } - } - } - - pframe = rtw_set_ie(pframe, EID_BSSIntolerantChlReport, k, InfoContent, &pattrib->pktlen); - } - } - } - - pattrib->last_txcmdsz = pattrib->pktlen; - - dump_mgntframe(padapter, pmgntframe); -} - -unsigned int send_delba(struct adapter *padapter, u8 initiator, u8 *addr) -{ - struct sta_priv *pstapriv = &padapter->stapriv; - struct sta_info *psta = NULL; - /* struct recv_reorder_ctrl *preorder_ctrl; */ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - u16 tid; - - if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE) - if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) - return _SUCCESS; - - psta = rtw_get_stainfo(pstapriv, addr); - if (!psta) - return _SUCCESS; - - if (initiator == 0) { /* recipient */ - for (tid = 0; tid < MAXTID; tid++) { - if (psta->recvreorder_ctrl[tid].enable) { - issue_action_BA(padapter, addr, WLAN_ACTION_DELBA, - (((tid << 1) | initiator) & 0x1F), NULL); - psta->recvreorder_ctrl[tid].enable = false; - psta->recvreorder_ctrl[tid].indicate_seq = 0xffff; - } - } - } else if (initiator == 1) { /* originator */ - for (tid = 0; tid < MAXTID; tid++) { - if (psta->htpriv.agg_enable_bitmap & BIT(tid)) { - issue_action_BA(padapter, addr, WLAN_ACTION_DELBA, - (((tid << 1) | initiator) & 0x1F), NULL); - psta->htpriv.agg_enable_bitmap &= ~BIT(tid); - psta->htpriv.candidate_tid_bitmap &= ~BIT(tid); - } - } - } - - return _SUCCESS; -} - -unsigned int send_beacon(struct adapter *padapter) -{ - bool bxmitok = false; - int issue = 0; - int poll = 0; - - clear_beacon_valid_bit(padapter); - - do { - issue_beacon(padapter, 100); - issue++; - do { - yield(); - bxmitok = get_beacon_valid_bit(padapter); - poll++; - } while ((poll % 10) != 0 && !bxmitok && !padapter->bSurpriseRemoved && !padapter->bDriverStopped); - } while (!bxmitok && issue < 100 && !padapter->bSurpriseRemoved && !padapter->bDriverStopped); - - if (padapter->bSurpriseRemoved || padapter->bDriverStopped || !bxmitok) - return _FAIL; - - return _SUCCESS; -} - -bool get_beacon_valid_bit(struct adapter *adapter) -{ - int res; - u8 reg; - - res = rtw_read8(adapter, REG_TDECTRL + 2, ®); - if (res) - return false; - - /* BIT(16) of REG_TDECTRL = BIT(0) of REG_TDECTRL+2 */ - return BIT(0) & reg; -} - -void clear_beacon_valid_bit(struct adapter *adapter) -{ - int res; - u8 reg; - - res = rtw_read8(adapter, REG_TDECTRL + 2, ®); - if (res) - return; - - /* BIT(16) of REG_TDECTRL = BIT(0) of REG_TDECTRL+2, write 1 to clear, Clear by sw */ - rtw_write8(adapter, REG_TDECTRL + 2, reg | BIT(0)); -} - -void rtw_resume_tx_beacon(struct adapter *adapt) -{ - struct hal_data_8188e *haldata = &adapt->haldata; - - /* 2010.03.01. Marked by tynli. No need to call workitem beacause we record the value */ - /* which should be read from register to a global variable. */ - - rtw_write8(adapt, REG_FWHW_TXQ_CTRL + 2, (haldata->RegFwHwTxQCtrl) | BIT(6)); - haldata->RegFwHwTxQCtrl |= BIT(6); - rtw_write8(adapt, REG_TBTT_PROHIBIT + 1, 0xff); - haldata->RegReg542 |= BIT(0); - rtw_write8(adapt, REG_TBTT_PROHIBIT + 2, haldata->RegReg542); -} - -void rtw_stop_tx_beacon(struct adapter *adapt) -{ - struct hal_data_8188e *haldata = &adapt->haldata; - - /* 2010.03.01. Marked by tynli. No need to call workitem beacause we record the value */ - /* which should be read from register to a global variable. */ - - rtw_write8(adapt, REG_FWHW_TXQ_CTRL + 2, (haldata->RegFwHwTxQCtrl) & (~BIT(6))); - haldata->RegFwHwTxQCtrl &= (~BIT(6)); - rtw_write8(adapt, REG_TBTT_PROHIBIT + 1, 0x64); - haldata->RegReg542 &= ~(BIT(0)); - rtw_write8(adapt, REG_TBTT_PROHIBIT + 2, haldata->RegReg542); - - /* todo: CheckFwRsvdPageContent(Adapter); 2010.06.23. Added by tynli. */ -} - -static void rtw_set_opmode(struct adapter *adapter, u8 mode) -{ - u8 val8; - int res; - - /* disable Port0 TSF update */ - res = rtw_read8(adapter, REG_BCN_CTRL, &val8); - if (res) - return; - - rtw_write8(adapter, REG_BCN_CTRL, val8 | BIT(4)); - - /* set net_type */ - res = rtw_read8(adapter, MSR, &val8); - if (res) - return; - - val8 &= 0x0c; - val8 |= mode; - rtw_write8(adapter, MSR, val8); - - if ((mode == _HW_STATE_STATION_) || (mode == _HW_STATE_NOLINK_)) { - rtw_stop_tx_beacon(adapter); - - rtw_write8(adapter, REG_BCN_CTRL, 0x19);/* disable atim wnd */ - } else if (mode == _HW_STATE_ADHOC_) { - rtw_resume_tx_beacon(adapter); - rtw_write8(adapter, REG_BCN_CTRL, 0x1a); - } else if (mode == _HW_STATE_AP_) { - rtw_resume_tx_beacon(adapter); - - rtw_write8(adapter, REG_BCN_CTRL, 0x12); - - /* Set RCR */ - rtw_write32(adapter, REG_RCR, 0x7000208e);/* CBSSID_DATA must set to 0,reject ICV_ERR packet */ - /* enable to rx data frame */ - rtw_write16(adapter, REG_RXFLTMAP2, 0xFFFF); - /* enable to rx ps-poll */ - rtw_write16(adapter, REG_RXFLTMAP1, 0x0400); - - /* Beacon Control related register for first time */ - rtw_write8(adapter, REG_BCNDMATIM, 0x02); /* 2ms */ - - rtw_write8(adapter, REG_ATIMWND, 0x0a); /* 10ms */ - rtw_write16(adapter, REG_BCNTCFG, 0x00); - rtw_write16(adapter, REG_TBTT_PROHIBIT, 0xff04); - rtw_write16(adapter, REG_TSFTR_SYN_OFFSET, 0x7fff);/* +32767 (~32ms) */ - - /* reset TSF */ - rtw_write8(adapter, REG_DUAL_TSF_RST, BIT(0)); - - /* BIT(3) - If set 0, hw will clr bcnq when tx becon ok/fail or port 0 */ - res = rtw_read8(adapter, REG_MBID_NUM, &val8); - if (res) - return; - - rtw_write8(adapter, REG_MBID_NUM, val8 | BIT(3) | BIT(4)); - - /* enable BCN0 Function for if1 */ - /* don't enable update TSF0 for if1 (due to TSF update when beacon/probe rsp are received) */ - rtw_write8(adapter, REG_BCN_CTRL, (DIS_TSF_UDT0_NORMAL_CHIP | EN_BCN_FUNCTION | BIT(1))); - - /* dis BCN1 ATIM WND if if2 is station */ - res = rtw_read8(adapter, REG_BCN_CTRL_1, &val8); - if (res) - return; - - rtw_write8(adapter, REG_BCN_CTRL_1, val8 | BIT(0)); - } -} - -/**************************************************************************** - -Following are some utility functions for WiFi MLME - -*****************************************************************************/ - -static void rtw_set_initial_gain(struct adapter *adapter, u8 gain) -{ - struct hal_data_8188e *haldata = &adapter->haldata; - struct odm_dm_struct *odmpriv = &haldata->odmpriv; - struct rtw_dig *digtable = &odmpriv->DM_DigTable; - - if (gain == 0xff) { - /* restore rx gain */ - ODM_Write_DIG(odmpriv, digtable->BackupIGValue); - } else { - digtable->BackupIGValue = digtable->CurIGValue; - ODM_Write_DIG(odmpriv, gain); - } -} - -void rtw_mlme_under_site_survey(struct adapter *adapter) -{ - /* config RCR to receive different BSSID & not to receive data frame */ - - int res; - u8 reg; - u32 v; - - res = rtw_read32(adapter, REG_RCR, &v); - if (res) - return; - - v &= ~(RCR_CBSSID_BCN); - rtw_write32(adapter, REG_RCR, v); - /* reject all data frame */ - rtw_write16(adapter, REG_RXFLTMAP2, 0x00); - - /* disable update TSF */ - res = rtw_read8(adapter, REG_BCN_CTRL, ®); - if (res) - return; - - rtw_write8(adapter, REG_BCN_CTRL, reg | BIT(4)); -} - -void rtw_mlme_site_survey_done(struct adapter *adapter) -{ - struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - u32 reg32; - int res; - u8 reg; - - if ((r8188eu_is_client_associated_to_ap(adapter)) || - ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE)) { - /* enable to rx data frame */ - rtw_write16(adapter, REG_RXFLTMAP2, 0xFFFF); - - /* enable update TSF */ - res = rtw_read8(adapter, REG_BCN_CTRL, ®); - if (res) - return; - - rtw_write8(adapter, REG_BCN_CTRL, reg & (~BIT(4))); - } else if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) { - rtw_write16(adapter, REG_RXFLTMAP2, 0xFFFF); - /* enable update TSF */ - res = rtw_read8(adapter, REG_BCN_CTRL, ®); - if (res) - return; - - rtw_write8(adapter, REG_BCN_CTRL, reg & (~BIT(4))); - } - - res = rtw_read32(adapter, REG_RCR, ®32); - if (res) - return; - - rtw_write32(adapter, REG_RCR, reg32 | RCR_CBSSID_BCN); -} - -void site_survey(struct adapter *padapter) -{ - unsigned char survey_channel = 0; - enum rt_scan_type ScanType = SCAN_PASSIVE; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - - if ((pwdinfo->rx_invitereq_info.scan_op_ch_only) || (pwdinfo->p2p_info.scan_op_ch_only)) { - if (pwdinfo->rx_invitereq_info.scan_op_ch_only) { - survey_channel = pwdinfo->rx_invitereq_info.operation_ch[pmlmeext->sitesurvey_res.channel_idx]; - } else { - survey_channel = pwdinfo->p2p_info.operation_ch[pmlmeext->sitesurvey_res.channel_idx]; - } - ScanType = SCAN_ACTIVE; - } else if (rtw_p2p_findphase_ex_is_social(pwdinfo)) { - /* Commented by Albert 2011/06/03 */ - /* The driver is in the find phase, it should go through the social channel. */ - int ch_set_idx; - survey_channel = pwdinfo->social_chan[pmlmeext->sitesurvey_res.channel_idx]; - ch_set_idx = rtw_ch_set_search_ch(pmlmeext->channel_set, survey_channel); - if (ch_set_idx >= 0) - ScanType = pmlmeext->channel_set[ch_set_idx].ScanType; - else - ScanType = SCAN_ACTIVE; - } else { - struct rtw_ieee80211_channel *ch; - if (pmlmeext->sitesurvey_res.channel_idx < pmlmeext->sitesurvey_res.ch_num) { - ch = &pmlmeext->sitesurvey_res.ch[pmlmeext->sitesurvey_res.channel_idx]; - survey_channel = ch->hw_value; - ScanType = (ch->flags & RTW_IEEE80211_CHAN_PASSIVE_SCAN) ? SCAN_PASSIVE : SCAN_ACTIVE; - } - } - - if (survey_channel != 0) { - if (pmlmeext->sitesurvey_res.channel_idx == 0) - set_channel_bwmode(padapter, survey_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20); - else - SelectChannel(padapter, survey_channel); - - if (ScanType == SCAN_ACTIVE) { /* obey the channel plan setting... */ - if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN) || - rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH)) { - issue_probereq_p2p(padapter); - issue_probereq_p2p(padapter); - issue_probereq_p2p(padapter); - } else { - int i; - for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) { - if (pmlmeext->sitesurvey_res.ssid[i].SsidLength) { - /* todo: to issue two probe req??? */ - issue_probereq(padapter, &pmlmeext->sitesurvey_res.ssid[i], NULL); - /* msleep(SURVEY_TO>>1); */ - issue_probereq(padapter, &pmlmeext->sitesurvey_res.ssid[i], NULL); - } - } - - if (pmlmeext->sitesurvey_res.scan_mode == SCAN_ACTIVE) { - /* todo: to issue two probe req??? */ - issue_probereq(padapter, NULL, NULL); - /* msleep(SURVEY_TO>>1); */ - issue_probereq(padapter, NULL, NULL); - } - } - } - - set_survey_timer(pmlmeext, pmlmeext->chan_scan_time); - } else { - /* channel number is 0 or this channel is not valid. */ - if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH)) { - if ((pwdinfo->rx_invitereq_info.scan_op_ch_only) || (pwdinfo->p2p_info.scan_op_ch_only)) { - /* Set the find_phase_state_exchange_cnt to P2P_FINDPHASE_EX_CNT. */ - /* This will let the following flow to run the scanning end. */ - rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_MAX); - } - } - - if (rtw_p2p_findphase_ex_is_needed(pwdinfo)) { - /* Set the P2P State to the listen state of find phase and set the current channel to the listen channel */ - set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20); - rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_LISTEN); - pmlmeext->sitesurvey_res.state = SCAN_DISABLE; - - /* restore RX GAIN */ - rtw_set_initial_gain(padapter, 0xff); - /* turn on dynamic functions */ - Restore_DM_Func_Flag(padapter); - /* Switch_DM_Func(padapter, DYNAMIC_FUNC_DIG|DYNAMIC_FUNC_HP|DYNAMIC_FUNC_SS, true); */ - - _set_timer(&pwdinfo->find_phase_timer, (u32)((u32)(pwdinfo->listen_dwell) * 100)); - } else { - /* 20100721:Interrupt scan operation here. */ - /* For SW antenna diversity before link, it needs to switch to another antenna and scan again. */ - /* It compares the scan result and selects a better one to do connection. */ - if (AntDivBeforeLink8188E(padapter)) { - pmlmeext->sitesurvey_res.bss_cnt = 0; - pmlmeext->sitesurvey_res.channel_idx = -1; - pmlmeext->chan_scan_time = SURVEY_TO / 2; - set_survey_timer(pmlmeext, pmlmeext->chan_scan_time); - return; - } - if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH)) - rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo)); - rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_NONE); - - pmlmeext->sitesurvey_res.state = SCAN_COMPLETE; - - /* switch back to the original channel */ - - if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_LISTEN)) - set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20); - else - set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); - - /* config MSR */ - Set_MSR(padapter, (pmlmeinfo->state & 0x3)); - - /* restore RX GAIN */ - rtw_set_initial_gain(padapter, 0xff); - /* turn on dynamic functions */ - Restore_DM_Func_Flag(padapter); - /* Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, true); */ - - if (r8188eu_is_client_associated_to_ap(padapter)) - issue_nulldata(padapter, NULL, 0, 3, 500); - - rtw_mlme_site_survey_done(padapter); - - report_surveydone_event(padapter); - - pmlmeext->chan_scan_time = SURVEY_TO; - pmlmeext->sitesurvey_res.state = SCAN_DISABLE; - - issue_action_BSSCoexistPacket(padapter); - issue_action_BSSCoexistPacket(padapter); - issue_action_BSSCoexistPacket(padapter); - } - } -} - -/* collect bss info from Beacon and Probe request/response frames. */ -u8 collect_bss_info(struct adapter *padapter, struct recv_frame *precv_frame, struct wlan_bssid_ex *bssid) -{ - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)precv_frame->rx_data; - int i; - u32 len; - u8 *p; - u16 val16; - u8 *pframe = precv_frame->rx_data; - u32 packet_len = precv_frame->len; - u8 ie_offset; - struct registry_priv *pregistrypriv = &padapter->registrypriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - __le32 le32_tmp; - - len = packet_len - sizeof(struct ieee80211_hdr_3addr); - - if (len > MAX_IE_SZ) - return _FAIL; - - memset(bssid, 0, sizeof(struct wlan_bssid_ex)); - - if (ieee80211_is_beacon(mgmt->frame_control)) { - bssid->Reserved[0] = 1; - ie_offset = _BEACON_IE_OFFSET_; - } else if (ieee80211_is_probe_req(mgmt->frame_control)) { - ie_offset = _PROBEREQ_IE_OFFSET_; - bssid->Reserved[0] = 2; - } else if (ieee80211_is_probe_resp(mgmt->frame_control)) { - ie_offset = _PROBERSP_IE_OFFSET_; - bssid->Reserved[0] = 3; - } else { - bssid->Reserved[0] = 0; - ie_offset = _FIXED_IE_LENGTH_; - } - - bssid->Length = sizeof(struct wlan_bssid_ex) - MAX_IE_SZ + len; - - /* below is to copy the information element */ - bssid->IELength = len; - memcpy(bssid->IEs, (pframe + sizeof(struct ieee80211_hdr_3addr)), bssid->IELength); - - /* get the signal strength */ - bssid->Rssi = precv_frame->attrib.phy_info.recvpower; /* in dBM.raw data */ - bssid->PhyInfo.SignalQuality = precv_frame->attrib.phy_info.SignalQuality;/* in percentage */ - bssid->PhyInfo.SignalStrength = precv_frame->attrib.phy_info.SignalStrength;/* in percentage */ - bssid->PhyInfo.Optimum_antenna = rtw_current_antenna(padapter); - - /* checking SSID */ - p = rtw_get_ie(bssid->IEs + ie_offset, _SSID_IE_, &len, bssid->IELength - ie_offset); - if (!p) - return _FAIL; - - if (*(p + 1)) { - if (len > NDIS_802_11_LENGTH_SSID) - return _FAIL; - memcpy(bssid->Ssid.Ssid, (p + 2), *(p + 1)); - bssid->Ssid.SsidLength = *(p + 1); - } else { - bssid->Ssid.SsidLength = 0; - } - - memset(bssid->SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX); - - /* checking rate info... */ - i = 0; - p = rtw_get_ie(bssid->IEs + ie_offset, _SUPPORTEDRATES_IE_, &len, bssid->IELength - ie_offset); - if (p) { - if (len > NDIS_802_11_LENGTH_RATES_EX) - return _FAIL; - memcpy(bssid->SupportedRates, (p + 2), len); - i = len; - } - - p = rtw_get_ie(bssid->IEs + ie_offset, _EXT_SUPPORTEDRATES_IE_, &len, bssid->IELength - ie_offset); - if (p) { - if (len > (NDIS_802_11_LENGTH_RATES_EX - i)) - return _FAIL; - memcpy(bssid->SupportedRates + i, (p + 2), len); - } - - if (bssid->IELength < 12) - return _FAIL; - - /* Checking for DSConfig */ - p = rtw_get_ie(bssid->IEs + ie_offset, _DSSET_IE_, &len, bssid->IELength - ie_offset); - - bssid->Configuration.DSConfig = 0; - bssid->Configuration.Length = 0; - - if (p) { - bssid->Configuration.DSConfig = *(p + 2); - } else {/* In 5G, some ap do not have DSSET IE */ - /* checking HT info for channel */ - p = rtw_get_ie(bssid->IEs + ie_offset, _HT_ADD_INFO_IE_, &len, bssid->IELength - ie_offset); - if (p) { - struct HT_info_element *HT_info = (struct HT_info_element *)(p + 2); - bssid->Configuration.DSConfig = HT_info->primary_channel; - } else { /* use current channel */ - bssid->Configuration.DSConfig = rtw_get_oper_ch(padapter); - } - } - - memcpy(&le32_tmp, rtw_get_beacon_interval_from_ie(bssid->IEs), 2); - bssid->Configuration.BeaconPeriod = le32_to_cpu(le32_tmp); - - val16 = rtw_get_capability((struct wlan_bssid_ex *)bssid); - - if (val16 & BIT(0)) { - bssid->InfrastructureMode = Ndis802_11Infrastructure; - memcpy(bssid->MacAddress, GetAddr2Ptr(pframe), ETH_ALEN); - } else { - bssid->InfrastructureMode = Ndis802_11IBSS; - memcpy(bssid->MacAddress, GetAddr3Ptr(pframe), ETH_ALEN); - } - - if (val16 & BIT(4)) - bssid->Privacy = 1; - else - bssid->Privacy = 0; - - bssid->Configuration.ATIMWindow = 0; - - /* 20/40 BSS Coexistence check */ - if ((pregistrypriv->wifi_spec == 1) && (!pmlmeinfo->bwmode_updated)) { - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - p = rtw_get_ie(bssid->IEs + ie_offset, _HT_CAPABILITY_IE_, &len, bssid->IELength - ie_offset); - if (p && len > 0) { - struct HT_caps_element *pHT_caps; - pHT_caps = (struct HT_caps_element *)(p + 2); - - if (le16_to_cpu(pHT_caps->u.HT_cap_element.HT_caps_info) & BIT(14)) - pmlmepriv->num_FortyMHzIntolerant++; - } else { - pmlmepriv->num_sta_no_ht++; - } - } - - /* mark bss info receiving from nearby channel as SignalQuality 101 */ - if (bssid->Configuration.DSConfig != rtw_get_oper_ch(padapter)) - bssid->PhyInfo.SignalQuality = 101; - return _SUCCESS; -} - -static void rtw_set_bssid(struct adapter *adapter, u8 *bssid) -{ - int i; - - for (i = 0; i < ETH_ALEN; i++) - rtw_write8(adapter, REG_BSSID + i, bssid[i]); -} - -static void mlme_join(struct adapter *adapter, int type) -{ - struct mlme_priv *mlmepriv = &adapter->mlmepriv; - u8 retry_limit = 0x30, reg; - u32 reg32; - int res; - - switch (type) { - case 0: - /* prepare to join */ - /* enable to rx data frame, accept all data frame */ - rtw_write16(adapter, REG_RXFLTMAP2, 0xFFFF); - - res = rtw_read32(adapter, REG_RCR, ®32); - if (res) - return; - - rtw_write32(adapter, REG_RCR, - reg32 | RCR_CBSSID_DATA | RCR_CBSSID_BCN); - - if (check_fwstate(mlmepriv, WIFI_STATION_STATE)) { - retry_limit = 48; - } else { - /* ad-hoc mode */ - retry_limit = 0x7; - } - break; - case 1: - /* joinbss_event call back when join res < 0 */ - rtw_write16(adapter, REG_RXFLTMAP2, 0x00); - break; - case 2: - /* sta add event call back */ - /* enable update TSF */ - res = rtw_read8(adapter, REG_BCN_CTRL, ®); - if (res) - return; - - rtw_write8(adapter, REG_BCN_CTRL, reg & (~BIT(4))); - - if (check_fwstate(mlmepriv, WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE)) - retry_limit = 0x7; - break; - default: - break; - } - - rtw_write16(adapter, REG_RL, - retry_limit << RETRY_LIMIT_SHORT_SHIFT | retry_limit << RETRY_LIMIT_LONG_SHIFT); -} - -void start_create_ibss(struct adapter *padapter) -{ - unsigned short caps; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&pmlmeinfo->network); - pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig; - pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork); - - /* update wireless mode */ - update_wireless_mode(padapter); - - /* update capability */ - caps = rtw_get_capability((struct wlan_bssid_ex *)pnetwork); - update_capinfo(padapter, caps); - if (caps & cap_IBSS) {/* adhoc master */ - rtw_write8(padapter, REG_SECCFG, 0xcf); - - /* switch channel */ - /* SelectChannel(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE); */ - set_channel_bwmode(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20); - - beacon_timing_control(padapter); - - /* set msr to WIFI_FW_ADHOC_STATE */ - pmlmeinfo->state = WIFI_FW_ADHOC_STATE; - Set_MSR(padapter, (pmlmeinfo->state & 0x3)); - - /* issue beacon */ - if (send_beacon(padapter) == _FAIL) { - report_join_res(padapter, -1); - pmlmeinfo->state = WIFI_FW_NULL_STATE; - } else { - rtw_set_bssid(padapter, padapter->registrypriv.dev_network.MacAddress); - mlme_join(padapter, 0); - - report_join_res(padapter, 1); - pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS; - rtw_indicate_connect(padapter); - } - } else { - return; - } - /* update bc/mc sta_info */ - update_bmc_sta(padapter); -} - -void start_clnt_join(struct adapter *padapter) -{ - unsigned short caps; - u8 val8; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&pmlmeinfo->network); - int beacon_timeout; - - pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig; - pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork); - - /* update wireless mode */ - update_wireless_mode(padapter); - - /* update capability */ - caps = rtw_get_capability((struct wlan_bssid_ex *)pnetwork); - update_capinfo(padapter, caps); - if (caps & cap_ESS) { - Set_MSR(padapter, WIFI_FW_STATION_STATE); - - val8 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X) ? 0xcc : 0xcf; - - rtw_write8(padapter, REG_SECCFG, val8); - - /* switch channel */ - set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); - - /* here wait for receiving the beacon to start auth */ - /* and enable a timer */ - beacon_timeout = decide_wait_for_beacon_timeout(pmlmeinfo->bcn_interval); - set_link_timer(pmlmeext, beacon_timeout); - _set_timer(&padapter->mlmepriv.assoc_timer, - (REAUTH_TO * REAUTH_LIMIT) + (REASSOC_TO * REASSOC_LIMIT) + beacon_timeout); - - pmlmeinfo->state = WIFI_FW_AUTH_NULL | WIFI_FW_STATION_STATE; - } else if (caps & cap_IBSS) { /* adhoc client */ - Set_MSR(padapter, WIFI_FW_ADHOC_STATE); - - rtw_write8(padapter, REG_SECCFG, 0xcf); - - /* switch channel */ - set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); - - beacon_timing_control(padapter); - - pmlmeinfo->state = WIFI_FW_ADHOC_STATE; - - report_join_res(padapter, 1); - } else { - return; - } -} - -void start_clnt_auth(struct adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - _cancel_timer_ex(&pmlmeext->link_timer); - - pmlmeinfo->state &= (~WIFI_FW_AUTH_NULL); - pmlmeinfo->state |= WIFI_FW_AUTH_STATE; - - pmlmeinfo->auth_seq = 1; - pmlmeinfo->reauth_count = 0; - pmlmeinfo->reassoc_count = 0; - pmlmeinfo->link_count = 0; - pmlmeext->retry = 0; - - /* Because of AP's not receiving deauth before */ - /* AP may: 1)not response auth or 2)deauth us after link is complete */ - /* issue deauth before issuing auth to deal with the situation */ - /* Commented by Albert 2012/07/21 */ - /* For the Win8 P2P connection, it will be hard to have a successful connection if this Wi-Fi doesn't connect to it. */ - issue_deauth(padapter, (&pmlmeinfo->network)->MacAddress, WLAN_REASON_DEAUTH_LEAVING); - - issue_auth(padapter, NULL, 0); - - set_link_timer(pmlmeext, REAUTH_TO); -} - -void start_clnt_assoc(struct adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - _cancel_timer_ex(&pmlmeext->link_timer); - - pmlmeinfo->state &= (~(WIFI_FW_AUTH_NULL | WIFI_FW_AUTH_STATE)); - pmlmeinfo->state |= (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE); - - issue_assocreq(padapter); - - set_link_timer(pmlmeext, REASSOC_TO); -} - -void receive_disconnect(struct adapter *padapter, unsigned char *MacAddr, unsigned short reason) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - /* check A3 */ - if (!(!memcmp(MacAddr, get_my_bssid(&pmlmeinfo->network), ETH_ALEN))) - return; - - if ((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE) { - if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) { - pmlmeinfo->state = WIFI_FW_NULL_STATE; - report_del_sta_event(padapter, MacAddr, reason); - } else if (pmlmeinfo->state & WIFI_FW_LINKING_STATE) { - pmlmeinfo->state = WIFI_FW_NULL_STATE; - report_join_res(padapter, -2); - } - } -} - -static void process_80211d(struct adapter *padapter, struct wlan_bssid_ex *bssid) -{ - struct registry_priv *pregistrypriv; - struct mlme_ext_priv *pmlmeext; - struct rt_channel_info *chplan_new; - u8 channel; - u8 i; - - pregistrypriv = &padapter->registrypriv; - pmlmeext = &padapter->mlmeextpriv; - - /* Adjust channel plan by AP Country IE */ - if (pregistrypriv->enable80211d && - (!pmlmeext->update_channel_plan_by_ap_done)) { - u8 *ie, *p; - u32 len; - struct rt_channel_plan chplan_ap; - struct rt_channel_info chplan_sta[MAX_CHANNEL_NUM]; - u8 country[4]; - u8 fcn; /* first channel number */ - u8 noc; /* number of channel */ - u8 j, k; - - ie = rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, _COUNTRY_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_); - if (!ie) - return; - if (len < 6) - return; - ie += 2; - p = ie; - ie += len; - - memset(country, 0, 4); - memcpy(country, p, 3); - p += 3; - - i = 0; - while ((ie - p) >= 3) { - fcn = *(p++); - noc = *(p++); - p++; - - for (j = 0; j < noc; j++) { - channel = fcn + j; - chplan_ap.Channel[i++] = channel; - } - } - chplan_ap.Len = i; - - memcpy(chplan_sta, pmlmeext->channel_set, sizeof(chplan_sta)); - - memset(pmlmeext->channel_set, 0, sizeof(pmlmeext->channel_set)); - chplan_new = pmlmeext->channel_set; - - i = 0; - j = 0; - k = 0; - if (pregistrypriv->wireless_mode & WIRELESS_11G) { - do { - if ((i == MAX_CHANNEL_NUM) || - (chplan_sta[i].ChannelNum == 0)) - break; - - if (j == chplan_ap.Len) - break; - - if (chplan_sta[i].ChannelNum == chplan_ap.Channel[j]) { - chplan_new[k].ChannelNum = chplan_ap.Channel[j]; - chplan_new[k].ScanType = SCAN_ACTIVE; - i++; - j++; - k++; - } else if (chplan_sta[i].ChannelNum < chplan_ap.Channel[j]) { - chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum; - chplan_new[k].ScanType = SCAN_PASSIVE; - i++; - k++; - } else if (chplan_sta[i].ChannelNum > chplan_ap.Channel[j]) { - chplan_new[k].ChannelNum = chplan_ap.Channel[j]; - chplan_new[k].ScanType = SCAN_ACTIVE; - j++; - k++; - } - } while (1); - - /* change AP not support channel to Passive scan */ - while ((i < MAX_CHANNEL_NUM) && - (chplan_sta[i].ChannelNum != 0) && - (chplan_sta[i].ChannelNum <= 14)) { - chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum; - chplan_new[k].ScanType = SCAN_PASSIVE; - i++; - k++; - } - - /* add channel AP supported */ - while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14)) { - chplan_new[k].ChannelNum = chplan_ap.Channel[j]; - chplan_new[k].ScanType = SCAN_ACTIVE; - j++; - k++; - } - } else { - /* keep original STA 2.4G channel plan */ - while ((i < MAX_CHANNEL_NUM) && - (chplan_sta[i].ChannelNum != 0) && - (chplan_sta[i].ChannelNum <= 14)) { - chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum; - chplan_new[k].ScanType = chplan_sta[i].ScanType; - i++; - k++; - } - - /* skip AP 2.4G channel plan */ - while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14)) - j++; - } - - /* keep original STA 5G channel plan */ - while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0)) { - chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum; - chplan_new[k].ScanType = chplan_sta[i].ScanType; - i++; - k++; - } - - pmlmeext->update_channel_plan_by_ap_done = 1; - } - - /* If channel is used by AP, set channel scan type to active */ - channel = bssid->Configuration.DSConfig; - chplan_new = pmlmeext->channel_set; - i = 0; - while ((i < MAX_CHANNEL_NUM) && (chplan_new[i].ChannelNum != 0)) { - if (chplan_new[i].ChannelNum == channel) { - if (chplan_new[i].ScanType == SCAN_PASSIVE) - chplan_new[i].ScanType = SCAN_ACTIVE; - break; - } - i++; - } -} - -/**************************************************************************** - -Following are the functions to report events - -*****************************************************************************/ - -void report_survey_event(struct adapter *padapter, struct recv_frame *precv_frame) -{ - struct cmd_obj *pcmd_obj; - u8 *pevtcmd; - u32 cmdsz; - struct survey_event *psurvey_evt; - struct C2HEvent_Header *pc2h_evt_hdr; - struct mlme_ext_priv *pmlmeext; - struct cmd_priv *pcmdpriv; - /* u8 *pframe = precv_frame->rx_data; */ - /* uint len = precv_frame->len; */ - - if (!padapter) - return; - - pmlmeext = &padapter->mlmeextpriv; - pcmdpriv = &padapter->cmdpriv; - - pcmd_obj = kzalloc(sizeof(*pcmd_obj), GFP_ATOMIC); - if (!pcmd_obj) - return; - - cmdsz = (sizeof(struct survey_event) + sizeof(struct C2HEvent_Header)); - pevtcmd = kzalloc(cmdsz, GFP_ATOMIC); - if (!pevtcmd) { - kfree(pcmd_obj); - return; - } - - INIT_LIST_HEAD(&pcmd_obj->list); - - pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); - pcmd_obj->cmdsz = cmdsz; - pcmd_obj->parmbuf = pevtcmd; - - pcmd_obj->rsp = NULL; - pcmd_obj->rspsz = 0; - - pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); - pc2h_evt_hdr->len = sizeof(struct survey_event); - pc2h_evt_hdr->ID = GEN_EVT_CODE(_Survey); - pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); - - psurvey_evt = (struct survey_event *)(pevtcmd + sizeof(struct C2HEvent_Header)); - - if (collect_bss_info(padapter, precv_frame, (struct wlan_bssid_ex *)&psurvey_evt->bss) == _FAIL) { - kfree(pcmd_obj); - kfree(pevtcmd); - return; - } - - process_80211d(padapter, &psurvey_evt->bss); - - rtw_enqueue_cmd(pcmdpriv, pcmd_obj); - - pmlmeext->sitesurvey_res.bss_cnt++; -} - -void report_surveydone_event(struct adapter *padapter) -{ - struct cmd_obj *pcmd_obj; - u8 *pevtcmd; - u32 cmdsz; - struct surveydone_event *psurveydone_evt; - struct C2HEvent_Header *pc2h_evt_hdr; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - - pcmd_obj = kzalloc(sizeof(*pcmd_obj), GFP_KERNEL); - if (!pcmd_obj) - return; - - cmdsz = (sizeof(struct surveydone_event) + sizeof(struct C2HEvent_Header)); - pevtcmd = kzalloc(cmdsz, GFP_KERNEL); - if (!pevtcmd) { - kfree(pcmd_obj); - return; - } - - INIT_LIST_HEAD(&pcmd_obj->list); - - pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); - pcmd_obj->cmdsz = cmdsz; - pcmd_obj->parmbuf = pevtcmd; - - pcmd_obj->rsp = NULL; - pcmd_obj->rspsz = 0; - - pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); - pc2h_evt_hdr->len = sizeof(struct surveydone_event); - pc2h_evt_hdr->ID = GEN_EVT_CODE(_SurveyDone); - pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); - - psurveydone_evt = (struct surveydone_event *)(pevtcmd + sizeof(struct C2HEvent_Header)); - psurveydone_evt->bss_cnt = pmlmeext->sitesurvey_res.bss_cnt; - - rtw_enqueue_cmd(pcmdpriv, pcmd_obj); -} - -void report_join_res(struct adapter *padapter, int res) -{ - struct cmd_obj *pcmd_obj; - u8 *pevtcmd; - u32 cmdsz; - struct joinbss_event *pjoinbss_evt; - struct C2HEvent_Header *pc2h_evt_hdr; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - - pcmd_obj = kzalloc(sizeof(*pcmd_obj), GFP_ATOMIC); - if (!pcmd_obj) - return; - - cmdsz = (sizeof(struct joinbss_event) + sizeof(struct C2HEvent_Header)); - pevtcmd = kzalloc(cmdsz, GFP_ATOMIC); - if (!pevtcmd) { - kfree(pcmd_obj); - return; - } - - INIT_LIST_HEAD(&pcmd_obj->list); - - pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); - pcmd_obj->cmdsz = cmdsz; - pcmd_obj->parmbuf = pevtcmd; - - pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); - pc2h_evt_hdr->len = sizeof(struct joinbss_event); - pc2h_evt_hdr->ID = GEN_EVT_CODE(_JoinBss); - pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); - - pjoinbss_evt = (struct joinbss_event *)(pevtcmd + sizeof(struct C2HEvent_Header)); - memcpy((unsigned char *)(&pjoinbss_evt->network.network), &pmlmeinfo->network, sizeof(struct wlan_bssid_ex)); - pjoinbss_evt->network.join_res = res; - pjoinbss_evt->network.aid = res; - - rtw_joinbss_event_prehandle(padapter, (u8 *)&pjoinbss_evt->network); - - rtw_enqueue_cmd(pcmdpriv, pcmd_obj); -} - -void report_del_sta_event(struct adapter *padapter, unsigned char *MacAddr, unsigned short reason) -{ - struct cmd_obj *pcmd_obj; - u8 *pevtcmd; - u32 cmdsz; - struct sta_info *psta; - int mac_id; - struct stadel_event *pdel_sta_evt; - struct C2HEvent_Header *pc2h_evt_hdr; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - - pcmd_obj = kzalloc(sizeof(*pcmd_obj), GFP_ATOMIC); - if (!pcmd_obj) - return; - - cmdsz = (sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header)); - pevtcmd = kzalloc(cmdsz, GFP_ATOMIC); - if (!pevtcmd) { - kfree(pcmd_obj); - return; - } - - INIT_LIST_HEAD(&pcmd_obj->list); - - pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); - pcmd_obj->cmdsz = cmdsz; - pcmd_obj->parmbuf = pevtcmd; - - pcmd_obj->rsp = NULL; - pcmd_obj->rspsz = 0; - - pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); - pc2h_evt_hdr->len = sizeof(struct stadel_event); - pc2h_evt_hdr->ID = GEN_EVT_CODE(_DelSTA); - pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); - - pdel_sta_evt = (struct stadel_event *)(pevtcmd + sizeof(struct C2HEvent_Header)); - memcpy((unsigned char *)(&pdel_sta_evt->macaddr), MacAddr, ETH_ALEN); - memcpy((unsigned char *)(pdel_sta_evt->rsvd), (unsigned char *)(&reason), 2); - - psta = rtw_get_stainfo(&padapter->stapriv, MacAddr); - if (psta) - mac_id = (int)psta->mac_id; - else - mac_id = (-1); - - pdel_sta_evt->mac_id = mac_id; - - rtw_enqueue_cmd(pcmdpriv, pcmd_obj); -} - -void report_add_sta_event(struct adapter *padapter, unsigned char *MacAddr, int cam_idx) -{ - struct cmd_obj *pcmd_obj; - u8 *pevtcmd; - u32 cmdsz; - struct stassoc_event *padd_sta_evt; - struct C2HEvent_Header *pc2h_evt_hdr; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - - pcmd_obj = kzalloc(sizeof(*pcmd_obj), GFP_KERNEL); - if (!pcmd_obj) - return; - - cmdsz = (sizeof(struct stassoc_event) + sizeof(struct C2HEvent_Header)); - pevtcmd = kzalloc(cmdsz, GFP_KERNEL); - if (!pevtcmd) { - kfree(pcmd_obj); - return; - } - - INIT_LIST_HEAD(&pcmd_obj->list); - - pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); - pcmd_obj->cmdsz = cmdsz; - pcmd_obj->parmbuf = pevtcmd; - - pcmd_obj->rsp = NULL; - pcmd_obj->rspsz = 0; - - pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); - pc2h_evt_hdr->len = sizeof(struct stassoc_event); - pc2h_evt_hdr->ID = GEN_EVT_CODE(_AddSTA); - pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); - - padd_sta_evt = (struct stassoc_event *)(pevtcmd + sizeof(struct C2HEvent_Header)); - memcpy((unsigned char *)(&padd_sta_evt->macaddr), MacAddr, ETH_ALEN); - padd_sta_evt->cam_id = cam_idx; - - rtw_enqueue_cmd(pcmdpriv, pcmd_obj); -} - -/**************************************************************************** - -Following are the event callback functions - -*****************************************************************************/ - -/* for sta/adhoc mode */ -void update_sta_info(struct adapter *padapter, struct sta_info *psta) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - /* ERP */ - VCS_update(padapter, psta); - - /* HT */ - if (pmlmepriv->htpriv.ht_option) { - psta->htpriv.ht_option = true; - - psta->htpriv.ampdu_enable = pmlmepriv->htpriv.ampdu_enable; - - if (support_short_GI(padapter, &pmlmeinfo->HT_caps)) - psta->htpriv.sgi = true; - - psta->qos_option = true; - } else { - psta->htpriv.ht_option = false; - - psta->htpriv.ampdu_enable = false; - - psta->htpriv.sgi = false; - psta->qos_option = false; - } - psta->htpriv.bwmode = pmlmeext->cur_bwmode; - psta->htpriv.ch_offset = pmlmeext->cur_ch_offset; - - psta->htpriv.agg_enable_bitmap = 0x0;/* reset */ - psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */ - - /* QoS */ - if (pmlmepriv->qospriv.qos_option) - psta->qos_option = true; - - psta->state = _FW_LINKED; -} - -static void rtw_reset_dm_func_flag(struct adapter *adapter) -{ - struct hal_data_8188e *haldata = &adapter->haldata; - struct dm_priv *dmpriv = &haldata->dmpriv; - struct odm_dm_struct *odmpriv = &haldata->odmpriv; - - odmpriv->SupportAbility = dmpriv->InitODMFlag; -} - -static void rtw_clear_dm_func_flag(struct adapter *adapter) -{ - struct hal_data_8188e *haldata = &adapter->haldata; - struct odm_dm_struct *odmpriv = &haldata->odmpriv; - - odmpriv->SupportAbility = 0; -} - -void mlmeext_joinbss_event_callback(struct adapter *padapter, int join_res) -{ - struct sta_info *psta, *psta_bmc; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *cur_network = &pmlmeinfo->network; - struct sta_priv *pstapriv = &padapter->stapriv; - u16 media_status; - - if (join_res < 0) { - mlme_join(padapter, 1); - rtw_set_bssid(padapter, null_addr); - - /* restore to initial setting. */ - update_tx_basic_rate(padapter, padapter->registrypriv.wireless_mode); - - return; - } - - if ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) { - /* for bc/mc */ - psta_bmc = rtw_get_bcmc_stainfo(padapter); - if (psta_bmc) { - pmlmeinfo->FW_sta_info[psta_bmc->mac_id].psta = psta_bmc; - update_bmc_sta_support_rate(padapter, psta_bmc->mac_id); - Update_RA_Entry(padapter, psta_bmc->mac_id); - } - } - - /* turn on dynamic functions */ - rtw_reset_dm_func_flag(padapter); - - /* update IOT-releated issue */ - update_IOT_info(padapter); - - rtw_set_basic_rate(padapter, cur_network->SupportedRates); - - /* BCN interval */ - rtw_write16(padapter, REG_BCN_INTERVAL, pmlmeinfo->bcn_interval); - - /* update capability */ - update_capinfo(padapter, pmlmeinfo->capability); - - /* WMM, Update EDCA param */ - WMMOnAssocRsp(padapter); - - /* HT */ - HTOnAssocRsp(padapter); - - set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); - - psta = rtw_get_stainfo(pstapriv, cur_network->MacAddress); - if (psta) { /* only for infra. mode */ - pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta; - - psta->wireless_mode = pmlmeext->cur_wireless_mode; - - /* set per sta rate after updating HT cap. */ - set_sta_rate(padapter, psta); - rtw_set_max_rpt_macid(padapter, psta->mac_id); - - media_status = (psta->mac_id << 8) | 1; /* MACID|OPMODE: 1 means connect */ - rtl8188e_set_FwMediaStatus_cmd(padapter, media_status); - } - - mlme_join(padapter, 2); - - if ((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE) { - /* correcting TSF */ - correct_TSF(padapter); - } - rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_CONNECT, 0); -} - -void mlmeext_sta_add_event_callback(struct adapter *padapter, struct sta_info *psta) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - if ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) { - if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {/* adhoc master or sta_count>1 */ - /* nothing to do */ - } else { /* adhoc client */ - /* correcting TSF */ - correct_TSF(padapter); - - /* start beacon */ - if (send_beacon(padapter) == _FAIL) { - pmlmeinfo->FW_sta_info[psta->mac_id].status = 0; - pmlmeinfo->state ^= WIFI_FW_ADHOC_STATE; - return; - } - pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS; - } - mlme_join(padapter, 2); - } - - pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta; - - /* rate radaptive */ - Update_RA_Entry(padapter, psta->mac_id); - - /* update adhoc sta_info */ - update_sta_info(padapter, psta); -} - -static void mlme_disconnect(struct adapter *adapter) -{ - int res; - u8 reg; - - /* Set RCR to not to receive data frame when NO LINK state */ - /* reject all data frames */ - rtw_write16(adapter, REG_RXFLTMAP2, 0x00); - - /* reset TSF */ - rtw_write8(adapter, REG_DUAL_TSF_RST, (BIT(0) | BIT(1))); - - /* disable update TSF */ - - res = rtw_read8(adapter, REG_BCN_CTRL, ®); - if (res) - return; - - rtw_write8(adapter, REG_BCN_CTRL, reg | BIT(4)); -} - -void mlmeext_sta_del_event_callback(struct adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - if (r8188eu_is_client_associated_to_ap(padapter) || r8188eu_is_ibss_empty(padapter)) { - mlme_disconnect(padapter); - rtw_set_bssid(padapter, null_addr); - - /* restore to initial setting. */ - update_tx_basic_rate(padapter, padapter->registrypriv.wireless_mode); - - /* switch to the 20M Hz mode after disconnect */ - pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20; - pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - - /* SelectChannel(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset); */ - set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); - - flush_all_cam_entry(padapter); - - pmlmeinfo->state = WIFI_FW_NULL_STATE; - - /* set MSR to no link state -> infra. mode */ - Set_MSR(padapter, _HW_STATE_STATION_); - - _cancel_timer_ex(&pmlmeext->link_timer); - } -} - -/**************************************************************************** - -Following are the functions for the timer handlers - -*****************************************************************************/ -static u8 chk_ap_is_alive(struct sta_info *psta) -{ - u8 ret = false; - - if ((sta_rx_data_pkts(psta) == sta_last_rx_data_pkts(psta)) && - sta_rx_beacon_pkts(psta) == sta_last_rx_beacon_pkts(psta) && - sta_rx_probersp_pkts(psta) == sta_last_rx_probersp_pkts(psta)) - ret = false; - else - ret = true; - - sta_update_last_rx_pkts(psta); - - return ret; -} - -static int rtl8188e_sreset_linked_status_check(struct adapter *padapter) -{ - u32 rx_dma_status; - int res; - u8 reg; - - res = rtw_read32(padapter, REG_RXDMA_STATUS, &rx_dma_status); - if (res) - return res; - - if (rx_dma_status != 0x00) - rtw_write32(padapter, REG_RXDMA_STATUS, rx_dma_status); - - return rtw_read8(padapter, REG_FMETHR, ®); -} - -void linked_status_chk(struct adapter *padapter) -{ - u32 i; - struct sta_info *psta; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct sta_priv *pstapriv = &padapter->stapriv; - - rtl8188e_sreset_linked_status_check(padapter); - - if (r8188eu_is_client_associated_to_ap(padapter)) { - /* linked infrastructure client mode */ - - int tx_chk = _SUCCESS, rx_chk = _SUCCESS; - int rx_chk_limit; - - rx_chk_limit = 4; - psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress); - if (psta) { - bool is_p2p_enable = false; - is_p2p_enable = !rtw_p2p_chk_state(&padapter->wdinfo, P2P_STATE_NONE); - - if (!chk_ap_is_alive(psta)) - rx_chk = _FAIL; - - if (pxmitpriv->last_tx_pkts == pxmitpriv->tx_pkts) - tx_chk = _FAIL; - - if (pmlmeext->active_keep_alive_check && (rx_chk == _FAIL || tx_chk == _FAIL)) { - u8 backup_oper_channel = 0; - - /* switch to correct channel of current network before issue keep-alive frames */ - if (rtw_get_oper_ch(padapter) != pmlmeext->cur_channel) { - backup_oper_channel = rtw_get_oper_ch(padapter); - SelectChannel(padapter, pmlmeext->cur_channel); - } - - if (rx_chk != _SUCCESS) - issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, psta->hwaddr); - - if ((tx_chk != _SUCCESS && pmlmeinfo->link_count++ == 0xf) || rx_chk != _SUCCESS) { - tx_chk = issue_nulldata(padapter, psta->hwaddr, 0, 3, 1); - /* if tx acked and p2p disabled, set rx_chk _SUCCESS to reset retry count */ - if (tx_chk == _SUCCESS && !is_p2p_enable) - rx_chk = _SUCCESS; - } - - /* back to the original operation channel */ - if (backup_oper_channel > 0) - SelectChannel(padapter, backup_oper_channel); - } else { - if (rx_chk != _SUCCESS) { - if (pmlmeext->retry == 0) { - issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress); - issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress); - issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress); - } - } - - if (tx_chk != _SUCCESS && pmlmeinfo->link_count++ == 0xf) { - tx_chk = issue_nulldata(padapter, NULL, 0, 1, 0); - } - } - - if (rx_chk == _FAIL) { - pmlmeext->retry++; - if (pmlmeext->retry > rx_chk_limit) { - receive_disconnect(padapter, pmlmeinfo->network.MacAddress, - WLAN_REASON_EXPIRATION_CHK); - return; - } - } else { - pmlmeext->retry = 0; - } - - if (tx_chk == _FAIL) { - pmlmeinfo->link_count &= 0xf; - } else { - pxmitpriv->last_tx_pkts = pxmitpriv->tx_pkts; - pmlmeinfo->link_count = 0; - } - } /* end of if ((psta = rtw_get_stainfo(pstapriv, passoc_res->network.MacAddress)) != NULL) */ - } else if (r8188eu_is_client_associated_to_ibss(padapter)) { - /* linked IBSS mode */ - /* for each assoc list entry to check the rx pkt counter */ - for (i = IBSS_START_MAC_ID; i < NUM_STA; i++) { - if (pmlmeinfo->FW_sta_info[i].status == 1) { - psta = pmlmeinfo->FW_sta_info[i].psta; - - if (psta == NULL) - continue; - if (pmlmeinfo->FW_sta_info[i].rx_pkt == sta_rx_pkts(psta)) { - if (pmlmeinfo->FW_sta_info[i].retry < 3) { - pmlmeinfo->FW_sta_info[i].retry++; - } else { - pmlmeinfo->FW_sta_info[i].retry = 0; - pmlmeinfo->FW_sta_info[i].status = 0; - report_del_sta_event(padapter, psta->hwaddr - , 65535/* indicate disconnect caused by no rx */ - ); - } - } else { - pmlmeinfo->FW_sta_info[i].retry = 0; - pmlmeinfo->FW_sta_info[i].rx_pkt = (u32)sta_rx_pkts(psta); - } - } - } - } -} - -void survey_timer_hdl(struct adapter *padapter) -{ - struct cmd_obj *ph2c; - struct sitesurvey_parm *psurveyPara; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - - /* issue rtw_sitesurvey_cmd */ - if (pmlmeext->sitesurvey_res.state > SCAN_START) { - if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) - pmlmeext->sitesurvey_res.channel_idx++; - - if (pmlmeext->scan_abort) { - if (!rtw_p2p_chk_state(&padapter->wdinfo, P2P_STATE_NONE)) { - rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_MAX); - pmlmeext->sitesurvey_res.channel_idx = 3; - } else { - pmlmeext->sitesurvey_res.channel_idx = pmlmeext->sitesurvey_res.ch_num; - } - - pmlmeext->scan_abort = false;/* reset */ - } - - ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC); - if (!ph2c) - goto exit_survey_timer_hdl; - - psurveyPara = kzalloc(sizeof(*psurveyPara), GFP_ATOMIC); - if (!psurveyPara) { - kfree(ph2c); - goto exit_survey_timer_hdl; - } - - init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, GEN_CMD_CODE(_SiteSurvey)); - rtw_enqueue_cmd(pcmdpriv, ph2c); - } - -exit_survey_timer_hdl: - return; -} - -void link_timer_hdl(struct adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) { - pmlmeinfo->state = WIFI_FW_NULL_STATE; - report_join_res(padapter, -3); - } else if (pmlmeinfo->state & WIFI_FW_AUTH_STATE) { - /* re-auth timer */ - if (++pmlmeinfo->reauth_count > REAUTH_LIMIT) { - pmlmeinfo->state = 0; - report_join_res(padapter, -1); - return; - } - - pmlmeinfo->auth_seq = 1; - issue_auth(padapter, NULL, 0); - set_link_timer(pmlmeext, REAUTH_TO); - } else if (pmlmeinfo->state & WIFI_FW_ASSOC_STATE) { - /* re-assoc timer */ - if (++pmlmeinfo->reassoc_count > REASSOC_LIMIT) { - pmlmeinfo->state = WIFI_FW_NULL_STATE; - report_join_res(padapter, -2); - return; - } - - issue_assocreq(padapter); - set_link_timer(pmlmeext, REASSOC_TO); - } -} - -void addba_timer_hdl(struct sta_info *psta) -{ - struct ht_priv *phtpriv; - - if (!psta) - return; - - phtpriv = &psta->htpriv; - - if ((phtpriv->ht_option) && (phtpriv->ampdu_enable)) { - if (phtpriv->candidate_tid_bitmap) - phtpriv->candidate_tid_bitmap = 0x0; - } -} - -u8 NULL_hdl(struct adapter *padapter, u8 *pbuf) -{ - return H2C_SUCCESS; -} - -u8 setopmode_hdl(struct adapter *padapter, u8 *pbuf) -{ - u8 type; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct setopmode_parm *psetop = (struct setopmode_parm *)pbuf; - - if (psetop->mode == Ndis802_11APMode) { - pmlmeinfo->state = WIFI_FW_AP_STATE; - type = _HW_STATE_AP_; - } else if (psetop->mode == Ndis802_11Infrastructure) { - pmlmeinfo->state &= ~(BIT(0) | BIT(1));/* clear state */ - pmlmeinfo->state |= WIFI_FW_STATION_STATE;/* set to STATION_STATE */ - type = _HW_STATE_STATION_; - } else if (psetop->mode == Ndis802_11IBSS) { - type = _HW_STATE_ADHOC_; - } else { - type = _HW_STATE_NOLINK_; - } - - rtw_set_opmode(padapter, type); - - return H2C_SUCCESS; -} - -u8 createbss_hdl(struct adapter *padapter, u8 *pbuf) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&pmlmeinfo->network); - struct joinbss_parm *pparm = (struct joinbss_parm *)pbuf; - /* u32 initialgain; */ - - if (pparm->network.InfrastructureMode == Ndis802_11APMode) { - if (pmlmeinfo->state == WIFI_FW_AP_STATE) { - /* todo: */ - return H2C_SUCCESS; - } - } - - /* below is for ad-hoc master */ - if (pparm->network.InfrastructureMode == Ndis802_11IBSS) { - rtw_joinbss_reset(padapter); - - pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20; - pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - pmlmeinfo->ERP_enable = 0; - pmlmeinfo->WMM_enable = 0; - pmlmeinfo->HT_enable = 0; - pmlmeinfo->HT_caps_enable = 0; - pmlmeinfo->HT_info_enable = 0; - pmlmeinfo->agg_enable_bitmap = 0; - pmlmeinfo->candidate_tid_bitmap = 0; - - /* disable dynamic functions, such as high power, DIG */ - Save_DM_Func_Flag(padapter); - rtw_clear_dm_func_flag(padapter); - - /* cancel link timer */ - _cancel_timer_ex(&pmlmeext->link_timer); - - /* clear CAM */ - flush_all_cam_entry(padapter); - - memcpy(pnetwork, pbuf, offsetof(struct wlan_bssid_ex, IELength)); - pnetwork->IELength = ((struct wlan_bssid_ex *)pbuf)->IELength; - - if (pnetwork->IELength > MAX_IE_SZ)/* Check pbuf->IELength */ - return H2C_PARAMETERS_ERROR; - - memcpy(pnetwork->IEs, ((struct wlan_bssid_ex *)pbuf)->IEs, pnetwork->IELength); - - start_create_ibss(padapter); - } - - return H2C_SUCCESS; -} - -u8 join_cmd_hdl(struct adapter *padapter, u8 *pbuf) -{ - struct ndis_802_11_var_ie *pIE; - struct registry_priv *pregpriv = &padapter->registrypriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&pmlmeinfo->network); - struct joinbss_parm *pparm = (struct joinbss_parm *)pbuf; - u32 i; - - /* check already connecting to AP or not */ - if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) { - if (pmlmeinfo->state & WIFI_FW_STATION_STATE) - issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, 5, 100); - - pmlmeinfo->state = WIFI_FW_NULL_STATE; - - /* clear CAM */ - flush_all_cam_entry(padapter); - - _cancel_timer_ex(&pmlmeext->link_timer); - - /* set MSR to nolink -> infra. mode */ - Set_MSR(padapter, _HW_STATE_STATION_); - - mlme_disconnect(padapter); - } - - rtw_antenna_select_cmd(padapter, pparm->network.PhyInfo.Optimum_antenna, false); - - rtw_joinbss_reset(padapter); - - pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20; - pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - pmlmeinfo->ERP_enable = 0; - pmlmeinfo->WMM_enable = 0; - pmlmeinfo->HT_enable = 0; - pmlmeinfo->HT_caps_enable = 0; - pmlmeinfo->HT_info_enable = 0; - pmlmeinfo->agg_enable_bitmap = 0; - pmlmeinfo->candidate_tid_bitmap = 0; - pmlmeinfo->bwmode_updated = false; - - memcpy(pnetwork, pbuf, offsetof(struct wlan_bssid_ex, IELength)); - pnetwork->IELength = ((struct wlan_bssid_ex *)pbuf)->IELength; - - if (pnetwork->IELength > MAX_IE_SZ)/* Check pbuf->IELength */ - return H2C_PARAMETERS_ERROR; - - memcpy(pnetwork->IEs, ((struct wlan_bssid_ex *)pbuf)->IEs, pnetwork->IELength); - - /* Check AP vendor to move rtw_joinbss_cmd() */ - - for (i = sizeof(struct ndis_802_11_fixed_ie); i < pnetwork->IELength;) { - pIE = (struct ndis_802_11_var_ie *)(pnetwork->IEs + i); - - switch (pIE->ElementID) { - case _VENDOR_SPECIFIC_IE_:/* Get WMM IE. */ - if (!memcmp(pIE->data, WMM_OUI, 4)) - pmlmeinfo->WMM_enable = 1; - break; - case _HT_CAPABILITY_IE_: /* Get HT Cap IE. */ - pmlmeinfo->HT_caps_enable = 1; - break; - case _HT_EXTRA_INFO_IE_: /* Get HT Info IE. */ - pmlmeinfo->HT_info_enable = 1; - - /* spec case only for cisco's ap because cisco's ap issue assoc rsp using mcs rate @40MHz or @20MHz */ - { - struct HT_info_element *pht_info = (struct HT_info_element *)(pIE->data); - - if ((pregpriv->cbw40_enable) && (pht_info->infos[0] & BIT(2))) { - /* switch to the 40M Hz mode according to the AP */ - pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40; - switch (pht_info->infos[0] & 0x3) { - case 1: - pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER; - break; - case 3: - pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER; - break; - default: - pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - break; - } - } - } - break; - default: - break; - } - - i += (pIE->Length + 2); - } - /* disable dynamic functions, such as high power, DIG */ - - /* config the initial gain under linking, need to write the BB registers */ - - rtw_set_bssid(padapter, pmlmeinfo->network.MacAddress); - mlme_join(padapter, 0); - - /* cancel link timer */ - _cancel_timer_ex(&pmlmeext->link_timer); - - start_clnt_join(padapter); - - return H2C_SUCCESS; -} - -u8 disconnect_hdl(struct adapter *padapter, unsigned char *pbuf) -{ - struct disconnect_parm *param = (struct disconnect_parm *)pbuf; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&pmlmeinfo->network); - u8 val8; - int res; - - if (r8188eu_is_client_associated_to_ap(padapter)) - issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, param->deauth_timeout_ms / 100, 100); - - mlme_disconnect(padapter); - rtw_set_bssid(padapter, null_addr); - - /* restore to initial setting. */ - update_tx_basic_rate(padapter, padapter->registrypriv.wireless_mode); - - if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) { - /* Stop BCN */ - res = rtw_read8(padapter, REG_BCN_CTRL, &val8); - if (res) - return H2C_DROPPED; - - rtw_write8(padapter, REG_BCN_CTRL, val8 & (~(EN_BCN_FUNCTION | EN_TXBCN_RPT))); - } - - /* set MSR to no link state -> infra. mode */ - Set_MSR(padapter, _HW_STATE_STATION_); - - pmlmeinfo->state = WIFI_FW_NULL_STATE; - - /* switch to the 20M Hz mode after disconnect */ - pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20; - pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - - set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); - - flush_all_cam_entry(padapter); - - _cancel_timer_ex(&pmlmeext->link_timer); - - rtw_free_uc_swdec_pending_queue(padapter); - - return H2C_SUCCESS; -} - -static int rtw_scan_ch_decision(struct adapter *padapter, struct rtw_ieee80211_channel *out, - u32 out_num, struct rtw_ieee80211_channel *in, u32 in_num) -{ - int i, j; - int set_idx; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - /* clear out first */ - memset(out, 0, sizeof(struct rtw_ieee80211_channel) * out_num); - - /* acquire channels from in */ - j = 0; - for (i = 0; i < in_num; i++) { - set_idx = rtw_ch_set_search_ch(pmlmeext->channel_set, in[i].hw_value); - if (in[i].hw_value && !(in[i].flags & RTW_IEEE80211_CHAN_DISABLED) && - set_idx >= 0) { - memcpy(&out[j], &in[i], sizeof(struct rtw_ieee80211_channel)); - - if (pmlmeext->channel_set[set_idx].ScanType == SCAN_PASSIVE) - out[j].flags &= RTW_IEEE80211_CHAN_PASSIVE_SCAN; - - j++; - } - if (j >= out_num) - break; - } - - /* if out is empty, use channel_set as default */ - if (j == 0) { - for (i = 0; i < pmlmeext->max_chan_nums; i++) { - out[i].hw_value = pmlmeext->channel_set[i].ChannelNum; - - if (pmlmeext->channel_set[i].ScanType == SCAN_PASSIVE) - out[i].flags &= RTW_IEEE80211_CHAN_PASSIVE_SCAN; - - j++; - } - } - - return j; -} - -u8 sitesurvey_cmd_hdl(struct adapter *padapter, u8 *pbuf) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct sitesurvey_parm *pparm = (struct sitesurvey_parm *)pbuf; - u8 bdelayscan = false; - u32 i; - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - - if (pmlmeext->sitesurvey_res.state == SCAN_DISABLE) { - /* for first time sitesurvey_cmd */ - - pmlmeext->sitesurvey_res.state = SCAN_START; - pmlmeext->sitesurvey_res.bss_cnt = 0; - pmlmeext->sitesurvey_res.channel_idx = 0; - - for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) { - if (pparm->ssid[i].SsidLength) { - memcpy(pmlmeext->sitesurvey_res.ssid[i].Ssid, pparm->ssid[i].Ssid, IW_ESSID_MAX_SIZE); - pmlmeext->sitesurvey_res.ssid[i].SsidLength = pparm->ssid[i].SsidLength; - } else { - pmlmeext->sitesurvey_res.ssid[i].SsidLength = 0; - } - } - - pmlmeext->sitesurvey_res.ch_num = rtw_scan_ch_decision(padapter - , pmlmeext->sitesurvey_res.ch, RTW_CHANNEL_SCAN_AMOUNT - , pparm->ch, pparm->ch_num - ); - - pmlmeext->sitesurvey_res.scan_mode = pparm->scan_mode; - - /* issue null data if associating to the AP */ - if (r8188eu_is_client_associated_to_ap(padapter)) { - pmlmeext->sitesurvey_res.state = SCAN_TXNULL; - - issue_nulldata(padapter, NULL, 1, 3, 500); - - bdelayscan = true; - } - if (bdelayscan) { - /* delay 50ms to protect nulldata(1). */ - set_survey_timer(pmlmeext, 50); - return H2C_SUCCESS; - } - } - - if ((pmlmeext->sitesurvey_res.state == SCAN_START) || (pmlmeext->sitesurvey_res.state == SCAN_TXNULL)) { - /* disable dynamic functions, such as high power, DIG */ - Save_DM_Func_Flag(padapter); - rtw_clear_dm_func_flag(padapter); - - /* config the initial gain under scanning, need to write the BB registers */ - if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) - rtw_set_initial_gain(padapter, 0x1e); - else - rtw_set_initial_gain(padapter, 0x28); - - - /* set MSR to no link state */ - Set_MSR(padapter, _HW_STATE_NOLINK_); - - rtw_mlme_under_site_survey(padapter); - - pmlmeext->sitesurvey_res.state = SCAN_PROCESS; - } - - site_survey(padapter); - - return H2C_SUCCESS; -} - -u8 setauth_hdl(struct adapter *padapter, unsigned char *pbuf) -{ - struct setauth_parm *pparm = (struct setauth_parm *)pbuf; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - if (pparm->mode < 4) - pmlmeinfo->auth_algo = pparm->mode; - return H2C_SUCCESS; -} - -u8 setkey_hdl(struct adapter *padapter, u8 *pbuf) -{ - unsigned short ctrl; - struct setkey_parm *pparm = (struct setkey_parm *)pbuf; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - unsigned char null_sta[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - - /* main tx key for wep. */ - if (pparm->set_tx) - pmlmeinfo->key_index = pparm->keyid; - - /* write cam */ - ctrl = BIT(15) | ((pparm->algorithm) << 2) | pparm->keyid; - - write_cam(padapter, pparm->keyid, ctrl, null_sta, pparm->key); - - return H2C_SUCCESS; -} - -u8 set_stakey_hdl(struct adapter *padapter, u8 *pbuf) -{ - u16 ctrl = 0; - u8 cam_id;/* cam_entry */ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct set_stakey_parm *pparm = (struct set_stakey_parm *)pbuf; - - /* cam_entry: */ - /* 0~3 for default key */ - - /* for concurrent mode (ap+sta): */ - /* default key is disable, using sw encrypt/decrypt */ - /* cam_entry = 4 for sta mode (macid = 0) */ - /* cam_entry(macid+3) = 5 ~ N for ap mode (aid = 1~N, macid = 2 ~N) */ - - /* for concurrent mode (sta+sta): */ - /* default key is disable, using sw encrypt/decrypt */ - /* cam_entry = 4 mapping to macid = 0 */ - /* cam_entry = 5 mapping to macid = 2 */ - - cam_id = 4; - - if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) { - struct sta_info *psta; - struct sta_priv *pstapriv = &padapter->stapriv; - - if (pparm->algorithm == _NO_PRIVACY_) /* clear cam entry */ { - clear_cam_entry(padapter, pparm->id); - return H2C_SUCCESS_RSP; - } - - psta = rtw_get_stainfo(pstapriv, pparm->addr); - if (psta) { - ctrl = (BIT(15) | ((pparm->algorithm) << 2)); - - if ((psta->mac_id < 1) || (psta->mac_id > (NUM_STA - 4))) - return H2C_REJECTED; - - cam_id = (psta->mac_id + 3);/* 0~3 for default key, cmd_id = macid + 3, macid = aid+1; */ - - write_cam(padapter, cam_id, ctrl, pparm->addr, pparm->key); - - return H2C_SUCCESS_RSP; - } else { - return H2C_REJECTED; - } - } - - /* below for sta mode */ - - if (pparm->algorithm == _NO_PRIVACY_) { /* clear cam entry */ - clear_cam_entry(padapter, pparm->id); - return H2C_SUCCESS; - } - ctrl = BIT(15) | ((pparm->algorithm) << 2); - write_cam(padapter, cam_id, ctrl, pparm->addr, pparm->key); - pmlmeinfo->enc_algo = pparm->algorithm; - return H2C_SUCCESS; -} - -u8 add_ba_hdl(struct adapter *padapter, unsigned char *pbuf) -{ - struct addBaReq_parm *pparm = (struct addBaReq_parm *)pbuf; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, pparm->addr); - - if (!psta) - return H2C_SUCCESS; - - if (((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) && (pmlmeinfo->HT_enable)) || - ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) { - issue_action_BA(padapter, pparm->addr, WLAN_ACTION_ADDBA_REQ, (u16)pparm->tid, NULL); - _set_timer(&psta->addba_retry_timer, ADDBA_TO); - } else { - psta->htpriv.candidate_tid_bitmap &= ~BIT(pparm->tid); - } - return H2C_SUCCESS; -} - -u8 set_tx_beacon_cmd(struct adapter *padapter) -{ - struct cmd_obj *ph2c; - struct Tx_Beacon_param *ptxBeacon_parm; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - u8 res = _SUCCESS; - int len_diff = 0; - - ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC); - if (!ph2c) { - res = _FAIL; - goto exit; - } - - ptxBeacon_parm = kzalloc(sizeof(*ptxBeacon_parm), GFP_ATOMIC); - if (!ptxBeacon_parm) { - kfree(ph2c); - res = _FAIL; - goto exit; - } - - memcpy(&ptxBeacon_parm->network, &pmlmeinfo->network, sizeof(struct wlan_bssid_ex)); - - len_diff = update_hidden_ssid(ptxBeacon_parm->network.IEs + _BEACON_IE_OFFSET_, - ptxBeacon_parm->network.IELength - _BEACON_IE_OFFSET_, - pmlmeinfo->hidden_ssid_mode); - ptxBeacon_parm->network.IELength += len_diff; - - init_h2fwcmd_w_parm_no_rsp(ph2c, ptxBeacon_parm, GEN_CMD_CODE(_TX_Beacon)); - - res = rtw_enqueue_cmd(pcmdpriv, ph2c); - -exit: - - return res; -} - -u8 mlme_evt_hdl(struct adapter *padapter, unsigned char *pbuf) -{ - u8 evt_code; - u16 evt_sz; - uint *peventbuf; - void (*event_callback)(struct adapter *dev, u8 *pbuf); - struct evt_priv *pevt_priv = &padapter->evtpriv; - - peventbuf = (uint *)pbuf; - evt_sz = (u16)(*peventbuf & 0xffff); - evt_code = (u8)((*peventbuf >> 16) & 0xff); - - /* checking if event code is valid */ - if (evt_code >= MAX_C2HEVT) - goto _abort_event_; - - /* checking if event size match the event parm size */ - if ((wlanevents[evt_code].parmsize != 0) && - (wlanevents[evt_code].parmsize != evt_sz)) - goto _abort_event_; - - atomic_inc(&pevt_priv->event_seq); - - peventbuf += 2; - - if (peventbuf) { - event_callback = wlanevents[evt_code].event_callback; - event_callback(padapter, (u8 *)peventbuf); - } - -_abort_event_: - return H2C_SUCCESS; -} - -u8 h2c_msg_hdl(struct adapter *padapter, unsigned char *pbuf) -{ - if (!pbuf) - return H2C_PARAMETERS_ERROR; - - return H2C_SUCCESS; -} - -u8 tx_beacon_hdl(struct adapter *padapter, unsigned char *pbuf) -{ - if (send_beacon(padapter) == _FAIL) { - return H2C_PARAMETERS_ERROR; - } else { - /* tx bc/mc frames after update TIM */ - struct sta_info *psta_bmc; - struct list_head *xmitframe_plist, *xmitframe_phead; - struct xmit_frame *pxmitframe = NULL; - struct sta_priv *pstapriv = &padapter->stapriv; - - /* for BC/MC Frames */ - psta_bmc = rtw_get_bcmc_stainfo(padapter); - if (!psta_bmc) - return H2C_SUCCESS; - - if ((pstapriv->tim_bitmap & BIT(0)) && (psta_bmc->sleepq_len > 0)) { - msleep(10);/* 10ms, ATIM(HIQ) Windows */ - spin_lock_bh(&psta_bmc->sleep_q.lock); - - xmitframe_phead = get_list_head(&psta_bmc->sleep_q); - xmitframe_plist = xmitframe_phead->next; - - while (xmitframe_phead != xmitframe_plist) { - pxmitframe = container_of(xmitframe_plist, struct xmit_frame, list); - - xmitframe_plist = xmitframe_plist->next; - - list_del_init(&pxmitframe->list); - - psta_bmc->sleepq_len--; - if (psta_bmc->sleepq_len > 0) - pxmitframe->attrib.mdata = 1; - else - pxmitframe->attrib.mdata = 0; - - pxmitframe->attrib.triggered = 1; - - pxmitframe->attrib.qsel = 0x11;/* HIQ */ - - spin_unlock_bh(&psta_bmc->sleep_q.lock); - if (rtl8188eu_hal_xmit(padapter, pxmitframe)) - rtw_xmit_complete(padapter, pxmitframe); - spin_lock_bh(&psta_bmc->sleep_q.lock); - } - spin_unlock_bh(&psta_bmc->sleep_q.lock); - } - } - return H2C_SUCCESS; -} - -u8 set_ch_hdl(struct adapter *padapter, u8 *pbuf) -{ - struct set_ch_parm *set_ch_parm; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - if (!pbuf) - return H2C_PARAMETERS_ERROR; - - set_ch_parm = (struct set_ch_parm *)pbuf; - - pmlmeext->cur_channel = set_ch_parm->ch; - pmlmeext->cur_ch_offset = set_ch_parm->ch_offset; - pmlmeext->cur_bwmode = set_ch_parm->bw; - - set_channel_bwmode(padapter, set_ch_parm->ch, set_ch_parm->ch_offset, set_ch_parm->bw); - - return H2C_SUCCESS; -} - -u8 set_chplan_hdl(struct adapter *padapter, unsigned char *pbuf) -{ - struct SetChannelPlan_param *setChannelPlan_param; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - if (!pbuf) - return H2C_PARAMETERS_ERROR; - - setChannelPlan_param = (struct SetChannelPlan_param *)pbuf; - - pmlmeext->max_chan_nums = init_channel_set(padapter, setChannelPlan_param->channel_plan, pmlmeext->channel_set); - init_channel_list(padapter, pmlmeext->channel_set, pmlmeext->max_chan_nums, &pmlmeext->channel_list); - - return H2C_SUCCESS; -} - -u8 led_blink_hdl(struct adapter *padapter, unsigned char *pbuf) -{ - if (!pbuf) - return H2C_PARAMETERS_ERROR; - return H2C_SUCCESS; -} - -u8 set_csa_hdl(struct adapter *padapter, unsigned char *pbuf) -{ - return H2C_REJECTED; -} - -/* TDLS_WRCR : write RCR DATA BIT */ -/* TDLS_SD_PTI : issue peer traffic indication */ -/* TDLS_CS_OFF : go back to the channel linked with AP, terminating channel switch procedure */ -/* TDLS_INIT_CH_SEN : init channel sensing, receive all data and mgnt frame */ -/* TDLS_DONE_CH_SEN: channel sensing and report candidate channel */ -/* TDLS_OFF_CH : first time set channel to off channel */ -/* TDLS_BASE_CH : go back tp the channel linked with AP when set base channel as target channel */ -/* TDLS_P_OFF_CH : periodically go to off channel */ -/* TDLS_P_BASE_CH : periodically go back to base channel */ -/* TDLS_RS_RCR : restore RCR */ -/* TDLS_CKALV_PH1 : check alive timer phase1 */ -/* TDLS_CKALV_PH2 : check alive timer phase2 */ -/* TDLS_FREE_STA : free tdls sta */ -u8 tdls_hdl(struct adapter *padapter, unsigned char *pbuf) -{ - return H2C_REJECTED; -} diff --git a/drivers/staging/r8188eu/core/rtw_p2p.c b/drivers/staging/r8188eu/core/rtw_p2p.c deleted file mode 100644 index 93d3c9c4399c..000000000000 --- a/drivers/staging/r8188eu/core/rtw_p2p.c +++ /dev/null @@ -1,1918 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#define _RTW_P2P_C_ - -#include "../include/drv_types.h" -#include "../include/rtw_p2p.h" -#include "../include/wifi.h" - -static int rtw_p2p_is_channel_list_ok(u8 desired_ch, u8 *ch_list, u8 ch_cnt) -{ - int found = 0, i = 0; - - for (i = 0; i < ch_cnt; i++) { - if (ch_list[i] == desired_ch) { - found = 1; - break; - } - } - return found; -} - -static u32 go_add_group_info_attr(struct wifidirect_info *pwdinfo, u8 *pbuf) -{ - struct list_head *phead, *plist; - u32 len = 0; - u16 attr_len = 0; - u8 tmplen, *pdata_attr, *pstart, *pcur; - struct sta_info *psta = NULL; - struct adapter *padapter = pwdinfo->padapter; - struct sta_priv *pstapriv = &padapter->stapriv; - - pdata_attr = kzalloc(MAX_P2P_IE_LEN, GFP_KERNEL); - - pstart = pdata_attr; - pcur = pdata_attr; - - spin_lock_bh(&pstapriv->asoc_list_lock); - phead = &pstapriv->asoc_list; - plist = phead->next; - - /* look up sta asoc_queue */ - while (phead != plist) { - psta = container_of(plist, struct sta_info, asoc_list); - - plist = plist->next; - - if (psta->is_p2p_device) { - tmplen = 0; - - pcur++; - - /* P2P device address */ - memcpy(pcur, psta->dev_addr, ETH_ALEN); - pcur += ETH_ALEN; - - /* P2P interface address */ - memcpy(pcur, psta->hwaddr, ETH_ALEN); - pcur += ETH_ALEN; - - *pcur = psta->dev_cap; - pcur++; - - /* u16*)(pcur) = cpu_to_be16(psta->config_methods); */ - RTW_PUT_BE16(pcur, psta->config_methods); - pcur += 2; - - memcpy(pcur, psta->primary_dev_type, 8); - pcur += 8; - - *pcur = psta->num_of_secdev_type; - pcur++; - - memcpy(pcur, psta->secdev_types_list, psta->num_of_secdev_type * 8); - pcur += psta->num_of_secdev_type * 8; - - if (psta->dev_name_len > 0) { - /* u16*)(pcur) = cpu_to_be16(WPS_ATTR_DEVICE_NAME); */ - RTW_PUT_BE16(pcur, WPS_ATTR_DEVICE_NAME); - pcur += 2; - - /* u16*)(pcur) = cpu_to_be16(psta->dev_name_len); */ - RTW_PUT_BE16(pcur, psta->dev_name_len); - pcur += 2; - - memcpy(pcur, psta->dev_name, psta->dev_name_len); - pcur += psta->dev_name_len; - } - - tmplen = (u8)(pcur - pstart); - - *pstart = (tmplen - 1); - - attr_len += tmplen; - - /* pstart += tmplen; */ - pstart = pcur; - } - } - spin_unlock_bh(&pstapriv->asoc_list_lock); - - if (attr_len > 0) - len = rtw_set_p2p_attr_content(pbuf, P2P_ATTR_GROUP_INFO, attr_len, pdata_attr); - - kfree(pdata_attr); - return len; -} - -static void issue_group_disc_req(struct wifidirect_info *pwdinfo, u8 *da) -{ - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct ieee80211_hdr *pwlanhdr; - __le16 *fctrl; - struct adapter *padapter = pwdinfo->padapter; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - unsigned char category = RTW_WLAN_CATEGORY_P2P;/* P2P action frame */ - __be32 p2poui = cpu_to_be32(P2POUI); - u8 oui_subtype = P2P_GO_DISC_REQUEST; - u8 dialogToken = 0; - - pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (!pmgntframe) - return; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib(padapter, pattrib); - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct ieee80211_hdr *)pframe; - - fctrl = &pwlanhdr->frame_control; - *(fctrl) = 0; - - memcpy(pwlanhdr->addr1, da, ETH_ALEN); - memcpy(pwlanhdr->addr2, pwdinfo->interface_addr, ETH_ALEN); - memcpy(pwlanhdr->addr3, pwdinfo->interface_addr, ETH_ALEN); - - SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); - pmlmeext->mgnt_seq++; - SetFrameSubType(pframe, WIFI_ACTION); - - pframe += sizeof(struct ieee80211_hdr_3addr); - pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); - - /* Build P2P action frame header */ - pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen); - pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&p2poui, &pattrib->pktlen); - pframe = rtw_set_fixed_ie(pframe, 1, &oui_subtype, &pattrib->pktlen); - pframe = rtw_set_fixed_ie(pframe, 1, &dialogToken, &pattrib->pktlen); - - /* there is no IE in this P2P action frame */ - - pattrib->last_txcmdsz = pattrib->pktlen; - - dump_mgntframe(padapter, pmgntframe); -} - -static void issue_p2p_devdisc_resp(struct wifidirect_info *pwdinfo, u8 *da, u8 status, u8 dialogToken) -{ - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct ieee80211_hdr *pwlanhdr; - __le16 *fctrl; - struct adapter *padapter = pwdinfo->padapter; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - unsigned char category = WLAN_CATEGORY_PUBLIC; - u8 action = P2P_PUB_ACTION_ACTION; - __be32 p2poui = cpu_to_be32(P2POUI); - u8 oui_subtype = P2P_DEVDISC_RESP; - u8 p2pie[8] = { 0x00 }; - u32 p2pielen = 0; - - pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (!pmgntframe) - return; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib(padapter, pattrib); - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct ieee80211_hdr *)pframe; - - fctrl = &pwlanhdr->frame_control; - *(fctrl) = 0; - - memcpy(pwlanhdr->addr1, da, ETH_ALEN); - memcpy(pwlanhdr->addr2, pwdinfo->device_addr, ETH_ALEN); - memcpy(pwlanhdr->addr3, pwdinfo->device_addr, ETH_ALEN); - - SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); - pmlmeext->mgnt_seq++; - SetFrameSubType(pframe, WIFI_ACTION); - - pframe += sizeof(struct ieee80211_hdr_3addr); - pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); - - /* Build P2P public action frame header */ - pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen); - pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen); - pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&p2poui, &pattrib->pktlen); - pframe = rtw_set_fixed_ie(pframe, 1, &oui_subtype, &pattrib->pktlen); - pframe = rtw_set_fixed_ie(pframe, 1, &dialogToken, &pattrib->pktlen); - - /* Build P2P IE */ - /* P2P OUI */ - p2pielen = 0; - p2pie[p2pielen++] = 0x50; - p2pie[p2pielen++] = 0x6F; - p2pie[p2pielen++] = 0x9A; - p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */ - - /* P2P_ATTR_STATUS */ - p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_STATUS, 1, &status); - - pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, p2pie, &pattrib->pktlen); - - pattrib->last_txcmdsz = pattrib->pktlen; - - dump_mgntframe(padapter, pmgntframe); -} - -static void issue_p2p_provision_resp(struct wifidirect_info *pwdinfo, u8 *raddr, u8 *frame_body, u16 config_method) -{ - struct adapter *padapter = pwdinfo->padapter; - unsigned char category = WLAN_CATEGORY_PUBLIC; - u8 action = P2P_PUB_ACTION_ACTION; - u8 dialogToken = frame_body[7]; /* The Dialog Token of provisioning discovery request frame. */ - __be32 p2poui = cpu_to_be32(P2POUI); - u8 oui_subtype = P2P_PROVISION_DISC_RESP; - u8 wpsie[100] = { 0x00 }; - u8 wpsielen = 0; - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct ieee80211_hdr *pwlanhdr; - __le16 *fctrl; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (!pmgntframe) - return; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib(padapter, pattrib); - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct ieee80211_hdr *)pframe; - - fctrl = &pwlanhdr->frame_control; - *(fctrl) = 0; - - memcpy(pwlanhdr->addr1, raddr, ETH_ALEN); - memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN); - memcpy(pwlanhdr->addr3, myid(&padapter->eeprompriv), ETH_ALEN); - - SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); - pmlmeext->mgnt_seq++; - SetFrameSubType(pframe, WIFI_ACTION); - - pframe += sizeof(struct ieee80211_hdr_3addr); - pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); - - pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen); - pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen); - pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&p2poui, &pattrib->pktlen); - pframe = rtw_set_fixed_ie(pframe, 1, &oui_subtype, &pattrib->pktlen); - pframe = rtw_set_fixed_ie(pframe, 1, &dialogToken, &pattrib->pktlen); - - wpsielen = 0; - /* WPS OUI */ - RTW_PUT_BE32(wpsie, WPSOUI); - wpsielen += 4; - - /* Config Method */ - /* Type: */ - RTW_PUT_BE16(wpsie + wpsielen, WPS_ATTR_CONF_METHOD); - wpsielen += 2; - - /* Length: */ - RTW_PUT_BE16(wpsie + wpsielen, 0x0002); - wpsielen += 2; - - /* Value: */ - RTW_PUT_BE16(wpsie + wpsielen, config_method); - wpsielen += 2; - - pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *)wpsie, &pattrib->pktlen); - - pattrib->last_txcmdsz = pattrib->pktlen; - - dump_mgntframe(padapter, pmgntframe); -} - -static void issue_p2p_presence_resp(struct wifidirect_info *pwdinfo, u8 *da, u8 status, u8 dialogToken) -{ - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct ieee80211_hdr *pwlanhdr; - __le16 *fctrl; - struct adapter *padapter = pwdinfo->padapter; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - unsigned char category = RTW_WLAN_CATEGORY_P2P;/* P2P action frame */ - __be32 p2poui = cpu_to_be32(P2POUI); - u8 oui_subtype = P2P_PRESENCE_RESPONSE; - u8 p2pie[MAX_P2P_IE_LEN] = { 0x00 }; - u8 noa_attr_content[32] = { 0x00 }; - u32 p2pielen = 0; - - pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (!pmgntframe) - return; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib(padapter, pattrib); - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct ieee80211_hdr *)pframe; - - fctrl = &pwlanhdr->frame_control; - *(fctrl) = 0; - - memcpy(pwlanhdr->addr1, da, ETH_ALEN); - memcpy(pwlanhdr->addr2, pwdinfo->interface_addr, ETH_ALEN); - memcpy(pwlanhdr->addr3, pwdinfo->interface_addr, ETH_ALEN); - - SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); - pmlmeext->mgnt_seq++; - SetFrameSubType(pframe, WIFI_ACTION); - - pframe += sizeof(struct ieee80211_hdr_3addr); - pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); - - /* Build P2P action frame header */ - pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen); - pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&p2poui, &pattrib->pktlen); - pframe = rtw_set_fixed_ie(pframe, 1, &oui_subtype, &pattrib->pktlen); - pframe = rtw_set_fixed_ie(pframe, 1, &dialogToken, &pattrib->pktlen); - - /* Add P2P IE header */ - /* P2P OUI */ - p2pielen = 0; - p2pie[p2pielen++] = 0x50; - p2pie[p2pielen++] = 0x6F; - p2pie[p2pielen++] = 0x9A; - p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */ - - /* Add Status attribute in P2P IE */ - p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_STATUS, 1, &status); - - /* Add NoA attribute in P2P IE */ - noa_attr_content[0] = 0x1;/* index */ - noa_attr_content[1] = 0x0;/* CTWindow and OppPS Parameters */ - - /* todo: Notice of Absence Descriptor(s) */ - - p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_NOA, 2, noa_attr_content); - - pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, p2pie, &pattrib->pktlen); - - pattrib->last_txcmdsz = pattrib->pktlen; - - dump_mgntframe(padapter, pmgntframe); -} - -u32 build_beacon_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf) -{ - u8 p2pie[MAX_P2P_IE_LEN] = { 0x00 }; - u16 capability = 0; - u32 len = 0, p2pielen = 0; - __le16 le_tmp; - - /* P2P OUI */ - p2pielen = 0; - p2pie[p2pielen++] = 0x50; - p2pie[p2pielen++] = 0x6F; - p2pie[p2pielen++] = 0x9A; - p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */ - - /* According to the P2P Specification, the beacon frame should contain 3 P2P attributes */ - /* 1. P2P Capability */ - /* 2. P2P Device ID */ - /* 3. Notice of Absence (NOA) */ - - /* P2P Capability ATTR */ - /* Type: */ - /* Length: */ - /* Value: */ - /* Device Capability Bitmap, 1 byte */ - /* Be able to participate in additional P2P Groups and */ - /* support the P2P Invitation Procedure */ - /* Group Capability Bitmap, 1 byte */ - capability = P2P_DEVCAP_INVITATION_PROC | P2P_DEVCAP_CLIENT_DISCOVERABILITY; - capability |= ((P2P_GRPCAP_GO | P2P_GRPCAP_INTRABSS) << 8); - if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_PROVISIONING_ING)) - capability |= (P2P_GRPCAP_GROUP_FORMATION << 8); - - le_tmp = cpu_to_le16(capability); - p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_CAPABILITY, 2, (u8 *)&le_tmp); - - /* P2P Device ID ATTR */ - p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_DEVICE_ID, ETH_ALEN, pwdinfo->device_addr); - - /* Notice of Absence ATTR */ - /* Type: */ - /* Length: */ - /* Value: */ - - pbuf = rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &len); - return len; -} - -u32 build_probe_resp_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf) -{ - u8 p2pie[MAX_P2P_IE_LEN] = { 0x00 }; - u32 len = 0, p2pielen = 0; - - /* P2P OUI */ - p2pielen = 0; - p2pie[p2pielen++] = 0x50; - p2pie[p2pielen++] = 0x6F; - p2pie[p2pielen++] = 0x9A; - p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */ - - /* Commented by Albert 20100907 */ - /* According to the P2P Specification, the probe response frame should contain 5 P2P attributes */ - /* 1. P2P Capability */ - /* 2. Extended Listen Timing */ - /* 3. Notice of Absence (NOA) (Only GO needs this) */ - /* 4. Device Info */ - /* 5. Group Info (Only GO need this) */ - - /* P2P Capability ATTR */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_CAPABILITY; - - /* Length: */ - /* u16*) (p2pie + p2pielen) = cpu_to_le16(0x0002); */ - RTW_PUT_LE16(p2pie + p2pielen, 0x0002); - p2pielen += 2; - - /* Value: */ - /* Device Capability Bitmap, 1 byte */ - p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT; - - /* Group Capability Bitmap, 1 byte */ - if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) { - p2pie[p2pielen] = (P2P_GRPCAP_GO | P2P_GRPCAP_INTRABSS); - - if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_PROVISIONING_ING)) - p2pie[p2pielen] |= P2P_GRPCAP_GROUP_FORMATION; - - p2pielen++; - } else if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE)) { - /* Group Capability Bitmap, 1 byte */ - if (pwdinfo->persistent_supported) - p2pie[p2pielen++] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT; - else - p2pie[p2pielen++] = DMP_P2P_GRPCAP_SUPPORT; - } - - /* Extended Listen Timing ATTR */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_EX_LISTEN_TIMING; - - /* Length: */ - /* u16*) (p2pie + p2pielen) = cpu_to_le16(0x0004); */ - RTW_PUT_LE16(p2pie + p2pielen, 0x0004); - p2pielen += 2; - - /* Value: */ - /* Availability Period */ - /* u16*) (p2pie + p2pielen) = cpu_to_le16(0xFFFF); */ - RTW_PUT_LE16(p2pie + p2pielen, 0xFFFF); - p2pielen += 2; - - /* Availability Interval */ - /* u16*) (p2pie + p2pielen) = cpu_to_le16(0xFFFF); */ - RTW_PUT_LE16(p2pie + p2pielen, 0xFFFF); - p2pielen += 2; - - /* Notice of Absence ATTR */ - /* Type: */ - /* Length: */ - /* Value: */ - - /* Device Info ATTR */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO; - - /* Length: */ - /* 21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */ - /* + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */ - /* u16*) (p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len); */ - RTW_PUT_LE16(p2pie + p2pielen, 21 + pwdinfo->device_name_len); - p2pielen += 2; - - /* Value: */ - /* P2P Device Address */ - memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN); - p2pielen += ETH_ALEN; - - /* Config Method */ - /* This field should be big endian. Noted by P2P specification. */ - /* u16*) (p2pie + p2pielen) = cpu_to_be16(pwdinfo->supported_wps_cm); */ - RTW_PUT_BE16(p2pie + p2pielen, pwdinfo->supported_wps_cm); - p2pielen += 2; - - /* Primary Device Type */ - /* Category ID */ - /* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA); */ - RTW_PUT_BE16(p2pie + p2pielen, WPS_PDT_CID_MULIT_MEDIA); - p2pielen += 2; - - /* OUI */ - /* u32*) (p2pie + p2pielen) = cpu_to_be32(WPSOUI); */ - RTW_PUT_BE32(p2pie + p2pielen, WPSOUI); - p2pielen += 4; - - /* Sub Category ID */ - /* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER); */ - RTW_PUT_BE16(p2pie + p2pielen, WPS_PDT_SCID_MEDIA_SERVER); - p2pielen += 2; - - /* Number of Secondary Device Types */ - p2pie[p2pielen++] = 0x00; /* No Secondary Device Type List */ - - /* Device Name */ - /* Type: */ - /* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME); */ - RTW_PUT_BE16(p2pie + p2pielen, WPS_ATTR_DEVICE_NAME); - p2pielen += 2; - - /* Length: */ - /* u16*) (p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len); */ - RTW_PUT_BE16(p2pie + p2pielen, pwdinfo->device_name_len); - p2pielen += 2; - - /* Value: */ - memcpy(p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len); - p2pielen += pwdinfo->device_name_len; - - /* Group Info ATTR */ - /* Type: */ - /* Length: */ - /* Value: */ - if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) - p2pielen += go_add_group_info_attr(pwdinfo, p2pie + p2pielen); - - pbuf = rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &len); - - return len; -} - -u32 build_prov_disc_request_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf, u8 *pssid, u8 ussidlen, u8 *pdev_raddr) -{ - u8 p2pie[MAX_P2P_IE_LEN] = { 0x00 }; - u32 len = 0, p2pielen = 0; - - /* P2P OUI */ - p2pielen = 0; - p2pie[p2pielen++] = 0x50; - p2pie[p2pielen++] = 0x6F; - p2pie[p2pielen++] = 0x9A; - p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */ - - /* Commented by Albert 20110301 */ - /* According to the P2P Specification, the provision discovery request frame should contain 3 P2P attributes */ - /* 1. P2P Capability */ - /* 2. Device Info */ - /* 3. Group ID (When joining an operating P2P Group) */ - - /* P2P Capability ATTR */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_CAPABILITY; - - /* Length: */ - /* u16*) (p2pie + p2pielen) = cpu_to_le16(0x0002); */ - RTW_PUT_LE16(p2pie + p2pielen, 0x0002); - p2pielen += 2; - - /* Value: */ - /* Device Capability Bitmap, 1 byte */ - p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT; - - /* Group Capability Bitmap, 1 byte */ - if (pwdinfo->persistent_supported) - p2pie[p2pielen++] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT; - else - p2pie[p2pielen++] = DMP_P2P_GRPCAP_SUPPORT; - - /* Device Info ATTR */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO; - - /* Length: */ - /* 21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */ - /* + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */ - /* u16*) (p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len); */ - RTW_PUT_LE16(p2pie + p2pielen, 21 + pwdinfo->device_name_len); - p2pielen += 2; - - /* Value: */ - /* P2P Device Address */ - memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN); - p2pielen += ETH_ALEN; - - /* Config Method */ - /* This field should be big endian. Noted by P2P specification. */ - if (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PBC) { - /* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_CONFIG_METHOD_PBC); */ - RTW_PUT_BE16(p2pie + p2pielen, WPS_CONFIG_METHOD_PBC); - } else { - /* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_CONFIG_METHOD_DISPLAY); */ - RTW_PUT_BE16(p2pie + p2pielen, WPS_CONFIG_METHOD_DISPLAY); - } - - p2pielen += 2; - - /* Primary Device Type */ - /* Category ID */ - /* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA); */ - RTW_PUT_BE16(p2pie + p2pielen, WPS_PDT_CID_MULIT_MEDIA); - p2pielen += 2; - - /* OUI */ - /* u32*) (p2pie + p2pielen) = cpu_to_be32(WPSOUI); */ - RTW_PUT_BE32(p2pie + p2pielen, WPSOUI); - p2pielen += 4; - - /* Sub Category ID */ - /* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER); */ - RTW_PUT_BE16(p2pie + p2pielen, WPS_PDT_SCID_MEDIA_SERVER); - p2pielen += 2; - - /* Number of Secondary Device Types */ - p2pie[p2pielen++] = 0x00; /* No Secondary Device Type List */ - - /* Device Name */ - /* Type: */ - /* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME); */ - RTW_PUT_BE16(p2pie + p2pielen, WPS_ATTR_DEVICE_NAME); - p2pielen += 2; - - /* Length: */ - /* u16*) (p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len); */ - RTW_PUT_BE16(p2pie + p2pielen, pwdinfo->device_name_len); - p2pielen += 2; - - /* Value: */ - memcpy(p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len); - p2pielen += pwdinfo->device_name_len; - - if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) { - /* Added by Albert 2011/05/19 */ - /* In this case, the pdev_raddr is the device address of the group owner. */ - - /* P2P Group ID ATTR */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_GROUP_ID; - - /* Length: */ - /* u16*) (p2pie + p2pielen) = cpu_to_le16(ETH_ALEN + ussidlen); */ - RTW_PUT_LE16(p2pie + p2pielen, ETH_ALEN + ussidlen); - p2pielen += 2; - - /* Value: */ - memcpy(p2pie + p2pielen, pdev_raddr, ETH_ALEN); - p2pielen += ETH_ALEN; - - memcpy(p2pie + p2pielen, pssid, ussidlen); - p2pielen += ussidlen; - } - - pbuf = rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &len); - - return len; -} - -u32 build_assoc_resp_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf, u8 status_code) -{ - u8 p2pie[MAX_P2P_IE_LEN] = { 0x00 }; - u32 len = 0, p2pielen = 0; - - /* P2P OUI */ - p2pielen = 0; - p2pie[p2pielen++] = 0x50; - p2pie[p2pielen++] = 0x6F; - p2pie[p2pielen++] = 0x9A; - p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */ - - /* According to the P2P Specification, the Association response frame should contain 2 P2P attributes */ - /* 1. Status */ - /* 2. Extended Listen Timing (optional) */ - - /* Status ATTR */ - p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_STATUS, 1, &status_code); - - /* Extended Listen Timing ATTR */ - /* Type: */ - /* Length: */ - /* Value: */ - - pbuf = rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &len); - - return len; -} - -u32 process_probe_req_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pframe, uint len) -{ - u8 *p; - u32 ret = false; - u8 *p2pie; - u32 p2pielen = 0; - int ssid_len = 0, rate_cnt = 0; - - p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _SUPPORTEDRATES_IE_, (int *)&rate_cnt, - len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_); - - if (rate_cnt <= 4) { - int i, g_rate = 0; - - for (i = 0; i < rate_cnt; i++) { - if (((*(p + 2 + i) & 0xff) != 0x02) && - ((*(p + 2 + i) & 0xff) != 0x04) && - ((*(p + 2 + i) & 0xff) != 0x0B) && - ((*(p + 2 + i) & 0xff) != 0x16)) - g_rate = 1; - } - - if (g_rate == 0) { - /* There is no OFDM rate included in SupportedRates IE of this probe request frame */ - /* The driver should response this probe request. */ - return ret; - } - } else { - /* rate_cnt > 4 means the SupportRates IE contains the OFDM rate because the count of CCK rates are 4. */ - /* We should proceed the following check for this probe request. */ - } - - /* Added comments by Albert 20100906 */ - /* There are several items we should check here. */ - /* 1. This probe request frame must contain the P2P IE. (Done) */ - /* 2. This probe request frame must contain the wildcard SSID. (Done) */ - /* 3. Wildcard BSSID. (Todo) */ - /* 4. Destination Address. (Done in mgt_dispatcher function) */ - /* 5. Requested Device Type in WSC IE. (Todo) */ - /* 6. Device ID attribute in P2P IE. (Todo) */ - - p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _SSID_IE_, (int *)&ssid_len, - len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_); - - ssid_len &= 0xff; /* Just last 1 byte is valid for ssid len of the probe request */ - if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE) || rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) { - p2pie = rtw_get_p2p_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_, NULL, &p2pielen); - if (p2pie) { - if (p && !memcmp((void *)(p + 2), (void *)pwdinfo->p2p_wildcard_ssid, 7)) { - /* todo: */ - /* Check Requested Device Type attributes in WSC IE. */ - /* Check Device ID attribute in P2P IE */ - - ret = true; - } else if (p && ssid_len == 0) { - ret = true; - } - } else { - /* non -p2p device */ - } - } - - return ret; -} - -u32 process_assoc_req_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pframe, uint len, struct sta_info *psta) -{ - u8 status_code = P2P_STATUS_SUCCESS; - u8 *pbuf, *pattr_content = NULL; - u32 attr_contentlen = 0; - u16 cap_attr = 0; - unsigned short frame_type, ie_offset = 0; - u8 *ies; - u32 ies_len; - u8 *p2p_ie; - u32 p2p_ielen = 0; - __be16 be_tmp; - __le16 le_tmp; - - if (!rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) - return P2P_STATUS_FAIL_REQUEST_UNABLE; - - frame_type = GetFrameSubType(pframe); - if (frame_type == WIFI_ASSOCREQ) - ie_offset = _ASOCREQ_IE_OFFSET_; - else /* WIFI_REASSOCREQ */ - ie_offset = _REASOCREQ_IE_OFFSET_; - - ies = pframe + WLAN_HDR_A3_LEN + ie_offset; - ies_len = len - WLAN_HDR_A3_LEN - ie_offset; - - p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen); - - if (!p2p_ie) - status_code = P2P_STATUS_FAIL_INVALID_PARAM; - - while (p2p_ie) { - /* Check P2P Capability ATTR */ - if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CAPABILITY, (u8 *)&le_tmp, (uint *)&attr_contentlen)) { - cap_attr = le16_to_cpu(le_tmp); - psta->dev_cap = cap_attr & 0xff; - } - - /* Check Extended Listen Timing ATTR */ - - /* Check P2P Device Info ATTR */ - if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_DEVICE_INFO, NULL, (uint *)&attr_contentlen)) { - pattr_content = kzalloc(attr_contentlen, GFP_KERNEL); - pbuf = pattr_content; - if (pattr_content) { - u8 num_of_secdev_type; - u16 dev_name_len; - - rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_DEVICE_INFO, pattr_content, (uint *)&attr_contentlen); - - memcpy(psta->dev_addr, pattr_content, ETH_ALEN);/* P2P Device Address */ - - pattr_content += ETH_ALEN; - - memcpy(&be_tmp, pattr_content, 2);/* Config Methods */ - psta->config_methods = be16_to_cpu(be_tmp); - - pattr_content += 2; - - memcpy(psta->primary_dev_type, pattr_content, 8); - - pattr_content += 8; - - num_of_secdev_type = *pattr_content; - pattr_content += 1; - - if (num_of_secdev_type == 0) { - psta->num_of_secdev_type = 0; - } else { - u32 len; - - psta->num_of_secdev_type = num_of_secdev_type; - - len = (sizeof(psta->secdev_types_list) < (num_of_secdev_type * 8)) ? - (sizeof(psta->secdev_types_list)) : (num_of_secdev_type * 8); - - memcpy(psta->secdev_types_list, pattr_content, len); - - pattr_content += (num_of_secdev_type * 8); - } - - psta->dev_name_len = 0; - if (be16_to_cpu(*(__be16 *)pattr_content) == WPS_ATTR_DEVICE_NAME) { - dev_name_len = be16_to_cpu(*(__be16 *)(pattr_content + 2)); - - psta->dev_name_len = (sizeof(psta->dev_name) < dev_name_len) ? sizeof(psta->dev_name) : dev_name_len; - - memcpy(psta->dev_name, pattr_content + 4, psta->dev_name_len); - } - kfree(pbuf); - } - } - - /* Get the next P2P IE */ - p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen); - } - - return status_code; -} - -u32 process_p2p_devdisc_req(struct wifidirect_info *pwdinfo, u8 *pframe, uint len) -{ - u8 *frame_body; - u8 status, dialogToken; - struct sta_info *psta = NULL; - struct adapter *padapter = pwdinfo->padapter; - struct sta_priv *pstapriv = &padapter->stapriv; - u8 *p2p_ie; - u32 p2p_ielen = 0; - - frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr)); - - dialogToken = frame_body[7]; - status = P2P_STATUS_FAIL_UNKNOWN_P2PGROUP; - - p2p_ie = rtw_get_p2p_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &p2p_ielen); - if (p2p_ie) { - u8 groupid[38] = { 0x00 }; - u8 dev_addr[ETH_ALEN] = { 0x00 }; - u32 attr_contentlen = 0; - - if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, groupid, &attr_contentlen)) { - if (!memcmp(pwdinfo->device_addr, groupid, ETH_ALEN) && - !memcmp(pwdinfo->p2p_group_ssid, groupid + ETH_ALEN, pwdinfo->p2p_group_ssid_len)) { - attr_contentlen = 0; - if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_DEVICE_ID, dev_addr, &attr_contentlen)) { - struct list_head *phead, *plist; - - spin_lock_bh(&pstapriv->asoc_list_lock); - phead = &pstapriv->asoc_list; - plist = phead->next; - - /* look up sta asoc_queue */ - while (phead != plist) { - psta = container_of(plist, struct sta_info, asoc_list); - - plist = plist->next; - - if (psta->is_p2p_device && (psta->dev_cap & P2P_DEVCAP_CLIENT_DISCOVERABILITY) && - !memcmp(psta->dev_addr, dev_addr, ETH_ALEN)) { - /* issue GO Discoverability Request */ - issue_group_disc_req(pwdinfo, psta->hwaddr); - status = P2P_STATUS_SUCCESS; - break; - } else { - status = P2P_STATUS_FAIL_INFO_UNAVAILABLE; - } - } - spin_unlock_bh(&pstapriv->asoc_list_lock); - } else { - status = P2P_STATUS_FAIL_INVALID_PARAM; - } - } else { - status = P2P_STATUS_FAIL_INVALID_PARAM; - } - } - } - - /* issue Device Discoverability Response */ - issue_p2p_devdisc_resp(pwdinfo, GetAddr2Ptr(pframe), status, dialogToken); - - return status == P2P_STATUS_SUCCESS; -} - -u32 process_p2p_devdisc_resp(struct wifidirect_info *pwdinfo, u8 *pframe, uint len) -{ - return true; -} - -u8 process_p2p_provdisc_req(struct wifidirect_info *pwdinfo, u8 *pframe, uint len) -{ - u8 *frame_body; - u8 *wpsie; - uint wps_ielen = 0, attr_contentlen = 0; - u16 uconfig_method = 0; - __be16 be_tmp; - - frame_body = (pframe + sizeof(struct ieee80211_hdr_3addr)); - - wpsie = rtw_get_wps_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &wps_ielen); - if (wpsie) { - if (rtw_get_wps_attr_content(wpsie, wps_ielen, WPS_ATTR_CONF_METHOD, (u8 *)&be_tmp, &attr_contentlen)) { - uconfig_method = be16_to_cpu(be_tmp); - switch (uconfig_method) { - case WPS_CM_DISPLYA: - memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "dis", 3); - break; - case WPS_CM_LABEL: - memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "lab", 3); - break; - case WPS_CM_PUSH_BUTTON: - memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pbc", 3); - break; - case WPS_CM_KEYPAD: - memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pad", 3); - break; - } - issue_p2p_provision_resp(pwdinfo, GetAddr2Ptr(pframe), frame_body, uconfig_method); - } - } - return true; -} - -u8 process_p2p_provdisc_resp(struct wifidirect_info *pwdinfo, u8 *pframe) -{ - return true; -} - -static u8 rtw_p2p_get_peer_ch_list(struct wifidirect_info *pwdinfo, u8 *ch_content, u8 ch_cnt, u8 *peer_ch_list) -{ - u8 i = 0, j = 0; - u8 temp = 0; - u8 ch_no = 0; - ch_content += 3; - ch_cnt -= 3; - - while (ch_cnt > 0) { - ch_content += 1; - ch_cnt -= 1; - temp = *ch_content; - for (i = 0 ; i < temp ; i++, j++) - peer_ch_list[j] = *(ch_content + 1 + i); - ch_content += (temp + 1); - ch_cnt -= (temp + 1); - ch_no += temp; - } - - return ch_no; -} - -static u8 rtw_p2p_ch_inclusion(struct mlme_ext_priv *pmlmeext, u8 *peer_ch_list, u8 peer_ch_num, u8 *ch_list_inclusioned) -{ - int i = 0, j = 0, temp = 0; - u8 ch_no = 0; - - for (i = 0; i < peer_ch_num; i++) { - for (j = temp; j < pmlmeext->max_chan_nums; j++) { - if (*(peer_ch_list + i) == pmlmeext->channel_set[j].ChannelNum) { - ch_list_inclusioned[ch_no++] = *(peer_ch_list + i); - temp = j; - break; - } - } - } - - return ch_no; -} - -u8 process_p2p_group_negotation_req(struct wifidirect_info *pwdinfo, u8 *pframe, uint len) -{ - struct adapter *padapter = pwdinfo->padapter; - u8 result = P2P_STATUS_SUCCESS; - u32 p2p_ielen = 0, wps_ielen = 0; - u8 *ies; - u32 ies_len; - u8 *p2p_ie; - u8 *wpsie; - u16 wps_devicepassword_id = 0x0000; - uint wps_devicepassword_id_len = 0; - __be16 be_tmp; - - wpsie = rtw_get_wps_ie(pframe + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &wps_ielen); - if (wpsie) { - /* Commented by Kurt 20120113 */ - /* If some device wants to do p2p handshake without sending prov_disc_req */ - /* We have to get peer_req_cm from here. */ - if (!memcmp(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "000", 3)) { - rtw_get_wps_attr_content(wpsie, wps_ielen, WPS_ATTR_DEVICE_PWID, (u8 *)&be_tmp, &wps_devicepassword_id_len); - wps_devicepassword_id = be16_to_cpu(be_tmp); - - if (wps_devicepassword_id == WPS_DPID_USER_SPEC) - memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "dis", 3); - else if (wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC) - memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pad", 3); - else - memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pbc", 3); - } - } else { - result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM; - rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL); - return result; - } - - if (pwdinfo->ui_got_wps_info == P2P_NO_WPSINFO) { - result = P2P_STATUS_FAIL_INFO_UNAVAILABLE; - rtw_p2p_set_state(pwdinfo, P2P_STATE_TX_INFOR_NOREADY); - return result; - } - - ies = pframe + _PUBLIC_ACTION_IE_OFFSET_; - ies_len = len - _PUBLIC_ACTION_IE_OFFSET_; - - p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen); - - if (!p2p_ie) { - result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM; - rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL); - } - - while (p2p_ie) { - u8 attr_content = 0x00; - u32 attr_contentlen = 0; - u8 ch_content[50] = { 0x00 }; - uint ch_cnt = 0; - u8 peer_ch_list[50] = { 0x00 }; - u8 peer_ch_num = 0; - u8 ch_list_inclusioned[50] = { 0x00 }; - u8 ch_num_inclusioned = 0; - - rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_ING); - - if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GO_INTENT, &attr_content, &attr_contentlen)) { - pwdinfo->peer_intent = attr_content; /* include both intent and tie breaker values. */ - - if (pwdinfo->intent == (pwdinfo->peer_intent >> 1)) { - /* Try to match the tie breaker value */ - if (pwdinfo->intent == P2P_MAX_INTENT) { - rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE); - result = P2P_STATUS_FAIL_BOTH_GOINTENT_15; - } else { - if (attr_content & 0x01) - rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT); - else - rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO); - } - } else if (pwdinfo->intent > (pwdinfo->peer_intent >> 1)) { - rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO); - } else { - rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT); - } - - if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) { - /* Store the group id information. */ - memcpy(pwdinfo->groupid_info.go_device_addr, pwdinfo->device_addr, ETH_ALEN); - memcpy(pwdinfo->groupid_info.ssid, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen); - } - } - - attr_contentlen = 0; - if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_INTENTED_IF_ADDR, pwdinfo->p2p_peer_interface_addr, &attr_contentlen)) { - if (attr_contentlen != ETH_ALEN) - memset(pwdinfo->p2p_peer_interface_addr, 0x00, ETH_ALEN); - } - - if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, ch_content, &ch_cnt)) { - peer_ch_num = rtw_p2p_get_peer_ch_list(pwdinfo, ch_content, ch_cnt, peer_ch_list); - ch_num_inclusioned = rtw_p2p_ch_inclusion(&padapter->mlmeextpriv, peer_ch_list, peer_ch_num, ch_list_inclusioned); - - if (ch_num_inclusioned == 0) { - result = P2P_STATUS_FAIL_NO_COMMON_CH; - rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL); - break; - } - - if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) { - if (!rtw_p2p_is_channel_list_ok(pwdinfo->operating_channel, - ch_list_inclusioned, ch_num_inclusioned)) { - u8 operatingch_info[5] = { 0x00 }, peer_operating_ch = 0; - attr_contentlen = 0; - - if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen)) - peer_operating_ch = operatingch_info[4]; - - if (rtw_p2p_is_channel_list_ok(peer_operating_ch, - ch_list_inclusioned, - ch_num_inclusioned)) - /** - * Change our operating channel as peer's for compatibility. - */ - pwdinfo->operating_channel = peer_operating_ch; - else - /* Take first channel of ch_list_inclusioned as operating channel */ - pwdinfo->operating_channel = ch_list_inclusioned[0]; - } - } - } - - /* Get the next P2P IE */ - p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen); - } - return result; -} - -u8 process_p2p_group_negotation_resp(struct wifidirect_info *pwdinfo, u8 *pframe, uint len) -{ - struct adapter *padapter = pwdinfo->padapter; - u8 result = P2P_STATUS_SUCCESS; - u32 p2p_ielen, wps_ielen; - u8 *ies; - u32 ies_len; - u8 *p2p_ie; - - ies = pframe + _PUBLIC_ACTION_IE_OFFSET_; - ies_len = len - _PUBLIC_ACTION_IE_OFFSET_; - - /* Be able to know which one is the P2P GO and which one is P2P client. */ - - if (!rtw_get_wps_ie(ies, ies_len, NULL, &wps_ielen)) { - result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM; - rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL); - } - - p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen); - if (!p2p_ie) { - rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE); - rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL); - result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM; - } else { - u8 attr_content = 0x00; - u32 attr_contentlen = 0; - u8 operatingch_info[5] = { 0x00 }; - u8 groupid[38]; - u8 peer_ch_list[50] = { 0x00 }; - u8 peer_ch_num = 0; - u8 ch_list_inclusioned[50] = { 0x00 }; - u8 ch_num_inclusioned = 0; - - while (p2p_ie) { /* Found the P2P IE. */ - rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, &attr_content, &attr_contentlen); - if (attr_contentlen == 1) { - if (attr_content == P2P_STATUS_SUCCESS) { - /* Do nothing. */ - } else { - if (attr_content == P2P_STATUS_FAIL_INFO_UNAVAILABLE) { - rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INFOR_NOREADY); - } else { - rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL); - } - rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE); - result = attr_content; - break; - } - } - - /* Try to get the peer's interface address */ - attr_contentlen = 0; - if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_INTENTED_IF_ADDR, pwdinfo->p2p_peer_interface_addr, &attr_contentlen)) { - if (attr_contentlen != ETH_ALEN) - memset(pwdinfo->p2p_peer_interface_addr, 0x00, ETH_ALEN); - } - - /* Try to get the peer's intent and tie breaker value. */ - attr_content = 0x00; - attr_contentlen = 0; - if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GO_INTENT, &attr_content, &attr_contentlen)) { - pwdinfo->peer_intent = attr_content; /* include both intent and tie breaker values. */ - - if (pwdinfo->intent == (pwdinfo->peer_intent >> 1)) { - /* Try to match the tie breaker value */ - if (pwdinfo->intent == P2P_MAX_INTENT) { - rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE); - result = P2P_STATUS_FAIL_BOTH_GOINTENT_15; - rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL); - } else { - rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK); - rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK); - if (attr_content & 0x01) - rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT); - else - rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO); - } - } else if (pwdinfo->intent > (pwdinfo->peer_intent >> 1)) { - rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK); - rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK); - rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO); - } else { - rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK); - rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK); - rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT); - } - - if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) { - /* Store the group id information. */ - memcpy(pwdinfo->groupid_info.go_device_addr, pwdinfo->device_addr, ETH_ALEN); - memcpy(pwdinfo->groupid_info.ssid, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen); - } - } - - /* Try to get the operation channel information */ - - attr_contentlen = 0; - if (rtw_get_p2p_attr_content(p2p_ie, - p2p_ielen, - P2P_ATTR_OPERATING_CH, - operatingch_info, - &attr_contentlen)) - pwdinfo->peer_operating_ch = operatingch_info[4]; - - /* Try to get the channel list information */ - if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, pwdinfo->channel_list_attr, &pwdinfo->channel_list_attr_len)) { - - peer_ch_num = rtw_p2p_get_peer_ch_list(pwdinfo, pwdinfo->channel_list_attr, pwdinfo->channel_list_attr_len, peer_ch_list); - ch_num_inclusioned = rtw_p2p_ch_inclusion(&padapter->mlmeextpriv, peer_ch_list, peer_ch_num, ch_list_inclusioned); - - if (ch_num_inclusioned == 0) { - result = P2P_STATUS_FAIL_NO_COMMON_CH; - rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL); - break; - } - - if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) { - if (!rtw_p2p_is_channel_list_ok(pwdinfo->operating_channel, - ch_list_inclusioned, ch_num_inclusioned)) { - u8 operatingch_info[5] = { 0x00 }, peer_operating_ch = 0; - attr_contentlen = 0; - - if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen)) - peer_operating_ch = operatingch_info[4]; - - if (rtw_p2p_is_channel_list_ok(peer_operating_ch, - ch_list_inclusioned, ch_num_inclusioned)) - /** - * Change our operating channel as peer's for compatibility. - */ - pwdinfo->operating_channel = peer_operating_ch; - else - /* Take first channel of ch_list_inclusioned as operating channel */ - pwdinfo->operating_channel = ch_list_inclusioned[0]; - } - } - } - - /* Try to get the group id information if peer is GO */ - attr_contentlen = 0; - memset(groupid, 0x00, 38); - if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, groupid, &attr_contentlen)) { - memcpy(pwdinfo->groupid_info.go_device_addr, &groupid[0], ETH_ALEN); - memcpy(pwdinfo->groupid_info.ssid, &groupid[6], attr_contentlen - ETH_ALEN); - } - - /* Get the next P2P IE */ - p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen); - } - } - return result; -} - -u8 process_p2p_group_negotation_confirm(struct wifidirect_info *pwdinfo, u8 *pframe, uint len) -{ - u8 *ies; - u32 ies_len; - u8 *p2p_ie; - u32 p2p_ielen = 0; - u8 result = P2P_STATUS_SUCCESS; - ies = pframe + _PUBLIC_ACTION_IE_OFFSET_; - ies_len = len - _PUBLIC_ACTION_IE_OFFSET_; - - p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen); - while (p2p_ie) { /* Found the P2P IE. */ - u8 attr_content = 0x00, operatingch_info[5] = { 0x00 }; - u8 groupid[38] = { 0x00 }; - u32 attr_contentlen = 0; - - pwdinfo->negotiation_dialog_token = 1; - rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, &attr_content, &attr_contentlen); - if (attr_contentlen == 1) { - result = attr_content; - - if (attr_content == P2P_STATUS_SUCCESS) { - del_timer_sync(&pwdinfo->restore_p2p_state_timer); - - /* Commented by Albert 20100911 */ - /* Todo: Need to handle the case which both Intents are the same. */ - rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK); - rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK); - if ((pwdinfo->intent) > (pwdinfo->peer_intent >> 1)) { - rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO); - } else if ((pwdinfo->intent) < (pwdinfo->peer_intent >> 1)) { - rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT); - } else { - /* Have to compare the Tie Breaker */ - if (pwdinfo->peer_intent & 0x01) - rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT); - else - rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO); - } - } else { - rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE); - rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL); - break; - } - } - - /* Try to get the group id information */ - attr_contentlen = 0; - memset(groupid, 0x00, 38); - if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, groupid, &attr_contentlen)) { - memcpy(pwdinfo->groupid_info.go_device_addr, &groupid[0], ETH_ALEN); - memcpy(pwdinfo->groupid_info.ssid, &groupid[6], attr_contentlen - ETH_ALEN); - } - - attr_contentlen = 0; - if (rtw_get_p2p_attr_content(p2p_ie, - p2p_ielen, - P2P_ATTR_OPERATING_CH, - operatingch_info, - &attr_contentlen)) - pwdinfo->peer_operating_ch = operatingch_info[4]; - - /* Get the next P2P IE */ - p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen); - } - return result; -} - -u8 process_p2p_presence_req(struct wifidirect_info *pwdinfo, u8 *pframe, uint len) -{ - u8 *frame_body; - u8 dialogToken = 0; - u8 status = P2P_STATUS_SUCCESS; - - frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr)); - - dialogToken = frame_body[6]; - - /* todo: check NoA attribute */ - - issue_p2p_presence_resp(pwdinfo, GetAddr2Ptr(pframe), status, dialogToken); - - return true; -} - -static void find_phase_handler(struct adapter *padapter) -{ - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct ndis_802_11_ssid ssid; - - memset((unsigned char *)&ssid, 0, sizeof(struct ndis_802_11_ssid)); - memcpy(ssid.Ssid, pwdinfo->p2p_wildcard_ssid, P2P_WILDCARD_SSID_LEN); - ssid.SsidLength = P2P_WILDCARD_SSID_LEN; - - rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH); - - spin_lock_bh(&pmlmepriv->lock); - spin_unlock_bh(&pmlmepriv->lock); - -} - -void p2p_concurrent_handler(struct adapter *padapter); - -static void restore_p2p_state_handler(struct adapter *padapter) -{ - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - - if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL)) - rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE); - rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo)); - - if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE)) { - /* In the P2P client mode, the driver should not switch back to its listen channel */ - /* because this P2P client should stay at the operating channel of P2P GO. */ - set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20); - } - -} - -static void pre_tx_invitereq_handler(struct adapter *padapter) -{ - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - - set_channel_bwmode(padapter, pwdinfo->invitereq_info.peer_ch, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20); - rtw_mlme_under_site_survey(padapter); - issue_probereq_p2p(padapter); - _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT); - -} - -static void pre_tx_provdisc_handler(struct adapter *padapter) -{ - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - - set_channel_bwmode(padapter, pwdinfo->tx_prov_disc_info.peer_channel_num[0], HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20); - rtw_mlme_under_site_survey(padapter); - issue_probereq_p2p(padapter); - _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT); - -} - -static void pre_tx_negoreq_handler(struct adapter *padapter) -{ - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - - set_channel_bwmode(padapter, pwdinfo->nego_req_info.peer_channel_num[0], HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20); - rtw_mlme_under_site_survey(padapter); - issue_probereq_p2p(padapter); - _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT); - -} - -void p2p_protocol_wk_hdl(struct adapter *padapter, int intCmdType) -{ - - switch (intCmdType) { - case P2P_FIND_PHASE_WK: - find_phase_handler(padapter); - break; - case P2P_RESTORE_STATE_WK: - restore_p2p_state_handler(padapter); - break; - case P2P_PRE_TX_PROVDISC_PROCESS_WK: - pre_tx_provdisc_handler(padapter); - break; - case P2P_PRE_TX_INVITEREQ_PROCESS_WK: - pre_tx_invitereq_handler(padapter); - break; - case P2P_PRE_TX_NEGOREQ_PROCESS_WK: - pre_tx_negoreq_handler(padapter); - break; - } - -} - -void process_p2p_ps_ie(struct adapter *padapter, u8 *IEs, u32 IELength) -{ - u8 *p2p_ie; - u32 p2p_ielen = 0; - u8 noa_attr[MAX_P2P_IE_LEN] = { 0x00 };/* NoA length should be n*(13) + 2 */ - u32 attr_contentlen = 0; - - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - u8 find_p2p = false, find_p2p_ps = false; - u8 noa_offset, noa_num, noa_index; - - if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) - return; - - p2p_ie = rtw_get_p2p_ie(IEs, IELength, NULL, &p2p_ielen); - - while (p2p_ie) { - find_p2p = true; - /* Get Notice of Absence IE. */ - if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_NOA, noa_attr, &attr_contentlen)) { - find_p2p_ps = true; - noa_index = noa_attr[0]; - - if ((pwdinfo->p2p_ps_mode == P2P_PS_NONE) || - (noa_index != pwdinfo->noa_index)) { /* if index change, driver should reconfigure related setting. */ - pwdinfo->noa_index = noa_index; - pwdinfo->opp_ps = noa_attr[1] >> 7; - pwdinfo->ctwindow = noa_attr[1] & 0x7F; - - noa_offset = 2; - noa_num = 0; - /* NoA length should be n*(13) + 2 */ - if (attr_contentlen > 2) { - while (noa_offset < attr_contentlen) { - /* memcpy(&wifidirect_info->noa_count[noa_num], &noa_attr[noa_offset], 1); */ - pwdinfo->noa_count[noa_num] = noa_attr[noa_offset]; - noa_offset += 1; - - memcpy(&pwdinfo->noa_duration[noa_num], &noa_attr[noa_offset], 4); - noa_offset += 4; - - memcpy(&pwdinfo->noa_interval[noa_num], &noa_attr[noa_offset], 4); - noa_offset += 4; - - memcpy(&pwdinfo->noa_start_time[noa_num], &noa_attr[noa_offset], 4); - noa_offset += 4; - - noa_num++; - } - } - pwdinfo->noa_num = noa_num; - - if (pwdinfo->opp_ps == 1) { - pwdinfo->p2p_ps_mode = P2P_PS_CTWINDOW; - /* driver should wait LPS for entering CTWindow */ - if (padapter->pwrctrlpriv.bFwCurrentInPSMode) - p2p_ps_wk_cmd(padapter, P2P_PS_ENABLE, 1); - } else if (pwdinfo->noa_num > 0) { - pwdinfo->p2p_ps_mode = P2P_PS_NOA; - p2p_ps_wk_cmd(padapter, P2P_PS_ENABLE, 1); - } else if (pwdinfo->p2p_ps_mode > P2P_PS_NONE) { - p2p_ps_wk_cmd(padapter, P2P_PS_DISABLE, 1); - } - } - - break; /* find target, just break. */ - } - - /* Get the next P2P IE */ - p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, IELength - (p2p_ie - IEs + p2p_ielen), NULL, &p2p_ielen); - } - - if (find_p2p) { - if ((pwdinfo->p2p_ps_mode > P2P_PS_NONE) && !find_p2p_ps) - p2p_ps_wk_cmd(padapter, P2P_PS_DISABLE, 1); - } - -} - -void p2p_ps_wk_hdl(struct adapter *padapter, u8 p2p_ps_state) -{ - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - - /* Pre action for p2p state */ - switch (p2p_ps_state) { - case P2P_PS_DISABLE: - pwdinfo->p2p_ps_state = p2p_ps_state; - - rtl8188e_set_p2p_ps_offload_cmd(padapter, p2p_ps_state); - - pwdinfo->noa_index = 0; - pwdinfo->ctwindow = 0; - pwdinfo->opp_ps = 0; - pwdinfo->noa_num = 0; - pwdinfo->p2p_ps_mode = P2P_PS_NONE; - if (padapter->pwrctrlpriv.bFwCurrentInPSMode) { - if (pwrpriv->smart_ps == 0) { - pwrpriv->smart_ps = 2; - rtw_set_firmware_ps_mode(padapter, pwrpriv->pwr_mode); - } - } - break; - case P2P_PS_ENABLE: - if (pwdinfo->p2p_ps_mode > P2P_PS_NONE) { - pwdinfo->p2p_ps_state = p2p_ps_state; - - if (pwdinfo->ctwindow > 0) { - if (pwrpriv->smart_ps != 0) { - pwrpriv->smart_ps = 0; - rtw_set_firmware_ps_mode(padapter, pwrpriv->pwr_mode); - } - } - rtl8188e_set_p2p_ps_offload_cmd(padapter, p2p_ps_state); - } - break; - case P2P_PS_SCAN: - case P2P_PS_SCAN_DONE: - case P2P_PS_ALLSTASLEEP: - if (pwdinfo->p2p_ps_mode > P2P_PS_NONE) { - pwdinfo->p2p_ps_state = p2p_ps_state; - rtl8188e_set_p2p_ps_offload_cmd(padapter, p2p_ps_state); - } - break; - default: - break; - } - -} - -u8 p2p_ps_wk_cmd(struct adapter *padapter, u8 p2p_ps_state, u8 enqueue) -{ - struct cmd_obj *ph2c; - struct drvextra_cmd_parm *pdrvextra_cmd_parm; - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - u8 res = _SUCCESS; - - if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) - return res; - - if (enqueue) { - ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (!ph2c) { - res = _FAIL; - goto exit; - } - - pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_ATOMIC); - if (!pdrvextra_cmd_parm) { - kfree(ph2c); - res = _FAIL; - goto exit; - } - - pdrvextra_cmd_parm->ec_id = P2P_PS_WK_CID; - pdrvextra_cmd_parm->type_size = p2p_ps_state; - pdrvextra_cmd_parm->pbuf = NULL; - - init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); - - res = rtw_enqueue_cmd(pcmdpriv, ph2c); - } else { - p2p_ps_wk_hdl(padapter, p2p_ps_state); - } - -exit: - - return res; -} - -static void reset_ch_sitesurvey_timer_process(struct timer_list *t) -{ - struct adapter *adapter = from_timer(adapter, t, pwrctrlpriv.pwr_state_check_timer); - struct wifidirect_info *pwdinfo = &adapter->wdinfo; - - if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) - return; - - /* Reset the operation channel information */ - pwdinfo->rx_invitereq_info.operation_ch[0] = 0; - pwdinfo->rx_invitereq_info.scan_op_ch_only = 0; -} - -static void reset_ch_sitesurvey_timer_process2(struct timer_list *t) -{ - struct adapter *adapter = from_timer(adapter, t, pwrctrlpriv.pwr_state_check_timer); - struct wifidirect_info *pwdinfo = &adapter->wdinfo; - - if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) - return; - - /* Reset the operation channel information */ - pwdinfo->p2p_info.operation_ch[0] = 0; - pwdinfo->p2p_info.scan_op_ch_only = 0; -} - -static void restore_p2p_state_timer_process(struct timer_list *t) -{ - struct adapter *adapter = from_timer(adapter, t, wdinfo.restore_p2p_state_timer); - struct wifidirect_info *pwdinfo = &adapter->wdinfo; - - if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) - return; - - p2p_protocol_wk_cmd(adapter, P2P_RESTORE_STATE_WK); -} - -static void pre_tx_scan_timer_process(struct timer_list *t) -{ - struct adapter *adapter = from_timer(adapter, t, wdinfo.pre_tx_scan_timer); - struct wifidirect_info *pwdinfo = &adapter->wdinfo; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - - if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) - return; - - spin_lock_bh(&pmlmepriv->lock); - - if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ)) { - if (pwdinfo->tx_prov_disc_info.benable) { /* the provision discovery request frame is trigger to send or not */ - p2p_protocol_wk_cmd(adapter, P2P_PRE_TX_PROVDISC_PROCESS_WK); - /* issue_probereq_p2p(adapter); */ - /* _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT); */ - } - } else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING)) { - if (pwdinfo->nego_req_info.benable) - p2p_protocol_wk_cmd(adapter, P2P_PRE_TX_NEGOREQ_PROCESS_WK); - } else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_INVITE_REQ)) { - if (pwdinfo->invitereq_info.benable) - p2p_protocol_wk_cmd(adapter, P2P_PRE_TX_INVITEREQ_PROCESS_WK); - } - - spin_unlock_bh(&pmlmepriv->lock); -} - -static void find_phase_timer_process(struct timer_list *t) -{ - struct adapter *adapter = from_timer(adapter, t, wdinfo.find_phase_timer); - struct wifidirect_info *pwdinfo = &adapter->wdinfo; - - if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) - return; - - adapter->wdinfo.find_phase_state_exchange_cnt++; - - p2p_protocol_wk_cmd(adapter, P2P_FIND_PHASE_WK); -} - -void reset_global_wifidirect_info(struct adapter *padapter) -{ - struct wifidirect_info *pwdinfo; - - pwdinfo = &padapter->wdinfo; - pwdinfo->persistent_supported = 0; - pwdinfo->session_available = true; -} - -void rtw_init_wifidirect_timers(struct adapter *padapter) -{ - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - - timer_setup(&pwdinfo->find_phase_timer, find_phase_timer_process, 0); - timer_setup(&pwdinfo->restore_p2p_state_timer, restore_p2p_state_timer_process, 0); - timer_setup(&pwdinfo->pre_tx_scan_timer, pre_tx_scan_timer_process, 0); - timer_setup(&pwdinfo->reset_ch_sitesurvey, reset_ch_sitesurvey_timer_process, 0); - timer_setup(&pwdinfo->reset_ch_sitesurvey2, reset_ch_sitesurvey_timer_process2, 0); -} - -void rtw_init_wifidirect_addrs(struct adapter *padapter, u8 *dev_addr, u8 *iface_addr) -{ - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - - /*init device&interface address */ - if (dev_addr) - memcpy(pwdinfo->device_addr, dev_addr, ETH_ALEN); - if (iface_addr) - memcpy(pwdinfo->interface_addr, iface_addr, ETH_ALEN); -} - -void init_wifidirect_info(struct adapter *padapter, enum P2P_ROLE role) -{ - struct wifidirect_info *pwdinfo; - - pwdinfo = &padapter->wdinfo; - pwdinfo->padapter = padapter; - - /* 1, 6, 11 are the social channel defined in the WiFi Direct specification. */ - pwdinfo->social_chan[0] = 1; - pwdinfo->social_chan[1] = 6; - pwdinfo->social_chan[2] = 11; - pwdinfo->social_chan[3] = 0; /* channel 0 for scanning ending in site survey function. */ - - /* Use the channel 11 as the listen channel */ - pwdinfo->listen_channel = 11; - - if (role == P2P_ROLE_DEVICE) { - rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE); - rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN); - pwdinfo->intent = 1; - rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_LISTEN); - } else if (role == P2P_ROLE_CLIENT) { - rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT); - rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK); - pwdinfo->intent = 1; - rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK); - } else if (role == P2P_ROLE_GO) { - rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO); - rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK); - pwdinfo->intent = 15; - rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK); - } - -/* Use the OFDM rate in the P2P probe response frame. (6(B), 9(B), 12, 18, 24, 36, 48, 54) */ - pwdinfo->support_rate[0] = 0x8c; /* 6(B) */ - pwdinfo->support_rate[1] = 0x92; /* 9(B) */ - pwdinfo->support_rate[2] = 0x18; /* 12 */ - pwdinfo->support_rate[3] = 0x24; /* 18 */ - pwdinfo->support_rate[4] = 0x30; /* 24 */ - pwdinfo->support_rate[5] = 0x48; /* 36 */ - pwdinfo->support_rate[6] = 0x60; /* 48 */ - pwdinfo->support_rate[7] = 0x6c; /* 54 */ - - memcpy(pwdinfo->p2p_wildcard_ssid, "DIRECT-", 7); - - memset(pwdinfo->device_name, 0x00, WPS_MAX_DEVICE_NAME_LEN); - pwdinfo->device_name_len = 0; - - memset(&pwdinfo->invitereq_info, 0x00, sizeof(struct tx_invite_req_info)); - pwdinfo->invitereq_info.token = 3; /* Token used for P2P invitation request frame. */ - - memset(&pwdinfo->inviteresp_info, 0x00, sizeof(struct tx_invite_resp_info)); - pwdinfo->inviteresp_info.token = 0; - - pwdinfo->profileindex = 0; - memset(&pwdinfo->profileinfo[0], 0x00, sizeof(struct profile_info) * P2P_MAX_PERSISTENT_GROUP_NUM); - - rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_NONE); - - pwdinfo->listen_dwell = (u8)((jiffies % 3) + 1); - - memset(&pwdinfo->tx_prov_disc_info, 0x00, sizeof(struct tx_provdisc_req_info)); - pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_NONE; - - memset(&pwdinfo->nego_req_info, 0x00, sizeof(struct tx_nego_req_info)); - - pwdinfo->device_password_id_for_nego = WPS_DPID_PBC; - pwdinfo->negotiation_dialog_token = 1; - - memset(pwdinfo->nego_ssid, 0x00, WLAN_SSID_MAXLEN); - pwdinfo->nego_ssidlen = 0; - - pwdinfo->ui_got_wps_info = P2P_NO_WPSINFO; - pwdinfo->supported_wps_cm = WPS_CONFIG_METHOD_DISPLAY | WPS_CONFIG_METHOD_PBC | WPS_CONFIG_METHOD_KEYPAD; - pwdinfo->channel_list_attr_len = 0; - memset(pwdinfo->channel_list_attr, 0x00, 100); - - memset(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, 0x00, 4); - memset(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, '0', 3); - memset(&pwdinfo->groupid_info, 0x00, sizeof(struct group_id_info)); - memset(pwdinfo->p2p_peer_interface_addr, 0x00, ETH_ALEN); - memset(pwdinfo->p2p_peer_device_addr, 0x00, ETH_ALEN); - - pwdinfo->rx_invitereq_info.operation_ch[0] = 0; - pwdinfo->rx_invitereq_info.operation_ch[1] = 0; /* Used to indicate the scan end in site survey function */ - pwdinfo->rx_invitereq_info.scan_op_ch_only = 0; - pwdinfo->p2p_info.operation_ch[0] = 0; - pwdinfo->p2p_info.operation_ch[1] = 0; /* Used to indicate the scan end in site survey function */ - pwdinfo->p2p_info.scan_op_ch_only = 0; -} - -int rtw_p2p_enable(struct adapter *padapter, enum P2P_ROLE role) -{ - int ret; - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - - if (role == P2P_ROLE_DEVICE || role == P2P_ROLE_CLIENT || role == P2P_ROLE_GO) { - /* leave IPS/Autosuspend */ - ret = rtw_pwr_wakeup(padapter); - if (ret) - return ret; - - /* Added by Albert 2011/03/22 */ - /* In the P2P mode, the driver should not support the b mode. */ - /* So, the Tx packet shouldn't use the CCK rate */ - update_tx_basic_rate(padapter, (WIRELESS_11G | WIRELESS_11_24N)); - - /* Enable P2P function */ - init_wifidirect_info(padapter, role); - - } else if (role == P2P_ROLE_DISABLE) { - ret = rtw_pwr_wakeup(padapter); - if (ret) - return ret; - - /* Disable P2P function */ - if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) { - _cancel_timer_ex(&pwdinfo->find_phase_timer); - _cancel_timer_ex(&pwdinfo->restore_p2p_state_timer); - _cancel_timer_ex(&pwdinfo->pre_tx_scan_timer); - _cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey); - _cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey2); - rtw_p2p_set_state(pwdinfo, P2P_STATE_NONE); - rtw_p2p_set_role(pwdinfo, P2P_ROLE_DISABLE); - memset(&pwdinfo->rx_prov_disc_info, 0x00, sizeof(struct rx_provdisc_req_info)); - } - - /* Restore to initial setting. */ - update_tx_basic_rate(padapter, padapter->registrypriv.wireless_mode); - } - - return 0; -} diff --git a/drivers/staging/r8188eu/core/rtw_pwrctrl.c b/drivers/staging/r8188eu/core/rtw_pwrctrl.c deleted file mode 100644 index 051cdcb11ff5..000000000000 --- a/drivers/staging/r8188eu/core/rtw_pwrctrl.c +++ /dev/null @@ -1,445 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2007 - 2012 Realtek Corporation. */ - -#define _RTW_PWRCTRL_C_ - -#include "../include/osdep_service.h" -#include "../include/drv_types.h" -#include "../include/osdep_intf.h" -#include "../include/linux/usb.h" - -static void ips_enter(struct adapter *padapter) -{ - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - struct xmit_priv *pxmit_priv = &padapter->xmitpriv; - - if (pxmit_priv->free_xmitbuf_cnt != NR_XMITBUFF || - pxmit_priv->free_xmit_extbuf_cnt != NR_XMIT_EXTBUFF) - return; - - mutex_lock(&pwrpriv->lock); - - pwrpriv->bips_processing = true; - - /* syn ips_mode with request */ - pwrpriv->ips_mode = pwrpriv->ips_mode_req; - - pwrpriv->ips_enter_cnts++; - pwrpriv->bpower_saving = true; - - if (pwrpriv->ips_mode == IPS_LEVEL_2) - pwrpriv->bkeepfwalive = true; - - rtw_ips_pwr_down(padapter); - pwrpriv->rf_pwrstate = rf_off; - - pwrpriv->bips_processing = false; - - mutex_unlock(&pwrpriv->lock); -} - -static int ips_leave(struct adapter *padapter) -{ - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - int result = _SUCCESS; - int keyid; - - mutex_lock(&pwrpriv->lock); - - if ((pwrpriv->rf_pwrstate == rf_off) && (!pwrpriv->bips_processing)) { - pwrpriv->bips_processing = true; - pwrpriv->ips_leave_cnts++; - - result = rtw_ips_pwr_up(padapter); - if (result == _SUCCESS) { - pwrpriv->rf_pwrstate = rf_on; - } - - if ((psecuritypriv->dot11PrivacyAlgrthm == _WEP40_) || (psecuritypriv->dot11PrivacyAlgrthm == _WEP104_)) { - set_channel_bwmode(padapter, padapter->mlmeextpriv.cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20); - for (keyid = 0; keyid < 4; keyid++) { - if (pmlmepriv->key_mask & BIT(keyid)) { - if (keyid == psecuritypriv->dot11PrivacyKeyIndex) - result = rtw_set_key(padapter, psecuritypriv, keyid, 1); - else - result = rtw_set_key(padapter, psecuritypriv, keyid, 0); - } - } - } - - pwrpriv->bips_processing = false; - - pwrpriv->bkeepfwalive = false; - pwrpriv->bpower_saving = false; - } - - mutex_unlock(&pwrpriv->lock); - - return result; -} - -static bool rtw_pwr_unassociated_idle(struct adapter *adapter) -{ - struct adapter *buddy = adapter->pbuddy_adapter; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - struct wifidirect_info *pwdinfo = &adapter->wdinfo; - bool ret = false; - - if (time_after_eq(adapter->pwrctrlpriv.ips_deny_time, jiffies)) - goto exit; - - if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE | WIFI_SITE_MONITOR) || - check_fwstate(pmlmepriv, WIFI_UNDER_LINKING | WIFI_UNDER_WPS) || - check_fwstate(pmlmepriv, WIFI_UNDER_WPS) || - check_fwstate(pmlmepriv, WIFI_AP_STATE) || - check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE | WIFI_ADHOC_STATE) || - !rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) - goto exit; - - /* consider buddy, if exist */ - if (buddy) { - struct mlme_priv *b_pmlmepriv = &buddy->mlmepriv; - struct wifidirect_info *b_pwdinfo = &buddy->wdinfo; - - if (check_fwstate(b_pmlmepriv, WIFI_ASOC_STATE | WIFI_SITE_MONITOR) || - check_fwstate(b_pmlmepriv, WIFI_UNDER_LINKING | WIFI_UNDER_WPS) || - check_fwstate(b_pmlmepriv, WIFI_AP_STATE) || - check_fwstate(b_pmlmepriv, WIFI_ADHOC_MASTER_STATE | WIFI_ADHOC_STATE) || - !rtw_p2p_chk_state(b_pwdinfo, P2P_STATE_NONE)) - goto exit; - } - ret = true; - -exit: - return ret; -} - -void rtw_ps_processor(struct adapter *padapter) -{ - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - - pwrpriv->ps_processing = true; - - if (pwrpriv->bips_processing) - goto exit; - - if (pwrpriv->ips_mode_req == IPS_NONE) - goto exit; - - if (!rtw_pwr_unassociated_idle(padapter)) - goto exit; - - if (pwrpriv->rf_pwrstate == rf_on) - ips_enter(padapter); - -exit: - rtw_set_pwr_state_check_timer(&padapter->pwrctrlpriv); - pwrpriv->ps_processing = false; -} - -static void pwr_state_check_handler(struct timer_list *t) -{ - struct adapter *padapter = - from_timer(padapter, t, - pwrctrlpriv.pwr_state_check_timer); - rtw_ps_cmd(padapter); -} - -static bool PS_RDY_CHECK(struct adapter *padapter) -{ - u32 curr_time, delta_time; - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - curr_time = jiffies; - delta_time = curr_time - pwrpriv->DelayLPSLastTimeStamp; - - if (delta_time < LPS_DELAY_TIME) - return false; - - if (!check_fwstate(pmlmepriv, _FW_LINKED) || - check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) || - check_fwstate(pmlmepriv, WIFI_AP_STATE) || - check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) || - check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) - return false; - if (pwrpriv->bInSuspend) - return false; - if (padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X && - !padapter->securitypriv.binstallGrpkey) - return false; - return true; -} - -void rtw_set_firmware_ps_mode(struct adapter *adapter, u8 mode) -{ - struct hal_data_8188e *haldata = &adapter->haldata; - struct odm_dm_struct *odmpriv = &haldata->odmpriv; - - /* Force leave RF low power mode for 1T1R to prevent - * conflicting setting in firmware power saving sequence. - */ - if (mode != PS_MODE_ACTIVE) - ODM_RF_Saving(odmpriv, true); - rtl8188e_set_FwPwrMode_cmd(adapter, mode); -} - -void rtw_set_ps_mode(struct adapter *padapter, u8 ps_mode, u8 smart_ps, u8 bcn_ant_mode) -{ - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - - if (ps_mode > PM_Card_Disable) - return; - - if (pwrpriv->pwr_mode == ps_mode) { - if (ps_mode == PS_MODE_ACTIVE) - return; - - if ((pwrpriv->smart_ps == smart_ps) && - (pwrpriv->bcn_ant_mode == bcn_ant_mode)) - return; - } - - if (ps_mode == PS_MODE_ACTIVE) { - if (pwdinfo->opp_ps == 0) { - pwrpriv->pwr_mode = ps_mode; - rtw_set_firmware_ps_mode(padapter, ps_mode); - pwrpriv->bFwCurrentInPSMode = false; - } - } else { - if (PS_RDY_CHECK(padapter)) { - pwrpriv->bFwCurrentInPSMode = true; - pwrpriv->pwr_mode = ps_mode; - pwrpriv->smart_ps = smart_ps; - pwrpriv->bcn_ant_mode = bcn_ant_mode; - rtw_set_firmware_ps_mode(padapter, ps_mode); - - /* Set CTWindow after LPS */ - if (pwdinfo->opp_ps == 1) - p2p_ps_wk_cmd(padapter, P2P_PS_ENABLE, 0); - } - } -} - -static bool lps_rf_on(struct adapter *adapter) -{ - int res; - u32 reg; - - /* When we halt NIC, we should check if FW LPS is leave. */ - if (adapter->pwrctrlpriv.rf_pwrstate == rf_off) { - /* If it is in HW/SW Radio OFF or IPS state, we do not check Fw LPS Leave, */ - /* because Fw is unload. */ - return true; - } - - res = rtw_read32(adapter, REG_RCR, ®); - if (res) - return false; - - if (reg & 0x00070000) - return false; - - return true; -} - -/* - * Return: - * 0: Leave OK - * -1: Timeout - * -2: Other error - */ -static s32 LPS_RF_ON_check(struct adapter *padapter, u32 delay_ms) -{ - unsigned long timeout = jiffies + msecs_to_jiffies(delay_ms); - s32 err = 0; - - while (1) { - if (lps_rf_on(padapter)) - break; - - if (padapter->bSurpriseRemoved) { - err = -2; - break; - } - - if (time_after(jiffies, timeout)) { - err = -1; - break; - } - mdelay(1); - } - - return err; -} - -/* */ -/* Description: */ -/* Enter the leisure power save mode. */ -/* */ -void LPS_Enter(struct adapter *padapter) -{ - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - - if (!PS_RDY_CHECK(padapter)) - return; - - if (pwrpriv->bLeisurePs) { - /* Idle for a while if we connect to AP a while ago. */ - if (pwrpriv->LpsIdleCount >= 2) { /* 4 Sec */ - if (pwrpriv->pwr_mode == PS_MODE_ACTIVE) { - pwrpriv->bpower_saving = true; - /* For Tenda W311R IOT issue */ - rtw_set_ps_mode(padapter, pwrpriv->power_mgnt, - pwrpriv->smart_ps, 0x40); - } - } else { - pwrpriv->LpsIdleCount++; - } - } - -} - -#define LPS_LEAVE_TIMEOUT_MS 100 - -/* Description: */ -/* Leave the leisure power save mode. */ -void LPS_Leave(struct adapter *padapter) -{ - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - - if (pwrpriv->bLeisurePs) { - if (pwrpriv->pwr_mode != PS_MODE_ACTIVE) { - rtw_set_ps_mode(padapter, PS_MODE_ACTIVE, 0, 0x40); - - if (pwrpriv->pwr_mode == PS_MODE_ACTIVE) - LPS_RF_ON_check(padapter, LPS_LEAVE_TIMEOUT_MS); - } - } - - pwrpriv->bpower_saving = false; - -} - -/* */ -/* Description: Leave all power save mode: LPS, FwLPS, IPS if needed. */ -/* Move code to function by tynli. 2010.03.26. */ -/* */ -void LeaveAllPowerSaveMode(struct adapter *Adapter) -{ - struct mlme_priv *pmlmepriv = &Adapter->mlmepriv; - u8 enqueue = 0; - - if (check_fwstate(pmlmepriv, _FW_LINKED)) { /* connect */ - p2p_ps_wk_cmd(Adapter, P2P_PS_DISABLE, enqueue); - - rtw_lps_ctrl_wk_cmd(Adapter, LPS_CTRL_LEAVE, enqueue); - } - -} - -void rtw_init_pwrctrl_priv(struct adapter *padapter) -{ - struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv; - - mutex_init(&pwrctrlpriv->lock); - pwrctrlpriv->rf_pwrstate = rf_on; - pwrctrlpriv->ips_enter_cnts = 0; - pwrctrlpriv->ips_leave_cnts = 0; - pwrctrlpriv->bips_processing = false; - - pwrctrlpriv->ips_mode = padapter->registrypriv.ips_mode; - pwrctrlpriv->ips_mode_req = padapter->registrypriv.ips_mode; - - pwrctrlpriv->pwr_state_check_interval = RTW_PWR_STATE_CHK_INTERVAL; - pwrctrlpriv->bInSuspend = false; - pwrctrlpriv->bkeepfwalive = false; - - pwrctrlpriv->LpsIdleCount = 0; - pwrctrlpriv->power_mgnt = padapter->registrypriv.power_mgnt;/* PS_MODE_MIN; */ - pwrctrlpriv->bLeisurePs = pwrctrlpriv->power_mgnt != PS_MODE_ACTIVE; - - pwrctrlpriv->bFwCurrentInPSMode = false; - - pwrctrlpriv->pwr_mode = PS_MODE_ACTIVE; - pwrctrlpriv->smart_ps = padapter->registrypriv.smart_ps; - pwrctrlpriv->bcn_ant_mode = 0; - - timer_setup(&pwrctrlpriv->pwr_state_check_timer, pwr_state_check_handler, 0); -} - -/* Wake the NIC up from: 1)IPS 2)USB autosuspend */ -int rtw_pwr_wakeup(struct adapter *padapter) -{ - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - unsigned long timeout = jiffies + msecs_to_jiffies(3000); - unsigned long deny_time; - int ret; - - while (pwrpriv->ps_processing && time_before(jiffies, timeout)) - msleep(10); - - /* I think this should be check in IPS, LPS, autosuspend functions... */ - /* Below goto is a success path taken for already linked devices */ - ret = 0; - if (check_fwstate(pmlmepriv, _FW_LINKED)) - goto exit; - - if (pwrpriv->rf_pwrstate == rf_off && ips_leave(padapter) == _FAIL) { - ret = -ENOMEM; - goto exit; - } - - if (padapter->bDriverStopped || !padapter->bup || !padapter->hw_init_completed) { - ret = -EBUSY; - goto exit; - } - -exit: - deny_time = jiffies + msecs_to_jiffies(RTW_PWR_STATE_CHK_INTERVAL); - if (time_before(pwrpriv->ips_deny_time, deny_time)) - pwrpriv->ips_deny_time = deny_time; - return ret; -} - -int rtw_pm_set_lps(struct adapter *padapter, u8 mode) -{ - int ret = 0; - struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv; - - if (mode < PS_MODE_NUM) { - if (pwrctrlpriv->power_mgnt != mode) { - if (mode == PS_MODE_ACTIVE) - LeaveAllPowerSaveMode(padapter); - else - pwrctrlpriv->LpsIdleCount = 2; - pwrctrlpriv->power_mgnt = mode; - pwrctrlpriv->bLeisurePs = pwrctrlpriv->power_mgnt != PS_MODE_ACTIVE; - } - } else { - ret = -EINVAL; - } - - return ret; -} - -int rtw_pm_set_ips(struct adapter *padapter, u8 mode) -{ - struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv; - - if (mode == IPS_NORMAL || mode == IPS_LEVEL_2) { - rtw_ips_mode_req(pwrctrlpriv, mode); - return 0; - } else if (mode == IPS_NONE) { - rtw_ips_mode_req(pwrctrlpriv, mode); - if ((padapter->bSurpriseRemoved == 0) && rtw_pwr_wakeup(padapter)) - return -EFAULT; - } else { - return -EINVAL; - } - return 0; -} diff --git a/drivers/staging/r8188eu/core/rtw_recv.c b/drivers/staging/r8188eu/core/rtw_recv.c deleted file mode 100644 index fc7568cf948b..000000000000 --- a/drivers/staging/r8188eu/core/rtw_recv.c +++ /dev/null @@ -1,2010 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2007 - 2012 Realtek Corporation. */ - -#define _RTW_RECV_C_ - -#include -#include "../include/osdep_service.h" -#include "../include/drv_types.h" -#include "../include/usb_ops.h" -#include "../include/wifi.h" -#include "../include/rtl8188e_recv.h" - -static u8 SNAP_ETH_TYPE_IPX[2] = {0x81, 0x37}; -static u8 SNAP_ETH_TYPE_APPLETALK_AARP[2] = {0x80, 0xf3}; - -/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */ -static u8 rtw_bridge_tunnel_header[] = { - 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 -}; - -static u8 rtw_rfc1042_header[] = { - 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 -}; - -static void rtw_signal_stat_timer_hdl(struct timer_list *t); - -void _rtw_init_sta_recv_priv(struct sta_recv_priv *psta_recvpriv) -{ - - memset((u8 *)psta_recvpriv, 0, sizeof(struct sta_recv_priv)); - - spin_lock_init(&psta_recvpriv->lock); - - rtw_init_queue(&psta_recvpriv->defrag_q); - -} - -static int rtl8188eu_init_recv_priv(struct adapter *padapter) -{ - struct recv_priv *precvpriv = &padapter->recvpriv; - int i, err = 0; - struct recv_buf *precvbuf; - - tasklet_init(&precvpriv->recv_tasklet, - rtl8188eu_recv_tasklet, - (unsigned long)padapter); - - /* init recv_buf */ - rtw_init_queue(&precvpriv->free_recv_buf_queue); - - precvpriv->pallocated_recv_buf = kzalloc(NR_RECVBUFF * sizeof(struct recv_buf) + 4, - GFP_KERNEL); - if (!precvpriv->pallocated_recv_buf) - return -ENOMEM; - - precvpriv->precv_buf = (u8 *)ALIGN((size_t)(precvpriv->pallocated_recv_buf), 4); - - precvbuf = (struct recv_buf *)precvpriv->precv_buf; - - for (i = 0; i < NR_RECVBUFF; i++) { - precvbuf->pskb = NULL; - precvbuf->reuse = false; - precvbuf->purb = usb_alloc_urb(0, GFP_KERNEL); - if (!precvbuf->purb) { - err = -ENOMEM; - break; - } - precvbuf->adapter = padapter; - precvbuf++; - } - precvpriv->free_recv_buf_queue_cnt = NR_RECVBUFF; - skb_queue_head_init(&precvpriv->rx_skb_queue); - { - int i; - size_t tmpaddr = 0; - size_t alignment = 0; - struct sk_buff *pskb = NULL; - - skb_queue_head_init(&precvpriv->free_recv_skb_queue); - - for (i = 0; i < NR_PREALLOC_RECV_SKB; i++) { - pskb = __netdev_alloc_skb(padapter->pnetdev, - MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ, GFP_KERNEL); - if (pskb) { - pskb->dev = padapter->pnetdev; - tmpaddr = (size_t)pskb->data; - alignment = tmpaddr & (RECVBUFF_ALIGN_SZ - 1); - skb_reserve(pskb, (RECVBUFF_ALIGN_SZ - alignment)); - - skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb); - } - pskb = NULL; - } - } - - return err; -} - -int _rtw_init_recv_priv(struct recv_priv *precvpriv, struct adapter *padapter) -{ - int i; - struct recv_frame *precvframe; - int err; - - spin_lock_init(&precvpriv->lock); - - rtw_init_queue(&precvpriv->free_recv_queue); - rtw_init_queue(&precvpriv->recv_pending_queue); - rtw_init_queue(&precvpriv->uc_swdec_pending_queue); - - precvpriv->adapter = padapter; - - precvpriv->free_recvframe_cnt = NR_RECVFRAME; - - precvpriv->pallocated_frame_buf = vzalloc(NR_RECVFRAME * sizeof(struct recv_frame) + RXFRAME_ALIGN_SZ); - if (!precvpriv->pallocated_frame_buf) - return -ENOMEM; - - precvpriv->precv_frame_buf = (u8 *)ALIGN((size_t)(precvpriv->pallocated_frame_buf), RXFRAME_ALIGN_SZ); - - precvframe = (struct recv_frame *)precvpriv->precv_frame_buf; - - for (i = 0; i < NR_RECVFRAME; i++) { - INIT_LIST_HEAD(&precvframe->list); - - list_add_tail(&precvframe->list, &precvpriv->free_recv_queue.queue); - - precvframe->pkt = NULL; - - precvframe->len = 0; - - precvframe->adapter = padapter; - precvframe++; - } - precvpriv->rx_pending_cnt = 1; - - err = rtl8188eu_init_recv_priv(padapter); - - timer_setup(&precvpriv->signal_stat_timer, rtw_signal_stat_timer_hdl, 0); - precvpriv->signal_stat_sampling_interval = 1000; /* ms */ - - rtw_set_signal_stat_timer(precvpriv); - - return err; -} - -static void rtl8188eu_free_recv_priv(struct adapter *padapter) -{ - int i; - struct recv_buf *precvbuf; - struct recv_priv *precvpriv = &padapter->recvpriv; - - precvbuf = (struct recv_buf *)precvpriv->precv_buf; - - for (i = 0; i < NR_RECVBUFF; i++) { - usb_free_urb(precvbuf->purb); - precvbuf++; - } - - kfree(precvpriv->pallocated_recv_buf); - - skb_queue_purge(&precvpriv->rx_skb_queue); - - skb_queue_purge(&precvpriv->free_recv_skb_queue); -} - -void _rtw_free_recv_priv(struct recv_priv *precvpriv) -{ - struct adapter *padapter = precvpriv->adapter; - - rtw_free_uc_swdec_pending_queue(padapter); - - vfree(precvpriv->pallocated_frame_buf); - - rtl8188eu_free_recv_priv(padapter); - _cancel_timer_ex(&precvpriv->signal_stat_timer); -} - -struct recv_frame *_rtw_alloc_recvframe(struct __queue *pfree_recv_queue) -{ - struct recv_frame *hdr; - struct list_head *plist, *phead; - struct adapter *padapter; - struct recv_priv *precvpriv; - - if (list_empty(&pfree_recv_queue->queue)) { - hdr = NULL; - } else { - phead = get_list_head(pfree_recv_queue); - - plist = phead->next; - - hdr = container_of(plist, struct recv_frame, list); - - list_del_init(&hdr->list); - padapter = hdr->adapter; - if (padapter) { - precvpriv = &padapter->recvpriv; - if (pfree_recv_queue == &precvpriv->free_recv_queue) - precvpriv->free_recvframe_cnt--; - } - } - - return (struct recv_frame *)hdr; -} - -struct recv_frame *rtw_alloc_recvframe(struct __queue *pfree_recv_queue) -{ - struct recv_frame *precvframe; - - spin_lock_bh(&pfree_recv_queue->lock); - - precvframe = _rtw_alloc_recvframe(pfree_recv_queue); - - spin_unlock_bh(&pfree_recv_queue->lock); - - return precvframe; -} - -int rtw_free_recvframe(struct recv_frame *precvframe, struct __queue *pfree_recv_queue) -{ - struct adapter *padapter; - struct recv_priv *precvpriv; - - if (!precvframe) - return _FAIL; - padapter = precvframe->adapter; - precvpriv = &padapter->recvpriv; - if (precvframe->pkt) { - dev_kfree_skb_any(precvframe->pkt);/* free skb by driver */ - precvframe->pkt = NULL; - } - - spin_lock_bh(&pfree_recv_queue->lock); - - list_del_init(&precvframe->list); - - precvframe->len = 0; - - list_add_tail(&precvframe->list, get_list_head(pfree_recv_queue)); - - if (padapter && (pfree_recv_queue == &precvpriv->free_recv_queue)) - precvpriv->free_recvframe_cnt++; - - spin_unlock_bh(&pfree_recv_queue->lock); - - return _SUCCESS; -} - -int _rtw_enqueue_recvframe(struct recv_frame *precvframe, struct __queue *queue) -{ - struct adapter *padapter = precvframe->adapter; - struct recv_priv *precvpriv = &padapter->recvpriv; - - list_del_init(&precvframe->list); - list_add_tail(&precvframe->list, get_list_head(queue)); - - if (padapter) { - if (queue == &precvpriv->free_recv_queue) - precvpriv->free_recvframe_cnt++; - } - - return _SUCCESS; -} - -int rtw_enqueue_recvframe(struct recv_frame *precvframe, struct __queue *queue) -{ - int ret; - - spin_lock_bh(&queue->lock); - ret = _rtw_enqueue_recvframe(precvframe, queue); - spin_unlock_bh(&queue->lock); - - return ret; -} - -/* - * caller : defrag ; recvframe_chk_defrag in recv_thread (passive) - * pframequeue: defrag_queue : will be accessed in recv_thread (passive) - * - * using spinlock to protect - * - */ - -void rtw_free_recvframe_queue(struct __queue *pframequeue, struct __queue *pfree_recv_queue) -{ - struct recv_frame *hdr; - struct list_head *plist, *phead; - - spin_lock(&pframequeue->lock); - - phead = get_list_head(pframequeue); - plist = phead->next; - - while (phead != plist) { - hdr = container_of(plist, struct recv_frame, list); - - plist = plist->next; - - rtw_free_recvframe((struct recv_frame *)hdr, pfree_recv_queue); - } - - spin_unlock(&pframequeue->lock); - -} - -u32 rtw_free_uc_swdec_pending_queue(struct adapter *adapter) -{ - u32 cnt = 0; - struct recv_frame *pending_frame; - - while ((pending_frame = rtw_alloc_recvframe(&adapter->recvpriv.uc_swdec_pending_queue))) { - rtw_free_recvframe(pending_frame, &adapter->recvpriv.free_recv_queue); - cnt++; - } - - return cnt; -} - -static void rtw_handle_tkip_mic_err(struct adapter *padapter, u8 bgroup) -{ - union iwreq_data wrqu; - struct iw_michaelmicfailure ev; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - u32 cur_time = 0; - - if (psecuritypriv->last_mic_err_time == 0) { - psecuritypriv->last_mic_err_time = jiffies; - } else { - cur_time = jiffies; - - if (cur_time - psecuritypriv->last_mic_err_time < 60 * HZ) { - psecuritypriv->btkip_countermeasure = true; - psecuritypriv->last_mic_err_time = 0; - psecuritypriv->btkip_countermeasure_time = cur_time; - } else { - psecuritypriv->last_mic_err_time = jiffies; - } - } - - memset(&ev, 0x00, sizeof(ev)); - if (bgroup) - ev.flags |= IW_MICFAILURE_GROUP; - else - ev.flags |= IW_MICFAILURE_PAIRWISE; - - ev.src_addr.sa_family = ARPHRD_ETHER; - memcpy(ev.src_addr.sa_data, &pmlmepriv->assoc_bssid[0], ETH_ALEN); - memset(&wrqu, 0x00, sizeof(wrqu)); - wrqu.data.length = sizeof(ev); - wireless_send_event(padapter->pnetdev, IWEVMICHAELMICFAILURE, - &wrqu, (char *)&ev); -} - -static int recvframe_chkmic(struct adapter *adapter, struct recv_frame *precvframe) -{ - int i, res = _SUCCESS; - u32 datalen; - u8 miccode[8]; - u8 bmic_err = false, brpt_micerror = true; - u8 *pframe, *payload, *pframemic; - u8 *mickey; - struct sta_info *stainfo; - struct rx_pkt_attrib *prxattrib = &precvframe->attrib; - struct security_priv *psecuritypriv = &adapter->securitypriv; - - struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - stainfo = rtw_get_stainfo(&adapter->stapriv, &prxattrib->ta[0]); - - if (prxattrib->encrypt == _TKIP_) { - /* calculate mic code */ - if (stainfo) { - if (is_multicast_ether_addr(prxattrib->ra)) { - mickey = &psecuritypriv->dot118021XGrprxmickey[prxattrib->key_index].skey[0]; - - if (!psecuritypriv) { - res = _FAIL; - goto exit; - } - } else { - mickey = &stainfo->dot11tkiprxmickey.skey[0]; - } - - datalen = precvframe->len - prxattrib->hdrlen - prxattrib->iv_len - prxattrib->icv_len - 8;/* icv_len included the mic code */ - pframe = precvframe->rx_data; - payload = pframe + prxattrib->hdrlen + prxattrib->iv_len; - - rtw_seccalctkipmic(mickey, pframe, payload, datalen, &miccode[0], - (unsigned char)prxattrib->priority); /* care the length of the data */ - - pframemic = payload + datalen; - - bmic_err = false; - - for (i = 0; i < 8; i++) { - if (miccode[i] != *(pframemic + i)) - bmic_err = true; - } - - if (bmic_err) { - /* double check key_index for some timing issue , */ - /* cannot compare with psecuritypriv->dot118021XGrpKeyid also cause timing issue */ - if (is_multicast_ether_addr(prxattrib->ra) && prxattrib->key_index != pmlmeinfo->key_index) - brpt_micerror = false; - - if ((prxattrib->bdecrypted) && (brpt_micerror)) - rtw_handle_tkip_mic_err(adapter, (u8)is_multicast_ether_addr(prxattrib->ra)); - - res = _FAIL; - } else { - /* mic checked ok */ - if (!psecuritypriv->bcheck_grpkey && is_multicast_ether_addr(prxattrib->ra)) - psecuritypriv->bcheck_grpkey = true; - } - } - - recvframe_pull_tail(precvframe, 8); - } - -exit: - - return res; -} - -/* decrypt and set the ivlen, icvlen of the recv_frame */ -static struct recv_frame *decryptor(struct adapter *padapter, struct recv_frame *precv_frame) -{ - struct rx_pkt_attrib *prxattrib = &precv_frame->attrib; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct recv_frame *return_packet = precv_frame; - u32 res = _SUCCESS; - - if (prxattrib->encrypt > 0) { - u8 *iv = precv_frame->rx_data + prxattrib->hdrlen; - - prxattrib->key_index = (((iv[3]) >> 6) & 0x3); - - if (prxattrib->key_index > WEP_KEYS) { - switch (prxattrib->encrypt) { - case _WEP40_: - case _WEP104_: - prxattrib->key_index = psecuritypriv->dot11PrivacyKeyIndex; - break; - case _TKIP_: - case _AES_: - default: - prxattrib->key_index = psecuritypriv->dot118021XGrpKeyid; - break; - } - } - } - - if ((prxattrib->encrypt > 0) && ((prxattrib->bdecrypted == 0) || (psecuritypriv->sw_decrypt))) { - psecuritypriv->hw_decrypted = false; - - switch (prxattrib->encrypt) { - case _WEP40_: - case _WEP104_: - rtw_wep_decrypt(padapter, precv_frame); - break; - case _TKIP_: - res = rtw_tkip_decrypt(padapter, precv_frame); - break; - case _AES_: - res = rtw_aes_decrypt(padapter, precv_frame); - break; - default: - break; - } - } else if (prxattrib->bdecrypted == 1 && prxattrib->encrypt > 0 && - (psecuritypriv->busetkipkey == 1 || prxattrib->encrypt != _TKIP_)) - psecuritypriv->hw_decrypted = true; - - if (res == _FAIL) { - rtw_free_recvframe(return_packet, &padapter->recvpriv.free_recv_queue); - return_packet = NULL; - } else { - prxattrib->bdecrypted = true; - } - - return return_packet; -} - -/* set the security information in the recv_frame */ -static struct recv_frame *portctrl(struct adapter *adapter, struct recv_frame *precv_frame) -{ - u8 *psta_addr, *ptr; - uint auth_alg; - struct recv_frame *pfhdr; - struct sta_info *psta; - struct sta_priv *pstapriv; - struct recv_frame *prtnframe; - u16 ether_type = 0; - u16 eapol_type = 0x888e;/* for Funia BD's WPA issue */ - struct rx_pkt_attrib *pattrib; - __be16 be_tmp; - - pstapriv = &adapter->stapriv; - - auth_alg = adapter->securitypriv.dot11AuthAlgrthm; - - ptr = precv_frame->rx_data; - pfhdr = precv_frame; - pattrib = &pfhdr->attrib; - psta_addr = pattrib->ta; - - prtnframe = NULL; - - psta = rtw_get_stainfo(pstapriv, psta_addr); - - if (auth_alg == 2) { - if (psta && psta->ieee8021x_blocked) { - /* blocked */ - /* only accept EAPOL frame */ - prtnframe = precv_frame; - - /* get ether_type */ - ptr = ptr + pfhdr->attrib.hdrlen + pfhdr->attrib.iv_len + LLC_HEADER_SIZE; - memcpy(&be_tmp, ptr, 2); - ether_type = ntohs(be_tmp); - - if (ether_type == eapol_type) { - prtnframe = precv_frame; - } else { - /* free this frame */ - rtw_free_recvframe(precv_frame, &adapter->recvpriv.free_recv_queue); - prtnframe = NULL; - } - } else { - /* allowed */ - /* check decryption status, and decrypt the frame if needed */ - prtnframe = precv_frame; - } - } else { - prtnframe = precv_frame; - } - - return prtnframe; -} - -static int recv_decache(struct recv_frame *precv_frame, u8 bretry, struct stainfo_rxcache *prxcache) -{ - int tid = precv_frame->attrib.priority; - - u16 seq_ctrl = ((precv_frame->attrib.seq_num & 0xffff) << 4) | - (precv_frame->attrib.frag_num & 0xf); - - if (tid > 15) - return _FAIL; - - if (1) {/* if (bretry) */ - if (seq_ctrl == prxcache->tid_rxseq[tid]) - return _FAIL; - } - - prxcache->tid_rxseq[tid] = seq_ctrl; - - return _SUCCESS; -} - -static void process_pwrbit_data(struct adapter *padapter, struct recv_frame *precv_frame) -{ - unsigned char pwrbit; - u8 *ptr = precv_frame->rx_data; - struct rx_pkt_attrib *pattrib = &precv_frame->attrib; - struct sta_priv *pstapriv = &padapter->stapriv; - struct sta_info *psta = NULL; - - psta = rtw_get_stainfo(pstapriv, pattrib->src); - - pwrbit = GetPwrMgt(ptr); - - if (psta) { - if (pwrbit) { - if (!(psta->state & WIFI_SLEEP_STATE)) - stop_sta_xmit(padapter, psta); - } else { - if (psta->state & WIFI_SLEEP_STATE) - wakeup_sta_to_xmit(padapter, psta); - } - } -} - -static void process_wmmps_data(struct adapter *padapter, struct recv_frame *precv_frame) -{ - struct rx_pkt_attrib *pattrib = &precv_frame->attrib; - struct sta_priv *pstapriv = &padapter->stapriv; - struct sta_info *psta = NULL; - - psta = rtw_get_stainfo(pstapriv, pattrib->src); - - if (!psta) - return; - - if (!psta->qos_option) - return; - - if (!(psta->qos_info & 0xf)) - return; - - if (psta->state & WIFI_SLEEP_STATE) { - u8 wmmps_ac = 0; - - switch (pattrib->priority) { - case 1: - case 2: - wmmps_ac = psta->uapsd_bk & BIT(1); - break; - case 4: - case 5: - wmmps_ac = psta->uapsd_vi & BIT(1); - break; - case 6: - case 7: - wmmps_ac = psta->uapsd_vo & BIT(1); - break; - case 0: - case 3: - default: - wmmps_ac = psta->uapsd_be & BIT(1); - break; - } - - if (wmmps_ac) { - if (psta->sleepq_ac_len > 0) { - /* process received triggered frame */ - xmit_delivery_enabled_frames(padapter, psta); - } else { - /* issue one qos null frame with More data bit = 0 and the EOSP bit set (= 1) */ - issue_qos_nulldata(padapter, psta->hwaddr, (u16)pattrib->priority, 0, 0); - } - } - } -} - -static void count_rx_stats(struct adapter *padapter, struct recv_frame *prframe, struct sta_info *sta) -{ - int sz; - struct sta_info *psta = NULL; - struct stainfo_stats *pstats = NULL; - struct rx_pkt_attrib *pattrib = &prframe->attrib; - struct recv_priv *precvpriv = &padapter->recvpriv; - - sz = get_recvframe_len(prframe); - precvpriv->rx_bytes += sz; - - padapter->mlmepriv.LinkDetectInfo.NumRxOkInPeriod++; - - if (!is_broadcast_ether_addr(pattrib->dst) && !is_multicast_ether_addr(pattrib->dst)) - padapter->mlmepriv.LinkDetectInfo.NumRxUnicastOkInPeriod++; - - if (sta) - psta = sta; - else - psta = prframe->psta; - - if (psta) { - pstats = &psta->sta_stats; - - pstats->rx_data_pkts++; - pstats->rx_bytes += sz; - } -} - -static int sta2sta_data_frame(struct adapter *adapter, - struct recv_frame *precv_frame, struct sta_info **psta) -{ - int ret = _SUCCESS; - struct rx_pkt_attrib *pattrib = &precv_frame->attrib; - struct sta_priv *pstapriv = &adapter->stapriv; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - u8 *mybssid = get_bssid(pmlmepriv); - u8 *myhwaddr = myid(&adapter->eeprompriv); - u8 *sta_addr = NULL; - bool bmcast = is_multicast_ether_addr(pattrib->dst); - - if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) || - check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) { - /* filter packets that SA is myself or multicast or broadcast */ - if (!memcmp(myhwaddr, pattrib->src, ETH_ALEN)) { - ret = _FAIL; - goto exit; - } - - if ((memcmp(myhwaddr, pattrib->dst, ETH_ALEN)) && (!bmcast)) { - ret = _FAIL; - goto exit; - } - - if (!memcmp(pattrib->bssid, "\x0\x0\x0\x0\x0\x0", ETH_ALEN) || - !memcmp(mybssid, "\x0\x0\x0\x0\x0\x0", ETH_ALEN) || - memcmp(pattrib->bssid, mybssid, ETH_ALEN)) { - ret = _FAIL; - goto exit; - } - - sta_addr = pattrib->src; - } else if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { - /* For Station mode, sa and bssid should always be BSSID, and DA is my mac-address */ - if (memcmp(pattrib->bssid, pattrib->src, ETH_ALEN)) { - ret = _FAIL; - goto exit; - } - sta_addr = pattrib->bssid; - } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - if (bmcast) { - /* For AP mode, if DA == MCAST, then BSSID should be also MCAST */ - if (!is_multicast_ether_addr(pattrib->bssid)) { - ret = _FAIL; - goto exit; - } - } else { /* not mc-frame */ - /* For AP mode, if DA is non-MCAST, then it must be BSSID, and bssid == BSSID */ - if (memcmp(pattrib->bssid, pattrib->dst, ETH_ALEN)) { - ret = _FAIL; - goto exit; - } - - sta_addr = pattrib->src; - } - } else if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) { - sta_addr = mybssid; - } else { - ret = _FAIL; - } - - if (bmcast) - *psta = rtw_get_bcmc_stainfo(adapter); - else - *psta = rtw_get_stainfo(pstapriv, sta_addr); /* get ap_info */ - - if (!*psta) - goto exit; - -exit: - - return ret; -} - -static int ap2sta_data_frame( - struct adapter *adapter, - struct recv_frame *precv_frame, - struct sta_info **psta) -{ - u8 *ptr = precv_frame->rx_data; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)precv_frame->rx_data; - struct rx_pkt_attrib *pattrib = &precv_frame->attrib; - int ret = _SUCCESS; - struct sta_priv *pstapriv = &adapter->stapriv; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - u8 *mybssid = get_bssid(pmlmepriv); - u8 *myhwaddr = myid(&adapter->eeprompriv); - bool bmcast = is_multicast_ether_addr(pattrib->dst); - - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) && - (check_fwstate(pmlmepriv, _FW_LINKED) || - check_fwstate(pmlmepriv, _FW_UNDER_LINKING))) { - /* filter packets that SA is myself or multicast or broadcast */ - if (!memcmp(myhwaddr, pattrib->src, ETH_ALEN)) { - ret = _FAIL; - goto exit; - } - - /* da should be for me */ - if ((memcmp(myhwaddr, pattrib->dst, ETH_ALEN)) && (!bmcast)) { - ret = _FAIL; - goto exit; - } - - /* check BSSID */ - if (is_zero_ether_addr(pattrib->bssid) || is_zero_ether_addr(mybssid) || - (memcmp(pattrib->bssid, mybssid, ETH_ALEN))) { - if (!bmcast) - issue_deauth(adapter, pattrib->bssid, WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA); - - ret = _FAIL; - goto exit; - } - - if (bmcast) - *psta = rtw_get_bcmc_stainfo(adapter); - else - *psta = rtw_get_stainfo(pstapriv, pattrib->bssid); /* get ap_info */ - - if (!*psta) { - ret = _FAIL; - goto exit; - } - - if (ieee80211_is_nullfunc(hdr->frame_control)) { - /* We count the nullfunc frame, but we'll not pass it on to higher layers. */ - count_rx_stats(adapter, precv_frame, *psta); - ret = RTW_RX_HANDLED; - goto exit; - } - } else if (check_fwstate(pmlmepriv, WIFI_MP_STATE) && - check_fwstate(pmlmepriv, _FW_LINKED)) { - memcpy(pattrib->src, GetAddr2Ptr(ptr), ETH_ALEN); - - memcpy(pattrib->bssid, mybssid, ETH_ALEN); - - *psta = rtw_get_stainfo(pstapriv, pattrib->bssid); /* get sta_info */ - if (!*psta) { - ret = _FAIL; - goto exit; - } - } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - /* Special case */ - ret = RTW_RX_HANDLED; - goto exit; - } else { - if (!memcmp(myhwaddr, pattrib->dst, ETH_ALEN) && (!bmcast)) { - *psta = rtw_get_stainfo(pstapriv, pattrib->bssid); /* get sta_info */ - if (!*psta) - issue_deauth(adapter, pattrib->bssid, WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA); - } - - ret = _FAIL; - } - -exit: - - return ret; -} - -static int sta2ap_data_frame(struct adapter *adapter, - struct recv_frame *precv_frame, - struct sta_info **psta) -{ - struct rx_pkt_attrib *pattrib = &precv_frame->attrib; - struct sta_priv *pstapriv = &adapter->stapriv; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - u8 *ptr = precv_frame->rx_data; - __le16 fc = *(__le16 *)ptr; - unsigned char *mybssid = get_bssid(pmlmepriv); - int ret = _SUCCESS; - - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - /* For AP mode, RA = BSSID, TX = STA(SRC_ADDR), A3 = DST_ADDR */ - if (memcmp(pattrib->bssid, mybssid, ETH_ALEN)) { - ret = _FAIL; - goto exit; - } - - *psta = rtw_get_stainfo(pstapriv, pattrib->src); - if (!*psta) { - issue_deauth(adapter, pattrib->src, WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA); - - ret = RTW_RX_HANDLED; - goto exit; - } - - process_pwrbit_data(adapter, precv_frame); - - if (ieee80211_is_data_qos(fc)) - process_wmmps_data(adapter, precv_frame); - - if (GetFrameSubType(ptr) & BIT(6)) { - /* No data, will not indicate to upper layer, temporily count it here */ - count_rx_stats(adapter, precv_frame, *psta); - ret = RTW_RX_HANDLED; - goto exit; - } - } else { - u8 *myhwaddr = myid(&adapter->eeprompriv); - - if (memcmp(pattrib->ra, myhwaddr, ETH_ALEN)) { - ret = RTW_RX_HANDLED; - goto exit; - } - issue_deauth(adapter, pattrib->src, WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA); - ret = RTW_RX_HANDLED; - goto exit; - } - -exit: - - return ret; -} - -static void validate_recv_ctrl_frame(struct adapter *padapter, - struct recv_frame *precv_frame) -{ - struct rx_pkt_attrib *pattrib = &precv_frame->attrib; - struct sta_priv *pstapriv = &padapter->stapriv; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)precv_frame->rx_data; - struct ieee80211_pspoll *pspoll = (struct ieee80211_pspoll *)hdr; - u8 wmmps_ac; - struct sta_info *psta; - - /* receive the frames that ra(a1) is my address */ - if (memcmp(hdr->addr1, myid(&padapter->eeprompriv), ETH_ALEN)) - return; - - /* only handle ps-poll */ - if (!ieee80211_is_pspoll(hdr->frame_control)) - return; - - psta = rtw_get_stainfo(pstapriv, hdr->addr2); - if (!psta || psta->aid != (le16_to_cpu(pspoll->aid) & 0x3FFF)) - return; - - /* for rx pkt statistics */ - psta->sta_stats.rx_ctrl_pkts++; - - switch (pattrib->priority) { - case 1: - case 2: - wmmps_ac = psta->uapsd_bk & BIT(0); - break; - case 4: - case 5: - wmmps_ac = psta->uapsd_vi & BIT(0); - break; - case 6: - case 7: - wmmps_ac = psta->uapsd_vo & BIT(0); - break; - case 0: - case 3: - default: - wmmps_ac = psta->uapsd_be & BIT(0); - break; - } - - if (wmmps_ac) - return; - - if (psta->state & WIFI_STA_ALIVE_CHK_STATE) { - psta->expire_to = pstapriv->expire_to; - psta->state ^= WIFI_STA_ALIVE_CHK_STATE; - } - - if ((psta->state & WIFI_SLEEP_STATE) && (pstapriv->sta_dz_bitmap & BIT(psta->aid))) { - struct list_head *xmitframe_plist, *xmitframe_phead; - struct xmit_frame *pxmitframe = NULL; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - spin_lock_bh(&pxmitpriv->lock); - - xmitframe_phead = get_list_head(&psta->sleep_q); - xmitframe_plist = xmitframe_phead->next; - - if (xmitframe_phead != xmitframe_plist) { - pxmitframe = container_of(xmitframe_plist, struct xmit_frame, list); - - xmitframe_plist = xmitframe_plist->next; - - list_del_init(&pxmitframe->list); - - psta->sleepq_len--; - - if (psta->sleepq_len > 0) - pxmitframe->attrib.mdata = 1; - else - pxmitframe->attrib.mdata = 0; - - pxmitframe->attrib.triggered = 1; - - if (psta->sleepq_len == 0) { - pstapriv->tim_bitmap &= ~BIT(psta->aid); - - /* update BCN for TIM IE */ - /* update_BCNTIM(padapter); */ - update_beacon(padapter, _TIM_IE_, NULL, false); - } - } else { - if (pstapriv->tim_bitmap & BIT(psta->aid)) { - if (psta->sleepq_len == 0) - /* issue nulldata with More data bit = 0 to indicate we have no buffered packets */ - issue_nulldata(padapter, psta->hwaddr, 0, 0, 0); - else - psta->sleepq_len = 0; - - pstapriv->tim_bitmap &= ~BIT(psta->aid); - - /* update BCN for TIM IE */ - /* update_BCNTIM(padapter); */ - update_beacon(padapter, _TIM_IE_, NULL, false); - } - } - spin_unlock_bh(&pxmitpriv->lock); - } -} - -struct recv_frame *recvframe_chk_defrag(struct adapter *padapter, struct recv_frame *precv_frame); - -static void validate_recv_mgnt_frame(struct adapter *padapter, - struct recv_frame *precv_frame) -{ - struct sta_info *psta; - struct ieee80211_hdr *hdr; - - precv_frame = recvframe_chk_defrag(padapter, precv_frame); - if (!precv_frame) - return; - - hdr = (struct ieee80211_hdr *)precv_frame->rx_data; - psta = rtw_get_stainfo(&padapter->stapriv, hdr->addr2); - if (psta) { - psta->sta_stats.rx_mgnt_pkts++; - if (ieee80211_is_beacon(hdr->frame_control)) - psta->sta_stats.rx_beacon_pkts++; - else if (ieee80211_is_probe_req(hdr->frame_control)) - psta->sta_stats.rx_probereq_pkts++; - else if (ieee80211_is_probe_resp(hdr->frame_control)) { - if (!memcmp(padapter->eeprompriv.mac_addr, hdr->addr1, ETH_ALEN)) - psta->sta_stats.rx_probersp_pkts++; - else if (is_broadcast_mac_addr(hdr->addr1) || is_multicast_mac_addr(hdr->addr1)) - psta->sta_stats.rx_probersp_bm_pkts++; - else - psta->sta_stats.rx_probersp_uo_pkts++; - } - } - - mgt_dispatcher(padapter, precv_frame); -} - -static int validate_recv_data_frame(struct adapter *adapter, - struct recv_frame *precv_frame) -{ - struct sta_info *psta = NULL; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)precv_frame->rx_data; - struct rx_pkt_attrib *pattrib = &precv_frame->attrib; - struct security_priv *psecuritypriv = &adapter->securitypriv; - int ret; - - memcpy(pattrib->dst, ieee80211_get_DA(hdr), ETH_ALEN); - memcpy(pattrib->src, ieee80211_get_SA(hdr), ETH_ALEN); - - /* address4 is used only if both to_ds and from_ds are set */ - if (ieee80211_has_a4(hdr->frame_control)) - return _FAIL; - - memcpy(pattrib->ra, hdr->addr1, ETH_ALEN); - memcpy(pattrib->ta, hdr->addr2, ETH_ALEN); - - if (ieee80211_has_fromds(hdr->frame_control)) { - memcpy(pattrib->bssid, hdr->addr2, ETH_ALEN); - ret = ap2sta_data_frame(adapter, precv_frame, &psta); - } else if (ieee80211_has_tods(hdr->frame_control)) { - memcpy(pattrib->bssid, hdr->addr1, ETH_ALEN); - ret = sta2ap_data_frame(adapter, precv_frame, &psta); - } else { - memcpy(pattrib->bssid, hdr->addr3, ETH_ALEN); - ret = sta2sta_data_frame(adapter, precv_frame, &psta); - } - - if (ret == _FAIL || ret == RTW_RX_HANDLED) - return ret; - - if (!psta) - return _FAIL; - - precv_frame->psta = psta; - - pattrib->amsdu = 0; - pattrib->ack_policy = 0; - /* parsing QC field */ - if (pattrib->qos) { - struct ieee80211_qos_hdr *qos_hdr = (struct ieee80211_qos_hdr *)hdr; - - pattrib->priority = ieee80211_get_tid(hdr); - pattrib->ack_policy = GetAckpolicy(&qos_hdr->qos_ctrl); - pattrib->amsdu = GetAMsdu(&qos_hdr->qos_ctrl); - pattrib->hdrlen = sizeof(*qos_hdr); - - if (pattrib->priority != 0 && pattrib->priority != 3) - adapter->recvpriv.bIsAnyNonBEPkts = true; - } else { - pattrib->priority = 0; - pattrib->hdrlen = 24; - } - - if (pattrib->order)/* HT-CTRL 11n */ - pattrib->hdrlen += 4; - - precv_frame->preorder_ctrl = &psta->recvreorder_ctrl[pattrib->priority]; - - /* decache, drop duplicate recv packets */ - if (recv_decache(precv_frame, ieee80211_has_retry(hdr->frame_control), - &psta->sta_recvpriv.rxcache) == _FAIL) - return _FAIL; - - if (pattrib->privacy) { - GET_ENCRY_ALGO(psecuritypriv, psta, pattrib->encrypt, is_multicast_ether_addr(pattrib->ra)); - - SET_ICE_IV_LEN(pattrib->iv_len, pattrib->icv_len, pattrib->encrypt); - } else { - pattrib->encrypt = 0; - pattrib->iv_len = 0; - pattrib->icv_len = 0; - } - - return _SUCCESS; -} - -static int validate_recv_frame(struct adapter *adapter, struct recv_frame *precv_frame) -{ - /* shall check frame subtype, to / from ds, da, bssid */ - - /* then call check if rx seq/frag. duplicated. */ - - int retval = _FAIL; - struct rx_pkt_attrib *pattrib = &precv_frame->attrib; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)precv_frame->rx_data; - struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv; - - if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) { - int ch_set_idx = rtw_ch_set_search_ch(pmlmeext->channel_set, rtw_get_oper_ch(adapter)); - - if (ch_set_idx >= 0) - pmlmeext->channel_set[ch_set_idx].rx_count++; - } - - if ((hdr->frame_control & cpu_to_le16(IEEE80211_FCTL_VERS)) != 0) - return _FAIL; - - pattrib->frag_num = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG; - pattrib->seq_num = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)); - - pattrib->pw_save = ieee80211_has_pm(hdr->frame_control); - pattrib->mfrag = ieee80211_has_morefrags(hdr->frame_control); - pattrib->mdata = ieee80211_has_moredata(hdr->frame_control); - pattrib->privacy = ieee80211_has_protected(hdr->frame_control); - pattrib->order = ieee80211_has_order(hdr->frame_control); - - /* We return _SUCCESS only for data frames. */ - if (ieee80211_is_mgmt(hdr->frame_control)) - validate_recv_mgnt_frame(adapter, precv_frame); - else if (ieee80211_is_ctl(hdr->frame_control)) - validate_recv_ctrl_frame(adapter, precv_frame); - else if (ieee80211_is_data(hdr->frame_control)) { - rtw_led_control(adapter, LED_CTL_RX); - pattrib->qos = ieee80211_is_data_qos(hdr->frame_control); - retval = validate_recv_data_frame(adapter, precv_frame); - if (retval == _FAIL) { - struct recv_priv *precvpriv = &adapter->recvpriv; - - precvpriv->rx_drop++; - } - } - - return retval; -} - -/* remove the wlanhdr and add the eth_hdr */ - -static int wlanhdr_to_ethhdr(struct recv_frame *precvframe) -{ - int rmv_len; - u16 eth_type, len; - __be16 be_tmp; - u8 bsnaphdr; - u8 *psnap_type; - struct ieee80211_snap_hdr *psnap; - - int ret = _SUCCESS; - struct adapter *adapter = precvframe->adapter; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - - u8 *ptr = precvframe->rx_data; /* point to frame_ctrl field */ - struct rx_pkt_attrib *pattrib = &precvframe->attrib; - - if (pattrib->encrypt) - recvframe_pull_tail(precvframe, pattrib->icv_len); - - psnap = (struct ieee80211_snap_hdr *)(ptr + pattrib->hdrlen + pattrib->iv_len); - psnap_type = ptr + pattrib->hdrlen + pattrib->iv_len + SNAP_SIZE; - /* convert hdr + possible LLC headers into Ethernet header */ - if ((!memcmp(psnap, rtw_rfc1042_header, SNAP_SIZE) && - memcmp(psnap_type, SNAP_ETH_TYPE_IPX, 2) && - memcmp(psnap_type, SNAP_ETH_TYPE_APPLETALK_AARP, 2)) || - !memcmp(psnap, rtw_bridge_tunnel_header, SNAP_SIZE)) { - /* remove RFC1042 or Bridge-Tunnel encapsulation and replace EtherType */ - bsnaphdr = true; - } else { - /* Leave Ethernet header part of hdr and full payload */ - bsnaphdr = false; - } - - rmv_len = pattrib->hdrlen + pattrib->iv_len + (bsnaphdr ? SNAP_SIZE : 0); - len = precvframe->len - rmv_len; - - memcpy(&be_tmp, ptr + rmv_len, 2); - eth_type = ntohs(be_tmp); /* pattrib->ether_type */ - pattrib->eth_type = eth_type; - - if ((check_fwstate(pmlmepriv, WIFI_MP_STATE))) { - ptr += rmv_len; - *ptr = 0x87; - *(ptr + 1) = 0x12; - - eth_type = 0x8712; - /* append rx status for mp test packets */ - ptr = recvframe_pull(precvframe, (rmv_len - sizeof(struct ethhdr) + 2) - 24); - if (!ptr) - return _FAIL; - memcpy(ptr, get_rxmem(precvframe), 24); - ptr += 24; - } else { - ptr = recvframe_pull(precvframe, (rmv_len - sizeof(struct ethhdr) + (bsnaphdr ? 2 : 0))); - if (!ptr) - return _FAIL; - } - - memcpy(ptr, pattrib->dst, ETH_ALEN); - memcpy(ptr + ETH_ALEN, pattrib->src, ETH_ALEN); - - if (!bsnaphdr) { - be_tmp = htons(len); - memcpy(ptr + 12, &be_tmp, 2); - } - - return ret; -} - -/* perform defrag */ -static struct recv_frame *recvframe_defrag(struct adapter *adapter, struct __queue *defrag_q) -{ - struct list_head *plist, *phead; - u8 wlanhdr_offset; - u8 curfragnum; - struct recv_frame *pfhdr, *pnfhdr; - struct recv_frame *prframe, *pnextrframe; - struct __queue *pfree_recv_queue; - - curfragnum = 0; - pfree_recv_queue = &adapter->recvpriv.free_recv_queue; - - phead = get_list_head(defrag_q); - plist = phead->next; - pfhdr = container_of(plist, struct recv_frame, list); - prframe = (struct recv_frame *)pfhdr; - list_del_init(&prframe->list); - - if (curfragnum != pfhdr->attrib.frag_num) { - /* the first fragment number must be 0 */ - /* free the whole queue */ - rtw_free_recvframe(prframe, pfree_recv_queue); - rtw_free_recvframe_queue(defrag_q, pfree_recv_queue); - - return NULL; - } - - curfragnum++; - - plist = get_list_head(defrag_q); - plist = phead->next; - pfhdr = container_of(plist, struct recv_frame, list); - prframe = (struct recv_frame *)pfhdr; - list_del_init(&prframe->list); - - plist = plist->next; - - while (phead != plist) { - pnfhdr = container_of(plist, struct recv_frame, list); - pnextrframe = (struct recv_frame *)pnfhdr; - - /* check the fragment sequence (2nd ~n fragment frame) */ - - if (curfragnum != pnfhdr->attrib.frag_num) { - /* the fragment number must be increasing (after decache) */ - /* release the defrag_q & prframe */ - rtw_free_recvframe(prframe, pfree_recv_queue); - rtw_free_recvframe_queue(defrag_q, pfree_recv_queue); - return NULL; - } - - curfragnum++; - - /* copy the 2nd~n fragment frame's payload to the first fragment */ - /* get the 2nd~last fragment frame's payload */ - - wlanhdr_offset = pnfhdr->attrib.hdrlen + pnfhdr->attrib.iv_len; - - recvframe_pull(pnextrframe, wlanhdr_offset); - - /* append to first fragment frame's tail (if privacy frame, pull the ICV) */ - recvframe_pull_tail(prframe, pfhdr->attrib.icv_len); - - /* memcpy */ - memcpy(pfhdr->rx_tail, pnfhdr->rx_data, pnfhdr->len); - - recvframe_put(prframe, pnfhdr->len); - - pfhdr->attrib.icv_len = pnfhdr->attrib.icv_len; - plist = plist->next; - } - - /* free the defrag_q queue and return the prframe */ - rtw_free_recvframe_queue(defrag_q, pfree_recv_queue); - - return prframe; -} - -/* check if need to defrag, if needed queue the frame to defrag_q */ -struct recv_frame *recvframe_chk_defrag(struct adapter *padapter, struct recv_frame *precv_frame) -{ - u8 ismfrag; - u8 fragnum; - u8 *psta_addr; - struct recv_frame *pfhdr; - struct sta_info *psta; - struct sta_priv *pstapriv; - struct list_head *phead; - struct recv_frame *prtnframe = NULL; - struct __queue *pfree_recv_queue, *pdefrag_q; - - pstapriv = &padapter->stapriv; - - pfhdr = precv_frame; - - pfree_recv_queue = &padapter->recvpriv.free_recv_queue; - - /* need to define struct of wlan header frame ctrl */ - ismfrag = pfhdr->attrib.mfrag; - fragnum = pfhdr->attrib.frag_num; - - psta_addr = pfhdr->attrib.ta; - psta = rtw_get_stainfo(pstapriv, psta_addr); - if (!psta) { - __le16 fc = *(__le16 *)pfhdr->rx_data; - - if (ieee80211_is_data(fc)) { - psta = rtw_get_bcmc_stainfo(padapter); - pdefrag_q = &psta->sta_recvpriv.defrag_q; - } else { - pdefrag_q = NULL; - } - } else { - pdefrag_q = &psta->sta_recvpriv.defrag_q; - } - - if ((ismfrag == 0) && (fragnum == 0)) - prtnframe = precv_frame;/* isn't a fragment frame */ - - if (ismfrag == 1) { - /* 0~(n-1) fragment frame */ - /* enqueue to defraf_g */ - if (pdefrag_q) { - if (fragnum == 0) { - /* the first fragment */ - if (!list_empty(&pdefrag_q->queue)) { - /* free current defrag_q */ - rtw_free_recvframe_queue(pdefrag_q, pfree_recv_queue); - } - } - - /* Then enqueue the 0~(n-1) fragment into the defrag_q */ - - phead = get_list_head(pdefrag_q); - list_add_tail(&pfhdr->list, phead); - - prtnframe = NULL; - } else { - /* can't find this ta's defrag_queue, so free this recv_frame */ - if (precv_frame && pfree_recv_queue) - rtw_free_recvframe(precv_frame, pfree_recv_queue); - prtnframe = NULL; - } - } - - if ((ismfrag == 0) && (fragnum != 0)) { - /* the last fragment frame */ - /* enqueue the last fragment */ - if (pdefrag_q) { - phead = get_list_head(pdefrag_q); - list_add_tail(&pfhdr->list, phead); - - /* call recvframe_defrag to defrag */ - precv_frame = recvframe_defrag(padapter, pdefrag_q); - prtnframe = precv_frame; - } else { - /* can't find this ta's defrag_queue, so free this recv_frame */ - if (precv_frame && pfree_recv_queue) - rtw_free_recvframe(precv_frame, pfree_recv_queue); - prtnframe = NULL; - } - } - - if (prtnframe && prtnframe->attrib.privacy) { - /* after defrag we must check tkip mic code */ - if (recvframe_chkmic(padapter, prtnframe) == _FAIL) { - if (precv_frame && pfree_recv_queue) - rtw_free_recvframe(prtnframe, pfree_recv_queue); - prtnframe = NULL; - } - } - - return prtnframe; -} - -static int amsdu_to_msdu(struct adapter *padapter, struct recv_frame *prframe) -{ - int a_len, padding_len; - u16 eth_type, nSubframe_Length; - u8 nr_subframes, i; - unsigned char *pdata; - struct rx_pkt_attrib *pattrib; - struct sk_buff *sub_skb, *subframes[MAX_SUBFRAME_COUNT]; - - struct recv_priv *precvpriv = &padapter->recvpriv; - struct __queue *pfree_recv_queue = &precvpriv->free_recv_queue; - - nr_subframes = 0; - - pattrib = &prframe->attrib; - - recvframe_pull(prframe, prframe->attrib.hdrlen); - - if (prframe->attrib.iv_len > 0) - recvframe_pull(prframe, prframe->attrib.iv_len); - - a_len = prframe->len; - - pdata = prframe->rx_data; - - while (a_len > ETH_HLEN) { - /* Offset 12 denote 2 mac address */ - nSubframe_Length = RTW_GET_BE16(pdata + 12); - - if (a_len < ETH_HLEN + nSubframe_Length) - goto exit; - - /* move the data point to data content */ - pdata += ETH_HLEN; - a_len -= ETH_HLEN; - - /* Allocate new skb for releasing to upper layer */ - sub_skb = dev_alloc_skb(nSubframe_Length + 12); - if (sub_skb) { - skb_reserve(sub_skb, 12); - skb_put_data(sub_skb, pdata, nSubframe_Length); - } else { - sub_skb = skb_clone(prframe->pkt, GFP_ATOMIC); - if (sub_skb) { - sub_skb->data = pdata; - sub_skb->len = nSubframe_Length; - skb_set_tail_pointer(sub_skb, nSubframe_Length); - } else { - break; - } - } - - subframes[nr_subframes++] = sub_skb; - - if (nr_subframes >= MAX_SUBFRAME_COUNT) - break; - - pdata += nSubframe_Length; - a_len -= nSubframe_Length; - if (a_len != 0) { - padding_len = 4 - ((nSubframe_Length + ETH_HLEN) & (4 - 1)); - if (padding_len == 4) - padding_len = 0; - - if (a_len < padding_len) - goto exit; - - pdata += padding_len; - a_len -= padding_len; - } - } - - for (i = 0; i < nr_subframes; i++) { - sub_skb = subframes[i]; - /* convert hdr + possible LLC headers into Ethernet header */ - eth_type = RTW_GET_BE16(&sub_skb->data[6]); - if (sub_skb->len >= 8 && - ((!memcmp(sub_skb->data, rtw_rfc1042_header, SNAP_SIZE) && - eth_type != ETH_P_AARP && eth_type != ETH_P_IPX) || - !memcmp(sub_skb->data, rtw_bridge_tunnel_header, SNAP_SIZE))) { - /* remove RFC1042 or Bridge-Tunnel encapsulation and replace EtherType */ - skb_pull(sub_skb, SNAP_SIZE); - memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->src, ETH_ALEN); - memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->dst, ETH_ALEN); - } else { - __be16 len; - /* Leave Ethernet header part of hdr and full payload */ - len = htons(sub_skb->len); - memcpy(skb_push(sub_skb, 2), &len, 2); - memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->src, ETH_ALEN); - memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->dst, ETH_ALEN); - } - - /* Indicate the packets to upper layer */ - /* Insert NAT2.5 RX here! */ - sub_skb->protocol = eth_type_trans(sub_skb, padapter->pnetdev); - sub_skb->dev = padapter->pnetdev; - - sub_skb->ip_summed = CHECKSUM_NONE; - - netif_rx(sub_skb); - } - -exit: - - prframe->len = 0; - rtw_free_recvframe(prframe, pfree_recv_queue);/* free this recv_frame */ - - return _SUCCESS; -} - -static bool check_indicate_seq(struct recv_reorder_ctrl *preorder_ctrl, u16 seq_num) -{ - u8 wsize = preorder_ctrl->wsize_b; - u16 wend = (preorder_ctrl->indicate_seq + wsize - 1) & 0xFFF;/* 4096; */ - - /* Rx Reorder initialize condition. */ - if (preorder_ctrl->indicate_seq == 0xFFFF) - preorder_ctrl->indicate_seq = seq_num; - - /* Drop out the packet which SeqNum is smaller than WinStart */ - if (SN_LESS(seq_num, preorder_ctrl->indicate_seq)) - return false; - - /* */ - /* Sliding window manipulation. Conditions includes: */ - /* 1. Incoming SeqNum is equal to WinStart =>Window shift 1 */ - /* 2. Incoming SeqNum is larger than the WinEnd => Window shift N */ - /* */ - if (SN_EQUAL(seq_num, preorder_ctrl->indicate_seq)) { - preorder_ctrl->indicate_seq = (preorder_ctrl->indicate_seq + 1) & 0xFFF; - } else if (SN_LESS(wend, seq_num)) { - if (seq_num >= (wsize - 1)) - preorder_ctrl->indicate_seq = seq_num + 1 - wsize; - else - preorder_ctrl->indicate_seq = 0xFFF - (wsize - (seq_num + 1)) + 1; - } - - return true; -} - -static bool enqueue_reorder_recvframe(struct recv_reorder_ctrl *preorder_ctrl, struct recv_frame *prframe) -{ - struct rx_pkt_attrib *pattrib = &prframe->attrib; - struct __queue *ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue; - struct list_head *phead, *plist; - struct recv_frame *hdr; - struct rx_pkt_attrib *pnextattrib; - - phead = get_list_head(ppending_recvframe_queue); - plist = phead->next; - - while (phead != plist) { - hdr = container_of(plist, struct recv_frame, list); - pnextattrib = &hdr->attrib; - - if (SN_LESS(pnextattrib->seq_num, pattrib->seq_num)) - plist = plist->next; - else if (SN_EQUAL(pnextattrib->seq_num, pattrib->seq_num)) - return false; - else - break; - } - - list_del_init(&prframe->list); - - list_add_tail(&prframe->list, plist); - return true; -} - -static int rtw_recv_indicatepkt(struct adapter *padapter, struct recv_frame *precv_frame) -{ - struct recv_priv *precvpriv; - struct __queue *pfree_recv_queue; - struct sk_buff *skb; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - precvpriv = &padapter->recvpriv; - pfree_recv_queue = &precvpriv->free_recv_queue; - - skb = precv_frame->pkt; - if (!skb) - goto _recv_indicatepkt_drop; - - skb->data = precv_frame->rx_data; - - skb_set_tail_pointer(skb, precv_frame->len); - - skb->len = precv_frame->len; - - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - struct sk_buff *pskb2 = NULL; - struct sta_info *psta = NULL; - struct sta_priv *pstapriv = &padapter->stapriv; - struct rx_pkt_attrib *pattrib = &precv_frame->attrib; - bool bmcast = is_multicast_ether_addr(pattrib->dst); - - if (memcmp(pattrib->dst, myid(&padapter->eeprompriv), ETH_ALEN)) { - if (bmcast) { - psta = rtw_get_bcmc_stainfo(padapter); - pskb2 = skb_clone(skb, GFP_ATOMIC); - } else { - psta = rtw_get_stainfo(pstapriv, pattrib->dst); - } - - if (psta) { - struct net_device *pnetdev; - - pnetdev = (struct net_device *)padapter->pnetdev; - skb->dev = pnetdev; - skb_set_queue_mapping(skb, rtw_recv_select_queue(skb)); - - rtw_xmit_entry(skb, pnetdev); - - if (bmcast) - skb = pskb2; - else - goto _recv_indicatepkt_end; - } - } - } - - rcu_read_lock(); - rcu_dereference(padapter->pnetdev->rx_handler_data); - rcu_read_unlock(); - - skb->ip_summed = CHECKSUM_NONE; - skb->dev = padapter->pnetdev; - skb->protocol = eth_type_trans(skb, padapter->pnetdev); - - netif_rx(skb); - -_recv_indicatepkt_end: - - /* pointers to NULL before rtw_free_recvframe() */ - precv_frame->pkt = NULL; - - rtw_free_recvframe(precv_frame, pfree_recv_queue); - - return _SUCCESS; - -_recv_indicatepkt_drop: - - /* enqueue back to free_recv_queue */ - rtw_free_recvframe(precv_frame, pfree_recv_queue); - - return _FAIL; -} - -static bool recv_indicatepkts_in_order(struct adapter *padapter, struct recv_reorder_ctrl *preorder_ctrl, int bforced) -{ - struct list_head *phead, *plist; - struct recv_frame *prframe; - struct rx_pkt_attrib *pattrib; - int bPktInBuf = false; - struct recv_priv *precvpriv = &padapter->recvpriv; - struct __queue *ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue; - - phead = get_list_head(ppending_recvframe_queue); - plist = phead->next; - - /* Handling some condition for forced indicate case. */ - if (bforced) { - if (list_empty(phead)) - return true; - - prframe = container_of(plist, struct recv_frame, list); - pattrib = &prframe->attrib; - preorder_ctrl->indicate_seq = pattrib->seq_num; - } - - /* Prepare indication list and indication. */ - /* Check if there is any packet need indicate. */ - while (!list_empty(phead)) { - prframe = container_of(plist, struct recv_frame, list); - pattrib = &prframe->attrib; - - if (!SN_LESS(preorder_ctrl->indicate_seq, pattrib->seq_num)) { - plist = plist->next; - list_del_init(&prframe->list); - - if (SN_EQUAL(preorder_ctrl->indicate_seq, pattrib->seq_num)) - preorder_ctrl->indicate_seq = (preorder_ctrl->indicate_seq + 1) & 0xFFF; - - /* Set this as a lock to make sure that only one thread is indicating packet. */ - - /* indicate this recv_frame */ - if (!pattrib->amsdu) { - if ((!padapter->bDriverStopped) && - (!padapter->bSurpriseRemoved)) - rtw_recv_indicatepkt(padapter, prframe);/* indicate this recv_frame */ - } else if (pattrib->amsdu == 1) { - if (amsdu_to_msdu(padapter, prframe) != _SUCCESS) - rtw_free_recvframe(prframe, &precvpriv->free_recv_queue); - } else { - /* error condition; */ - } - - /* Update local variables. */ - bPktInBuf = false; - } else { - bPktInBuf = true; - break; - } - } - return bPktInBuf; -} - -static int recv_indicatepkt_reorder(struct adapter *padapter, struct recv_frame *prframe) -{ - int retval = _SUCCESS; - struct rx_pkt_attrib *pattrib = &prframe->attrib; - struct recv_reorder_ctrl *preorder_ctrl = prframe->preorder_ctrl; - struct __queue *ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue; - - if (!pattrib->amsdu) { - /* s1. */ - wlanhdr_to_ethhdr(prframe); - - if (!pattrib->qos) { - if (!padapter->bDriverStopped && - !padapter->bSurpriseRemoved) { - rtw_recv_indicatepkt(padapter, prframe); - return _SUCCESS; - } - - return _FAIL; - } - - if (!preorder_ctrl->enable) { - /* indicate this recv_frame */ - preorder_ctrl->indicate_seq = pattrib->seq_num; - rtw_recv_indicatepkt(padapter, prframe); - - preorder_ctrl->indicate_seq = (preorder_ctrl->indicate_seq + 1) % 4096; - return _SUCCESS; - } - } else if (pattrib->amsdu == 1) { /* temp filter -> means didn't support A-MSDUs in a A-MPDU */ - if (!preorder_ctrl->enable) { - preorder_ctrl->indicate_seq = pattrib->seq_num; - retval = amsdu_to_msdu(padapter, prframe); - - preorder_ctrl->indicate_seq = (preorder_ctrl->indicate_seq + 1) % 4096; - return retval; - } - } - - spin_lock_bh(&ppending_recvframe_queue->lock); - - /* s2. check if winstart_b(indicate_seq) needs to been updated */ - if (!check_indicate_seq(preorder_ctrl, pattrib->seq_num)) - goto _err_exit; - - /* s3. Insert all packet into Reorder Queue to maintain its ordering. */ - if (!enqueue_reorder_recvframe(preorder_ctrl, prframe)) - goto _err_exit; - - /* s4. */ - /* Indication process. */ - /* After Packet dropping and Sliding Window shifting as above, we can now just indicate the packets */ - /* with the SeqNum smaller than latest WinStart and buffer other packets. */ - /* */ - /* For Rx Reorder condition: */ - /* 1. All packets with SeqNum smaller than WinStart => Indicate */ - /* 2. All packets with SeqNum larger than or equal to WinStart => Buffer it. */ - /* */ - - /* recv_indicatepkts_in_order(padapter, preorder_ctrl, true); */ - if (recv_indicatepkts_in_order(padapter, preorder_ctrl, false)) { - _set_timer(&preorder_ctrl->reordering_ctrl_timer, REORDER_WAIT_TIME); - spin_unlock_bh(&ppending_recvframe_queue->lock); - } else { - spin_unlock_bh(&ppending_recvframe_queue->lock); - _cancel_timer_ex(&preorder_ctrl->reordering_ctrl_timer); - } - - return _SUCCESS; - -_err_exit: - - spin_unlock_bh(&ppending_recvframe_queue->lock); - - return _FAIL; -} - -void rtw_reordering_ctrl_timeout_handler(void *pcontext) -{ - struct recv_reorder_ctrl *preorder_ctrl = (struct recv_reorder_ctrl *)pcontext; - struct adapter *padapter = preorder_ctrl->padapter; - struct __queue *ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue; - - if (padapter->bDriverStopped || padapter->bSurpriseRemoved) - return; - - spin_lock_bh(&ppending_recvframe_queue->lock); - - if (recv_indicatepkts_in_order(padapter, preorder_ctrl, true)) - _set_timer(&preorder_ctrl->reordering_ctrl_timer, REORDER_WAIT_TIME); - - spin_unlock_bh(&ppending_recvframe_queue->lock); -} - -static int process_recv_indicatepkts(struct adapter *padapter, struct recv_frame *prframe) -{ - int retval = _SUCCESS; - /* struct recv_priv *precvpriv = &padapter->recvpriv; */ - /* struct rx_pkt_attrib *pattrib = &prframe->attrib; */ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct ht_priv *phtpriv = &pmlmepriv->htpriv; - - if (phtpriv->ht_option) { /* B/G/N Mode */ - /* prframe->preorder_ctrl = &precvpriv->recvreorder_ctrl[pattrib->priority]; */ - - if (recv_indicatepkt_reorder(padapter, prframe) != _SUCCESS) { - /* including perform A-MPDU Rx Ordering Buffer Control */ - if ((!padapter->bDriverStopped) && - (!padapter->bSurpriseRemoved)) { - retval = _FAIL; - return retval; - } - } - } else { /* B/G mode */ - retval = wlanhdr_to_ethhdr(prframe); - if (retval != _SUCCESS) - return retval; - - if ((!padapter->bDriverStopped) && - (!padapter->bSurpriseRemoved)) { - /* indicate this recv_frame */ - rtw_recv_indicatepkt(padapter, prframe); - } else { - retval = _FAIL; - return retval; - } - } - - return retval; -} - -static int recv_func_prehandle(struct adapter *padapter, struct recv_frame *rframe) -{ - int ret = _SUCCESS; - struct __queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue; - - /* check the frame crtl field and decache */ - ret = validate_recv_frame(padapter, rframe); - if (ret != _SUCCESS) - rtw_free_recvframe(rframe, pfree_recv_queue);/* free this recv_frame */ - - return ret; -} - -static int recv_func_posthandle(struct adapter *padapter, struct recv_frame *prframe) -{ - int ret = _SUCCESS; - struct recv_frame *orig_prframe = prframe; - struct recv_priv *precvpriv = &padapter->recvpriv; - struct __queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue; - - /* DATA FRAME */ - rtw_led_control(padapter, LED_CTL_RX); - - prframe = decryptor(padapter, prframe); - if (!prframe) { - ret = _FAIL; - goto _recv_data_drop; - } - - prframe = recvframe_chk_defrag(padapter, prframe); - if (!prframe) - goto _recv_data_drop; - - prframe = portctrl(padapter, prframe); - if (!prframe) { - ret = _FAIL; - goto _recv_data_drop; - } - - count_rx_stats(padapter, prframe, NULL); - - ret = process_recv_indicatepkts(padapter, prframe); - if (ret != _SUCCESS) { - rtw_free_recvframe(orig_prframe, pfree_recv_queue);/* free this recv_frame */ - goto _recv_data_drop; - } - return ret; - -_recv_data_drop: - precvpriv->rx_drop++; - return ret; -} - -static int recv_func(struct adapter *padapter, struct recv_frame *rframe) -{ - int ret; - struct rx_pkt_attrib *prxattrib = &rframe->attrib; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct mlme_priv *mlmepriv = &padapter->mlmepriv; - struct recv_priv *recvpriv = &padapter->recvpriv; - - /* check if need to handle uc_swdec_pending_queue*/ - if (check_fwstate(mlmepriv, WIFI_STATION_STATE) && - psecuritypriv->busetkipkey) { - struct recv_frame *pending_frame; - - while ((pending_frame = rtw_alloc_recvframe(&padapter->recvpriv.uc_swdec_pending_queue))) - recv_func_posthandle(padapter, pending_frame); - } - - ret = recv_func_prehandle(padapter, rframe); - - if (ret == _SUCCESS) { - /* check if need to enqueue into uc_swdec_pending_queue*/ - if (check_fwstate(mlmepriv, WIFI_STATION_STATE) && - !is_multicast_ether_addr(prxattrib->ra) && prxattrib->encrypt > 0 && - (prxattrib->bdecrypted == 0 || psecuritypriv->sw_decrypt) && - psecuritypriv->ndisauthtype == Ndis802_11AuthModeWPAPSK && - !psecuritypriv->busetkipkey) { - rtw_enqueue_recvframe(rframe, &padapter->recvpriv.uc_swdec_pending_queue); - if (recvpriv->free_recvframe_cnt < NR_RECVFRAME / 4) { - /* - * to prevent from recvframe starvation, - * get recvframe from uc_swdec_pending_queue to - * free_recvframe_cnt - */ - rframe = rtw_alloc_recvframe(&padapter->recvpriv.uc_swdec_pending_queue); - if (rframe) - goto do_posthandle; - } - goto exit; - } -do_posthandle: - ret = recv_func_posthandle(padapter, rframe); - } - -exit: - return ret; -} - -s32 rtw_recv_entry(struct recv_frame *precvframe) -{ - struct adapter *padapter; - struct recv_priv *precvpriv; - s32 ret = _SUCCESS; - - padapter = precvframe->adapter; - - precvpriv = &padapter->recvpriv; - - ret = recv_func(padapter, precvframe); - if (ret == _FAIL) - goto _recv_entry_drop; - - precvpriv->rx_pkts++; - - return ret; - -_recv_entry_drop: - - return ret; -} - -static void rtw_signal_stat_timer_hdl(struct timer_list *t) -{ - struct adapter *adapter = from_timer(adapter, t, recvpriv.signal_stat_timer); - struct recv_priv *recvpriv = &adapter->recvpriv; - - u32 tmp_s, tmp_q; - u8 avg_signal_strength = 0; - u8 avg_signal_qual = 0; - u8 _alpha = 3; /* this value is based on converging_constant = 5000 and sampling_interval = 1000 */ - - if (adapter->recvpriv.is_signal_dbg) { - /* update the user specific value, signal_strength_dbg, to signal_strength, rssi */ - adapter->recvpriv.signal_strength = adapter->recvpriv.signal_strength_dbg; - adapter->recvpriv.rssi = (s8)translate_percentage_to_dbm((u8)adapter->recvpriv.signal_strength_dbg); - } else { - if (recvpriv->signal_strength_data.update_req == 0) {/* update_req is clear, means we got rx */ - avg_signal_strength = recvpriv->signal_strength_data.avg_val; - /* after avg_vals are acquired, we can re-stat the signal values */ - recvpriv->signal_strength_data.update_req = 1; - } - - if (recvpriv->signal_qual_data.update_req == 0) {/* update_req is clear, means we got rx */ - avg_signal_qual = recvpriv->signal_qual_data.avg_val; - /* after avg_vals are acquired, we can re-stat the signal values */ - recvpriv->signal_qual_data.update_req = 1; - } - - /* update value of signal_strength, rssi, signal_qual */ - if (!check_fwstate(&adapter->mlmepriv, _FW_UNDER_SURVEY)) { - tmp_s = (avg_signal_strength + (_alpha - 1) * recvpriv->signal_strength); - if (tmp_s % _alpha) - tmp_s = tmp_s / _alpha + 1; - else - tmp_s = tmp_s / _alpha; - if (tmp_s > 100) - tmp_s = 100; - - tmp_q = (avg_signal_qual + (_alpha - 1) * recvpriv->signal_qual); - if (tmp_q % _alpha) - tmp_q = tmp_q / _alpha + 1; - else - tmp_q = tmp_q / _alpha; - if (tmp_q > 100) - tmp_q = 100; - - recvpriv->signal_strength = tmp_s; - recvpriv->rssi = (s8)translate_percentage_to_dbm(tmp_s); - recvpriv->signal_qual = tmp_q; - } - } - rtw_set_signal_stat_timer(recvpriv); -} diff --git a/drivers/staging/r8188eu/core/rtw_rf.c b/drivers/staging/r8188eu/core/rtw_rf.c deleted file mode 100644 index 2d2f0fc4c942..000000000000 --- a/drivers/staging/r8188eu/core/rtw_rf.c +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#include "../include/drv_types.h" - -static const u32 ch_freq_map[] = { - 2412, - 2417, - 2422, - 2427, - 2432, - 2437, - 2442, - 2447, - 2452, - 2457, - 2462, - 2467, - 2472, - 2484 -}; - -u32 rtw_ch2freq(u32 channel) -{ - if (channel == 0 || channel > ARRAY_SIZE(ch_freq_map)) - return 2412; - - return ch_freq_map[channel - 1]; -} diff --git a/drivers/staging/r8188eu/core/rtw_security.c b/drivers/staging/r8188eu/core/rtw_security.c deleted file mode 100644 index 780019ce1b98..000000000000 --- a/drivers/staging/r8188eu/core/rtw_security.c +++ /dev/null @@ -1,1374 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#define _RTW_SECURITY_C_ - -#include "../include/osdep_service.h" -#include "../include/drv_types.h" -#include "../include/wifi.h" -#include "../include/osdep_intf.h" - -/* WEP related ===== */ - -/* - Need to consider the fragment situation -*/ -void rtw_wep_encrypt(struct adapter *padapter, struct xmit_frame *pxmitframe) -{ /* exclude ICV */ - union { - __le32 f0; - u8 f1[4]; - } crc; - - int curfragnum, length; - u32 keylength; - - u8 *pframe, *payload, *iv; /* wepkey */ - u8 wepkey[16]; - u8 hw_hdr_offset = 0; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct arc4_ctx *ctx = &psecuritypriv->xmit_arc4_ctx; - - if (!pxmitframe->buf_addr) - return; - - hw_hdr_offset = TXDESC_SIZE + pxmitframe->pkt_offset * PACKET_OFFSET_SZ; - pframe = pxmitframe->buf_addr + hw_hdr_offset; - - /* start to encrypt each fragment */ - if ((pattrib->encrypt == _WEP40_) || (pattrib->encrypt == _WEP104_)) { - keylength = psecuritypriv->dot11DefKeylen[psecuritypriv->dot11PrivacyKeyIndex]; - - for (curfragnum = 0; curfragnum < pattrib->nr_frags; curfragnum++) { - iv = pframe + pattrib->hdrlen; - memcpy(&wepkey[0], iv, 3); - memcpy(&wepkey[3], &psecuritypriv->dot11DefKey[psecuritypriv->dot11PrivacyKeyIndex].skey[0], keylength); - payload = pframe + pattrib->iv_len + pattrib->hdrlen; - - if ((curfragnum + 1) == pattrib->nr_frags) { /* the last fragment */ - length = pattrib->last_txcmdsz - pattrib->hdrlen - pattrib->iv_len - pattrib->icv_len; - - crc.f0 = cpu_to_le32(~crc32_le(~0, payload, length)); - - arc4_setkey(ctx, wepkey, 3 + keylength); - arc4_crypt(ctx, payload, payload, length); - arc4_crypt(ctx, payload + length, crc.f1, 4); - } else { - length = pxmitpriv->frag_len - pattrib->hdrlen - pattrib->iv_len - pattrib->icv_len; - crc.f0 = cpu_to_le32(~crc32_le(~0, payload, length)); - arc4_setkey(ctx, wepkey, 3 + keylength); - arc4_crypt(ctx, payload, payload, length); - arc4_crypt(ctx, payload + length, crc.f1, 4); - - pframe += pxmitpriv->frag_len; - pframe = PTR_ALIGN(pframe, 4); - } - } - } - -} - -void rtw_wep_decrypt(struct adapter *padapter, struct recv_frame *precvframe) -{ - /* exclude ICV */ - int length; - u32 keylength; - u8 *pframe, *payload, *iv, wepkey[16]; - u8 keyindex; - struct rx_pkt_attrib *prxattrib = &precvframe->attrib; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct arc4_ctx *ctx = &psecuritypriv->recv_arc4_ctx; - - pframe = precvframe->rx_data; - - /* start to decrypt recvframe */ - if ((prxattrib->encrypt == _WEP40_) || (prxattrib->encrypt == _WEP104_)) { - iv = pframe + prxattrib->hdrlen; - keyindex = prxattrib->key_index; - keylength = psecuritypriv->dot11DefKeylen[keyindex]; - memcpy(&wepkey[0], iv, 3); - memcpy(&wepkey[3], &psecuritypriv->dot11DefKey[keyindex].skey[0], keylength); - length = precvframe->len - prxattrib->hdrlen - prxattrib->iv_len; - - payload = pframe + prxattrib->iv_len + prxattrib->hdrlen; - - /* decrypt payload include icv */ - arc4_setkey(ctx, wepkey, 3 + keylength); - arc4_crypt(ctx, payload, payload, length); - } -} - -/* 3 ===== TKIP related ===== */ - -static u32 secmicgetuint32(u8 *p) -/* Convert from Byte[] to Us3232 in a portable way */ -{ - s32 i; - u32 res = 0; - - for (i = 0; i < 4; i++) - res |= ((u32)(*p++)) << (8 * i); - - return res; -} - -static void secmicputuint32(u8 *p, u32 val) -/* Convert from Us3232 to Byte[] in a portable way */ -{ - long i; - - for (i = 0; i < 4; i++) { - *p++ = (u8)(val & 0xff); - val >>= 8; - } - -} - -static void secmicclear(struct mic_data *pmicdata) -{ -/* Reset the state to the empty message. */ - - pmicdata->L = pmicdata->K0; - pmicdata->R = pmicdata->K1; - pmicdata->nBytesInM = 0; - pmicdata->M = 0; - -} - -void rtw_secmicsetkey(struct mic_data *pmicdata, u8 *key) -{ - /* Set the key */ - - pmicdata->K0 = secmicgetuint32(key); - pmicdata->K1 = secmicgetuint32(key + 4); - /* and reset the message */ - secmicclear(pmicdata); - -} - -void rtw_secmicappendbyte(struct mic_data *pmicdata, u8 b) -{ - - /* Append the byte to our word-sized buffer */ - pmicdata->M |= ((unsigned long)b) << (8 * pmicdata->nBytesInM); - pmicdata->nBytesInM++; - /* Process the word if it is full. */ - if (pmicdata->nBytesInM >= 4) { - pmicdata->L ^= pmicdata->M; - pmicdata->R ^= ROL32(pmicdata->L, 17); - pmicdata->L += pmicdata->R; - pmicdata->R ^= ((pmicdata->L & 0xff00ff00) >> 8) | ((pmicdata->L & 0x00ff00ff) << 8); - pmicdata->L += pmicdata->R; - pmicdata->R ^= ROL32(pmicdata->L, 3); - pmicdata->L += pmicdata->R; - pmicdata->R ^= ROR32(pmicdata->L, 2); - pmicdata->L += pmicdata->R; - /* Clear the buffer */ - pmicdata->M = 0; - pmicdata->nBytesInM = 0; - } - -} - -void rtw_secmicappend(struct mic_data *pmicdata, u8 *src, u32 nbytes) -{ - - /* This is simple */ - while (nbytes > 0) { - rtw_secmicappendbyte(pmicdata, *src++); - nbytes--; - } - -} - -void rtw_secgetmic(struct mic_data *pmicdata, u8 *dst) -{ - - /* Append the minimum padding */ - rtw_secmicappendbyte(pmicdata, 0x5a); - rtw_secmicappendbyte(pmicdata, 0); - rtw_secmicappendbyte(pmicdata, 0); - rtw_secmicappendbyte(pmicdata, 0); - rtw_secmicappendbyte(pmicdata, 0); - /* and then zeroes until the length is a multiple of 4 */ - while (pmicdata->nBytesInM != 0) - rtw_secmicappendbyte(pmicdata, 0); - /* The appendByte function has already computed the result. */ - secmicputuint32(dst, pmicdata->L); - secmicputuint32(dst + 4, pmicdata->R); - /* Reset to the empty message. */ - secmicclear(pmicdata); - -} - -void rtw_seccalctkipmic(u8 *key, u8 *header, u8 *data, u32 data_len, u8 *mic_code, u8 pri) -{ - struct mic_data micdata; - u8 priority[4] = {0x0, 0x0, 0x0, 0x0}; - - rtw_secmicsetkey(&micdata, key); - priority[0] = pri; - - /* Michael MIC pseudo header: DA, SA, 3 x 0, Priority */ - if (header[1] & 1) { /* ToDS == 1 */ - rtw_secmicappend(&micdata, &header[16], 6); /* DA */ - if (header[1] & 2) /* From Ds == 1 */ - rtw_secmicappend(&micdata, &header[24], 6); - else - rtw_secmicappend(&micdata, &header[10], 6); - } else { /* ToDS == 0 */ - rtw_secmicappend(&micdata, &header[4], 6); /* DA */ - if (header[1] & 2) /* From Ds == 1 */ - rtw_secmicappend(&micdata, &header[16], 6); - else - rtw_secmicappend(&micdata, &header[10], 6); - } - rtw_secmicappend(&micdata, &priority[0], 4); - - rtw_secmicappend(&micdata, data, data_len); - - rtw_secgetmic(&micdata, mic_code); - -} - -/* macros for extraction/creation of unsigned char/unsigned short values */ -#define RotR1(v16) ((((v16) >> 1) & 0x7FFF) ^ (((v16) & 1) << 15)) -#define Lo8(v16) ((u8)((v16) & 0x00FF)) -#define Hi8(v16) ((u8)(((v16) >> 8) & 0x00FF)) -#define Lo16(v32) ((u16)((v32) & 0xFFFF)) -#define Hi16(v32) ((u16)(((v32) >> 16) & 0xFFFF)) -#define Mk16(hi, lo) ((lo) ^ (((u16)(hi)) << 8)) - -/* select the Nth 16-bit word of the temporal key unsigned char array TK[] */ -#define TK16(N) Mk16(tk[2 * (N) + 1], tk[2 * (N)]) - -/* S-box lookup: 16 bits --> 16 bits */ -#define _S_(v16) (Sbox1[0][Lo8(v16)] ^ Sbox1[1][Hi8(v16)]) - -/* fixed algorithm "parameters" */ -#define PHASE1_LOOP_CNT 8 /* this needs to be "big enough" */ -#define TA_SIZE 6 /* 48-bit transmitter address */ -#define TK_SIZE 16 /* 128-bit temporal key */ -#define P1K_SIZE 10 /* 80-bit Phase1 key */ -#define RC4_KEY_SIZE 16 /* 128-bit RC4KEY (104 bits unknown) */ - -/* 2-unsigned char by 2-unsigned char subset of the full AES S-box table */ -static const unsigned short Sbox1[2][256] = { /* Sbox for hash (can be in ROM) */ -{ - 0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154, - 0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A, - 0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B, - 0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B, - 0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F, - 0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F, - 0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5, - 0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F, - 0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB, - 0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397, - 0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED, - 0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A, - 0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194, - 0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3, - 0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104, - 0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D, - 0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39, - 0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695, - 0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83, - 0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76, - 0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4, - 0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B, - 0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0, - 0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018, - 0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751, - 0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85, - 0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12, - 0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9, - 0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7, - 0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A, - 0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8, - 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A, - }, - - { /* second half of table is unsigned char-reversed version of first! */ - 0xA5C6, 0x84F8, 0x99EE, 0x8DF6, 0x0DFF, 0xBDD6, 0xB1DE, 0x5491, - 0x5060, 0x0302, 0xA9CE, 0x7D56, 0x19E7, 0x62B5, 0xE64D, 0x9AEC, - 0x458F, 0x9D1F, 0x4089, 0x87FA, 0x15EF, 0xEBB2, 0xC98E, 0x0BFB, - 0xEC41, 0x67B3, 0xFD5F, 0xEA45, 0xBF23, 0xF753, 0x96E4, 0x5B9B, - 0xC275, 0x1CE1, 0xAE3D, 0x6A4C, 0x5A6C, 0x417E, 0x02F5, 0x4F83, - 0x5C68, 0xF451, 0x34D1, 0x08F9, 0x93E2, 0x73AB, 0x5362, 0x3F2A, - 0x0C08, 0x5295, 0x6546, 0x5E9D, 0x2830, 0xA137, 0x0F0A, 0xB52F, - 0x090E, 0x3624, 0x9B1B, 0x3DDF, 0x26CD, 0x694E, 0xCD7F, 0x9FEA, - 0x1B12, 0x9E1D, 0x7458, 0x2E34, 0x2D36, 0xB2DC, 0xEEB4, 0xFB5B, - 0xF6A4, 0x4D76, 0x61B7, 0xCE7D, 0x7B52, 0x3EDD, 0x715E, 0x9713, - 0xF5A6, 0x68B9, 0x0000, 0x2CC1, 0x6040, 0x1FE3, 0xC879, 0xEDB6, - 0xBED4, 0x468D, 0xD967, 0x4B72, 0xDE94, 0xD498, 0xE8B0, 0x4A85, - 0x6BBB, 0x2AC5, 0xE54F, 0x16ED, 0xC586, 0xD79A, 0x5566, 0x9411, - 0xCF8A, 0x10E9, 0x0604, 0x81FE, 0xF0A0, 0x4478, 0xBA25, 0xE34B, - 0xF3A2, 0xFE5D, 0xC080, 0x8A05, 0xAD3F, 0xBC21, 0x4870, 0x04F1, - 0xDF63, 0xC177, 0x75AF, 0x6342, 0x3020, 0x1AE5, 0x0EFD, 0x6DBF, - 0x4C81, 0x1418, 0x3526, 0x2FC3, 0xE1BE, 0xA235, 0xCC88, 0x392E, - 0x5793, 0xF255, 0x82FC, 0x477A, 0xACC8, 0xE7BA, 0x2B32, 0x95E6, - 0xA0C0, 0x9819, 0xD19E, 0x7FA3, 0x6644, 0x7E54, 0xAB3B, 0x830B, - 0xCA8C, 0x29C7, 0xD36B, 0x3C28, 0x79A7, 0xE2BC, 0x1D16, 0x76AD, - 0x3BDB, 0x5664, 0x4E74, 0x1E14, 0xDB92, 0x0A0C, 0x6C48, 0xE4B8, - 0x5D9F, 0x6EBD, 0xEF43, 0xA6C4, 0xA839, 0xA431, 0x37D3, 0x8BF2, - 0x32D5, 0x438B, 0x596E, 0xB7DA, 0x8C01, 0x64B1, 0xD29C, 0xE049, - 0xB4D8, 0xFAAC, 0x07F3, 0x25CF, 0xAFCA, 0x8EF4, 0xE947, 0x1810, - 0xD56F, 0x88F0, 0x6F4A, 0x725C, 0x2438, 0xF157, 0xC773, 0x5197, - 0x23CB, 0x7CA1, 0x9CE8, 0x213E, 0xDD96, 0xDC61, 0x860D, 0x850F, - 0x90E0, 0x427C, 0xC471, 0xAACC, 0xD890, 0x0506, 0x01F7, 0x121C, - 0xA3C2, 0x5F6A, 0xF9AE, 0xD069, 0x9117, 0x5899, 0x273A, 0xB927, - 0x38D9, 0x13EB, 0xB32B, 0x3322, 0xBBD2, 0x70A9, 0x8907, 0xA733, - 0xB62D, 0x223C, 0x9215, 0x20C9, 0x4987, 0xFFAA, 0x7850, 0x7AA5, - 0x8F03, 0xF859, 0x8009, 0x171A, 0xDA65, 0x31D7, 0xC684, 0xB8D0, - 0xC382, 0xB029, 0x775A, 0x111E, 0xCB7B, 0xFCA8, 0xD66D, 0x3A2C, - } -}; - - /* -********************************************************************** -* Routine: Phase 1 -- generate P1K, given TA, TK, IV32 -* -* Inputs: -* tk[] = temporal key [128 bits] -* ta[] = transmitter's MAC address [ 48 bits] -* iv32 = upper 32 bits of IV [ 32 bits] -* Output: -* p1k[] = Phase 1 key [ 80 bits] -* -* Note: -* This function only needs to be called every 2**16 packets, -* although in theory it could be called every packet. -* -********************************************************************** -*/ -static void phase1(u16 *p1k, const u8 *tk, const u8 *ta, u32 iv32) -{ - int i; - - /* Initialize the 80 bits of P1K[] from IV32 and TA[0..5] */ - p1k[0] = Lo16(iv32); - p1k[1] = Hi16(iv32); - p1k[2] = Mk16(ta[1], ta[0]); /* use TA[] as little-endian */ - p1k[3] = Mk16(ta[3], ta[2]); - p1k[4] = Mk16(ta[5], ta[4]); - - /* Now compute an unbalanced Feistel cipher with 80-bit block */ - /* size on the 80-bit block P1K[], using the 128-bit key TK[] */ - for (i = 0; i < PHASE1_LOOP_CNT; i++) { /* Each add operation here is mod 2**16 */ - p1k[0] += _S_(p1k[4] ^ TK16((i & 1) + 0)); - p1k[1] += _S_(p1k[0] ^ TK16((i & 1) + 2)); - p1k[2] += _S_(p1k[1] ^ TK16((i & 1) + 4)); - p1k[3] += _S_(p1k[2] ^ TK16((i & 1) + 6)); - p1k[4] += _S_(p1k[3] ^ TK16((i & 1) + 0)); - p1k[4] += (unsigned short)i; /* avoid "slide attacks" */ - } - -} - -/* -********************************************************************** -* Routine: Phase 2 -- generate RC4KEY, given TK, P1K, IV16 -* -* Inputs: -* tk[] = Temporal key [128 bits] -* p1k[] = Phase 1 output key [ 80 bits] -* iv16 = low 16 bits of IV counter [ 16 bits] -* Output: -* rc4key[] = the key used to encrypt the packet [128 bits] -* -* Note: -* The value {TA, IV32, IV16} for Phase1/Phase2 must be unique -* across all packets using the same key TK value. Then, for a -* given value of TK[], this TKIP48 construction guarantees that -* the final RC4KEY value is unique across all packets. -* -* Suggested implementation optimization: if PPK[] is "overlaid" -* appropriately on RC4KEY[], there is no need for the final -* for loop below that copies the PPK[] result into RC4KEY[]. -* -********************************************************************** -*/ -static void phase2(u8 *rc4key, const u8 *tk, const u16 *p1k, u16 iv16) -{ - int i; - u16 PPK[6]; /* temporary key for mixing */ - - /* Note: all adds in the PPK[] equations below are mod 2**16 */ - for (i = 0; i < 5; i++) - PPK[i] = p1k[i]; /* first, copy P1K to PPK */ - PPK[5] = p1k[4] + iv16; /* next, add in IV16 */ - - /* Bijective non-linear mixing of the 96 bits of PPK[0..5] */ - PPK[0] += _S_(PPK[5] ^ TK16(0)); /* Mix key in each "round" */ - PPK[1] += _S_(PPK[0] ^ TK16(1)); - PPK[2] += _S_(PPK[1] ^ TK16(2)); - PPK[3] += _S_(PPK[2] ^ TK16(3)); - PPK[4] += _S_(PPK[3] ^ TK16(4)); - PPK[5] += _S_(PPK[4] ^ TK16(5)); /* Total # S-box lookups == 6 */ - - /* Final sweep: bijective, "linear". Rotates kill LSB correlations */ - PPK[0] += RotR1(PPK[5] ^ TK16(6)); - PPK[1] += RotR1(PPK[0] ^ TK16(7)); /* Use all of TK[] in Phase2 */ - PPK[2] += RotR1(PPK[1]); - PPK[3] += RotR1(PPK[2]); - PPK[4] += RotR1(PPK[3]); - PPK[5] += RotR1(PPK[4]); - /* Note: At this point, for a given key TK[0..15], the 96-bit output */ - /* value PPK[0..5] is guaranteed to be unique, as a function */ - /* of the 96-bit "input" value {TA, IV32, IV16}. That is, P1K */ - /* is now a keyed permutation of {TA, IV32, IV16}. */ - - /* Set RC4KEY[0..3], which includes "cleartext" portion of RC4 key */ - rc4key[0] = Hi8(iv16); /* RC4KEY[0..2] is the WEP IV */ - rc4key[1] = (Hi8(iv16) | 0x20) & 0x7F; /* Help avoid weak (FMS) keys */ - rc4key[2] = Lo8(iv16); - rc4key[3] = Lo8((PPK[5] ^ TK16(0)) >> 1); - - /* Copy 96 bits of PPK[0..5] to RC4KEY[4..15] (little-endian) */ - for (i = 0; i < 6; i++) { - rc4key[4 + 2 * i] = Lo8(PPK[i]); - rc4key[5 + 2 * i] = Hi8(PPK[i]); - } - -} - -/* The hlen isn't include the IV */ -u32 rtw_tkip_encrypt(struct adapter *padapter, struct xmit_frame *pxmitframe) -{ /* exclude ICV */ - u16 pnl; - u32 pnh; - u8 rc4key[16]; - u8 ttkey[16]; - union { - __le32 f0; - u8 f1[4]; - } crc; - u8 hw_hdr_offset = 0; - int curfragnum, length; - - u8 *pframe, *payload, *iv, *prwskey; - union pn48 dot11txpn; - struct sta_info *stainfo; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct arc4_ctx *ctx = &psecuritypriv->xmit_arc4_ctx; - u32 res = _SUCCESS; - - if (!pxmitframe->buf_addr) - return _FAIL; - - hw_hdr_offset = TXDESC_SIZE + pxmitframe->pkt_offset * PACKET_OFFSET_SZ; - pframe = pxmitframe->buf_addr + hw_hdr_offset; - - /* 4 start to encrypt each fragment */ - if (pattrib->encrypt == _TKIP_) { - if (pattrib->psta) - stainfo = pattrib->psta; - else - stainfo = rtw_get_stainfo(&padapter->stapriv, &pattrib->ra[0]); - - if (stainfo) { - if (is_multicast_ether_addr(pattrib->ra)) - prwskey = psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey; - else - prwskey = &stainfo->dot118021x_UncstKey.skey[0]; - - for (curfragnum = 0; curfragnum < pattrib->nr_frags; curfragnum++) { - iv = pframe + pattrib->hdrlen; - payload = pframe + pattrib->iv_len + pattrib->hdrlen; - - GET_TKIP_PN(iv, dot11txpn); - - pnl = (u16)(dot11txpn.val); - pnh = (u32)(dot11txpn.val >> 16); - phase1((u16 *)&ttkey[0], prwskey, &pattrib->ta[0], pnh); - phase2(&rc4key[0], prwskey, (u16 *)&ttkey[0], pnl); - - if ((curfragnum + 1) == pattrib->nr_frags) { /* 4 the last fragment */ - length = pattrib->last_txcmdsz - pattrib->hdrlen - pattrib->iv_len - pattrib->icv_len; - crc.f0 = cpu_to_le32(~crc32_le(~0, payload, length)); - - arc4_setkey(ctx, rc4key, 16); - arc4_crypt(ctx, payload, payload, length); - arc4_crypt(ctx, payload + length, crc.f1, 4); - } else { - length = pxmitpriv->frag_len - pattrib->hdrlen - pattrib->iv_len - pattrib->icv_len; - crc.f0 = cpu_to_le32(~crc32_le(~0, payload, length)); - - arc4_setkey(ctx, rc4key, 16); - arc4_crypt(ctx, payload, payload, length); - arc4_crypt(ctx, payload + length, crc.f1, 4); - - pframe += pxmitpriv->frag_len; - pframe = PTR_ALIGN(pframe, 4); - } - } - } else { - res = _FAIL; - } - } - - return res; -} - -/* The hlen isn't include the IV */ -u32 rtw_tkip_decrypt(struct adapter *padapter, struct recv_frame *precvframe) -{ /* exclude ICV */ - u16 pnl; - u32 pnh; - u8 rc4key[16]; - u8 ttkey[16]; - union { - __le32 f0; - u8 f1[4]; - } crc; - int length; - - u8 *pframe, *payload, *iv, *prwskey; - union pn48 dot11txpn; - struct sta_info *stainfo; - struct rx_pkt_attrib *prxattrib = &precvframe->attrib; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct arc4_ctx *ctx = &psecuritypriv->recv_arc4_ctx; - u32 res = _SUCCESS; - - pframe = precvframe->rx_data; - - /* 4 start to decrypt recvframe */ - if (prxattrib->encrypt == _TKIP_) { - stainfo = rtw_get_stainfo(&padapter->stapriv, &prxattrib->ta[0]); - if (stainfo) { - if (is_multicast_ether_addr(prxattrib->ra)) { - if (!psecuritypriv->binstallGrpkey) { - res = _FAIL; - goto exit; - } - prwskey = psecuritypriv->dot118021XGrpKey[prxattrib->key_index].skey; - } else { - prwskey = &stainfo->dot118021x_UncstKey.skey[0]; - } - - iv = pframe + prxattrib->hdrlen; - payload = pframe + prxattrib->iv_len + prxattrib->hdrlen; - length = precvframe->len - prxattrib->hdrlen - prxattrib->iv_len; - - GET_TKIP_PN(iv, dot11txpn); - - pnl = (u16)(dot11txpn.val); - pnh = (u32)(dot11txpn.val >> 16); - - phase1((u16 *)&ttkey[0], prwskey, &prxattrib->ta[0], pnh); - phase2(&rc4key[0], prwskey, (unsigned short *)&ttkey[0], pnl); - - /* 4 decrypt payload include icv */ - - arc4_setkey(ctx, rc4key, 16); - arc4_crypt(ctx, payload, payload, length); - - crc.f0 = cpu_to_le32(~crc32_le(~0, payload, length)); - - if (crc.f1[3] != payload[length - 1] || - crc.f1[2] != payload[length - 2] || - crc.f1[1] != payload[length - 3] || - crc.f1[0] != payload[length - 4]) - res = _FAIL; - } else { - res = _FAIL; - } - } - -exit: - return res; -} - -/* 3 ===== AES related ===== */ - -#define MAX_MSG_SIZE 2048 -/*****************************/ -/******** SBOX Table *********/ -/*****************************/ - -static u8 sbox_table[256] = { - 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, - 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, - 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, - 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, - 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, - 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, - 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, - 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, - 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, - 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, - 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, - 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, - 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, - 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, - 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, - 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, - 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, - 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, - 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, - 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, - 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, - 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, - 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, - 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, - 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, - 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, - 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, - 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, - 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, - 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, - 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, - 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 -}; - -/*****************************/ -/**** Function Prototypes ****/ -/*****************************/ - -static void bitwise_xor(u8 *ina, u8 *inb, u8 *out); -static void construct_mic_iv(u8 *mic_header1, int qc_exists, int a4_exists, u8 *mpdu, uint payload_length, u8 *pn_vector); -static void construct_mic_header1(u8 *mic_header1, int header_length, u8 *mpdu); -static void construct_mic_header2(u8 *mic_header2, u8 *mpdu, int a4_exists, int qc_exists); -static void construct_ctr_preload(u8 *ctr_preload, int a4_exists, int qc_exists, u8 *mpdu, u8 *pn_vector, int c); -static void xor_128(u8 *a, u8 *b, u8 *out); -static void xor_32(u8 *a, u8 *b, u8 *out); -static u8 sbox(u8 a); -static void next_key(u8 *key, int round); -static void byte_sub(u8 *in, u8 *out); -static void shift_row(u8 *in, u8 *out); -static void mix_column(u8 *in, u8 *out); -static void aes128k128d(u8 *key, u8 *data, u8 *ciphertext); - -/****************************************/ -/* aes128k128d() */ -/* Performs a 128 bit AES encrypt with */ -/* 128 bit data. */ -/****************************************/ -static void xor_128(u8 *a, u8 *b, u8 *out) -{ - int i; - - for (i = 0; i < 16; i++) - out[i] = a[i] ^ b[i]; - -} - -static void xor_32(u8 *a, u8 *b, u8 *out) -{ - int i; - - for (i = 0; i < 4; i++) - out[i] = a[i] ^ b[i]; - -} - -static u8 sbox(u8 a) -{ - return sbox_table[(int)a]; -} - -static void next_key(u8 *key, int round) -{ - u8 rcon; - u8 sbox_key[4]; - u8 rcon_table[12] = { - 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, - 0x1b, 0x36, 0x36, 0x36 - }; - - sbox_key[0] = sbox(key[13]); - sbox_key[1] = sbox(key[14]); - sbox_key[2] = sbox(key[15]); - sbox_key[3] = sbox(key[12]); - - rcon = rcon_table[round]; - - xor_32(&key[0], sbox_key, &key[0]); - key[0] = key[0] ^ rcon; - - xor_32(&key[4], &key[0], &key[4]); - xor_32(&key[8], &key[4], &key[8]); - xor_32(&key[12], &key[8], &key[12]); - -} - -static void byte_sub(u8 *in, u8 *out) -{ - int i; - - for (i = 0; i < 16; i++) - out[i] = sbox(in[i]); - -} - -static void shift_row(u8 *in, u8 *out) -{ - - out[0] = in[0]; - out[1] = in[5]; - out[2] = in[10]; - out[3] = in[15]; - out[4] = in[4]; - out[5] = in[9]; - out[6] = in[14]; - out[7] = in[3]; - out[8] = in[8]; - out[9] = in[13]; - out[10] = in[2]; - out[11] = in[7]; - out[12] = in[12]; - out[13] = in[1]; - out[14] = in[6]; - out[15] = in[11]; - -} - -static void mix_column(u8 *in, u8 *out) -{ - int i; - u8 add1b[4]; - u8 add1bf7[4]; - u8 rotl[4]; - u8 swap_halfs[4]; - u8 andf7[4]; - u8 rotr[4]; - u8 temp[4]; - u8 tempb[4]; - - for (i = 0 ; i < 4; i++) { - if ((in[i] & 0x80) == 0x80) - add1b[i] = 0x1b; - else - add1b[i] = 0x00; - } - - swap_halfs[0] = in[2]; /* Swap halves */ - swap_halfs[1] = in[3]; - swap_halfs[2] = in[0]; - swap_halfs[3] = in[1]; - - rotl[0] = in[3]; /* Rotate left 8 bits */ - rotl[1] = in[0]; - rotl[2] = in[1]; - rotl[3] = in[2]; - - andf7[0] = in[0] & 0x7f; - andf7[1] = in[1] & 0x7f; - andf7[2] = in[2] & 0x7f; - andf7[3] = in[3] & 0x7f; - - for (i = 3; i > 0; i--) { /* logical shift left 1 bit */ - andf7[i] = andf7[i] << 1; - if ((andf7[i - 1] & 0x80) == 0x80) - andf7[i] = (andf7[i] | 0x01); - } - andf7[0] = andf7[0] << 1; - andf7[0] = andf7[0] & 0xfe; - - xor_32(add1b, andf7, add1bf7); - - xor_32(in, add1bf7, rotr); - - temp[0] = rotr[0]; /* Rotate right 8 bits */ - rotr[0] = rotr[1]; - rotr[1] = rotr[2]; - rotr[2] = rotr[3]; - rotr[3] = temp[0]; - - xor_32(add1bf7, rotr, temp); - xor_32(swap_halfs, rotl, tempb); - xor_32(temp, tempb, out); - -} - -static void aes128k128d(u8 *key, u8 *data, u8 *ciphertext) -{ - int round; - int i; - u8 intermediatea[16]; - u8 intermediateb[16]; - u8 round_key[16]; - - for (i = 0; i < 16; i++) - round_key[i] = key[i]; - for (round = 0; round < 11; round++) { - if (round == 0) { - xor_128(round_key, data, ciphertext); - next_key(round_key, round); - } else if (round == 10) { - byte_sub(ciphertext, intermediatea); - shift_row(intermediatea, intermediateb); - xor_128(intermediateb, round_key, ciphertext); - } else { /* 1 - 9 */ - byte_sub(ciphertext, intermediatea); - shift_row(intermediatea, intermediateb); - mix_column(&intermediateb[0], &intermediatea[0]); - mix_column(&intermediateb[4], &intermediatea[4]); - mix_column(&intermediateb[8], &intermediatea[8]); - mix_column(&intermediateb[12], &intermediatea[12]); - xor_128(intermediatea, round_key, ciphertext); - next_key(round_key, round); - } - } - -} - -/************************************************/ -/* construct_mic_iv() */ -/* Builds the MIC IV from header fields and PN */ -/************************************************/ -static void construct_mic_iv(u8 *mic_iv, int qc_exists, int a4_exists, u8 *mpdu, - uint payload_length, u8 *pn_vector) -{ - int i; - - mic_iv[0] = 0x59; - if (qc_exists && a4_exists) - mic_iv[1] = mpdu[30] & 0x0f; /* QoS_TC */ - if (qc_exists && !a4_exists) - mic_iv[1] = mpdu[24] & 0x0f; /* mute bits 7-4 */ - if (!qc_exists) - mic_iv[1] = 0x00; - for (i = 2; i < 8; i++) - mic_iv[i] = mpdu[i + 8]; /* mic_iv[2:7] = A2[0:5] = mpdu[10:15] */ - for (i = 8; i < 14; i++) - mic_iv[i] = pn_vector[13 - i]; /* mic_iv[8:13] = PN[5:0] */ - mic_iv[14] = (unsigned char)(payload_length / 256); - mic_iv[15] = (unsigned char)(payload_length % 256); - -} - -/************************************************/ -/* construct_mic_header1() */ -/* Builds the first MIC header block from */ -/* header fields. */ -/************************************************/ -static void construct_mic_header1(u8 *mic_header1, int header_length, u8 *mpdu) -{ - - mic_header1[0] = (u8)((header_length - 2) / 256); - mic_header1[1] = (u8)((header_length - 2) % 256); - mic_header1[2] = mpdu[0] & 0xcf; /* Mute CF poll & CF ack bits */ - mic_header1[3] = mpdu[1] & 0xc7; /* Mute retry, more data and pwr mgt bits */ - mic_header1[4] = mpdu[4]; /* A1 */ - mic_header1[5] = mpdu[5]; - mic_header1[6] = mpdu[6]; - mic_header1[7] = mpdu[7]; - mic_header1[8] = mpdu[8]; - mic_header1[9] = mpdu[9]; - mic_header1[10] = mpdu[10]; /* A2 */ - mic_header1[11] = mpdu[11]; - mic_header1[12] = mpdu[12]; - mic_header1[13] = mpdu[13]; - mic_header1[14] = mpdu[14]; - mic_header1[15] = mpdu[15]; - -} - -/************************************************/ -/* construct_mic_header2() */ -/* Builds the last MIC header block from */ -/* header fields. */ -/************************************************/ -static void construct_mic_header2(u8 *mic_header2, u8 *mpdu, int a4_exists, int qc_exists) -{ - int i; - - for (i = 0; i < 16; i++) - mic_header2[i] = 0x00; - - mic_header2[0] = mpdu[16]; /* A3 */ - mic_header2[1] = mpdu[17]; - mic_header2[2] = mpdu[18]; - mic_header2[3] = mpdu[19]; - mic_header2[4] = mpdu[20]; - mic_header2[5] = mpdu[21]; - - mic_header2[6] = 0x00; - mic_header2[7] = 0x00; /* mpdu[23]; */ - - if (!qc_exists && a4_exists) { - for (i = 0; i < 6; i++) - mic_header2[8 + i] = mpdu[24 + i]; /* A4 */ - } - - if (qc_exists && !a4_exists) { - mic_header2[8] = mpdu[24] & 0x0f; /* mute bits 15 - 4 */ - mic_header2[9] = mpdu[25] & 0x00; - } - - if (qc_exists && a4_exists) { - for (i = 0; i < 6; i++) - mic_header2[8 + i] = mpdu[24 + i]; /* A4 */ - - mic_header2[14] = mpdu[30] & 0x0f; - mic_header2[15] = mpdu[31] & 0x00; - } - -} - -/************************************************/ -/* construct_mic_header2() */ -/* Builds the last MIC header block from */ -/* header fields. */ -/************************************************/ -static void construct_ctr_preload(u8 *ctr_preload, int a4_exists, int qc_exists, u8 *mpdu, u8 *pn_vector, int c) -{ - int i; - - for (i = 0; i < 16; i++) - ctr_preload[i] = 0x00; - i = 0; - - ctr_preload[0] = 0x01; /* flag */ - if (qc_exists && a4_exists) - ctr_preload[1] = mpdu[30] & 0x0f; /* QoC_Control */ - if (qc_exists && !a4_exists) - ctr_preload[1] = mpdu[24] & 0x0f; - - for (i = 2; i < 8; i++) - ctr_preload[i] = mpdu[i + 8]; /* ctr_preload[2:7] = A2[0:5] = mpdu[10:15] */ - for (i = 8; i < 14; i++) - ctr_preload[i] = pn_vector[13 - i]; /* ctr_preload[8:13] = PN[5:0] */ - ctr_preload[14] = (unsigned char)(c / 256); /* Ctr */ - ctr_preload[15] = (unsigned char)(c % 256); - -} - -/************************************/ -/* bitwise_xor() */ -/* A 128 bit, bitwise exclusive or */ -/************************************/ -static void bitwise_xor(u8 *ina, u8 *inb, u8 *out) -{ - int i; - - for (i = 0; i < 16; i++) - out[i] = ina[i] ^ inb[i]; - -} - -static void aes_cipher(u8 *key, uint hdrlen, u8 *pframe, uint plen) -{ - uint qc_exists, a4_exists, i, j, payload_remainder, - num_blocks, payload_index; - - u8 pn_vector[6]; - u8 mic_iv[16]; - u8 mic_header1[16]; - u8 mic_header2[16]; - u8 ctr_preload[16]; - - /* Intermediate Buffers */ - u8 chain_buffer[16]; - u8 aes_out[16]; - u8 padded_buffer[16]; - u8 mic[8]; - uint frtype = GetFrameType(pframe); - uint frsubtype = GetFrameSubType(pframe); - - frsubtype = frsubtype >> 4; - - memset((void *)mic_iv, 0, 16); - memset((void *)mic_header1, 0, 16); - memset((void *)mic_header2, 0, 16); - memset((void *)ctr_preload, 0, 16); - memset((void *)chain_buffer, 0, 16); - memset((void *)aes_out, 0, 16); - memset((void *)padded_buffer, 0, 16); - - if ((hdrlen == WLAN_HDR_A3_LEN) || (hdrlen == WLAN_HDR_A3_QOS_LEN)) - a4_exists = 0; - else - a4_exists = 1; - - if ((frtype == WIFI_DATA_CFACK) || (frtype == WIFI_DATA_CFPOLL) || (frtype == WIFI_DATA_CFACKPOLL)) { - qc_exists = 1; - if (hdrlen != WLAN_HDR_A3_QOS_LEN) - hdrlen += 2; - } else if ((frsubtype == 0x08) || (frsubtype == 0x09) || (frsubtype == 0x0a) || (frsubtype == 0x0b)) { - if (hdrlen != WLAN_HDR_A3_QOS_LEN) - hdrlen += 2; - qc_exists = 1; - } else { - qc_exists = 0; - } - - pn_vector[0] = pframe[hdrlen]; - pn_vector[1] = pframe[hdrlen + 1]; - pn_vector[2] = pframe[hdrlen + 4]; - pn_vector[3] = pframe[hdrlen + 5]; - pn_vector[4] = pframe[hdrlen + 6]; - pn_vector[5] = pframe[hdrlen + 7]; - - construct_mic_iv(mic_iv, qc_exists, a4_exists, pframe, plen, pn_vector); - - construct_mic_header1(mic_header1, hdrlen, pframe); - construct_mic_header2(mic_header2, pframe, a4_exists, qc_exists); - - payload_remainder = plen % 16; - num_blocks = plen / 16; - - /* Find start of payload */ - payload_index = (hdrlen + 8); - - /* Calculate MIC */ - aes128k128d(key, mic_iv, aes_out); - bitwise_xor(aes_out, mic_header1, chain_buffer); - aes128k128d(key, chain_buffer, aes_out); - bitwise_xor(aes_out, mic_header2, chain_buffer); - aes128k128d(key, chain_buffer, aes_out); - - for (i = 0; i < num_blocks; i++) { - bitwise_xor(aes_out, &pframe[payload_index], chain_buffer);/* bitwise_xor(aes_out, &message[payload_index], chain_buffer); */ - - payload_index += 16; - aes128k128d(key, chain_buffer, aes_out); - } - - /* Add on the final payload block if it needs padding */ - if (payload_remainder > 0) { - for (j = 0; j < 16; j++) - padded_buffer[j] = 0x00; - for (j = 0; j < payload_remainder; j++) - padded_buffer[j] = pframe[payload_index++];/* padded_buffer[j] = message[payload_index++]; */ - bitwise_xor(aes_out, padded_buffer, chain_buffer); - aes128k128d(key, chain_buffer, aes_out); - } - - for (j = 0; j < 8; j++) - mic[j] = aes_out[j]; - - /* Insert MIC into payload */ - for (j = 0; j < 8; j++) - pframe[payload_index + j] = mic[j]; /* message[payload_index+j] = mic[j]; */ - - payload_index = hdrlen + 8; - for (i = 0; i < num_blocks; i++) { - construct_ctr_preload(ctr_preload, a4_exists, qc_exists, pframe, pn_vector, i + 1); - aes128k128d(key, ctr_preload, aes_out); - bitwise_xor(aes_out, &pframe[payload_index], chain_buffer); - for (j = 0; j < 16; j++) - pframe[payload_index++] = chain_buffer[j]; - } - - if (payload_remainder > 0) { /* If there is a short final block, then pad it,*/ - /* encrypt it and copy the unpadded part back */ - construct_ctr_preload(ctr_preload, a4_exists, qc_exists, pframe, pn_vector, num_blocks + 1); - - for (j = 0; j < 16; j++) - padded_buffer[j] = 0x00; - for (j = 0; j < payload_remainder; j++) - padded_buffer[j] = pframe[payload_index + j]; - aes128k128d(key, ctr_preload, aes_out); - bitwise_xor(aes_out, padded_buffer, chain_buffer); - for (j = 0; j < payload_remainder; j++) - pframe[payload_index++] = chain_buffer[j]; - } - /* Encrypt the MIC */ - construct_ctr_preload(ctr_preload, a4_exists, qc_exists, pframe, pn_vector, 0); - - for (j = 0; j < 16; j++) - padded_buffer[j] = 0x00; - for (j = 0; j < 8; j++) - padded_buffer[j] = pframe[j + hdrlen + 8 + plen]; - - aes128k128d(key, ctr_preload, aes_out); - bitwise_xor(aes_out, padded_buffer, chain_buffer); - for (j = 0; j < 8; j++) - pframe[payload_index++] = chain_buffer[j]; -} - -u32 rtw_aes_encrypt(struct adapter *padapter, struct xmit_frame *pxmitframe) -{ /* exclude ICV */ - - /*static*/ -/* unsigned char message[MAX_MSG_SIZE]; */ - - /* Intermediate Buffers */ - int curfragnum, length; - u8 *pframe, *prwskey; /* *payload,*iv */ - u8 hw_hdr_offset = 0; - struct sta_info *stainfo; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - -/* uint offset = 0; */ - u32 res = _SUCCESS; - - if (!pxmitframe->buf_addr) - return _FAIL; - - hw_hdr_offset = TXDESC_SIZE + pxmitframe->pkt_offset * PACKET_OFFSET_SZ; - pframe = pxmitframe->buf_addr + hw_hdr_offset; - - /* 4 start to encrypt each fragment */ - if (pattrib->encrypt == _AES_) { - if (pattrib->psta) - stainfo = pattrib->psta; - else - stainfo = rtw_get_stainfo(&padapter->stapriv, &pattrib->ra[0]); - - if (stainfo) { - if (is_multicast_ether_addr(pattrib->ra)) - prwskey = psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey; - else - prwskey = &stainfo->dot118021x_UncstKey.skey[0]; - for (curfragnum = 0; curfragnum < pattrib->nr_frags; curfragnum++) { - if ((curfragnum + 1) == pattrib->nr_frags) { /* 4 the last fragment */ - length = pattrib->last_txcmdsz - pattrib->hdrlen - pattrib->iv_len - pattrib->icv_len; - - aes_cipher(prwskey, pattrib->hdrlen, pframe, length); - } else { - length = pxmitpriv->frag_len - pattrib->hdrlen - pattrib->iv_len - pattrib->icv_len; - - aes_cipher(prwskey, pattrib->hdrlen, pframe, length); - pframe += pxmitpriv->frag_len; - pframe = PTR_ALIGN(pframe, 4); - } - } - } else { - res = _FAIL; - } - } - - return res; -} - -static int aes_decipher(u8 *key, uint hdrlen, - u8 *pframe, uint plen) -{ - static u8 message[MAX_MSG_SIZE]; - uint qc_exists, a4_exists, i, j, payload_remainder, - num_blocks, payload_index; - int res = _SUCCESS; - u8 pn_vector[6]; - u8 mic_iv[16]; - u8 mic_header1[16]; - u8 mic_header2[16]; - u8 ctr_preload[16]; - - /* Intermediate Buffers */ - u8 chain_buffer[16]; - u8 aes_out[16]; - u8 padded_buffer[16]; - u8 mic[8]; - -/* uint offset = 0; */ - uint frtype = GetFrameType(pframe); - uint frsubtype = GetFrameSubType(pframe); - - frsubtype = frsubtype >> 4; - - memset((void *)mic_iv, 0, 16); - memset((void *)mic_header1, 0, 16); - memset((void *)mic_header2, 0, 16); - memset((void *)ctr_preload, 0, 16); - memset((void *)chain_buffer, 0, 16); - memset((void *)aes_out, 0, 16); - memset((void *)padded_buffer, 0, 16); - - /* start to decrypt the payload */ - - num_blocks = (plen - 8) / 16; /* plen including llc, payload_length and mic) */ - - payload_remainder = (plen - 8) % 16; - - pn_vector[0] = pframe[hdrlen]; - pn_vector[1] = pframe[hdrlen + 1]; - pn_vector[2] = pframe[hdrlen + 4]; - pn_vector[3] = pframe[hdrlen + 5]; - pn_vector[4] = pframe[hdrlen + 6]; - pn_vector[5] = pframe[hdrlen + 7]; - - if ((hdrlen == WLAN_HDR_A3_LEN) || (hdrlen == WLAN_HDR_A3_QOS_LEN)) - a4_exists = 0; - else - a4_exists = 1; - - if ((frtype == WIFI_DATA_CFACK) || (frtype == WIFI_DATA_CFPOLL) || - (frtype == WIFI_DATA_CFACKPOLL)) { - qc_exists = 1; - if (hdrlen != WLAN_HDR_A3_QOS_LEN) - hdrlen += 2; - } else if ((frsubtype == 0x08) || (frsubtype == 0x09) || - (frsubtype == 0x0a) || (frsubtype == 0x0b)) { - if (hdrlen != WLAN_HDR_A3_QOS_LEN) - hdrlen += 2; - qc_exists = 1; - } else { - qc_exists = 0; - } - - /* now, decrypt pframe with hdrlen offset and plen long */ - - payload_index = hdrlen + 8; /* 8 is for extiv */ - - for (i = 0; i < num_blocks; i++) { - construct_ctr_preload(ctr_preload, a4_exists, qc_exists, pframe, pn_vector, i + 1); - - aes128k128d(key, ctr_preload, aes_out); - bitwise_xor(aes_out, &pframe[payload_index], chain_buffer); - - for (j = 0; j < 16; j++) - pframe[payload_index++] = chain_buffer[j]; - } - - if (payload_remainder > 0) { /* If there is a short final block, then pad it,*/ - /* encrypt it and copy the unpadded part back */ - construct_ctr_preload(ctr_preload, a4_exists, qc_exists, pframe, pn_vector, num_blocks + 1); - - for (j = 0; j < 16; j++) - padded_buffer[j] = 0x00; - for (j = 0; j < payload_remainder; j++) - padded_buffer[j] = pframe[payload_index + j]; - aes128k128d(key, ctr_preload, aes_out); - bitwise_xor(aes_out, padded_buffer, chain_buffer); - for (j = 0; j < payload_remainder; j++) - pframe[payload_index++] = chain_buffer[j]; - } - - /* start to calculate the mic */ - if ((hdrlen + plen + 8) <= MAX_MSG_SIZE) - memcpy(message, pframe, (hdrlen + plen + 8)); /* 8 is for ext iv len */ - - pn_vector[0] = pframe[hdrlen]; - pn_vector[1] = pframe[hdrlen + 1]; - pn_vector[2] = pframe[hdrlen + 4]; - pn_vector[3] = pframe[hdrlen + 5]; - pn_vector[4] = pframe[hdrlen + 6]; - pn_vector[5] = pframe[hdrlen + 7]; - construct_mic_iv(mic_iv, qc_exists, a4_exists, message, plen - 8, pn_vector); - - construct_mic_header1(mic_header1, hdrlen, message); - construct_mic_header2(mic_header2, message, a4_exists, qc_exists); - - payload_remainder = (plen - 8) % 16; - num_blocks = (plen - 8) / 16; - - /* Find start of payload */ - payload_index = (hdrlen + 8); - - /* Calculate MIC */ - aes128k128d(key, mic_iv, aes_out); - bitwise_xor(aes_out, mic_header1, chain_buffer); - aes128k128d(key, chain_buffer, aes_out); - bitwise_xor(aes_out, mic_header2, chain_buffer); - aes128k128d(key, chain_buffer, aes_out); - - for (i = 0; i < num_blocks; i++) { - bitwise_xor(aes_out, &message[payload_index], chain_buffer); - - payload_index += 16; - aes128k128d(key, chain_buffer, aes_out); - } - - /* Add on the final payload block if it needs padding */ - if (payload_remainder > 0) { - for (j = 0; j < 16; j++) - padded_buffer[j] = 0x00; - for (j = 0; j < payload_remainder; j++) - padded_buffer[j] = message[payload_index++]; - bitwise_xor(aes_out, padded_buffer, chain_buffer); - aes128k128d(key, chain_buffer, aes_out); - } - - for (j = 0 ; j < 8; j++) - mic[j] = aes_out[j]; - - /* Insert MIC into payload */ - for (j = 0; j < 8; j++) - message[payload_index + j] = mic[j]; - - payload_index = hdrlen + 8; - for (i = 0; i < num_blocks; i++) { - construct_ctr_preload(ctr_preload, a4_exists, qc_exists, message, pn_vector, i + 1); - aes128k128d(key, ctr_preload, aes_out); - bitwise_xor(aes_out, &message[payload_index], chain_buffer); - for (j = 0; j < 16; j++) - message[payload_index++] = chain_buffer[j]; - } - - if (payload_remainder > 0) { /* If there is a short final block, then pad it,*/ - /* encrypt it and copy the unpadded part back */ - construct_ctr_preload(ctr_preload, a4_exists, qc_exists, message, pn_vector, num_blocks + 1); - - for (j = 0; j < 16; j++) - padded_buffer[j] = 0x00; - for (j = 0; j < payload_remainder; j++) - padded_buffer[j] = message[payload_index + j]; - aes128k128d(key, ctr_preload, aes_out); - bitwise_xor(aes_out, padded_buffer, chain_buffer); - for (j = 0; j < payload_remainder; j++) - message[payload_index++] = chain_buffer[j]; - } - - /* Encrypt the MIC */ - construct_ctr_preload(ctr_preload, a4_exists, qc_exists, message, pn_vector, 0); - - for (j = 0; j < 16; j++) - padded_buffer[j] = 0x00; - for (j = 0; j < 8; j++) - padded_buffer[j] = message[j + hdrlen + 8 + plen - 8]; - - aes128k128d(key, ctr_preload, aes_out); - bitwise_xor(aes_out, padded_buffer, chain_buffer); - for (j = 0; j < 8; j++) - message[payload_index++] = chain_buffer[j]; - - /* compare the mic */ - for (i = 0; i < 8; i++) { - if (pframe[hdrlen + 8 + plen - 8 + i] != message[hdrlen + 8 + plen - 8 + i]) - res = _FAIL; - } - - return res; -} - -u32 rtw_aes_decrypt(struct adapter *padapter, struct recv_frame *precvframe) -{ /* exclude ICV */ - /* Intermediate Buffers */ - int length; - u8 *pframe, *prwskey; /* *payload,*iv */ - struct sta_info *stainfo; - struct rx_pkt_attrib *prxattrib = &precvframe->attrib; - struct security_priv *psecuritypriv = &padapter->securitypriv; - u32 res = _SUCCESS; - - pframe = precvframe->rx_data; - - /* 4 start to encrypt each fragment */ - if (prxattrib->encrypt == _AES_) { - stainfo = rtw_get_stainfo(&padapter->stapriv, &prxattrib->ta[0]); - if (stainfo) { - if (is_multicast_ether_addr(prxattrib->ra)) { - /* in concurrent we should use sw descrypt in group key, so we remove this message */ - if (!psecuritypriv->binstallGrpkey) { - res = _FAIL; - goto exit; - } - prwskey = psecuritypriv->dot118021XGrpKey[prxattrib->key_index].skey; - if (psecuritypriv->dot118021XGrpKeyid != prxattrib->key_index) { - res = _FAIL; - goto exit; - } - } else { - prwskey = &stainfo->dot118021x_UncstKey.skey[0]; - } - length = precvframe->len - prxattrib->hdrlen - prxattrib->iv_len; - res = aes_decipher(prwskey, prxattrib->hdrlen, pframe, length); - } else { - res = _FAIL; - } - } - -exit: - return res; -} diff --git a/drivers/staging/r8188eu/core/rtw_sta_mgt.c b/drivers/staging/r8188eu/core/rtw_sta_mgt.c deleted file mode 100644 index e1ae1859686e..000000000000 --- a/drivers/staging/r8188eu/core/rtw_sta_mgt.c +++ /dev/null @@ -1,490 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#define _RTW_STA_MGT_C_ - -#include "../include/osdep_service.h" -#include "../include/drv_types.h" -#include "../include/sta_info.h" - -static void _rtw_init_stainfo(struct sta_info *psta) -{ - - memset((u8 *)psta, 0, sizeof(struct sta_info)); - - spin_lock_init(&psta->lock); - INIT_LIST_HEAD(&psta->list); - INIT_LIST_HEAD(&psta->hash_list); - rtw_init_queue(&psta->sleep_q); - psta->sleepq_len = 0; - - _rtw_init_sta_xmit_priv(&psta->sta_xmitpriv); - _rtw_init_sta_recv_priv(&psta->sta_recvpriv); - - INIT_LIST_HEAD(&psta->asoc_list); - - INIT_LIST_HEAD(&psta->auth_list); - - psta->expire_to = 0; - - psta->flags = 0; - - psta->capability = 0; - - psta->bpairwise_key_installed = false; - - psta->nonerp_set = 0; - psta->no_short_slot_time_set = 0; - psta->no_short_preamble_set = 0; - psta->no_ht_gf_set = 0; - psta->no_ht_set = 0; - psta->ht_20mhz_set = 0; - - psta->under_exist_checking = 0; - - psta->keep_alive_trycnt = 0; -} - -int _rtw_init_sta_priv(struct sta_priv *pstapriv) -{ - struct sta_info *psta; - s32 i; - - pstapriv->pallocated_stainfo_buf = vzalloc(sizeof(struct sta_info) * NUM_STA + 4); - - if (!pstapriv->pallocated_stainfo_buf) - return -ENOMEM; - - pstapriv->pstainfo_buf = pstapriv->pallocated_stainfo_buf + 4 - - ((size_t)(pstapriv->pallocated_stainfo_buf) & 3); - - rtw_init_queue(&pstapriv->free_sta_queue); - - spin_lock_init(&pstapriv->sta_hash_lock); - - pstapriv->asoc_sta_count = 0; - rtw_init_queue(&pstapriv->sleep_q); - rtw_init_queue(&pstapriv->wakeup_q); - - psta = (struct sta_info *)(pstapriv->pstainfo_buf); - - for (i = 0; i < NUM_STA; i++) { - _rtw_init_stainfo(psta); - - INIT_LIST_HEAD(&pstapriv->sta_hash[i]); - - list_add_tail(&psta->list, get_list_head(&pstapriv->free_sta_queue)); - - psta++; - } - - pstapriv->sta_dz_bitmap = 0; - pstapriv->tim_bitmap = 0; - - INIT_LIST_HEAD(&pstapriv->asoc_list); - INIT_LIST_HEAD(&pstapriv->auth_list); - spin_lock_init(&pstapriv->asoc_list_lock); - spin_lock_init(&pstapriv->auth_list_lock); - pstapriv->asoc_list_cnt = 0; - pstapriv->auth_list_cnt = 0; - - pstapriv->auth_to = 3; /* 3*2 = 6 sec */ - pstapriv->assoc_to = 3; - pstapriv->expire_to = 3; /* 3*2 = 6 sec */ - pstapriv->max_num_sta = NUM_STA; - - return 0; -} - -inline int rtw_stainfo_offset(struct sta_priv *stapriv, struct sta_info *sta) -{ - return (((u8 *)sta) - stapriv->pstainfo_buf) / sizeof(struct sta_info); -} - -inline struct sta_info *rtw_get_stainfo_by_offset(struct sta_priv *stapriv, int offset) -{ - return (struct sta_info *)(stapriv->pstainfo_buf + offset * sizeof(struct sta_info)); -} - -void _rtw_free_sta_priv(struct sta_priv *pstapriv) -{ - struct list_head *phead, *plist; - struct sta_info *psta = NULL; - struct recv_reorder_ctrl *preorder_ctrl; - int index; - - if (pstapriv) { - /* delete all reordering_ctrl_timer */ - spin_lock_bh(&pstapriv->sta_hash_lock); - for (index = 0; index < NUM_STA; index++) { - phead = &pstapriv->sta_hash[index]; - plist = phead->next; - - while (phead != plist) { - int i; - psta = container_of(plist, struct sta_info, hash_list); - plist = plist->next; - - for (i = 0; i < 16; i++) { - preorder_ctrl = &psta->recvreorder_ctrl[i]; - _cancel_timer_ex(&preorder_ctrl->reordering_ctrl_timer); - } - } - } - spin_unlock_bh(&pstapriv->sta_hash_lock); - /*===============================*/ - - vfree(pstapriv->pallocated_stainfo_buf); - } -} - -static void _rtw_reordering_ctrl_timeout_handler(struct timer_list *t) -{ - struct recv_reorder_ctrl *preorder_ctrl; - - preorder_ctrl = from_timer(preorder_ctrl, t, reordering_ctrl_timer); - rtw_reordering_ctrl_timeout_handler(preorder_ctrl); -} - -static void rtw_init_recv_timer(struct recv_reorder_ctrl *preorder_ctrl) -{ - timer_setup(&preorder_ctrl->reordering_ctrl_timer, _rtw_reordering_ctrl_timeout_handler, 0); -} - -static void _addba_timer_hdl(struct timer_list *t) -{ - struct sta_info *psta = from_timer(psta, t, addba_retry_timer); - - addba_timer_hdl(psta); -} - -static void init_addba_retry_timer(struct adapter *padapter, struct sta_info *psta) -{ - timer_setup(&psta->addba_retry_timer, _addba_timer_hdl, 0); -} - -struct sta_info *rtw_alloc_stainfo(struct sta_priv *pstapriv, u8 *hwaddr) -{ - s32 index; - struct list_head *phash_list; - struct sta_info *psta; - struct __queue *pfree_sta_queue; - struct recv_reorder_ctrl *preorder_ctrl; - int i = 0; - u16 wRxSeqInitialValue = 0xffff; - - pfree_sta_queue = &pstapriv->free_sta_queue; - - spin_lock_bh(&pfree_sta_queue->lock); - - if (list_empty(&pfree_sta_queue->queue)) { - spin_unlock_bh(&pfree_sta_queue->lock); - psta = NULL; - } else { - psta = container_of((&pfree_sta_queue->queue)->next, struct sta_info, list); - list_del_init(&psta->list); - spin_unlock_bh(&pfree_sta_queue->lock); - _rtw_init_stainfo(psta); - memcpy(psta->hwaddr, hwaddr, ETH_ALEN); - index = wifi_mac_hash(hwaddr); - if (index >= NUM_STA) { - psta = NULL; - goto exit; - } - phash_list = &pstapriv->sta_hash[index]; - - spin_lock_bh(&pstapriv->sta_hash_lock); - - list_add_tail(&psta->hash_list, phash_list); - - pstapriv->asoc_sta_count++; - - spin_unlock_bh(&pstapriv->sta_hash_lock); - -/* Commented by Albert 2009/08/13 */ -/* For the SMC router, the sequence number of first packet of WPS handshake will be 0. */ -/* In this case, this packet will be dropped by recv_decache function if we use the 0x00 as the default value for tid_rxseq variable. */ -/* So, we initialize the tid_rxseq variable as the 0xffff. */ - - for (i = 0; i < 16; i++) - memcpy(&psta->sta_recvpriv.rxcache.tid_rxseq[i], &wRxSeqInitialValue, 2); - - init_addba_retry_timer(pstapriv->padapter, psta); - - /* for A-MPDU Rx reordering buffer control */ - for (i = 0; i < 16; i++) { - preorder_ctrl = &psta->recvreorder_ctrl[i]; - - preorder_ctrl->padapter = pstapriv->padapter; - - preorder_ctrl->enable = false; - - preorder_ctrl->indicate_seq = 0xffff; - preorder_ctrl->wend_b = 0xffff; - preorder_ctrl->wsize_b = 64;/* 64; */ - - rtw_init_queue(&preorder_ctrl->pending_recvframe_queue); - - rtw_init_recv_timer(preorder_ctrl); - } - - /* init for DM */ - psta->rssi_stat.UndecoratedSmoothedPWDB = (-1); - psta->rssi_stat.UndecoratedSmoothedCCK = (-1); - - /* init for the sequence number of received management frame */ - psta->RxMgmtFrameSeqNum = 0xffff; - } - -exit: - - return psta; -} - -/* using pstapriv->sta_hash_lock to protect */ -void rtw_free_stainfo(struct adapter *padapter, struct sta_info *psta) -{ - int i; - struct __queue *pfree_sta_queue; - struct recv_reorder_ctrl *preorder_ctrl; - struct sta_xmit_priv *pstaxmitpriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct sta_priv *pstapriv = &padapter->stapriv; - - if (!psta) - return; - - pfree_sta_queue = &pstapriv->free_sta_queue; - - pstaxmitpriv = &psta->sta_xmitpriv; - - spin_lock_bh(&pxmitpriv->lock); - - rtw_free_xmitframe_list(pxmitpriv, get_list_head(&psta->sleep_q)); - psta->sleepq_len = 0; - - rtw_free_xmitframe_list(pxmitpriv, &pstaxmitpriv->vo_q.sta_pending); - - list_del_init(&pstaxmitpriv->vo_q.tx_pending); - - rtw_free_xmitframe_list(pxmitpriv, &pstaxmitpriv->vi_q.sta_pending); - - list_del_init(&pstaxmitpriv->vi_q.tx_pending); - - rtw_free_xmitframe_list(pxmitpriv, &pstaxmitpriv->bk_q.sta_pending); - - list_del_init(&pstaxmitpriv->bk_q.tx_pending); - - rtw_free_xmitframe_list(pxmitpriv, &pstaxmitpriv->be_q.sta_pending); - - list_del_init(&pstaxmitpriv->be_q.tx_pending); - - spin_unlock_bh(&pxmitpriv->lock); - - list_del_init(&psta->hash_list); - pstapriv->asoc_sta_count--; - - /* re-init sta_info; 20061114 */ - _rtw_init_sta_xmit_priv(&psta->sta_xmitpriv); - _rtw_init_sta_recv_priv(&psta->sta_recvpriv); - - _cancel_timer_ex(&psta->addba_retry_timer); - - /* for A-MPDU Rx reordering buffer control, cancel reordering_ctrl_timer */ - for (i = 0; i < 16 ; i++) { - struct list_head *phead, *plist; - struct recv_frame *prframe; - struct __queue *ppending_recvframe_queue; - struct __queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue; - - preorder_ctrl = &psta->recvreorder_ctrl[i]; - - _cancel_timer_ex(&preorder_ctrl->reordering_ctrl_timer); - - ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue; - - spin_lock_bh(&ppending_recvframe_queue->lock); - - phead = get_list_head(ppending_recvframe_queue); - plist = phead->next; - - while (!list_empty(phead)) { - prframe = container_of(plist, struct recv_frame, list); - - plist = plist->next; - - list_del_init(&prframe->list); - - rtw_free_recvframe(prframe, pfree_recv_queue); - } - - spin_unlock_bh(&ppending_recvframe_queue->lock); - } - - if (!(psta->state & WIFI_AP_STATE)) - rtl8188e_SetHalODMVar(padapter, psta, false); - - spin_lock_bh(&pstapriv->auth_list_lock); - if (!list_empty(&psta->auth_list)) { - list_del_init(&psta->auth_list); - pstapriv->auth_list_cnt--; - } - spin_unlock_bh(&pstapriv->auth_list_lock); - - psta->expire_to = 0; - - psta->sleepq_ac_len = 0; - psta->qos_info = 0; - - psta->max_sp_len = 0; - psta->uapsd_bk = 0; - psta->uapsd_be = 0; - psta->uapsd_vi = 0; - psta->uapsd_vo = 0; - psta->has_legacy_ac = 0; - - pstapriv->sta_dz_bitmap &= ~BIT(psta->aid); - pstapriv->tim_bitmap &= ~BIT(psta->aid); - - if ((psta->aid > 0) && (pstapriv->sta_aid[psta->aid - 1] == psta)) { - pstapriv->sta_aid[psta->aid - 1] = NULL; - psta->aid = 0; - } - - psta->under_exist_checking = 0; - - spin_lock_bh(&pfree_sta_queue->lock); - list_add_tail(&psta->list, get_list_head(pfree_sta_queue)); - spin_unlock_bh(&pfree_sta_queue->lock); -} - -/* free all stainfo which in sta_hash[all] */ -void rtw_free_all_stainfo(struct adapter *padapter) -{ - struct list_head *plist, *phead; - s32 index; - struct sta_info *psta = NULL; - struct sta_priv *pstapriv = &padapter->stapriv; - struct sta_info *pbcmc_stainfo = rtw_get_bcmc_stainfo(padapter); - - if (pstapriv->asoc_sta_count == 1) - return; - - spin_lock_bh(&pstapriv->sta_hash_lock); - - for (index = 0; index < NUM_STA; index++) { - phead = &pstapriv->sta_hash[index]; - plist = phead->next; - - while (phead != plist) { - psta = container_of(plist, struct sta_info, hash_list); - - plist = plist->next; - - if (pbcmc_stainfo != psta) - rtw_free_stainfo(padapter, psta); - } - } - spin_unlock_bh(&pstapriv->sta_hash_lock); -} - -/* any station allocated can be searched by hash list */ -struct sta_info *rtw_get_stainfo(struct sta_priv *pstapriv, u8 *hwaddr) -{ - struct sta_info *ploop, *psta = NULL; - u32 index; - u8 *addr; - u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - - if (!hwaddr) - return NULL; - - if (is_multicast_ether_addr(hwaddr)) - addr = bc_addr; - else - addr = hwaddr; - - index = wifi_mac_hash(addr); - - spin_lock_bh(&pstapriv->sta_hash_lock); - - list_for_each_entry(ploop, &pstapriv->sta_hash[index], hash_list) { - if (!memcmp(ploop->hwaddr, addr, ETH_ALEN)) { - psta = ploop; - break; - } - } - - spin_unlock_bh(&pstapriv->sta_hash_lock); - - return psta; -} - -u32 rtw_init_bcmc_stainfo(struct adapter *padapter) -{ - struct sta_info *psta; - u32 res = _SUCCESS; - unsigned char bcast_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - struct sta_priv *pstapriv = &padapter->stapriv; - - psta = rtw_alloc_stainfo(pstapriv, bcast_addr); - - if (!psta) { - res = _FAIL; - goto exit; - } - - /* default broadcast & multicast use macid 1 */ - psta->mac_id = 1; - -exit: - - return res; -} - -struct sta_info *rtw_get_bcmc_stainfo(struct adapter *padapter) -{ - struct sta_info *psta; - struct sta_priv *pstapriv = &padapter->stapriv; - u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - - psta = rtw_get_stainfo(pstapriv, bc_addr); - - return psta; -} - -u8 rtw_access_ctrl(struct adapter *padapter, u8 *mac_addr) -{ - u8 res = true; - struct list_head *plist, *phead; - struct rtw_wlan_acl_node *paclnode; - u8 match = false; - struct sta_priv *pstapriv = &padapter->stapriv; - struct wlan_acl_pool *pacl_list = &pstapriv->acl_list; - struct __queue *pacl_node_q = &pacl_list->acl_node_q; - - spin_lock_bh(&pacl_node_q->lock); - phead = get_list_head(pacl_node_q); - plist = phead->next; - while (phead != plist) { - paclnode = container_of(plist, struct rtw_wlan_acl_node, list); - plist = plist->next; - - if (!memcmp(paclnode->addr, mac_addr, ETH_ALEN)) { - if (paclnode->valid) { - match = true; - break; - } - } - } - spin_unlock_bh(&pacl_node_q->lock); - - if (pacl_list->mode == 1)/* accept unless in deny list */ - res = !match; - else if (pacl_list->mode == 2)/* deny unless in accept list */ - res = match; - else - res = true; - - return res; -} diff --git a/drivers/staging/r8188eu/core/rtw_wlan_util.c b/drivers/staging/r8188eu/core/rtw_wlan_util.c deleted file mode 100644 index f1ebb5358cb9..000000000000 --- a/drivers/staging/r8188eu/core/rtw_wlan_util.c +++ /dev/null @@ -1,1551 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2007 - 2012 Realtek Corporation. */ - -#define _RTW_WLAN_UTIL_C_ - -#include "../include/osdep_service.h" -#include "../include/drv_types.h" -#include "../include/wifi.h" - -static unsigned char ARTHEROS_OUI1[] = {0x00, 0x03, 0x7f}; -static unsigned char ARTHEROS_OUI2[] = {0x00, 0x13, 0x74}; - -static unsigned char BROADCOM_OUI1[] = {0x00, 0x10, 0x18}; -static unsigned char BROADCOM_OUI2[] = {0x00, 0x0a, 0xf7}; - -static unsigned char CISCO_OUI[] = {0x00, 0x40, 0x96}; -static unsigned char MARVELL_OUI[] = {0x00, 0x50, 0x43}; -static unsigned char RALINK_OUI[] = {0x00, 0x0c, 0x43}; -static unsigned char REALTEK_OUI[] = {0x00, 0xe0, 0x4c}; -static unsigned char AIRGOCAP_OUI[] = {0x00, 0x0a, 0xf5}; -static unsigned char EPIGRAM_OUI[] = {0x00, 0x90, 0x4c}; - -unsigned char REALTEK_96B_IE[] = {0x00, 0xe0, 0x4c, 0x02, 0x01, 0x20}; - -#define R2T_PHY_DELAY (0) - -/* define WAIT_FOR_BCN_TO_M (3000) */ -#define WAIT_FOR_BCN_TO_MIN (6000) -#define WAIT_FOR_BCN_TO_MAX (20000) - -static u8 rtw_basic_rate_cck[4] = { - IEEE80211_CCK_RATE_1MB | IEEE80211_BASIC_RATE_MASK, IEEE80211_CCK_RATE_2MB | IEEE80211_BASIC_RATE_MASK, - IEEE80211_CCK_RATE_5MB | IEEE80211_BASIC_RATE_MASK, IEEE80211_CCK_RATE_11MB | IEEE80211_BASIC_RATE_MASK -}; - -static u8 rtw_basic_rate_ofdm[3] = { - IEEE80211_OFDM_RATE_6MB | IEEE80211_BASIC_RATE_MASK, IEEE80211_OFDM_RATE_12MB | IEEE80211_BASIC_RATE_MASK, - IEEE80211_OFDM_RATE_24MB | IEEE80211_BASIC_RATE_MASK -}; - -static u8 rtw_basic_rate_mix[7] = { - IEEE80211_CCK_RATE_1MB | IEEE80211_BASIC_RATE_MASK, IEEE80211_CCK_RATE_2MB | IEEE80211_BASIC_RATE_MASK, - IEEE80211_CCK_RATE_5MB | IEEE80211_BASIC_RATE_MASK, IEEE80211_CCK_RATE_11MB | IEEE80211_BASIC_RATE_MASK, - IEEE80211_OFDM_RATE_6MB | IEEE80211_BASIC_RATE_MASK, IEEE80211_OFDM_RATE_12MB | IEEE80211_BASIC_RATE_MASK, - IEEE80211_OFDM_RATE_24MB | IEEE80211_BASIC_RATE_MASK -}; - -bool cckrates_included(unsigned char *rate, int ratelen) -{ - int i; - - for (i = 0; i < ratelen; i++) { - if ((((rate[i]) & 0x7f) == 2) || (((rate[i]) & 0x7f) == 4) || - (((rate[i]) & 0x7f) == 11) || (((rate[i]) & 0x7f) == 22)) - return true; - } - return false; -} - -bool cckratesonly_included(unsigned char *rate, int ratelen) -{ - int i; - - for (i = 0; i < ratelen; i++) { - if ((((rate[i]) & 0x7f) != 2) && (((rate[i]) & 0x7f) != 4) && - (((rate[i]) & 0x7f) != 11) && (((rate[i]) & 0x7f) != 22)) - return false; - } - - return true; -} - -unsigned char networktype_to_raid(unsigned char network_type) -{ - unsigned char raid; - - switch (network_type) { - case WIRELESS_11B: - raid = RATR_INX_WIRELESS_B; - break; - case WIRELESS_11G: - raid = RATR_INX_WIRELESS_G; - break; - case WIRELESS_11BG: - raid = RATR_INX_WIRELESS_GB; - break; - case WIRELESS_11_24N: - raid = RATR_INX_WIRELESS_N; - break; - case WIRELESS_11G_24N: - raid = RATR_INX_WIRELESS_NG; - break; - case WIRELESS_11BG_24N: - raid = RATR_INX_WIRELESS_NGB; - break; - default: - raid = RATR_INX_WIRELESS_GB; - break; - } - return raid; -} - -u8 judge_network_type(struct adapter *padapter, unsigned char *rate, int ratelen) -{ - u8 network_type = 0; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - if (pmlmeext->cur_channel > 14) { - network_type |= WIRELESS_INVALID; - } else { - if (pmlmeinfo->HT_enable) - network_type = WIRELESS_11_24N; - - if (cckratesonly_included(rate, ratelen)) - network_type |= WIRELESS_11B; - else if (cckrates_included(rate, ratelen)) - network_type |= WIRELESS_11BG; - else - network_type |= WIRELESS_11G; - } - return network_type; -} - -static unsigned char ratetbl_val_2wifirate(unsigned char rate) -{ - unsigned char val = 0; - - switch (rate & 0x7f) { - case 0: - val = IEEE80211_CCK_RATE_1MB; - break; - case 1: - val = IEEE80211_CCK_RATE_2MB; - break; - case 2: - val = IEEE80211_CCK_RATE_5MB; - break; - case 3: - val = IEEE80211_CCK_RATE_11MB; - break; - case 4: - val = IEEE80211_OFDM_RATE_6MB; - break; - case 5: - val = IEEE80211_OFDM_RATE_9MB; - break; - case 6: - val = IEEE80211_OFDM_RATE_12MB; - break; - case 7: - val = IEEE80211_OFDM_RATE_18MB; - break; - case 8: - val = IEEE80211_OFDM_RATE_24MB; - break; - case 9: - val = IEEE80211_OFDM_RATE_36MB; - break; - case 10: - val = IEEE80211_OFDM_RATE_48MB; - break; - case 11: - val = IEEE80211_OFDM_RATE_54MB; - break; - } - return val; -} - -static bool is_basicrate(struct adapter *padapter, unsigned char rate) -{ - int i; - unsigned char val; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - for (i = 0; i < NumRates; i++) { - val = pmlmeext->basicrate[i]; - - if ((val != 0xff) && (val != 0xfe)) { - if (rate == ratetbl_val_2wifirate(val)) - return true; - } - } - return false; -} - -static unsigned int ratetbl2rateset(struct adapter *padapter, unsigned char *rateset) -{ - int i; - unsigned char rate; - unsigned int len = 0; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - for (i = 0; i < NumRates; i++) { - rate = pmlmeext->datarate[i]; - - switch (rate) { - case 0xff: - return len; - case 0xfe: - continue; - default: - rate = ratetbl_val_2wifirate(rate); - - if (is_basicrate(padapter, rate)) - rate |= IEEE80211_BASIC_RATE_MASK; - - rateset[len] = rate; - len++; - break; - } - } - return len; -} - -void get_rate_set(struct adapter *padapter, unsigned char *pbssrate, int *bssrate_len) -{ - unsigned char supportedrates[NumRates]; - - memset(supportedrates, 0, NumRates); - *bssrate_len = ratetbl2rateset(padapter, supportedrates); - memcpy(pbssrate, supportedrates, *bssrate_len); -} - -void Save_DM_Func_Flag(struct adapter *padapter) -{ - struct hal_data_8188e *haldata = &padapter->haldata; - struct odm_dm_struct *odmpriv = &haldata->odmpriv; - - odmpriv->BK_SupportAbility = odmpriv->SupportAbility; -} - -void Restore_DM_Func_Flag(struct adapter *padapter) -{ - struct hal_data_8188e *haldata = &padapter->haldata; - struct odm_dm_struct *odmpriv = &haldata->odmpriv; - - odmpriv->SupportAbility = odmpriv->BK_SupportAbility; -} - -void Set_MSR(struct adapter *padapter, u8 type) -{ - u8 val8; - int res; - - res = rtw_read8(padapter, MSR, &val8); - if (res) - return; - - val8 &= 0x0c; - val8 |= type; - rtw_write8(padapter, MSR, val8); -} - -inline u8 rtw_get_oper_ch(struct adapter *adapter) -{ - return adapter->mlmeextpriv.oper_channel; -} - -inline void rtw_set_oper_ch(struct adapter *adapter, u8 ch) -{ - adapter->mlmeextpriv.oper_channel = ch; -} - -inline void rtw_set_oper_bw(struct adapter *adapter, u8 bw) -{ - adapter->mlmeextpriv.oper_bwmode = bw; -} - -inline void rtw_set_oper_choffset(struct adapter *adapter, u8 offset) -{ - adapter->mlmeextpriv.oper_ch_offset = offset; -} - -void SelectChannel(struct adapter *padapter, unsigned char channel) -{ - /* saved channel info */ - rtw_set_oper_ch(padapter, channel); - PHY_SwChnl8188E(padapter, channel); -} - -void SetBWMode(struct adapter *padapter, unsigned short bwmode, - unsigned char channel_offset) -{ - /* saved bw info */ - rtw_set_oper_bw(padapter, bwmode); - rtw_set_oper_choffset(padapter, channel_offset); - - PHY_SetBWMode8188E(padapter, (enum ht_channel_width)bwmode, channel_offset); -} - -void set_channel_bwmode(struct adapter *padapter, unsigned char channel, unsigned char channel_offset, unsigned short bwmode) -{ - u8 center_ch; - - if ((bwmode == HT_CHANNEL_WIDTH_20) || - (channel_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE)) { - /* SelectChannel(padapter, channel); */ - center_ch = channel; - } else { - /* switch to the proper channel */ - if (channel_offset == HAL_PRIME_CHNL_OFFSET_LOWER) { - /* SelectChannel(padapter, channel + 2); */ - center_ch = channel + 2; - } else { - /* SelectChannel(padapter, channel - 2); */ - center_ch = channel - 2; - } - } - - /* set Channel */ - /* saved channel/bw info */ - rtw_set_oper_ch(padapter, channel); - rtw_set_oper_bw(padapter, bwmode); - rtw_set_oper_choffset(padapter, channel_offset); - - PHY_SwChnl8188E(padapter, center_ch); /* set center channel */ - SetBWMode(padapter, bwmode, channel_offset); -} - -__inline u8 *get_my_bssid(struct wlan_bssid_ex *pnetwork) -{ - return pnetwork->MacAddress; -} - -u16 get_beacon_interval(struct wlan_bssid_ex *bss) -{ - __le16 val; - memcpy((unsigned char *)&val, rtw_get_beacon_interval_from_ie(bss->IEs), 2); - - return le16_to_cpu(val); -} - -bool r8188eu_is_client_associated_to_ap(struct adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext; - struct mlme_ext_info *pmlmeinfo; - - if (!padapter) - return false; - - pmlmeext = &padapter->mlmeextpriv; - pmlmeinfo = &pmlmeext->mlmext_info; - - if ((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) && ((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE)) - return true; - - return false; -} - -bool r8188eu_is_client_associated_to_ibss(struct adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - if ((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) && ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE)) - return true; - - return false; -} - -bool r8188eu_is_ibss_empty(struct adapter *padapter) -{ - unsigned int i; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - for (i = IBSS_START_MAC_ID; i < NUM_STA; i++) { - if (pmlmeinfo->FW_sta_info[i].status == 1) - return false; - } - return true; -} - -unsigned int decide_wait_for_beacon_timeout(unsigned int bcn_interval) -{ - if ((bcn_interval << 2) < WAIT_FOR_BCN_TO_MIN) - return WAIT_FOR_BCN_TO_MIN; - else if ((bcn_interval << 2) > WAIT_FOR_BCN_TO_MAX) - return WAIT_FOR_BCN_TO_MAX; - else - return bcn_interval << 2; -} - -void invalidate_cam_all(struct adapter *padapter) -{ - rtw_write32(padapter, RWCAM, BIT(31) | BIT(30)); -} - -void write_cam(struct adapter *padapter, u8 entry, u16 ctrl, u8 *mac, u8 *key) -{ - unsigned int i, val, addr; - int j; - u32 cam_val[2]; - - addr = entry << 3; - - for (j = 5; j >= 0; j--) { - switch (j) { - case 0: - val = (ctrl | (mac[0] << 16) | (mac[1] << 24)); - break; - case 1: - val = (mac[2] | (mac[3] << 8) | (mac[4] << 16) | (mac[5] << 24)); - break; - default: - i = (j - 2) << 2; - val = (key[i] | (key[i + 1] << 8) | (key[i + 2] << 16) | (key[i + 3] << 24)); - break; - } - - cam_val[0] = val; - cam_val[1] = addr + (unsigned int)j; - - rtw_write32(padapter, WCAMI, cam_val[0]); - rtw_write32(padapter, RWCAM, CAM_POLLINIG | CAM_WRITE | cam_val[1]); - } -} - -void clear_cam_entry(struct adapter *padapter, u8 entry) -{ - unsigned char null_sta[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - unsigned char null_key[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - - write_cam(padapter, entry, 0, null_sta, null_key); -} - -int allocate_fw_sta_entry(struct adapter *padapter) -{ - unsigned int mac_id; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - for (mac_id = IBSS_START_MAC_ID; mac_id < NUM_STA; mac_id++) { - if (pmlmeinfo->FW_sta_info[mac_id].status == 0) { - pmlmeinfo->FW_sta_info[mac_id].status = 1; - pmlmeinfo->FW_sta_info[mac_id].retry = 0; - break; - } - } - - return mac_id; -} - -void flush_all_cam_entry(struct adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - rtw_write32(padapter, RWCAM, BIT(31) | BIT(30)); - - memset((u8 *)(pmlmeinfo->FW_sta_info), 0, sizeof(pmlmeinfo->FW_sta_info)); -} - -int WMM_param_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE) -{ - /* struct registry_priv *pregpriv = &padapter->registrypriv; */ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - if (pmlmepriv->qospriv.qos_option == 0) { - pmlmeinfo->WMM_enable = 0; - return _FAIL; - } - - pmlmeinfo->WMM_enable = 1; - memcpy(&pmlmeinfo->WMM_param, pIE->data + 6, sizeof(struct WMM_para_element)); - return true; -} - -static void set_acm_ctrl(struct adapter *adapter, u8 acm_mask) -{ - u8 acmctrl; - int res = rtw_read8(adapter, REG_ACMHWCTRL, &acmctrl); - - if (res) - return; - - if (acm_mask > 1) - acmctrl = acmctrl | 0x1; - - if (acm_mask & BIT(3)) - acmctrl |= ACMHW_VOQEN; - else - acmctrl &= (~ACMHW_VOQEN); - - if (acm_mask & BIT(2)) - acmctrl |= ACMHW_VIQEN; - else - acmctrl &= (~ACMHW_VIQEN); - - if (acm_mask & BIT(1)) - acmctrl |= ACMHW_BEQEN; - else - acmctrl &= (~ACMHW_BEQEN); - - rtw_write8(adapter, REG_ACMHWCTRL, acmctrl); -} - -void WMMOnAssocRsp(struct adapter *padapter) -{ - u8 ACI, ACM, AIFS, ECWMin, ECWMax, aSifsTime; - u8 acm_mask; - u16 TXOP; - u32 acParm, i; - u32 edca[4], inx[4]; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct registry_priv *pregpriv = &padapter->registrypriv; - struct hal_data_8188e *haldata = &padapter->haldata; - - if (pmlmeinfo->WMM_enable == 0) { - padapter->mlmepriv.acm_mask = 0; - return; - } - - acm_mask = 0; - - if (pmlmeext->cur_wireless_mode == WIRELESS_11B) - aSifsTime = 10; - else - aSifsTime = 16; - - for (i = 0; i < 4; i++) { - ACI = (pmlmeinfo->WMM_param.ac_param[i].ACI_AIFSN >> 5) & 0x03; - ACM = (pmlmeinfo->WMM_param.ac_param[i].ACI_AIFSN >> 4) & 0x01; - - /* AIFS = AIFSN * slot time + SIFS - r2t phy delay */ - AIFS = (pmlmeinfo->WMM_param.ac_param[i].ACI_AIFSN & 0x0f) * pmlmeinfo->slotTime + aSifsTime; - - ECWMin = (pmlmeinfo->WMM_param.ac_param[i].CW & 0x0f); - ECWMax = (pmlmeinfo->WMM_param.ac_param[i].CW & 0xf0) >> 4; - TXOP = le16_to_cpu(pmlmeinfo->WMM_param.ac_param[i].TXOP_limit); - - acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16); - - switch (ACI) { - case 0x0: - haldata->AcParam_BE = acParm; - rtw_write32(padapter, REG_EDCA_BE_PARAM, acParm); - acm_mask |= (ACM ? BIT(1) : 0); - edca[XMIT_BE_QUEUE] = acParm; - break; - case 0x1: - rtw_write32(padapter, REG_EDCA_BK_PARAM, acParm); - edca[XMIT_BK_QUEUE] = acParm; - break; - case 0x2: - rtw_write32(padapter, REG_EDCA_VI_PARAM, acParm); - acm_mask |= (ACM ? BIT(2) : 0); - edca[XMIT_VI_QUEUE] = acParm; - break; - case 0x3: - rtw_write32(padapter, REG_EDCA_VO_PARAM, acParm); - acm_mask |= (ACM ? BIT(3) : 0); - edca[XMIT_VO_QUEUE] = acParm; - break; - } - } - - if (padapter->registrypriv.acm_method == 1) - set_acm_ctrl(padapter, acm_mask); - else - padapter->mlmepriv.acm_mask = acm_mask; - - inx[0] = 0; inx[1] = 1; inx[2] = 2; inx[3] = 3; - - if (pregpriv->wifi_spec == 1) { - u32 j, change_inx = false; - - /* entry indx: 0->vo, 1->vi, 2->be, 3->bk. */ - for (i = 0; i < 4; i++) { - for (j = i + 1; j < 4; j++) { - /* compare CW and AIFS */ - if ((edca[j] & 0xFFFF) < (edca[i] & 0xFFFF)) { - change_inx = true; - } else if ((edca[j] & 0xFFFF) == (edca[i] & 0xFFFF)) { - /* compare TXOP */ - if ((edca[j] >> 16) > (edca[i] >> 16)) - change_inx = true; - } - - if (change_inx) { - swap(edca[i], edca[j]); - swap(inx[i], inx[j]); - - change_inx = false; - } - } - } - } - - for (i = 0; i < 4; i++) - pxmitpriv->wmm_para_seq[i] = inx[i]; -} - -static void bwmode_update_check(struct adapter *padapter, struct ndis_802_11_var_ie *pIE) -{ - unsigned char new_bwmode; - unsigned char new_ch_offset; - struct HT_info_element *pHT_info; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct registry_priv *pregistrypriv = &padapter->registrypriv; - struct ht_priv *phtpriv = &pmlmepriv->htpriv; - - if (!pIE) - return; - - if (!phtpriv) - return; - - if (pIE->Length > sizeof(struct HT_info_element)) - return; - - pHT_info = (struct HT_info_element *)pIE->data; - - if ((pHT_info->infos[0] & BIT(2)) && pregistrypriv->cbw40_enable) { - new_bwmode = HT_CHANNEL_WIDTH_40; - - switch (pHT_info->infos[0] & 0x3) { - case 1: - new_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER; - break; - case 3: - new_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER; - break; - default: - new_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - break; - } - } else { - new_bwmode = HT_CHANNEL_WIDTH_20; - new_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - } - - if ((new_bwmode != pmlmeext->cur_bwmode) || - (new_ch_offset != pmlmeext->cur_ch_offset)) { - pmlmeinfo->bwmode_updated = true; - - pmlmeext->cur_bwmode = new_bwmode; - pmlmeext->cur_ch_offset = new_ch_offset; - - /* update HT info also */ - HT_info_handler(padapter, pIE); - } else { - pmlmeinfo->bwmode_updated = false; - } - - if (pmlmeinfo->bwmode_updated) { - struct sta_info *psta; - struct wlan_bssid_ex *cur_network = &pmlmeinfo->network; - struct sta_priv *pstapriv = &padapter->stapriv; - - /* set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); */ - - /* update ap's stainfo */ - psta = rtw_get_stainfo(pstapriv, cur_network->MacAddress); - if (psta) { - struct ht_priv *phtpriv_sta = &psta->htpriv; - - if (phtpriv_sta->ht_option) { - /* bwmode */ - phtpriv_sta->bwmode = pmlmeext->cur_bwmode; - phtpriv_sta->ch_offset = pmlmeext->cur_ch_offset; - } else { - phtpriv_sta->bwmode = HT_CHANNEL_WIDTH_20; - phtpriv_sta->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - } - } - } -} - -void HT_caps_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE) -{ - unsigned int i; - u8 max_AMPDU_len, min_MPDU_spacing; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct ht_priv *phtpriv = &pmlmepriv->htpriv; - - if (!pIE) - return; - - if (!phtpriv->ht_option) - return; - - pmlmeinfo->HT_caps_enable = 1; - - for (i = 0; i < (pIE->Length); i++) { - if (i != 2) { - /* Got the endian issue here. */ - pmlmeinfo->HT_caps.u.HT_cap[i] &= (pIE->data[i]); - } else { - /* modify from fw by Thomas 2010/11/17 */ - max_AMPDU_len = min(pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x3, - pIE->data[i] & 0x3); - - min_MPDU_spacing = max(pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c, - pIE->data[i] & 0x1c); - - pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para = max_AMPDU_len | min_MPDU_spacing; - } - } - - /* update the MCS rates */ - for (i = 0; i < 16; i++) - pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate[i] &= MCS_rate_1R[i]; -} - -void HT_info_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct ht_priv *phtpriv = &pmlmepriv->htpriv; - - if (!pIE) - return; - - if (!phtpriv->ht_option) - return; - - if (pIE->Length > sizeof(struct HT_info_element)) - return; - - pmlmeinfo->HT_info_enable = 1; - memcpy(&pmlmeinfo->HT_info, pIE->data, pIE->Length); -} - -static void set_min_ampdu_spacing(struct adapter *adapter, u8 spacing) -{ - u8 sec_spacing; - int res; - - if (spacing <= 7) { - switch (adapter->securitypriv.dot11PrivacyAlgrthm) { - case _NO_PRIVACY_: - case _AES_: - sec_spacing = 0; - break; - case _WEP40_: - case _WEP104_: - case _TKIP_: - case _TKIP_WTMIC_: - sec_spacing = 6; - break; - default: - sec_spacing = 7; - break; - } - - if (spacing < sec_spacing) - spacing = sec_spacing; - - res = rtw_read8(adapter, REG_AMPDU_MIN_SPACE, &sec_spacing); - if (res) - return; - - rtw_write8(adapter, REG_AMPDU_MIN_SPACE, - (sec_spacing & 0xf8) | spacing); - } -} - -static void set_ampdu_factor(struct adapter *adapter, u8 factor) -{ - u8 RegToSet_Normal[4] = {0x41, 0xa8, 0x72, 0xb9}; - u8 FactorToSet; - u8 *pRegToSet; - u8 index = 0; - - pRegToSet = RegToSet_Normal; /* 0xb972a841; */ - FactorToSet = factor; - if (FactorToSet <= 3) { - FactorToSet = (1 << (FactorToSet + 2)); - if (FactorToSet > 0xf) - FactorToSet = 0xf; - - for (index = 0; index < 4; index++) { - if ((pRegToSet[index] & 0xf0) > (FactorToSet << 4)) - pRegToSet[index] = (pRegToSet[index] & 0x0f) | (FactorToSet << 4); - - if ((pRegToSet[index] & 0x0f) > FactorToSet) - pRegToSet[index] = (pRegToSet[index] & 0xf0) | (FactorToSet); - - rtw_write8(adapter, (REG_AGGLEN_LMT + index), pRegToSet[index]); - } - } -} - -void HTOnAssocRsp(struct adapter *padapter) -{ - unsigned char max_AMPDU_len; - unsigned char min_MPDU_spacing; - /* struct registry_priv *pregpriv = &padapter->registrypriv; */ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - if ((pmlmeinfo->HT_info_enable) && (pmlmeinfo->HT_caps_enable)) { - pmlmeinfo->HT_enable = 1; - } else { - pmlmeinfo->HT_enable = 0; - return; - } - - /* handle A-MPDU parameter field */ - /* - AMPDU_para [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k - AMPDU_para [4:2]:Min MPDU Start Spacing - */ - max_AMPDU_len = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x03; - - min_MPDU_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c) >> 2; - - set_min_ampdu_spacing(padapter, min_MPDU_spacing); - - set_ampdu_factor(padapter, max_AMPDU_len); -} - -void ERP_IE_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - if (pIE->Length > 1) - return; - - pmlmeinfo->ERP_enable = 1; - memcpy(&pmlmeinfo->ERP_IE, pIE->data, pIE->Length); -} - -void VCS_update(struct adapter *padapter, struct sta_info *psta) -{ - struct registry_priv *pregpriv = &padapter->registrypriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - switch (pregpriv->vrtl_carrier_sense) { /* 0:off 1:on 2:auto */ - case 0: /* off */ - psta->rtsen = 0; - psta->cts2self = 0; - break; - case 1: /* on */ - if (pregpriv->vcs_type == 1) { /* 1:RTS/CTS 2:CTS to self */ - psta->rtsen = 1; - psta->cts2self = 0; - } else { - psta->rtsen = 0; - psta->cts2self = 1; - } - break; - case 2: /* auto */ - default: - if ((pmlmeinfo->ERP_enable) && (pmlmeinfo->ERP_IE & BIT(1))) { - if (pregpriv->vcs_type == 1) { - psta->rtsen = 1; - psta->cts2self = 0; - } else { - psta->rtsen = 0; - psta->cts2self = 1; - } - } else { - psta->rtsen = 0; - psta->cts2self = 0; - } - break; - } -} - -int rtw_check_bcn_info(struct adapter *Adapter, u8 *pframe, u32 packet_len) -{ - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)pframe; - unsigned int len; - unsigned char *p; - unsigned short val16; - struct wlan_network *cur_network = &Adapter->mlmepriv.cur_network; - /* u8 wpa_ie[255], rsn_ie[255]; */ - u16 wpa_len = 0, rsn_len = 0; - u8 encryp_protocol = 0; - struct wlan_bssid_ex *bssid; - int group_cipher = 0, pairwise_cipher = 0, is_8021x = 0; - unsigned char *pbuf; - u32 wpa_ielen = 0; - u8 *pbssid = GetAddr3Ptr(pframe); - u32 hidden_ssid = 0; - struct HT_info_element *pht_info = NULL; - struct ieee80211_ht_cap *pht_cap = NULL; - u32 bcn_channel; - unsigned short ht_cap_info; - unsigned char ht_info_infos_0; - - if (!r8188eu_is_client_associated_to_ap(Adapter)) - return true; - - len = packet_len - sizeof(struct ieee80211_hdr_3addr); - - if (len > MAX_IE_SZ) - return _FAIL; - - if (memcmp(cur_network->network.MacAddress, pbssid, 6)) - return true; - - bssid = kzalloc(sizeof(struct wlan_bssid_ex), GFP_ATOMIC); - if (!bssid) - return _FAIL; - - if (ieee80211_is_beacon(mgmt->frame_control)) - bssid->Reserved[0] = 1; - - bssid->Length = sizeof(struct wlan_bssid_ex) - MAX_IE_SZ + len; - - /* below is to copy the information element */ - bssid->IELength = len; - memcpy(bssid->IEs, (pframe + sizeof(struct ieee80211_hdr_3addr)), bssid->IELength); - - /* check bw and channel offset */ - /* parsing HT_CAP_IE */ - p = rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, _HT_CAPABILITY_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_); - if (p && len > 0) { - pht_cap = (struct ieee80211_ht_cap *)(p + 2); - ht_cap_info = le16_to_cpu(pht_cap->cap_info); - } else { - ht_cap_info = 0; - } - /* parsing HT_INFO_IE */ - p = rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, _HT_ADD_INFO_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_); - if (p && len > 0) { - pht_info = (struct HT_info_element *)(p + 2); - ht_info_infos_0 = pht_info->infos[0]; - } else { - ht_info_infos_0 = 0; - } - if (ht_cap_info != cur_network->BcnInfo.ht_cap_info || - ((ht_info_infos_0 & 0x03) != (cur_network->BcnInfo.ht_info_infos_0 & 0x03))) { - /* bcn_info_update */ - cur_network->BcnInfo.ht_cap_info = ht_cap_info; - cur_network->BcnInfo.ht_info_infos_0 = ht_info_infos_0; - /* to do : need to check that whether modify related register of BB or not */ - /* goto _mismatch; */ - } - - /* Checking for channel */ - p = rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, _DSSET_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_); - if (p) { - bcn_channel = *(p + 2); - } else {/* In 5G, some ap do not have DSSET IE checking HT info for channel */ - p = rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, _HT_ADD_INFO_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_); - if (pht_info) - bcn_channel = pht_info->primary_channel; - else /* we don't find channel IE, so don't check it */ - bcn_channel = Adapter->mlmeextpriv.cur_channel; - } - if (bcn_channel != Adapter->mlmeextpriv.cur_channel) - goto _mismatch; - - /* checking SSID */ - p = rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, _SSID_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_); - if (!p) - hidden_ssid = true; - else - hidden_ssid = false; - - if (p && (!hidden_ssid && (*(p + 1)))) { - memcpy(bssid->Ssid.Ssid, (p + 2), *(p + 1)); - bssid->Ssid.SsidLength = *(p + 1); - } else { - bssid->Ssid.SsidLength = 0; - bssid->Ssid.Ssid[0] = '\0'; - } - - if (memcmp(bssid->Ssid.Ssid, cur_network->network.Ssid.Ssid, 32) || - bssid->Ssid.SsidLength != cur_network->network.Ssid.SsidLength) { - /* not hidden ssid */ - if (bssid->Ssid.Ssid[0] != '\0' && bssid->Ssid.SsidLength != 0) - goto _mismatch; - } - - /* check encryption info */ - val16 = rtw_get_capability((struct wlan_bssid_ex *)bssid); - - if (val16 & BIT(4)) - bssid->Privacy = 1; - else - bssid->Privacy = 0; - - if (cur_network->network.Privacy != bssid->Privacy) - goto _mismatch; - - rtw_get_sec_ie(bssid->IEs, bssid->IELength, NULL, &rsn_len, NULL, &wpa_len); - - if (rsn_len > 0) { - encryp_protocol = ENCRYP_PROTOCOL_WPA2; - } else if (wpa_len > 0) { - encryp_protocol = ENCRYP_PROTOCOL_WPA; - } else { - if (bssid->Privacy) - encryp_protocol = ENCRYP_PROTOCOL_WEP; - } - - if (cur_network->BcnInfo.encryp_protocol != encryp_protocol) - goto _mismatch; - - if (encryp_protocol == ENCRYP_PROTOCOL_WPA || encryp_protocol == ENCRYP_PROTOCOL_WPA2) { - pbuf = rtw_get_wpa_ie(&bssid->IEs[12], &wpa_ielen, bssid->IELength - 12); - if (pbuf && (wpa_ielen > 0)) { - rtw_parse_wpa_ie(pbuf, wpa_ielen + 2, &group_cipher, &pairwise_cipher, &is_8021x); - } else { - pbuf = rtw_get_wpa2_ie(&bssid->IEs[12], &wpa_ielen, bssid->IELength - 12); - - if (pbuf && (wpa_ielen > 0)) - rtw_parse_wpa2_ie(pbuf, wpa_ielen + 2, &group_cipher, &pairwise_cipher, &is_8021x); - } - - if (pairwise_cipher != cur_network->BcnInfo.pairwise_cipher || - group_cipher != cur_network->BcnInfo.group_cipher) - goto _mismatch; - - if (is_8021x != cur_network->BcnInfo.is_8021x) - goto _mismatch; - } - - kfree(bssid); - - return _SUCCESS; - -_mismatch: - kfree(bssid); - - return _FAIL; -} - -void update_beacon_info(struct adapter *padapter, u8 *ie_ptr, uint ie_len, struct sta_info *psta) -{ - unsigned int i; - struct ndis_802_11_var_ie *pIE; - - for (i = 0; i < ie_len;) { - pIE = (struct ndis_802_11_var_ie *)(ie_ptr + i); - - switch (pIE->ElementID) { - case _HT_EXTRA_INFO_IE_: /* HT info */ - /* HT_info_handler(padapter, pIE); */ - bwmode_update_check(padapter, pIE); - break; - case _ERPINFO_IE_: - ERP_IE_handler(padapter, pIE); - VCS_update(padapter, psta); - break; - default: - break; - } - - i += (pIE->Length + 2); - } -} - -bool is_ap_in_tkip(struct adapter *padapter) -{ - u32 i; - struct ndis_802_11_var_ie *pIE; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *cur_network = &pmlmeinfo->network; - - if (rtw_get_capability((struct wlan_bssid_ex *)cur_network) & WLAN_CAPABILITY_PRIVACY) { - for (i = sizeof(struct ndis_802_11_fixed_ie); i < pmlmeinfo->network.IELength;) { - pIE = (struct ndis_802_11_var_ie *)(pmlmeinfo->network.IEs + i); - - switch (pIE->ElementID) { - case _VENDOR_SPECIFIC_IE_: - if ((!memcmp(pIE->data, RTW_WPA_OUI, 4)) && (!memcmp((pIE->data + 12), WPA_TKIP_CIPHER, 4))) - return true; - break; - case _RSN_IE_2_: - if (!memcmp((pIE->data + 8), RSN_TKIP_CIPHER, 4)) - return true; - break; - default: - break; - } - - i += (pIE->Length + 2); - } - return false; - } else { - return false; - } -} - -int wifirate2_ratetbl_inx(unsigned char rate) -{ - int inx = 0; - rate = rate & 0x7f; - - switch (rate) { - case 54 * 2: - inx = 11; - break; - case 48 * 2: - inx = 10; - break; - case 36 * 2: - inx = 9; - break; - case 24 * 2: - inx = 8; - break; - case 18 * 2: - inx = 7; - break; - case 12 * 2: - inx = 6; - break; - case 9 * 2: - inx = 5; - break; - case 6 * 2: - inx = 4; - break; - case 11 * 2: - inx = 3; - break; - case 11: - inx = 2; - break; - case 2 * 2: - inx = 1; - break; - case 1 * 2: - inx = 0; - break; - } - return inx; -} - -unsigned int update_basic_rate(unsigned char *ptn, unsigned int ptn_sz) -{ - unsigned int i, num_of_rate; - unsigned int mask = 0; - - num_of_rate = (ptn_sz > NumRates) ? NumRates : ptn_sz; - - for (i = 0; i < num_of_rate; i++) { - if ((*(ptn + i)) & 0x80) - mask |= 0x1 << wifirate2_ratetbl_inx(*(ptn + i)); - } - return mask; -} - -unsigned int update_supported_rate(unsigned char *ptn, unsigned int ptn_sz) -{ - unsigned int i, num_of_rate; - unsigned int mask = 0; - - num_of_rate = (ptn_sz > NumRates) ? NumRates : ptn_sz; - - for (i = 0; i < num_of_rate; i++) - mask |= 0x1 << wifirate2_ratetbl_inx(*(ptn + i)); - return mask; -} - -unsigned int update_MSC_rate(struct HT_caps_element *pHT_caps) -{ - unsigned int mask = 0; - - mask = ((pHT_caps->u.HT_cap_element.MCS_rate[0] << 12) | (pHT_caps->u.HT_cap_element.MCS_rate[1] << 20)); - - return mask; -} - -int support_short_GI(struct adapter *padapter, struct HT_caps_element *pHT_caps) -{ - unsigned char bit_offset; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - if (!(pmlmeinfo->HT_enable)) - return _FAIL; - - if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_RALINK) - return _FAIL; - - bit_offset = (pmlmeext->cur_bwmode & HT_CHANNEL_WIDTH_40) ? 6 : 5; - - if (__le16_to_cpu(pHT_caps->u.HT_cap_element.HT_caps_info) & (0x1 << bit_offset)) - return _SUCCESS; - else - return _FAIL; -} - -unsigned char get_highest_rate_idx(u32 mask) -{ - int i; - unsigned char rate_idx = 0; - - for (i = 27; i >= 0; i--) { - if (mask & BIT(i)) { - rate_idx = i; - break; - } - } - return rate_idx; -} - -void Update_RA_Entry(struct adapter *padapter, u32 mac_id) -{ - rtw_hal_update_ra_mask(padapter, mac_id, 0); -} - -static void enable_rate_adaptive(struct adapter *padapter, u32 mac_id) -{ - Update_RA_Entry(padapter, mac_id); -} - -void set_sta_rate(struct adapter *padapter, struct sta_info *psta) -{ - /* rate adaptive */ - enable_rate_adaptive(padapter, psta->mac_id); -} - -void rtw_set_basic_rate(struct adapter *adapter, u8 *rates) -{ - u16 BrateCfg = 0; - u8 RateIndex = 0; - int res; - u8 reg; - - /* 2007.01.16, by Emily */ - /* Select RRSR (in Legacy-OFDM and CCK) */ - /* For 8190, we select only 24M, 12M, 6M, 11M, 5.5M, 2M, and 1M from the Basic rate. */ - /* We do not use other rates. */ - HalSetBrateCfg(adapter, rates, &BrateCfg); - - /* 2011.03.30 add by Luke Lee */ - /* CCK 2M ACK should be disabled for some BCM and Atheros AP IOT */ - /* because CCK 2M has poor TXEVM */ - /* CCK 5.5M & 11M ACK should be enabled for better performance */ - - BrateCfg = (BrateCfg | 0xd) & 0x15d; - - BrateCfg |= 0x01; /* default enable 1M ACK rate */ - /* Set RRSR rate table. */ - rtw_write8(adapter, REG_RRSR, BrateCfg & 0xff); - rtw_write8(adapter, REG_RRSR + 1, (BrateCfg >> 8) & 0xff); - res = rtw_read8(adapter, REG_RRSR + 2, ®); - if (res) - return; - - rtw_write8(adapter, REG_RRSR + 2, reg & 0xf0); - - /* Set RTS initial rate */ - while (BrateCfg > 0x1) { - BrateCfg = (BrateCfg >> 1); - RateIndex++; - } - /* Ziv - Check */ - rtw_write8(adapter, REG_INIRTS_RATE_SEL, RateIndex); -} - -/* Update RRSR and Rate for USERATE */ -void update_tx_basic_rate(struct adapter *padapter, u8 wirelessmode) -{ - unsigned char supported_rates[NDIS_802_11_LENGTH_RATES_EX]; - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - - /* Added by Albert 2011/03/22 */ - /* In the P2P mode, the driver should not support the b mode. */ - /* So, the Tx packet shouldn't use the CCK rate */ - if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) - return; - memset(supported_rates, 0, NDIS_802_11_LENGTH_RATES_EX); - - if ((wirelessmode & WIRELESS_11B) && (wirelessmode == WIRELESS_11B)) - memcpy(supported_rates, rtw_basic_rate_cck, 4); - else if (wirelessmode & WIRELESS_11B) - memcpy(supported_rates, rtw_basic_rate_mix, 7); - else - memcpy(supported_rates, rtw_basic_rate_ofdm, 3); - - if (wirelessmode & WIRELESS_11B) - update_mgnt_tx_rate(padapter, IEEE80211_CCK_RATE_1MB); - else - update_mgnt_tx_rate(padapter, IEEE80211_OFDM_RATE_6MB); - - rtw_set_basic_rate(padapter, supported_rates); -} - -unsigned char check_assoc_AP(u8 *pframe, uint len) -{ - unsigned int i; - struct ndis_802_11_var_ie *pIE; - u8 epigram_vendor_flag; - u8 ralink_vendor_flag; - epigram_vendor_flag = 0; - ralink_vendor_flag = 0; - - for (i = sizeof(struct ndis_802_11_fixed_ie); i < len;) { - pIE = (struct ndis_802_11_var_ie *)(pframe + i); - - switch (pIE->ElementID) { - case _VENDOR_SPECIFIC_IE_: - if ((!memcmp(pIE->data, ARTHEROS_OUI1, 3)) || - (!memcmp(pIE->data, ARTHEROS_OUI2, 3))) { - return HT_IOT_PEER_ATHEROS; - } else if ((!memcmp(pIE->data, BROADCOM_OUI1, 3)) || - (!memcmp(pIE->data, BROADCOM_OUI2, 3))) { - return HT_IOT_PEER_BROADCOM; - } else if (!memcmp(pIE->data, MARVELL_OUI, 3)) { - return HT_IOT_PEER_MARVELL; - } else if (!memcmp(pIE->data, RALINK_OUI, 3)) { - if (!ralink_vendor_flag) { - ralink_vendor_flag = 1; - } else { - return HT_IOT_PEER_RALINK; - } - } else if (!memcmp(pIE->data, CISCO_OUI, 3)) { - return HT_IOT_PEER_CISCO; - } else if (!memcmp(pIE->data, REALTEK_OUI, 3)) { - return HT_IOT_PEER_REALTEK; - } else if (!memcmp(pIE->data, AIRGOCAP_OUI, 3)) { - return HT_IOT_PEER_AIRGO; - } else if (!memcmp(pIE->data, EPIGRAM_OUI, 3)) { - epigram_vendor_flag = 1; - if (ralink_vendor_flag) - return HT_IOT_PEER_TENDA; - } else { - break; - } - break; - - default: - break; - } - i += (pIE->Length + 2); - } - - if (ralink_vendor_flag && !epigram_vendor_flag) - return HT_IOT_PEER_RALINK; - else if (ralink_vendor_flag && epigram_vendor_flag) - return HT_IOT_PEER_TENDA; - else - return HT_IOT_PEER_UNKNOWN; -} - -void update_IOT_info(struct adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - switch (pmlmeinfo->assoc_AP_vendor) { - case HT_IOT_PEER_MARVELL: - pmlmeinfo->turboMode_cts2self = 1; - pmlmeinfo->turboMode_rtsen = 0; - break; - case HT_IOT_PEER_RALINK: - pmlmeinfo->turboMode_cts2self = 0; - pmlmeinfo->turboMode_rtsen = 1; - break; - case HT_IOT_PEER_REALTEK: - /* rtw_write16(padapter, 0x4cc, 0xffff); */ - /* rtw_write16(padapter, 0x546, 0x01c0); */ - break; - default: - pmlmeinfo->turboMode_cts2self = 0; - pmlmeinfo->turboMode_rtsen = 1; - break; - } -} - -static void set_ack_preamble(struct adapter *adapter, bool short_preamble) -{ - struct hal_data_8188e *haldata = &adapter->haldata; - u8 val8; - - /* Joseph marked out for Netgear 3500 TKIP channel 7 issue.(Temporarily) */ - val8 = haldata->nCur40MhzPrimeSC << 5; - if (short_preamble) - val8 |= 0x80; - - rtw_write8(adapter, REG_RRSR + 2, val8); -}; - -static void set_slot_time(struct adapter *adapter, u8 slot_time) -{ - u8 u1bAIFS, aSifsTime; - struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - rtw_write8(adapter, REG_SLOT, slot_time); - - if (pmlmeinfo->WMM_enable == 0) { - if (pmlmeext->cur_wireless_mode == WIRELESS_11B) - aSifsTime = 10; - else - aSifsTime = 16; - - u1bAIFS = aSifsTime + (2 * pmlmeinfo->slotTime); - - /* Temporary removed, 2008.06.20. */ - rtw_write8(adapter, REG_EDCA_VO_PARAM, u1bAIFS); - rtw_write8(adapter, REG_EDCA_VI_PARAM, u1bAIFS); - rtw_write8(adapter, REG_EDCA_BE_PARAM, u1bAIFS); - rtw_write8(adapter, REG_EDCA_BK_PARAM, u1bAIFS); - } -} - -void update_capinfo(struct adapter *Adapter, u16 updateCap) -{ - struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - /* Check preamble mode, 2005.01.06, by rcnjko. */ - /* Mark to update preamble value forever, 2008.03.18 by lanhsin */ - - if (updateCap & cShortPreamble) { /* Short Preamble */ - if (pmlmeinfo->preamble_mode != PREAMBLE_SHORT) { /* PREAMBLE_LONG or PREAMBLE_AUTO */ - pmlmeinfo->preamble_mode = PREAMBLE_SHORT; - set_ack_preamble(Adapter, true); - } - } else { /* Long Preamble */ - if (pmlmeinfo->preamble_mode != PREAMBLE_LONG) { /* PREAMBLE_SHORT or PREAMBLE_AUTO */ - pmlmeinfo->preamble_mode = PREAMBLE_LONG; - set_ack_preamble(Adapter, false); - } - } - - if (updateCap & cIBSS) { - /* Filen: See 802.11-2007 p.91 */ - pmlmeinfo->slotTime = NON_SHORT_SLOT_TIME; - } else { /* Filen: See 802.11-2007 p.90 */ - if (pmlmeext->cur_wireless_mode & (WIRELESS_11G | WIRELESS_11_24N)) { - if (updateCap & cShortSlotTime) { /* Short Slot Time */ - if (pmlmeinfo->slotTime != SHORT_SLOT_TIME) - pmlmeinfo->slotTime = SHORT_SLOT_TIME; - } else { /* Long Slot Time */ - if (pmlmeinfo->slotTime != NON_SHORT_SLOT_TIME) - pmlmeinfo->slotTime = NON_SHORT_SLOT_TIME; - } - } else { - /* B Mode */ - pmlmeinfo->slotTime = NON_SHORT_SLOT_TIME; - } - } - - set_slot_time(Adapter, pmlmeinfo->slotTime); -} - -void update_wireless_mode(struct adapter *padapter) -{ - int ratelen, network_type = 0; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *cur_network = &pmlmeinfo->network; - unsigned char *rate = cur_network->SupportedRates; - - ratelen = rtw_get_rateset_len(cur_network->SupportedRates); - - if ((pmlmeinfo->HT_info_enable) && (pmlmeinfo->HT_caps_enable)) - pmlmeinfo->HT_enable = 1; - - if (pmlmeext->cur_channel > 14) { - network_type |= WIRELESS_INVALID; - } else { - if (pmlmeinfo->HT_enable) - network_type = WIRELESS_11_24N; - - if (cckratesonly_included(rate, ratelen)) - network_type |= WIRELESS_11B; - else if (cckrates_included(rate, ratelen)) - network_type |= WIRELESS_11BG; - else - network_type |= WIRELESS_11G; - } - - pmlmeext->cur_wireless_mode = network_type & padapter->registrypriv.wireless_mode; - - /* RESP_SIFS for CCK */ - rtw_write8(padapter, REG_R2T_SIFS, 0x08); - rtw_write8(padapter, REG_R2T_SIFS + 1, 0x08); - /* RESP_SIFS for OFDM */ - rtw_write8(padapter, REG_T2T_SIFS, 0x0a); - rtw_write8(padapter, REG_T2T_SIFS + 1, 0x0a); - - if (pmlmeext->cur_wireless_mode & WIRELESS_11B) - update_mgnt_tx_rate(padapter, IEEE80211_CCK_RATE_1MB); - else - update_mgnt_tx_rate(padapter, IEEE80211_OFDM_RATE_6MB); -} - -void update_bmc_sta_support_rate(struct adapter *padapter, u32 mac_id) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - if (pmlmeext->cur_wireless_mode & WIRELESS_11B) { - /* Only B, B/G, and B/G/N AP could use CCK rate */ - memcpy((pmlmeinfo->FW_sta_info[mac_id].SupportedRates), rtw_basic_rate_cck, 4); - } else { - memcpy((pmlmeinfo->FW_sta_info[mac_id].SupportedRates), rtw_basic_rate_ofdm, 3); - } -} - -int update_sta_support_rate(struct adapter *padapter, u8 *pvar_ie, uint var_ie_len, int cam_idx) -{ - unsigned int ie_len; - struct ndis_802_11_var_ie *pIE; - int supportRateNum = 0; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - pIE = (struct ndis_802_11_var_ie *)rtw_get_ie(pvar_ie, _SUPPORTEDRATES_IE_, &ie_len, var_ie_len); - if (!pIE) - return _FAIL; - - memcpy(pmlmeinfo->FW_sta_info[cam_idx].SupportedRates, pIE->data, ie_len); - supportRateNum = ie_len; - - pIE = (struct ndis_802_11_var_ie *)rtw_get_ie(pvar_ie, _EXT_SUPPORTEDRATES_IE_, &ie_len, var_ie_len); - if (pIE) - memcpy((pmlmeinfo->FW_sta_info[cam_idx].SupportedRates + supportRateNum), pIE->data, ie_len); - - return _SUCCESS; -} - -void beacon_timing_control(struct adapter *padapter) -{ - SetBeaconRelatedRegisters8188EUsb(padapter); -} - -static struct adapter *pbuddy_padapter; - -void rtw_handle_dualmac(struct adapter *adapter, bool init) -{ - if (init) { - if (!pbuddy_padapter) { - pbuddy_padapter = adapter; - } else { - adapter->pbuddy_adapter = pbuddy_padapter; - pbuddy_padapter->pbuddy_adapter = adapter; - /* clear global value */ - pbuddy_padapter = NULL; - } - } else { - pbuddy_padapter = NULL; - } -} diff --git a/drivers/staging/r8188eu/core/rtw_xmit.c b/drivers/staging/r8188eu/core/rtw_xmit.c deleted file mode 100644 index df88b3e29e77..000000000000 --- a/drivers/staging/r8188eu/core/rtw_xmit.c +++ /dev/null @@ -1,2179 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2007 - 2012 Realtek Corporation. */ - -#define _RTW_XMIT_C_ - -#include "../include/osdep_service.h" -#include "../include/drv_types.h" -#include "../include/wifi.h" -#include "../include/osdep_intf.h" -#include "../include/usb_ops.h" -#include "../include/usb_osintf.h" -#include "../include/rtl8188e_xmit.h" - -static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 }; -static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 }; - -static void _init_txservq(struct tx_servq *ptxservq) -{ - INIT_LIST_HEAD(&ptxservq->tx_pending); - INIT_LIST_HEAD(&ptxservq->sta_pending); - ptxservq->qcnt = 0; -} - -void _rtw_init_sta_xmit_priv(struct sta_xmit_priv *psta_xmitpriv) -{ - memset((unsigned char *)psta_xmitpriv, 0, sizeof(struct sta_xmit_priv)); - spin_lock_init(&psta_xmitpriv->lock); - _init_txservq(&psta_xmitpriv->be_q); - _init_txservq(&psta_xmitpriv->bk_q); - _init_txservq(&psta_xmitpriv->vi_q); - _init_txservq(&psta_xmitpriv->vo_q); -} - -static int rtw_xmit_resource_alloc(struct adapter *padapter, struct xmit_buf *pxmitbuf, - u32 alloc_sz) -{ - pxmitbuf->pallocated_buf = kzalloc(alloc_sz, GFP_KERNEL); - if (!pxmitbuf->pallocated_buf) - return -ENOMEM; - - pxmitbuf->pbuf = (u8 *)ALIGN((size_t)(pxmitbuf->pallocated_buf), XMITBUF_ALIGN_SZ); - - pxmitbuf->pxmit_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!pxmitbuf->pxmit_urb) { - kfree(pxmitbuf->pallocated_buf); - return -ENOMEM; - } - - return 0; -} - -static void rtw_xmit_resource_free(struct adapter *padapter, struct xmit_buf *pxmitbuf, - u32 free_sz) -{ - usb_free_urb(pxmitbuf->pxmit_urb); - kfree(pxmitbuf->pallocated_buf); -} - -int _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter) -{ - int i; - struct xmit_buf *pxmitbuf; - struct xmit_frame *pxframe; - u32 max_xmit_extbuf_size = MAX_XMIT_EXTBUF_SZ; - u32 num_xmit_extbuf = NR_XMIT_EXTBUFF; - - /* We don't need to memset padapter->XXX to zero, because adapter is allocated by vzalloc(). */ - - spin_lock_init(&pxmitpriv->lock); - - /* - * Please insert all the queue initializaiton using rtw_init_queue below - */ - - pxmitpriv->adapter = padapter; - - INIT_LIST_HEAD(&pxmitpriv->be_pending); - INIT_LIST_HEAD(&pxmitpriv->bk_pending); - INIT_LIST_HEAD(&pxmitpriv->vi_pending); - INIT_LIST_HEAD(&pxmitpriv->vo_pending); - - rtw_init_queue(&pxmitpriv->free_xmit_queue); - - /* - * Please allocate memory with the sz = (struct xmit_frame) * NR_XMITFRAME, - * and initialize free_xmit_frame below. - * Please also apply free_txobj to link_up all the xmit_frames... - */ - - pxmitpriv->pallocated_frame_buf = vzalloc(NR_XMITFRAME * sizeof(struct xmit_frame) + 4); - - if (!pxmitpriv->pallocated_frame_buf) { - pxmitpriv->pxmit_frame_buf = NULL; - goto exit; - } - pxmitpriv->pxmit_frame_buf = (u8 *)ALIGN((size_t)(pxmitpriv->pallocated_frame_buf), 4); - /* pxmitpriv->pxmit_frame_buf = pxmitpriv->pallocated_frame_buf + 4 - */ - /* ((size_t) (pxmitpriv->pallocated_frame_buf) &3); */ - - pxframe = (struct xmit_frame *)pxmitpriv->pxmit_frame_buf; - - for (i = 0; i < NR_XMITFRAME; i++) { - INIT_LIST_HEAD(&pxframe->list); - - pxframe->padapter = padapter; - pxframe->frame_tag = NULL_FRAMETAG; - - pxframe->pkt = NULL; - - pxframe->buf_addr = NULL; - pxframe->pxmitbuf = NULL; - - list_add_tail(&pxframe->list, &pxmitpriv->free_xmit_queue.queue); - - pxframe++; - } - - pxmitpriv->free_xmitframe_cnt = NR_XMITFRAME; - - pxmitpriv->frag_len = MAX_FRAG_THRESHOLD; - - /* init xmit_buf */ - rtw_init_queue(&pxmitpriv->free_xmitbuf_queue); - rtw_init_queue(&pxmitpriv->pending_xmitbuf_queue); - - pxmitpriv->pallocated_xmitbuf = vzalloc(NR_XMITBUFF * sizeof(struct xmit_buf) + 4); - - if (!pxmitpriv->pallocated_xmitbuf) - goto free_frame_buf; - - pxmitpriv->pxmitbuf = (u8 *)ALIGN((size_t)(pxmitpriv->pallocated_xmitbuf), 4); - /* pxmitpriv->pxmitbuf = pxmitpriv->pallocated_xmitbuf + 4 - */ - /* ((size_t) (pxmitpriv->pallocated_xmitbuf) &3); */ - - pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmitbuf; - - for (i = 0; i < NR_XMITBUFF; i++) { - INIT_LIST_HEAD(&pxmitbuf->list); - - pxmitbuf->priv_data = NULL; - pxmitbuf->padapter = padapter; - pxmitbuf->ext_tag = false; - - /* Tx buf allocation may fail sometimes, so sleep and retry. */ - if (rtw_xmit_resource_alloc(padapter, pxmitbuf, (MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ))) { - msleep(10); - if (rtw_xmit_resource_alloc(padapter, pxmitbuf, (MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ))) - goto free_xmitbuf; - } - - pxmitbuf->high_queue = false; - - list_add_tail(&pxmitbuf->list, &pxmitpriv->free_xmitbuf_queue.queue); - pxmitbuf++; - } - - pxmitpriv->free_xmitbuf_cnt = NR_XMITBUFF; - - /* Init xmit extension buff */ - rtw_init_queue(&pxmitpriv->free_xmit_extbuf_queue); - - pxmitpriv->pallocated_xmit_extbuf = vzalloc(num_xmit_extbuf * sizeof(struct xmit_buf) + 4); - - if (!pxmitpriv->pallocated_xmit_extbuf) - goto free_xmitbuf; - - pxmitpriv->pxmit_extbuf = (u8 *)ALIGN((size_t)(pxmitpriv->pallocated_xmit_extbuf), 4); - - pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmit_extbuf; - - for (i = 0; i < num_xmit_extbuf; i++) { - INIT_LIST_HEAD(&pxmitbuf->list); - - pxmitbuf->priv_data = NULL; - pxmitbuf->padapter = padapter; - pxmitbuf->ext_tag = true; - - if (rtw_xmit_resource_alloc(padapter, pxmitbuf, max_xmit_extbuf_size + XMITBUF_ALIGN_SZ)) - goto free_xmit_extbuf; - - list_add_tail(&pxmitbuf->list, &pxmitpriv->free_xmit_extbuf_queue.queue); - pxmitbuf++; - } - - pxmitpriv->free_xmit_extbuf_cnt = num_xmit_extbuf; - - if (rtw_alloc_hwxmits(padapter)) - goto free_xmit_extbuf; - - for (i = 0; i < 4; i++) - pxmitpriv->wmm_para_seq[i] = i; - - pxmitpriv->ack_tx = false; - mutex_init(&pxmitpriv->ack_tx_mutex); - rtw_sctx_init(&pxmitpriv->ack_tx_ops, 0); - - tasklet_init(&pxmitpriv->xmit_tasklet, rtl8188eu_xmit_tasklet, (unsigned long)padapter); - - return 0; - -free_xmit_extbuf: - pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmit_extbuf; - while (i--) { - rtw_xmit_resource_free(padapter, pxmitbuf, (max_xmit_extbuf_size + XMITBUF_ALIGN_SZ)); - pxmitbuf++; - } - vfree(pxmitpriv->pallocated_xmit_extbuf); - i = NR_XMITBUFF; -free_xmitbuf: - pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmitbuf; - while (i--) { - rtw_xmit_resource_free(padapter, pxmitbuf, (MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ)); - pxmitbuf++; - } - vfree(pxmitpriv->pallocated_xmitbuf); -free_frame_buf: - vfree(pxmitpriv->pallocated_frame_buf); -exit: - return -ENOMEM; -} - -static void rtw_pkt_complete(struct adapter *padapter, struct sk_buff *pkt) -{ - u16 queue; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - queue = skb_get_queue_mapping(pkt); - if (padapter->registrypriv.wifi_spec) { - if (__netif_subqueue_stopped(padapter->pnetdev, queue) && - (pxmitpriv->hwxmits[queue].accnt < WMM_XMIT_THRESHOLD)) - netif_wake_subqueue(padapter->pnetdev, queue); - } else { - if (__netif_subqueue_stopped(padapter->pnetdev, queue)) - netif_wake_subqueue(padapter->pnetdev, queue); - } - - dev_kfree_skb_any(pkt); -} - -void rtw_xmit_complete(struct adapter *padapter, struct xmit_frame *pxframe) -{ - if (pxframe->pkt) - rtw_pkt_complete(padapter, pxframe->pkt); - pxframe->pkt = NULL; -} - -void _rtw_free_xmit_priv(struct xmit_priv *pxmitpriv) -{ - int i; - struct adapter *padapter = pxmitpriv->adapter; - struct xmit_frame *pxmitframe = (struct xmit_frame *)pxmitpriv->pxmit_frame_buf; - struct xmit_buf *pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmitbuf; - u32 max_xmit_extbuf_size = MAX_XMIT_EXTBUF_SZ; - u32 num_xmit_extbuf = NR_XMIT_EXTBUFF; - - if (!pxmitpriv->pxmit_frame_buf) - return; - - for (i = 0; i < NR_XMITFRAME; i++) { - rtw_xmit_complete(padapter, pxmitframe); - - pxmitframe++; - } - - for (i = 0; i < NR_XMITBUFF; i++) { - rtw_xmit_resource_free(padapter, pxmitbuf, (MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ)); - pxmitbuf++; - } - - vfree(pxmitpriv->pallocated_frame_buf); - - vfree(pxmitpriv->pallocated_xmitbuf); - - pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmit_extbuf; - for (i = 0; i < num_xmit_extbuf; i++) { - rtw_xmit_resource_free(padapter, pxmitbuf, (max_xmit_extbuf_size + XMITBUF_ALIGN_SZ)); - pxmitbuf++; - } - - vfree(pxmitpriv->pallocated_xmit_extbuf); - - kfree(pxmitpriv->hwxmits); - - mutex_destroy(&pxmitpriv->ack_tx_mutex); -} - -static void update_attrib_vcs_info(struct adapter *padapter, struct xmit_frame *pxmitframe) -{ - u32 sz; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct sta_info *psta = pattrib->psta; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - if (pattrib->nr_frags != 1) - sz = padapter->xmitpriv.frag_len; - else /* no frag */ - sz = pattrib->last_txcmdsz; - - /* (1) RTS_Threshold is compared to the MPDU, not MSDU. */ - /* (2) If there are more than one frag in this MSDU, only the first frag uses protection frame. */ - /* Other fragments are protected by previous fragment. */ - /* So we only need to check the length of first fragment. */ - if (pmlmeext->cur_wireless_mode < WIRELESS_11_24N || padapter->registrypriv.wifi_spec) { - if (sz > padapter->registrypriv.rts_thresh) { - pattrib->vcs_mode = RTS_CTS; - } else { - if (psta->rtsen) - pattrib->vcs_mode = RTS_CTS; - else if (psta->cts2self) - pattrib->vcs_mode = CTS_TO_SELF; - else - pattrib->vcs_mode = NONE_VCS; - } - } else { - while (true) { - /* IOT action */ - if ((pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_ATHEROS) && pattrib->ampdu_en && - (padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)) { - pattrib->vcs_mode = CTS_TO_SELF; - break; - } - - /* check ERP protection */ - if (psta->rtsen || psta->cts2self) { - if (psta->rtsen) - pattrib->vcs_mode = RTS_CTS; - else if (psta->cts2self) - pattrib->vcs_mode = CTS_TO_SELF; - - break; - } - - /* check HT op mode */ - if (pattrib->ht_en) { - u8 htopmode = pmlmeinfo->HT_protection; - - if ((pmlmeext->cur_bwmode && (htopmode == 2 || htopmode == 3)) || - (!pmlmeext->cur_bwmode && htopmode == 3)) { - pattrib->vcs_mode = RTS_CTS; - break; - } - } - - /* check rts */ - if (sz > padapter->registrypriv.rts_thresh) { - pattrib->vcs_mode = RTS_CTS; - break; - } - - /* to do list: check MIMO power save condition. */ - - /* check AMPDU aggregation for TXOP */ - if (pattrib->ampdu_en) { - pattrib->vcs_mode = RTS_CTS; - break; - } - - pattrib->vcs_mode = NONE_VCS; - break; - } - } -} - -static void update_attrib_phy_info(struct pkt_attrib *pattrib, struct sta_info *psta) -{ - /*if (psta->rtsen) - pattrib->vcs_mode = RTS_CTS; - else if (psta->cts2self) - pattrib->vcs_mode = CTS_TO_SELF; - else - pattrib->vcs_mode = NONE_VCS;*/ - - pattrib->mdata = 0; - pattrib->eosp = 0; - pattrib->triggered = 0; - - /* qos_en, ht_en, init rate, , bw, ch_offset, sgi */ - pattrib->qos_en = psta->qos_option; - - pattrib->raid = psta->raid; - pattrib->ht_en = psta->htpriv.ht_option; - pattrib->bwmode = psta->htpriv.bwmode; - pattrib->ch_offset = psta->htpriv.ch_offset; - pattrib->sgi = psta->htpriv.sgi; - pattrib->ampdu_en = false; - pattrib->retry_ctrl = false; -} - -u8 qos_acm(u8 acm_mask, u8 priority) -{ - u8 change_priority = priority; - - switch (priority) { - case 0: - case 3: - if (acm_mask & BIT(1)) - change_priority = 1; - break; - case 1: - case 2: - break; - case 4: - case 5: - if (acm_mask & BIT(2)) - change_priority = 0; - break; - case 6: - case 7: - if (acm_mask & BIT(3)) - change_priority = 5; - break; - default: - break; - } - - return change_priority; -} - -static void rtw_open_pktfile(struct sk_buff *pktptr, struct pkt_file *pfile) -{ - if (!pktptr) { - pr_err("8188eu: pktptr is NULL\n"); - return; - } - if (!pfile) { - pr_err("8188eu: pfile is NULL\n"); - return; - } - pfile->pkt = pktptr; - pfile->cur_addr = pktptr->data; - pfile->buf_start = pktptr->data; - pfile->pkt_len = pktptr->len; - pfile->buf_len = pktptr->len; - - pfile->cur_buffer = pfile->buf_start; -} - -static uint rtw_remainder_len(struct pkt_file *pfile) -{ - return pfile->buf_len - ((size_t)(pfile->cur_addr) - - (size_t)(pfile->buf_start)); -} - -static uint rtw_pktfile_read(struct pkt_file *pfile, u8 *rmem, uint rlen) -{ - uint len; - - len = min(rtw_remainder_len(pfile), rlen); - - if (rmem) - skb_copy_bits(pfile->pkt, pfile->buf_len - pfile->pkt_len, rmem, len); - - pfile->cur_addr += len; - pfile->pkt_len -= len; - - return len; -} - -static void set_qos(struct pkt_file *ppktfile, struct pkt_attrib *pattrib) -{ - struct ethhdr etherhdr; - struct iphdr ip_hdr; - s32 user_prio = 0; - - rtw_open_pktfile(ppktfile->pkt, ppktfile); - rtw_pktfile_read(ppktfile, (unsigned char *)ðerhdr, ETH_HLEN); - - /* get user_prio from IP hdr */ - if (pattrib->ether_type == 0x0800) { - rtw_pktfile_read(ppktfile, (u8 *)&ip_hdr, sizeof(ip_hdr)); -/* user_prio = (ntohs(ip_hdr.tos) >> 5) & 0x3; */ - user_prio = ip_hdr.tos >> 5; - } else if (pattrib->ether_type == 0x888e) { - /* "When priority processing of data frames is supported, */ - /* a STA's SME should send EAPOL-Key frames at the highest priority." */ - user_prio = 7; - } - - pattrib->priority = user_prio; - pattrib->hdrlen = WLAN_HDR_A3_QOS_LEN; - pattrib->subtype = IEEE80211_STYPE_QOS_DATA | IEEE80211_FTYPE_DATA; -} - -static s32 update_attrib(struct adapter *padapter, struct sk_buff *pkt, struct pkt_attrib *pattrib) -{ - struct pkt_file pktfile; - struct sta_info *psta = NULL; - struct ethhdr etherhdr; - - bool bmcast; - struct sta_priv *pstapriv = &padapter->stapriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct qos_priv *pqospriv = &pmlmepriv->qospriv; - int res = _SUCCESS; - - - - rtw_open_pktfile(pkt, &pktfile); - rtw_pktfile_read(&pktfile, (u8 *)ðerhdr, ETH_HLEN); - - pattrib->ether_type = ntohs(etherhdr.h_proto); - - memcpy(pattrib->dst, ðerhdr.h_dest, ETH_ALEN); - memcpy(pattrib->src, ðerhdr.h_source, ETH_ALEN); - - pattrib->pctrl = 0; - - if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) || - check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) { - memcpy(pattrib->ra, pattrib->dst, ETH_ALEN); - memcpy(pattrib->ta, pattrib->src, ETH_ALEN); - } else if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { - memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN); - memcpy(pattrib->ta, pattrib->src, ETH_ALEN); - } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - memcpy(pattrib->ra, pattrib->dst, ETH_ALEN); - memcpy(pattrib->ta, get_bssid(pmlmepriv), ETH_ALEN); - } - - pattrib->pktlen = pktfile.pkt_len; - - if (pattrib->ether_type == ETH_P_IP) { - /* The following is for DHCP and ARP packet, we use cck1M to tx these packets and let LPS awake some time */ - /* to prevent DHCP protocol fail */ - u8 tmp[24]; - - rtw_pktfile_read(&pktfile, &tmp[0], 24); - pattrib->dhcp_pkt = 0; - if (pktfile.pkt_len > 282) {/* MINIMUM_DHCP_PACKET_SIZE) { */ - if (((tmp[21] == 68) && (tmp[23] == 67)) || - ((tmp[21] == 67) && (tmp[23] == 68))) { - /* 68 : UDP BOOTP client */ - /* 67 : UDP BOOTP server */ - /* Use low rate to send DHCP packet. */ - pattrib->dhcp_pkt = 1; - } - } - } - - /* If EAPOL , ARP , OR DHCP packet, driver must be in active mode. */ - if ((pattrib->ether_type == 0x0806) || (pattrib->ether_type == 0x888e) || (pattrib->dhcp_pkt == 1)) - rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_SPECIAL_PACKET, 1); - - bmcast = is_multicast_ether_addr(pattrib->ra); - - /* get sta_info */ - if (bmcast) { - psta = rtw_get_bcmc_stainfo(padapter); - } else { - psta = rtw_get_stainfo(pstapriv, pattrib->ra); - if (!psta) { /* if we cannot get psta => drrp the pkt */ - res = _FAIL; - goto exit; - } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) && !(psta->state & _FW_LINKED)) { - res = _FAIL; - goto exit; - } - } - - if (psta) { - pattrib->mac_id = psta->mac_id; - pattrib->psta = psta; - } else { - /* if we cannot get psta => drop the pkt */ - res = _FAIL; - goto exit; - } - - pattrib->ack_policy = 0; - /* get ether_hdr_len */ - pattrib->pkt_hdrlen = ETH_HLEN;/* pattrib->ether_type == 0x8100) ? (14 + 4): 14; vlan tag */ - - pattrib->hdrlen = WLAN_HDR_A3_LEN; - pattrib->subtype = IEEE80211_FTYPE_DATA; - pattrib->priority = 0; - - if (check_fwstate(pmlmepriv, WIFI_AP_STATE | WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE)) { - if (psta->qos_option) - set_qos(&pktfile, pattrib); - } else { - if (pqospriv->qos_option) { - set_qos(&pktfile, pattrib); - - if (pmlmepriv->acm_mask != 0) - pattrib->priority = qos_acm(pmlmepriv->acm_mask, pattrib->priority); - } - } - - if (psta->ieee8021x_blocked) { - pattrib->encrypt = 0; - - if ((pattrib->ether_type != 0x888e) && !check_fwstate(pmlmepriv, WIFI_MP_STATE)) { - res = _FAIL; - goto exit; - } - } else { - GET_ENCRY_ALGO(psecuritypriv, psta, pattrib->encrypt, bmcast); - - switch (psecuritypriv->dot11AuthAlgrthm) { - case dot11AuthAlgrthm_Open: - case dot11AuthAlgrthm_Shared: - case dot11AuthAlgrthm_Auto: - pattrib->key_idx = (u8)psecuritypriv->dot11PrivacyKeyIndex; - break; - case dot11AuthAlgrthm_8021X: - if (bmcast) - pattrib->key_idx = (u8)psecuritypriv->dot118021XGrpKeyid; - else - pattrib->key_idx = 0; - break; - default: - pattrib->key_idx = 0; - break; - } - } - - switch (pattrib->encrypt) { - case _WEP40_: - case _WEP104_: - pattrib->iv_len = 4; - pattrib->icv_len = 4; - break; - case _TKIP_: - pattrib->iv_len = 8; - pattrib->icv_len = 4; - - if (padapter->securitypriv.busetkipkey == _FAIL) { - res = _FAIL; - goto exit; - } - break; - case _AES_: - pattrib->iv_len = 8; - pattrib->icv_len = 8; - break; - default: - pattrib->iv_len = 0; - pattrib->icv_len = 0; - break; - } - - if (pattrib->encrypt && - (padapter->securitypriv.sw_encrypt || !psecuritypriv->hw_decrypted)) - pattrib->bswenc = true; - else - pattrib->bswenc = false; - - update_attrib_phy_info(pattrib, psta); - -exit: - - return res; -} - -static s32 xmitframe_addmic(struct adapter *padapter, struct xmit_frame *pxmitframe) -{ - int curfragnum, length; - u8 *pframe, *payload, mic[8]; - struct mic_data micdata; - struct sta_info *stainfo; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - u8 priority[4] = {0x0, 0x0, 0x0, 0x0}; - u8 hw_hdr_offset = 0; - - if (pattrib->psta) - stainfo = pattrib->psta; - else - stainfo = rtw_get_stainfo(&padapter->stapriv, &pattrib->ra[0]); - - hw_hdr_offset = TXDESC_SIZE + (pxmitframe->pkt_offset * PACKET_OFFSET_SZ); - - if (pattrib->encrypt == _TKIP_) {/* if (psecuritypriv->dot11PrivacyAlgrthm == _TKIP_PRIVACY_) */ - /* encode mic code */ - if (stainfo) { - u8 null_key[16] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0}; - - pframe = pxmitframe->buf_addr + hw_hdr_offset; - - if (is_multicast_ether_addr(pattrib->ra)) { - if (!memcmp(psecuritypriv->dot118021XGrptxmickey[psecuritypriv->dot118021XGrpKeyid].skey, null_key, 16)) - return _FAIL; - /* start to calculate the mic code */ - rtw_secmicsetkey(&micdata, psecuritypriv->dot118021XGrptxmickey[psecuritypriv->dot118021XGrpKeyid].skey); - } else { - if (!memcmp(&stainfo->dot11tkiptxmickey.skey[0], null_key, 16)) { - /* msleep(10); */ - return _FAIL; - } - /* start to calculate the mic code */ - rtw_secmicsetkey(&micdata, &stainfo->dot11tkiptxmickey.skey[0]); - } - - if (pframe[1] & 1) { /* ToDS == 1 */ - rtw_secmicappend(&micdata, &pframe[16], 6); /* DA */ - if (pframe[1] & 2) /* From Ds == 1 */ - rtw_secmicappend(&micdata, &pframe[24], 6); - else - rtw_secmicappend(&micdata, &pframe[10], 6); - } else { /* ToDS == 0 */ - rtw_secmicappend(&micdata, &pframe[4], 6); /* DA */ - if (pframe[1] & 2) /* From Ds == 1 */ - rtw_secmicappend(&micdata, &pframe[16], 6); - else - rtw_secmicappend(&micdata, &pframe[10], 6); - } - - if (pattrib->qos_en) - priority[0] = (u8)pxmitframe->attrib.priority; - - rtw_secmicappend(&micdata, &priority[0], 4); - - payload = pframe; - - for (curfragnum = 0; curfragnum < pattrib->nr_frags; curfragnum++) { - payload = PTR_ALIGN(payload, 4); - - payload = payload + pattrib->hdrlen + pattrib->iv_len; - if ((curfragnum + 1) == pattrib->nr_frags) { - length = pattrib->last_txcmdsz - pattrib->hdrlen - pattrib->iv_len - ((pattrib->bswenc) ? pattrib->icv_len : 0); - rtw_secmicappend(&micdata, payload, length); - payload = payload + length; - } else { - length = pxmitpriv->frag_len - pattrib->hdrlen - pattrib->iv_len - ((pattrib->bswenc) ? pattrib->icv_len : 0); - rtw_secmicappend(&micdata, payload, length); - payload = payload + length + pattrib->icv_len; - } - } - rtw_secgetmic(&micdata, &mic[0]); - /* add mic code and add the mic code length in last_txcmdsz */ - - memcpy(payload, &mic[0], 8); - pattrib->last_txcmdsz += 8; - - payload = payload - pattrib->last_txcmdsz + 8; - } - } - - return _SUCCESS; -} - -static void xmitframe_swencrypt(struct adapter *padapter, struct xmit_frame *pxmitframe) -{ - struct pkt_attrib *pattrib = &pxmitframe->attrib; - - if (!pattrib->bswenc) - return; - - switch (pattrib->encrypt) { - case _WEP40_: - case _WEP104_: - rtw_wep_encrypt(padapter, pxmitframe); - break; - case _TKIP_: - rtw_tkip_encrypt(padapter, pxmitframe); - break; - case _AES_: - rtw_aes_encrypt(padapter, pxmitframe); - break; - default: - break; - } -} - -s32 rtw_make_wlanhdr(struct adapter *padapter, u8 *hdr, struct pkt_attrib *pattrib) -{ - u16 *qc; - - struct ieee80211_hdr *pwlanhdr = (struct ieee80211_hdr *)hdr; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct qos_priv *pqospriv = &pmlmepriv->qospriv; - bool qos_option; - __le16 *fctrl = &pwlanhdr->frame_control; - - struct sta_info *psta; - - if (pattrib->psta) - psta = pattrib->psta; - else if (is_multicast_ether_addr(pattrib->ra)) - psta = rtw_get_bcmc_stainfo(padapter); - else - psta = rtw_get_stainfo(&padapter->stapriv, pattrib->ra); - - memset(hdr, 0, WLANHDR_OFFSET); - - SetFrameSubType(fctrl, pattrib->subtype); - - if (!(pattrib->subtype & IEEE80211_FTYPE_DATA)) - return _SUCCESS; - - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { - /* to_ds = 1, fr_ds = 0; */ - /* Data transfer to AP */ - SetToDs(fctrl); - memcpy(pwlanhdr->addr1, get_bssid(pmlmepriv), ETH_ALEN); - memcpy(pwlanhdr->addr2, pattrib->src, ETH_ALEN); - memcpy(pwlanhdr->addr3, pattrib->dst, ETH_ALEN); - qos_option = pqospriv->qos_option; - } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - /* to_ds = 0, fr_ds = 1; */ - SetFrDs(fctrl); - memcpy(pwlanhdr->addr1, pattrib->dst, ETH_ALEN); - memcpy(pwlanhdr->addr2, get_bssid(pmlmepriv), ETH_ALEN); - memcpy(pwlanhdr->addr3, pattrib->src, ETH_ALEN); - qos_option = psta->qos_option; - } else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) || - check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) { - memcpy(pwlanhdr->addr1, pattrib->dst, ETH_ALEN); - memcpy(pwlanhdr->addr2, pattrib->src, ETH_ALEN); - memcpy(pwlanhdr->addr3, get_bssid(pmlmepriv), ETH_ALEN); - qos_option = psta->qos_option; - } else { - return _FAIL; - } - - if (pattrib->mdata) - SetMData(fctrl); - - if (pattrib->encrypt) - SetPrivacy(fctrl); - - if (qos_option) { - qc = (unsigned short *)(hdr + pattrib->hdrlen - 2); - - if (pattrib->priority) - SetPriority(qc, pattrib->priority); - - SetEOSP(qc, pattrib->eosp); - - SetAckpolicy(qc, pattrib->ack_policy); - } - - /* TODO: fill HT Control Field */ - - /* Update Seq Num will be handled by f/w */ - if (psta) { - psta->sta_xmitpriv.txseq_tid[pattrib->priority]++; - psta->sta_xmitpriv.txseq_tid[pattrib->priority] &= 0xFFF; - - pattrib->seqnum = psta->sta_xmitpriv.txseq_tid[pattrib->priority]; - - SetSeqNum(hdr, pattrib->seqnum); - - /* check if enable ampdu */ - if (pattrib->ht_en && psta->htpriv.ampdu_enable) { - if (psta->htpriv.agg_enable_bitmap & BIT(pattrib->priority)) - pattrib->ampdu_en = true; - } - - /* re-check if enable ampdu by BA_starting_seqctrl */ - if (pattrib->ampdu_en) { - u16 tx_seq; - - tx_seq = psta->BA_starting_seqctrl[pattrib->priority & 0x0f]; - - /* check BA_starting_seqctrl */ - if (SN_LESS(pattrib->seqnum, tx_seq)) { - pattrib->ampdu_en = false;/* AGG BK */ - } else if (SN_EQUAL(pattrib->seqnum, tx_seq)) { - psta->BA_starting_seqctrl[pattrib->priority & 0x0f] = (tx_seq + 1) & 0xfff; - - pattrib->ampdu_en = true;/* AGG EN */ - } else { - psta->BA_starting_seqctrl[pattrib->priority & 0x0f] = (pattrib->seqnum + 1) & 0xfff; - pattrib->ampdu_en = true;/* AGG EN */ - } - } - } - - return _SUCCESS; -} - -s32 rtw_txframes_pending(struct adapter *padapter) -{ - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - return (!list_empty(&pxmitpriv->be_pending) || - !list_empty(&pxmitpriv->bk_pending) || - !list_empty(&pxmitpriv->vi_pending) || - !list_empty(&pxmitpriv->vo_pending)); -} - -s32 rtw_txframes_sta_ac_pending(struct adapter *padapter, struct pkt_attrib *pattrib) -{ - struct sta_info *psta; - struct tx_servq *ptxservq; - int priority = pattrib->priority; - - psta = pattrib->psta; - - switch (priority) { - case 1: - case 2: - ptxservq = &psta->sta_xmitpriv.bk_q; - break; - case 4: - case 5: - ptxservq = &psta->sta_xmitpriv.vi_q; - break; - case 6: - case 7: - ptxservq = &psta->sta_xmitpriv.vo_q; - break; - case 0: - case 3: - default: - ptxservq = &psta->sta_xmitpriv.be_q; - break; - } - - if (ptxservq) - return ptxservq->qcnt; - return 0; -} - -/* - * This sub-routine will perform all the following: - * - * 1. remove 802.3 header. - * 2. create wlan_header, based on the info in pxmitframe - * 3. append sta's iv/ext-iv - * 4. append LLC - * 5. move frag chunk from pframe to pxmitframe->mem - * 6. apply sw-encrypt, if necessary. - */ -s32 rtw_xmitframe_coalesce(struct adapter *padapter, struct sk_buff *pkt, struct xmit_frame *pxmitframe) -{ - struct pkt_file pktfile; - s32 frg_inx, frg_len, mpdu_len, llc_sz, mem_sz; - u8 *pframe, *mem_start; - u8 hw_hdr_offset; - struct sta_info *psta; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - u8 *pbuf_start; - bool bmcst = is_multicast_ether_addr(pattrib->ra); - s32 res = _SUCCESS; - - if (!pkt) - return _FAIL; - - psta = rtw_get_stainfo(&padapter->stapriv, pattrib->ra); - - if (!psta) - return _FAIL; - - if (!pxmitframe->buf_addr) - return _FAIL; - - pbuf_start = pxmitframe->buf_addr; - - hw_hdr_offset = TXDESC_SIZE + (pxmitframe->pkt_offset * PACKET_OFFSET_SZ); - - mem_start = pbuf_start + hw_hdr_offset; - - if (rtw_make_wlanhdr(padapter, mem_start, pattrib) == _FAIL) { - res = _FAIL; - goto exit; - } - - rtw_open_pktfile(pkt, &pktfile); - rtw_pktfile_read(&pktfile, NULL, pattrib->pkt_hdrlen); - - frg_inx = 0; - frg_len = pxmitpriv->frag_len - 4;/* 2346-4 = 2342 */ - - while (1) { - llc_sz = 0; - - mpdu_len = frg_len; - - pframe = mem_start; - - SetMFrag(mem_start); - - pframe += pattrib->hdrlen; - mpdu_len -= pattrib->hdrlen; - - /* adding icv, if necessary... */ - if (pattrib->iv_len) { - switch (pattrib->encrypt) { - case _WEP40_: - case _WEP104_: - WEP_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx); - break; - case _TKIP_: - if (bmcst) - TKIP_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx); - else - TKIP_IV(pattrib->iv, psta->dot11txpn, 0); - break; - case _AES_: - if (bmcst) - AES_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx); - else - AES_IV(pattrib->iv, psta->dot11txpn, 0); - break; - } - - memcpy(pframe, pattrib->iv, pattrib->iv_len); - - pframe += pattrib->iv_len; - - mpdu_len -= pattrib->iv_len; - } - - if (frg_inx == 0) { - llc_sz = rtw_put_snap(pframe, pattrib->ether_type); - pframe += llc_sz; - mpdu_len -= llc_sz; - } - - if ((pattrib->icv_len > 0) && (pattrib->bswenc)) - mpdu_len -= pattrib->icv_len; - - if (bmcst) { - /* don't do fragment to broadcast/multicast packets */ - mem_sz = rtw_pktfile_read(&pktfile, pframe, pattrib->pktlen); - } else { - mem_sz = rtw_pktfile_read(&pktfile, pframe, mpdu_len); - } - - pframe += mem_sz; - - if ((pattrib->icv_len > 0) && (pattrib->bswenc)) { - memcpy(pframe, pattrib->icv, pattrib->icv_len); - pframe += pattrib->icv_len; - } - - frg_inx++; - - if (bmcst || pktfile.pkt_len == 0) { - pattrib->nr_frags = frg_inx; - - pattrib->last_txcmdsz = pattrib->hdrlen + pattrib->iv_len + ((pattrib->nr_frags == 1) ? llc_sz : 0) + - ((pattrib->bswenc) ? pattrib->icv_len : 0) + mem_sz; - - ClearMFrag(mem_start); - - break; - } - - mem_start = PTR_ALIGN(pframe, 4) + hw_hdr_offset; - memcpy(mem_start, pbuf_start + hw_hdr_offset, pattrib->hdrlen); - } - - if (xmitframe_addmic(padapter, pxmitframe) == _FAIL) { - res = _FAIL; - goto exit; - } - - xmitframe_swencrypt(padapter, pxmitframe); - - if (!bmcst) - update_attrib_vcs_info(padapter, pxmitframe); - else - pattrib->vcs_mode = NONE_VCS; - -exit: - - return res; -} - -/* Logical Link Control(LLC) SubNetwork Attachment Point(SNAP) header - * IEEE LLC/SNAP header contains 8 octets - * First 3 octets comprise the LLC portion - * SNAP portion, 5 octets, is divided into two fields: - * Organizationally Unique Identifier(OUI), 3 octets, - * type, defined by that organization, 2 octets. - */ -s32 rtw_put_snap(u8 *data, u16 h_proto) -{ - struct ieee80211_snap_hdr *snap; - u8 *oui; - - snap = (struct ieee80211_snap_hdr *)data; - snap->dsap = 0xaa; - snap->ssap = 0xaa; - snap->ctrl = 0x03; - - if (h_proto == 0x8137 || h_proto == 0x80f3) - oui = P802_1H_OUI; - else - oui = RFC1042_OUI; - - snap->oui[0] = oui[0]; - snap->oui[1] = oui[1]; - snap->oui[2] = oui[2]; - - *(__be16 *)(data + SNAP_SIZE) = htons(h_proto); - - return SNAP_SIZE + sizeof(u16); -} - -void rtw_count_tx_stats(struct adapter *padapter, struct xmit_frame *pxmitframe, int sz) -{ - struct sta_info *psta = NULL; - struct stainfo_stats *pstats = NULL; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - if ((pxmitframe->frame_tag & 0x0f) == DATA_FRAMETAG) { - pxmitpriv->tx_bytes += sz; - pmlmepriv->LinkDetectInfo.NumTxOkInPeriod += pxmitframe->agg_num; - - psta = pxmitframe->attrib.psta; - if (psta) { - pstats = &psta->sta_stats; - pstats->tx_pkts += pxmitframe->agg_num; - pstats->tx_bytes += sz; - } - } -} - -struct xmit_buf *rtw_alloc_xmitbuf_ext(struct xmit_priv *pxmitpriv) -{ - struct xmit_buf *pxmitbuf = NULL; - struct list_head *plist, *phead; - struct __queue *pfree_queue = &pxmitpriv->free_xmit_extbuf_queue; - unsigned long flags; - - spin_lock_irqsave(&pfree_queue->lock, flags); - - if (list_empty(&pfree_queue->queue)) { - pxmitbuf = NULL; - } else { - phead = get_list_head(pfree_queue); - - plist = phead->next; - - pxmitbuf = container_of(plist, struct xmit_buf, list); - - list_del_init(&pxmitbuf->list); - } - - if (pxmitbuf) { - pxmitpriv->free_xmit_extbuf_cnt--; - - pxmitbuf->priv_data = NULL; - /* pxmitbuf->ext_tag = true; */ - - if (pxmitbuf->sctx) - rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_BUF_ALLOC); - } - - spin_unlock_irqrestore(&pfree_queue->lock, flags); - - return pxmitbuf; -} - -s32 rtw_free_xmitbuf_ext(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf) -{ - struct __queue *pfree_queue = &pxmitpriv->free_xmit_extbuf_queue; - unsigned long flags; - - if (!pxmitbuf) - return _FAIL; - - spin_lock_irqsave(&pfree_queue->lock, flags); - - list_del_init(&pxmitbuf->list); - - list_add_tail(&pxmitbuf->list, get_list_head(pfree_queue)); - pxmitpriv->free_xmit_extbuf_cnt++; - - spin_unlock_irqrestore(&pfree_queue->lock, flags); - - return _SUCCESS; -} - -struct xmit_buf *rtw_alloc_xmitbuf(struct xmit_priv *pxmitpriv) -{ - struct xmit_buf *pxmitbuf = NULL; - struct list_head *plist, *phead; - struct __queue *pfree_xmitbuf_queue = &pxmitpriv->free_xmitbuf_queue; - unsigned long flags; - - spin_lock_irqsave(&pfree_xmitbuf_queue->lock, flags); - - if (list_empty(&pfree_xmitbuf_queue->queue)) { - pxmitbuf = NULL; - } else { - phead = get_list_head(pfree_xmitbuf_queue); - - plist = phead->next; - - pxmitbuf = container_of(plist, struct xmit_buf, list); - - list_del_init(&pxmitbuf->list); - } - - if (pxmitbuf) { - pxmitpriv->free_xmitbuf_cnt--; - pxmitbuf->priv_data = NULL; - if (pxmitbuf->sctx) - rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_BUF_ALLOC); - } - spin_unlock_irqrestore(&pfree_xmitbuf_queue->lock, flags); - - return pxmitbuf; -} - -s32 rtw_free_xmitbuf(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf) -{ - struct __queue *pfree_xmitbuf_queue = &pxmitpriv->free_xmitbuf_queue; - unsigned long flags; - - if (!pxmitbuf) - return _FAIL; - - if (pxmitbuf->sctx) - rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_BUF_FREE); - - if (pxmitbuf->ext_tag) { - rtw_free_xmitbuf_ext(pxmitpriv, pxmitbuf); - } else { - spin_lock_irqsave(&pfree_xmitbuf_queue->lock, flags); - - list_del_init(&pxmitbuf->list); - - list_add_tail(&pxmitbuf->list, get_list_head(pfree_xmitbuf_queue)); - - pxmitpriv->free_xmitbuf_cnt++; - spin_unlock_irqrestore(&pfree_xmitbuf_queue->lock, flags); - } - - return _SUCCESS; -} - -/* - * Calling context: - * 1. OS_TXENTRY - * 2. RXENTRY (rx_thread or RX_ISR/RX_CallBack) - * - * If we turn on USE_RXTHREAD, then, no need for critical section. - * Otherwise, we must use _enter/_exit critical to protect free_xmit_queue... - * - * Must be very very cautious... - */ -struct xmit_frame *rtw_alloc_xmitframe(struct xmit_priv *pxmitpriv)/* _queue *pfree_xmit_queue) */ -{ - /* - * Please remember to use all the osdep_service api, - * and lock/unlock or _enter/_exit critical to protect - * pfree_xmit_queue - */ - - struct xmit_frame *pxframe = NULL; - struct list_head *plist, *phead; - struct __queue *pfree_xmit_queue = &pxmitpriv->free_xmit_queue; - - spin_lock_bh(&pfree_xmit_queue->lock); - - if (list_empty(&pfree_xmit_queue->queue)) - goto out; - - phead = get_list_head(pfree_xmit_queue); - plist = phead->next; - pxframe = container_of(plist, struct xmit_frame, list); - list_del_init(&pxframe->list); - - pxmitpriv->free_xmitframe_cnt--; - - pxframe->buf_addr = NULL; - pxframe->pxmitbuf = NULL; - - memset(&pxframe->attrib, 0, sizeof(struct pkt_attrib)); - /* pxframe->attrib.psta = NULL; */ - - pxframe->frame_tag = DATA_FRAMETAG; - - pxframe->pkt = NULL; - pxframe->pkt_offset = 1;/* default use pkt_offset to fill tx desc */ - - pxframe->agg_num = 1; - pxframe->ack_report = 0; - -out: - spin_unlock_bh(&pfree_xmit_queue->lock); - return pxframe; -} - -s32 rtw_free_xmitframe(struct xmit_priv *pxmitpriv, struct xmit_frame *pxmitframe) -{ - struct __queue *pfree_xmit_queue = &pxmitpriv->free_xmit_queue; - struct adapter *padapter = pxmitpriv->adapter; - struct sk_buff *pndis_pkt = NULL; - - if (!pxmitframe) - goto exit; - - spin_lock_bh(&pfree_xmit_queue->lock); - - list_del_init(&pxmitframe->list); - - if (pxmitframe->pkt) { - pndis_pkt = pxmitframe->pkt; - pxmitframe->pkt = NULL; - } - - list_add_tail(&pxmitframe->list, get_list_head(pfree_xmit_queue)); - - pxmitpriv->free_xmitframe_cnt++; - - spin_unlock_bh(&pfree_xmit_queue->lock); - - if (pndis_pkt) - rtw_pkt_complete(padapter, pndis_pkt); - -exit: - - return _SUCCESS; -} - -void rtw_free_xmitframe_list(struct xmit_priv *pxmitpriv, struct list_head *xframe_list) -{ - struct xmit_frame *pxmitframe, *tmp_xmitframe; - - list_for_each_entry_safe(pxmitframe, tmp_xmitframe, xframe_list, list) - rtw_free_xmitframe(pxmitpriv, pxmitframe); -} - -struct xmit_frame *rtw_dequeue_xframe(struct xmit_priv *pxmitpriv, struct hw_xmit *phwxmit_i) -{ - struct hw_xmit *phwxmit; - struct tx_servq *ptxservq, *tmp_txservq; - struct list_head *xframe_list; - struct xmit_frame *pxmitframe = NULL; - struct adapter *padapter = pxmitpriv->adapter; - struct registry_priv *pregpriv = &padapter->registrypriv; - int i, inx[] = { 0, 1, 2, 3 }; - - if (pregpriv->wifi_spec == 1) { - for (i = 0; i < ARRAY_SIZE(inx); i++) - inx[i] = pxmitpriv->wmm_para_seq[i]; - } - - spin_lock_bh(&pxmitpriv->lock); - - for (i = 0; i < HWXMIT_ENTRY; i++) { - phwxmit = phwxmit_i + inx[i]; - list_for_each_entry_safe(ptxservq, tmp_txservq, phwxmit->sta_list, tx_pending) { - xframe_list = &ptxservq->sta_pending; - if (list_empty(xframe_list)) - continue; - - pxmitframe = container_of(xframe_list->next, struct xmit_frame, list); - list_del_init(&pxmitframe->list); - - phwxmit->accnt--; - ptxservq->qcnt--; - - /* Remove sta node when there are no pending packets. */ - if (list_empty(xframe_list)) - list_del_init(&ptxservq->tx_pending); - - goto exit; - } - } -exit: - spin_unlock_bh(&pxmitpriv->lock); - - return pxmitframe; -} - -struct tx_servq *rtw_get_sta_pending(struct adapter *padapter, struct sta_info *psta, int up, u8 *ac) -{ - struct tx_servq *ptxservq; - - switch (up) { - case 1: - case 2: - ptxservq = &psta->sta_xmitpriv.bk_q; - *(ac) = 3; - break; - case 4: - case 5: - ptxservq = &psta->sta_xmitpriv.vi_q; - *(ac) = 1; - break; - case 6: - case 7: - ptxservq = &psta->sta_xmitpriv.vo_q; - *(ac) = 0; - break; - case 0: - case 3: - default: - ptxservq = &psta->sta_xmitpriv.be_q; - *(ac) = 2; - break; - } - - return ptxservq; -} - -/* - * Will enqueue pxmitframe to the proper queue, - * and indicate it to xx_pending list..... - */ -s32 rtw_xmit_classifier(struct adapter *padapter, struct xmit_frame *pxmitframe) -{ - u8 ac_index; - struct sta_info *psta; - struct tx_servq *ptxservq; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct sta_priv *pstapriv = &padapter->stapriv; - struct hw_xmit *phwxmits = padapter->xmitpriv.hwxmits; - int res = _SUCCESS; - - if (pattrib->psta) - psta = pattrib->psta; - else - psta = rtw_get_stainfo(pstapriv, pattrib->ra); - - if (!psta) { - res = _FAIL; - goto exit; - } - - ptxservq = rtw_get_sta_pending(padapter, psta, pattrib->priority, (u8 *)(&ac_index)); - - if (list_empty(&ptxservq->tx_pending)) - list_add_tail(&ptxservq->tx_pending, phwxmits[ac_index].sta_list); - - list_add_tail(&pxmitframe->list, &ptxservq->sta_pending); - ptxservq->qcnt++; - phwxmits[ac_index].accnt++; -exit: - - return res; -} - -int rtw_alloc_hwxmits(struct adapter *padapter) -{ - struct hw_xmit *hwxmits; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - pxmitpriv->hwxmits = kcalloc(HWXMIT_ENTRY, sizeof(struct hw_xmit), GFP_KERNEL); - if (!pxmitpriv->hwxmits) - return -ENOMEM; - - hwxmits = pxmitpriv->hwxmits; - - hwxmits[0].sta_list = &pxmitpriv->vo_pending; - hwxmits[1].sta_list = &pxmitpriv->vi_pending; - hwxmits[2].sta_list = &pxmitpriv->be_pending; - hwxmits[3].sta_list = &pxmitpriv->bk_pending; - - return 0; -} - -static int rtw_br_client_tx(struct adapter *padapter, struct sk_buff **pskb) -{ - struct sk_buff *skb = *pskb; - int res, is_vlan_tag = 0, i, do_nat25 = 1; - unsigned short vlan_hdr = 0; - void *br_port = NULL; - - rcu_read_lock(); - br_port = rcu_dereference(padapter->pnetdev->rx_handler_data); - rcu_read_unlock(); - spin_lock_bh(&padapter->br_ext_lock); - if (!(skb->data[0] & 1) && br_port && - memcmp(skb->data + ETH_ALEN, padapter->br_mac, ETH_ALEN) && - *((__be16 *)(skb->data + ETH_ALEN * 2)) != htons(ETH_P_8021Q) && - *((__be16 *)(skb->data + ETH_ALEN * 2)) == htons(ETH_P_IP) && - !memcmp(padapter->scdb_mac, skb->data + ETH_ALEN, ETH_ALEN) && padapter->scdb_entry) { - memcpy(skb->data + ETH_ALEN, GET_MY_HWADDR(padapter), ETH_ALEN); - padapter->scdb_entry->ageing_timer = jiffies; - spin_unlock_bh(&padapter->br_ext_lock); - } else { - if (*((__be16 *)(skb->data + ETH_ALEN * 2)) == htons(ETH_P_8021Q)) { - is_vlan_tag = 1; - vlan_hdr = *((unsigned short *)(skb->data + ETH_ALEN * 2 + 2)); - for (i = 0; i < 6; i++) - *((unsigned short *)(skb->data + ETH_ALEN * 2 + 2 - i * 2)) = *((unsigned short *)(skb->data + ETH_ALEN * 2 - 2 - i * 2)); - skb_pull(skb, 4); - } - if (!memcmp(skb->data + ETH_ALEN, padapter->br_mac, ETH_ALEN) && - (*((__be16 *)(skb->data + ETH_ALEN * 2)) == htons(ETH_P_IP))) - memcpy(padapter->br_ip, skb->data + WLAN_ETHHDR_LEN + 12, 4); - - if (*((__be16 *)(skb->data + ETH_ALEN * 2)) == htons(ETH_P_IP)) { - if (memcmp(padapter->scdb_mac, skb->data + ETH_ALEN, ETH_ALEN)) { - padapter->scdb_entry = (struct nat25_network_db_entry *)scdb_findEntry(padapter, - skb->data + WLAN_ETHHDR_LEN + 12); - if (padapter->scdb_entry) { - memcpy(padapter->scdb_mac, skb->data + ETH_ALEN, ETH_ALEN); - memcpy(padapter->scdb_ip, skb->data + WLAN_ETHHDR_LEN + 12, 4); - padapter->scdb_entry->ageing_timer = jiffies; - do_nat25 = 0; - } - } else { - if (padapter->scdb_entry) { - padapter->scdb_entry->ageing_timer = jiffies; - do_nat25 = 0; - } else { - memset(padapter->scdb_mac, 0, ETH_ALEN); - memset(padapter->scdb_ip, 0, 4); - } - } - } - spin_unlock_bh(&padapter->br_ext_lock); - if (do_nat25) { - if (nat25_db_handle(padapter, skb, NAT25_CHECK) == 0) { - struct sk_buff *newskb; - - if (is_vlan_tag) { - skb_push(skb, 4); - for (i = 0; i < 6; i++) - *((unsigned short *)(skb->data + i * 2)) = *((unsigned short *)(skb->data + 4 + i * 2)); - *((__be16 *)(skb->data + ETH_ALEN * 2)) = htons(ETH_P_8021Q); - *((unsigned short *)(skb->data + ETH_ALEN * 2 + 2)) = vlan_hdr; - } - - newskb = skb_copy(skb, GFP_ATOMIC); - if (!newskb) - return -1; - dev_kfree_skb_any(skb); - - *pskb = skb = newskb; - if (is_vlan_tag) { - vlan_hdr = *((unsigned short *)(skb->data + ETH_ALEN * 2 + 2)); - for (i = 0; i < 6; i++) - *((unsigned short *)(skb->data + ETH_ALEN * 2 + 2 - i * 2)) = *((unsigned short *)(skb->data + ETH_ALEN * 2 - 2 - i * 2)); - skb_pull(skb, 4); - } - } - - res = skb_linearize(skb); - if (res < 0) - return -1; - - res = nat25_db_handle(padapter, skb, NAT25_INSERT); - if (res < 0) { - if (res == -2) - return -1; - - return 0; - } - } - - memcpy(skb->data + ETH_ALEN, GET_MY_HWADDR(padapter), ETH_ALEN); - - dhcp_flag_bcast(padapter, skb); - - if (is_vlan_tag) { - skb_push(skb, 4); - for (i = 0; i < 6; i++) - *((unsigned short *)(skb->data + i * 2)) = *((unsigned short *)(skb->data + 4 + i * 2)); - *((__be16 *)(skb->data + ETH_ALEN * 2)) = htons(ETH_P_8021Q); - *((unsigned short *)(skb->data + ETH_ALEN * 2 + 2)) = vlan_hdr; - } - } - - /* check if SA is equal to our MAC */ - if (memcmp(skb->data + ETH_ALEN, GET_MY_HWADDR(padapter), ETH_ALEN)) - return -1; - - return 0; -} - -u32 rtw_get_ff_hwaddr(struct xmit_frame *pxmitframe) -{ - u32 addr; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - - switch (pattrib->qsel) { - case 0: - case 3: - addr = BE_QUEUE_INX; - break; - case 1: - case 2: - addr = BK_QUEUE_INX; - break; - case 4: - case 5: - addr = VI_QUEUE_INX; - break; - case 6: - case 7: - addr = VO_QUEUE_INX; - break; - case 0x10: - addr = BCN_QUEUE_INX; - break; - case 0x11:/* BC/MC in PS (HIQ) */ - addr = HIGH_QUEUE_INX; - break; - case 0x12: - default: - addr = MGT_QUEUE_INX; - break; - } - - return addr; -} - -/* - * The main transmit(tx) entry - * - * Return - * 1 enqueue - * 0 success, hardware will handle this xmit frame(packet) - * <0 fail - */ -s32 rtw_xmit(struct adapter *padapter, struct sk_buff **ppkt) -{ - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct xmit_frame *pxmitframe = NULL; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - s32 res; - - pxmitframe = rtw_alloc_xmitframe(pxmitpriv); - if (!pxmitframe) - return -1; - - if (rcu_access_pointer(padapter->pnetdev->rx_handler_data) && - check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_ADHOC_STATE)) { - res = rtw_br_client_tx(padapter, ppkt); - if (res == -1) { - rtw_free_xmitframe(pxmitpriv, pxmitframe); - return -1; - } - } - - res = update_attrib(padapter, *ppkt, &pxmitframe->attrib); - - if (res == _FAIL) { - rtw_free_xmitframe(pxmitpriv, pxmitframe); - return -1; - } - pxmitframe->pkt = *ppkt; - - rtw_led_control(padapter, LED_CTL_TX); - - pxmitframe->attrib.qsel = pxmitframe->attrib.priority; - - spin_lock_bh(&pxmitpriv->lock); - if (xmitframe_enqueue_for_sleeping_sta(padapter, pxmitframe)) { - spin_unlock_bh(&pxmitpriv->lock); - return 1; - } - spin_unlock_bh(&pxmitpriv->lock); - - if (!rtl8188eu_hal_xmit(padapter, pxmitframe)) - return 1; - - return 0; -} - -int xmitframe_enqueue_for_sleeping_sta(struct adapter *padapter, struct xmit_frame *pxmitframe) -{ - int ret = false; - struct sta_info *psta = NULL; - struct sta_priv *pstapriv = &padapter->stapriv; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - bool bmcst = is_multicast_ether_addr(pattrib->ra); - - if (!check_fwstate(pmlmepriv, WIFI_AP_STATE)) - return ret; - - if (pattrib->psta) - psta = pattrib->psta; - else - psta = rtw_get_stainfo(pstapriv, pattrib->ra); - - if (!psta) - return ret; - - if (pattrib->triggered == 1) { - if (bmcst) - pattrib->qsel = 0x11;/* HIQ */ - return ret; - } - - if (bmcst) { - spin_lock_bh(&psta->sleep_q.lock); - - if (pstapriv->sta_dz_bitmap) {/* if any one sta is in ps mode */ - list_del_init(&pxmitframe->list); - - list_add_tail(&pxmitframe->list, get_list_head(&psta->sleep_q)); - - psta->sleepq_len++; - - pstapriv->tim_bitmap |= BIT(0);/* */ - pstapriv->sta_dz_bitmap |= BIT(0); - /* tx bc/mc packets after update bcn */ - update_beacon(padapter, _TIM_IE_, NULL, false); - - ret = true; - } - - spin_unlock_bh(&psta->sleep_q.lock); - - return ret; - } - - spin_lock_bh(&psta->sleep_q.lock); - - if (psta->state & WIFI_SLEEP_STATE) { - u8 wmmps_ac = 0; - - if (pstapriv->sta_dz_bitmap & BIT(psta->aid)) { - list_del_init(&pxmitframe->list); - - list_add_tail(&pxmitframe->list, get_list_head(&psta->sleep_q)); - - psta->sleepq_len++; - - switch (pattrib->priority) { - case 1: - case 2: - wmmps_ac = psta->uapsd_bk & BIT(0); - break; - case 4: - case 5: - wmmps_ac = psta->uapsd_vi & BIT(0); - break; - case 6: - case 7: - wmmps_ac = psta->uapsd_vo & BIT(0); - break; - case 0: - case 3: - default: - wmmps_ac = psta->uapsd_be & BIT(0); - break; - } - - if (wmmps_ac) - psta->sleepq_ac_len++; - - if (((psta->has_legacy_ac) && (!wmmps_ac)) || - ((!psta->has_legacy_ac) && (wmmps_ac))) { - pstapriv->tim_bitmap |= BIT(psta->aid); - - if (psta->sleepq_len == 1) { - /* update BCN for TIM IE */ - update_beacon(padapter, _TIM_IE_, NULL, false); - } - } - ret = true; - } - } - - spin_unlock_bh(&psta->sleep_q.lock); - - return ret; -} - -static void dequeue_xmitframes_to_sleeping_queue(struct adapter *padapter, struct sta_info *psta, struct list_head *phead) -{ - struct list_head *plist; - u8 ac_index; - struct tx_servq *ptxservq; - struct pkt_attrib *pattrib; - struct xmit_frame *pxmitframe; - struct hw_xmit *phwxmits = padapter->xmitpriv.hwxmits; - - plist = phead->next; - - while (phead != plist) { - pxmitframe = container_of(plist, struct xmit_frame, list); - - plist = plist->next; - - xmitframe_enqueue_for_sleeping_sta(padapter, pxmitframe); - - pattrib = &pxmitframe->attrib; - - ptxservq = rtw_get_sta_pending(padapter, psta, pattrib->priority, (u8 *)(&ac_index)); - - ptxservq->qcnt--; - phwxmits[ac_index].accnt--; - } -} - -void stop_sta_xmit(struct adapter *padapter, struct sta_info *psta) -{ - struct sta_info *psta_bmc; - struct sta_xmit_priv *pstaxmitpriv; - struct sta_priv *pstapriv = &padapter->stapriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - pstaxmitpriv = &psta->sta_xmitpriv; - - /* for BC/MC Frames */ - psta_bmc = rtw_get_bcmc_stainfo(padapter); - - spin_lock_bh(&pxmitpriv->lock); - - psta->state |= WIFI_SLEEP_STATE; - - pstapriv->sta_dz_bitmap |= BIT(psta->aid); - - dequeue_xmitframes_to_sleeping_queue(padapter, psta, &pstaxmitpriv->vo_q.sta_pending); - list_del_init(&pstaxmitpriv->vo_q.tx_pending); - - dequeue_xmitframes_to_sleeping_queue(padapter, psta, &pstaxmitpriv->vi_q.sta_pending); - list_del_init(&pstaxmitpriv->vi_q.tx_pending); - - dequeue_xmitframes_to_sleeping_queue(padapter, psta, &pstaxmitpriv->be_q.sta_pending); - list_del_init(&pstaxmitpriv->be_q.tx_pending); - - dequeue_xmitframes_to_sleeping_queue(padapter, psta, &pstaxmitpriv->bk_q.sta_pending); - list_del_init(&pstaxmitpriv->bk_q.tx_pending); - - /* for BC/MC Frames */ - pstaxmitpriv = &psta_bmc->sta_xmitpriv; - dequeue_xmitframes_to_sleeping_queue(padapter, psta_bmc, &pstaxmitpriv->be_q.sta_pending); - list_del_init(&pstaxmitpriv->be_q.tx_pending); - - spin_unlock_bh(&pxmitpriv->lock); -} - -void wakeup_sta_to_xmit(struct adapter *padapter, struct sta_info *psta) -{ - u8 update_mask = 0, wmmps_ac = 0; - struct sta_info *psta_bmc; - struct list_head *xmitframe_plist, *xmitframe_phead; - struct xmit_frame *pxmitframe = NULL; - struct sta_priv *pstapriv = &padapter->stapriv; - - spin_lock_bh(&psta->sleep_q.lock); - - xmitframe_phead = get_list_head(&psta->sleep_q); - xmitframe_plist = xmitframe_phead->next; - - while (xmitframe_phead != xmitframe_plist) { - pxmitframe = container_of(xmitframe_plist, struct xmit_frame, list); - - xmitframe_plist = xmitframe_plist->next; - - list_del_init(&pxmitframe->list); - - switch (pxmitframe->attrib.priority) { - case 1: - case 2: - wmmps_ac = psta->uapsd_bk & BIT(1); - break; - case 4: - case 5: - wmmps_ac = psta->uapsd_vi & BIT(1); - break; - case 6: - case 7: - wmmps_ac = psta->uapsd_vo & BIT(1); - break; - case 0: - case 3: - default: - wmmps_ac = psta->uapsd_be & BIT(1); - break; - } - - psta->sleepq_len--; - if (psta->sleepq_len > 0) - pxmitframe->attrib.mdata = 1; - else - pxmitframe->attrib.mdata = 0; - - if (wmmps_ac) { - psta->sleepq_ac_len--; - if (psta->sleepq_ac_len > 0) { - pxmitframe->attrib.mdata = 1; - pxmitframe->attrib.eosp = 0; - } else { - pxmitframe->attrib.mdata = 0; - pxmitframe->attrib.eosp = 1; - } - } - - pxmitframe->attrib.triggered = 1; - - spin_unlock_bh(&psta->sleep_q.lock); - if (rtl8188eu_hal_xmit(padapter, pxmitframe)) - rtw_xmit_complete(padapter, pxmitframe); - spin_lock_bh(&psta->sleep_q.lock); - } - - if (psta->sleepq_len == 0) { - pstapriv->tim_bitmap &= ~BIT(psta->aid); - - update_mask = BIT(0); - - if (psta->state & WIFI_SLEEP_STATE) - psta->state ^= WIFI_SLEEP_STATE; - - if (psta->state & WIFI_STA_ALIVE_CHK_STATE) { - psta->expire_to = pstapriv->expire_to; - psta->state ^= WIFI_STA_ALIVE_CHK_STATE; - } - - pstapriv->sta_dz_bitmap &= ~BIT(psta->aid); - } - - spin_unlock_bh(&psta->sleep_q.lock); - - /* for BC/MC Frames */ - psta_bmc = rtw_get_bcmc_stainfo(padapter); - if (!psta_bmc) - return; - - if ((pstapriv->sta_dz_bitmap & 0xfffe) == 0x0) { /* no any sta in ps mode */ - spin_lock_bh(&psta_bmc->sleep_q.lock); - - xmitframe_phead = get_list_head(&psta_bmc->sleep_q); - xmitframe_plist = xmitframe_phead->next; - - while (xmitframe_phead != xmitframe_plist) { - pxmitframe = container_of(xmitframe_plist, struct xmit_frame, list); - - xmitframe_plist = xmitframe_plist->next; - - list_del_init(&pxmitframe->list); - - psta_bmc->sleepq_len--; - if (psta_bmc->sleepq_len > 0) - pxmitframe->attrib.mdata = 1; - else - pxmitframe->attrib.mdata = 0; - - pxmitframe->attrib.triggered = 1; - - spin_unlock_bh(&psta_bmc->sleep_q.lock); - if (rtl8188eu_hal_xmit(padapter, pxmitframe)) - rtw_xmit_complete(padapter, pxmitframe); - spin_lock_bh(&psta_bmc->sleep_q.lock); - } - - if (psta_bmc->sleepq_len == 0) { - pstapriv->tim_bitmap &= ~BIT(0); - pstapriv->sta_dz_bitmap &= ~BIT(0); - - update_mask |= BIT(1); - } - - spin_unlock_bh(&psta_bmc->sleep_q.lock); - } - - if (update_mask) - update_beacon(padapter, _TIM_IE_, NULL, false); -} - -void xmit_delivery_enabled_frames(struct adapter *padapter, struct sta_info *psta) -{ - u8 wmmps_ac = 0; - struct list_head *xmitframe_plist, *xmitframe_phead; - struct xmit_frame *pxmitframe = NULL; - struct sta_priv *pstapriv = &padapter->stapriv; - - spin_lock_bh(&psta->sleep_q.lock); - - xmitframe_phead = get_list_head(&psta->sleep_q); - xmitframe_plist = xmitframe_phead->next; - - while (xmitframe_phead != xmitframe_plist) { - pxmitframe = container_of(xmitframe_plist, struct xmit_frame, list); - - xmitframe_plist = xmitframe_plist->next; - - switch (pxmitframe->attrib.priority) { - case 1: - case 2: - wmmps_ac = psta->uapsd_bk & BIT(1); - break; - case 4: - case 5: - wmmps_ac = psta->uapsd_vi & BIT(1); - break; - case 6: - case 7: - wmmps_ac = psta->uapsd_vo & BIT(1); - break; - case 0: - case 3: - default: - wmmps_ac = psta->uapsd_be & BIT(1); - break; - } - - if (!wmmps_ac) - continue; - - list_del_init(&pxmitframe->list); - - psta->sleepq_len--; - psta->sleepq_ac_len--; - - if (psta->sleepq_ac_len > 0) { - pxmitframe->attrib.mdata = 1; - pxmitframe->attrib.eosp = 0; - } else { - pxmitframe->attrib.mdata = 0; - pxmitframe->attrib.eosp = 1; - } - - pxmitframe->attrib.triggered = 1; - - if (rtl8188eu_hal_xmit(padapter, pxmitframe)) - rtw_xmit_complete(padapter, pxmitframe); - - if ((psta->sleepq_ac_len == 0) && (!psta->has_legacy_ac) && (wmmps_ac)) { - pstapriv->tim_bitmap &= ~BIT(psta->aid); - - /* update BCN for TIM IE */ - update_beacon(padapter, _TIM_IE_, NULL, false); - } - } - - spin_unlock_bh(&psta->sleep_q.lock); -} - -void rtw_sctx_init(struct submit_ctx *sctx, int timeout_ms) -{ - sctx->timeout_ms = timeout_ms; - sctx->submit_time = jiffies; - init_completion(&sctx->done); - sctx->status = RTW_SCTX_SUBMITTED; -} - -int rtw_sctx_wait(struct submit_ctx *sctx) -{ - int ret = _FAIL; - unsigned long expire; - int status = 0; - - expire = sctx->timeout_ms ? msecs_to_jiffies(sctx->timeout_ms) : MAX_SCHEDULE_TIMEOUT; - if (!wait_for_completion_timeout(&sctx->done, expire)) - /* timeout, do something?? */ - status = RTW_SCTX_DONE_TIMEOUT; - else - status = sctx->status; - - if (status == RTW_SCTX_DONE_SUCCESS) - ret = _SUCCESS; - - return ret; -} - -void rtw_sctx_done_err(struct submit_ctx **sctx, int status) -{ - if (*sctx) { - (*sctx)->status = status; - complete(&((*sctx)->done)); - *sctx = NULL; - } -} - -int rtw_ack_tx_wait(struct xmit_priv *pxmitpriv, u32 timeout_ms) -{ - struct submit_ctx *pack_tx_ops = &pxmitpriv->ack_tx_ops; - - pack_tx_ops->submit_time = jiffies; - pack_tx_ops->timeout_ms = timeout_ms; - pack_tx_ops->status = RTW_SCTX_SUBMITTED; - - return rtw_sctx_wait(pack_tx_ops); -} - -void rtw_ack_tx_done(struct xmit_priv *pxmitpriv, int status) -{ - struct submit_ctx *pack_tx_ops = &pxmitpriv->ack_tx_ops; - - if (pxmitpriv->ack_tx) - rtw_sctx_done_err(&pack_tx_ops, status); -} - -static void rtw_check_xmit_resource(struct adapter *padapter, struct sk_buff *pkt) -{ - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - u16 queue; - - queue = skb_get_queue_mapping(pkt); - if (padapter->registrypriv.wifi_spec) { - /* No free space for Tx, tx_worker is too slow */ - if (pxmitpriv->hwxmits[queue].accnt > WMM_XMIT_THRESHOLD) - netif_stop_subqueue(padapter->pnetdev, queue); - } else { - if (pxmitpriv->free_xmitframe_cnt <= 4) { - if (!netif_tx_queue_stopped(netdev_get_tx_queue(padapter->pnetdev, queue))) - netif_stop_subqueue(padapter->pnetdev, queue); - } - } -} - -static int rtw_mlcst2unicst(struct adapter *padapter, struct sk_buff *skb) -{ - struct sta_priv *pstapriv = &padapter->stapriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct list_head *phead, *plist; - struct sk_buff *newskb; - struct sta_info *psta = NULL; - s32 res; - - spin_lock_bh(&pstapriv->asoc_list_lock); - phead = &pstapriv->asoc_list; - plist = phead->next; - - /* free sta asoc_queue */ - while (phead != plist) { - psta = container_of(plist, struct sta_info, asoc_list); - - plist = plist->next; - - /* avoid come from STA1 and send back STA1 */ - if (!memcmp(psta->hwaddr, &skb->data[6], 6)) - continue; - - newskb = skb_copy(skb, GFP_ATOMIC); - - if (newskb) { - memcpy(newskb->data, psta->hwaddr, 6); - res = rtw_xmit(padapter, &newskb); - if (res < 0) { - pxmitpriv->tx_drop++; - dev_kfree_skb_any(newskb); - } else { - pxmitpriv->tx_pkts++; - } - } else { - pxmitpriv->tx_drop++; - - spin_unlock_bh(&pstapriv->asoc_list_lock); - return false; /* Caller shall tx this multicast frame via normal way. */ - } - } - - spin_unlock_bh(&pstapriv->asoc_list_lock); - dev_kfree_skb_any(skb); - return true; -} - -netdev_tx_t rtw_xmit_entry(struct sk_buff *pkt, struct net_device *pnetdev) -{ - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(pnetdev); - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - s32 res = 0; - - if (!rtw_if_up(padapter)) - goto drop_packet; - - rtw_check_xmit_resource(padapter, pkt); - - if (!rtw_mc2u_disable && check_fwstate(pmlmepriv, WIFI_AP_STATE) && - (IP_MCAST_MAC(pkt->data) || ICMPV6_MCAST_MAC(pkt->data)) && - (padapter->registrypriv.wifi_spec == 0)) { - if (pxmitpriv->free_xmitframe_cnt > (NR_XMITFRAME / 4)) { - res = rtw_mlcst2unicst(padapter, pkt); - if (res) - goto exit; - } - } - - res = rtw_xmit(padapter, &pkt); - if (res < 0) - goto drop_packet; - - pxmitpriv->tx_pkts++; - goto exit; - -drop_packet: - pxmitpriv->tx_drop++; - dev_kfree_skb_any(pkt); - -exit: - return NETDEV_TX_OK; -} diff --git a/drivers/staging/r8188eu/hal/Hal8188ERateAdaptive.c b/drivers/staging/r8188eu/hal/Hal8188ERateAdaptive.c deleted file mode 100644 index 1e04de3a6622..000000000000 --- a/drivers/staging/r8188eu/hal/Hal8188ERateAdaptive.c +++ /dev/null @@ -1,654 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright (c) Realtek Semiconductor Corp. */ - -#include "../include/drv_types.h" - -static u8 RETRY_PENALTY[PERENTRY][RETRYSIZE + 1] = { - {5, 4, 3, 2, 0, 3}, /* 92 , idx = 0 */ - {6, 5, 4, 3, 0, 4}, /* 86 , idx = 1 */ - {6, 5, 4, 2, 0, 4}, /* 81 , idx = 2 */ - {8, 7, 6, 4, 0, 6}, /* 75 , idx = 3 */ - {10, 9, 8, 6, 0, 8}, /* 71 , idx = 4 */ - {10, 9, 8, 4, 0, 8}, /* 66 , idx = 5 */ - {10, 9, 8, 2, 0, 8}, /* 62 , idx = 6 */ - {10, 9, 8, 0, 0, 8}, /* 59 , idx = 7 */ - {18, 17, 16, 8, 0, 16}, /* 53 , idx = 8 */ - {26, 25, 24, 16, 0, 24}, /* 50 , idx = 9 */ - {34, 33, 32, 24, 0, 32}, /* 47 , idx = 0x0a */ - {34, 31, 28, 20, 0, 32}, /* 43 , idx = 0x0b */ - {34, 31, 27, 18, 0, 32}, /* 40 , idx = 0x0c */ - {34, 31, 26, 16, 0, 32}, /* 37 , idx = 0x0d */ - {34, 30, 22, 16, 0, 32}, /* 32 , idx = 0x0e */ - {34, 30, 24, 16, 0, 32}, /* 26 , idx = 0x0f */ - {49, 46, 40, 16, 0, 48}, /* 20 , idx = 0x10 */ - {49, 45, 32, 0, 0, 48}, /* 17 , idx = 0x11 */ - {49, 45, 22, 18, 0, 48}, /* 15 , idx = 0x12 */ - {49, 40, 24, 16, 0, 48}, /* 12 , idx = 0x13 */ - {49, 32, 18, 12, 0, 48}, /* 9 , idx = 0x14 */ - {49, 22, 18, 14, 0, 48}, /* 6 , idx = 0x15 */ - {49, 16, 16, 0, 0, 48} - }; /* 3, idx = 0x16 */ - -static u8 PT_PENALTY[RETRYSIZE + 1] = {34, 31, 30, 24, 0, 32}; - -/* wilson modify */ -static u8 RETRY_PENALTY_IDX[2][RATESIZE] = { - {4, 4, 4, 5, 4, 4, 5, 7, 7, 7, 8, 0x0a, /* SS>TH */ - 4, 4, 4, 4, 6, 0x0a, 0x0b, 0x0d, - 5, 5, 7, 7, 8, 0x0b, 0x0d, 0x0f}, /* 0329 R01 */ - {0x0a, 0x0a, 0x0b, 0x0c, 0x0a, - 0x0a, 0x0b, 0x0c, 0x0d, 0x10, 0x13, 0x14, /* SSTH */ - 0x0f, 0x10, 0x10, 0x12, 0x12, 0x13, 0x14, 0x15, - 0x11, 0x11, 0x12, 0x13, 0x13, 0x13, 0x14, 0x15}; - -static u8 RSSI_THRESHOLD[RATESIZE] = { - 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x24, 0x26, 0x2a, - 0x18, 0x1a, 0x1d, 0x1f, 0x21, 0x27, 0x29, 0x2a, - 0, 0, 0, 0x1f, 0x23, 0x28, 0x2a, 0x2c}; - -static u16 N_THRESHOLD_HIGH[RATESIZE] = { - 4, 4, 8, 16, - 24, 36, 48, 72, 96, 144, 192, 216, - 60, 80, 100, 160, 240, 400, 560, 640, - 300, 320, 480, 720, 1000, 1200, 1600, 2000}; -static u16 N_THRESHOLD_LOW[RATESIZE] = { - 2, 2, 4, 8, - 12, 18, 24, 36, 48, 72, 96, 108, - 30, 40, 50, 80, 120, 200, 280, 320, - 150, 160, 240, 360, 500, 600, 800, 1000}; - -static u8 DROPING_NECESSARY[RATESIZE] = { - 1, 1, 1, 1, - 1, 2, 3, 4, 5, 6, 7, 8, - 1, 2, 3, 4, 5, 6, 7, 8, - 5, 6, 7, 8, 9, 10, 11, 12}; - -static u8 PendingForRateUpFail[5] = {2, 10, 24, 40, 60}; -static u16 DynamicTxRPTTiming[6] = { - 0x186a, 0x30d4, 0x493e, 0x61a8, 0x7a12, 0x927c}; /* 200ms-1200ms */ - -/* End Rate adaptive parameters */ - -static void odm_SetTxRPTTiming_8188E( - struct odm_dm_struct *dm_odm, - struct odm_ra_info *pRaInfo, - u8 extend - ) -{ - u8 idx = 0; - - for (idx = 0; idx < 5; idx++) - if (DynamicTxRPTTiming[idx] == pRaInfo->RptTime) - break; - - if (extend == 0) { /* back to default timing */ - idx = 0; /* 200ms */ - } else if (extend == 1) {/* increase the timing */ - idx += 1; - if (idx > 5) - idx = 5; - } else if (extend == 2) {/* decrease the timing */ - if (idx != 0) - idx -= 1; - } - pRaInfo->RptTime = DynamicTxRPTTiming[idx]; -} - -static int odm_RateDown_8188E(struct odm_dm_struct *dm_odm, struct odm_ra_info *pRaInfo) -{ - u8 RateID, LowestRate, HighestRate; - u8 i; - - if (NULL == pRaInfo) - return -1; - RateID = pRaInfo->PreRate; - LowestRate = pRaInfo->LowestRate; - HighestRate = pRaInfo->HighestRate; - - if (RateID > HighestRate) { - RateID = HighestRate; - } else if (pRaInfo->RateSGI) { - pRaInfo->RateSGI = 0; - } else if (RateID > LowestRate) { - if (RateID > 0) { - for (i = RateID - 1; i > LowestRate; i--) { - if (pRaInfo->RAUseRate & BIT(i)) { - RateID = i; - goto RateDownFinish; - } - } - } - } else if (RateID <= LowestRate) { - RateID = LowestRate; - } -RateDownFinish: - if (pRaInfo->RAWaitingCounter == 1) { - pRaInfo->RAWaitingCounter += 1; - pRaInfo->RAPendingCounter += 1; - } else if (pRaInfo->RAWaitingCounter == 0) { - ; - } else { - pRaInfo->RAWaitingCounter = 0; - pRaInfo->RAPendingCounter = 0; - } - - if (pRaInfo->RAPendingCounter >= 4) - pRaInfo->RAPendingCounter = 4; - - pRaInfo->DecisionRate = RateID; - odm_SetTxRPTTiming_8188E(dm_odm, pRaInfo, 2); - return 0; -} - -static int odm_RateUp_8188E( - struct odm_dm_struct *dm_odm, - struct odm_ra_info *pRaInfo - ) -{ - u8 RateID, HighestRate; - u8 i; - - if (NULL == pRaInfo) - return -1; - RateID = pRaInfo->PreRate; - HighestRate = pRaInfo->HighestRate; - if (pRaInfo->RAWaitingCounter == 1) { - pRaInfo->RAWaitingCounter = 0; - pRaInfo->RAPendingCounter = 0; - } else if (pRaInfo->RAWaitingCounter > 1) { - pRaInfo->PreRssiStaRA = pRaInfo->RssiStaRA; - goto RateUpfinish; - } - odm_SetTxRPTTiming_8188E(dm_odm, pRaInfo, 0); - - if (RateID < HighestRate) { - for (i = RateID + 1; i <= HighestRate; i++) { - if (pRaInfo->RAUseRate & BIT(i)) { - RateID = i; - goto RateUpfinish; - } - } - } else if (RateID == HighestRate) { - if (pRaInfo->SGIEnable && (pRaInfo->RateSGI != 1)) - pRaInfo->RateSGI = 1; - else if ((pRaInfo->SGIEnable) != 1) - pRaInfo->RateSGI = 0; - } else { - RateID = HighestRate; - } -RateUpfinish: - if (pRaInfo->RAWaitingCounter == (4 + PendingForRateUpFail[pRaInfo->RAPendingCounter])) - pRaInfo->RAWaitingCounter = 0; - else - pRaInfo->RAWaitingCounter++; - - pRaInfo->DecisionRate = RateID; - return 0; -} - -static void odm_ResetRaCounter_8188E(struct odm_ra_info *pRaInfo) -{ - u8 RateID; - - RateID = pRaInfo->DecisionRate; - pRaInfo->NscUp = (N_THRESHOLD_HIGH[RateID] + N_THRESHOLD_LOW[RateID]) >> 1; - pRaInfo->NscDown = (N_THRESHOLD_HIGH[RateID] + N_THRESHOLD_LOW[RateID]) >> 1; -} - -static void odm_RateDecision_8188E(struct odm_dm_struct *dm_odm, - struct odm_ra_info *pRaInfo - ) -{ - u8 RateID = 0, RtyPtID = 0, PenaltyID1 = 0, PenaltyID2 = 0; - /* u32 pool_retry; */ - static u8 DynamicTxRPTTimingCounter; - - if (pRaInfo->Active && (pRaInfo->TOTAL > 0)) { /* STA used and data packet exits */ - if ((pRaInfo->RssiStaRA < (pRaInfo->PreRssiStaRA - 3)) || - (pRaInfo->RssiStaRA > (pRaInfo->PreRssiStaRA + 3))) { - pRaInfo->RAWaitingCounter = 0; - pRaInfo->RAPendingCounter = 0; - } - /* Start RA decision */ - if (pRaInfo->PreRate > pRaInfo->HighestRate) - RateID = pRaInfo->HighestRate; - else - RateID = pRaInfo->PreRate; - if (pRaInfo->RssiStaRA > RSSI_THRESHOLD[RateID]) - RtyPtID = 0; - else - RtyPtID = 1; - PenaltyID1 = RETRY_PENALTY_IDX[RtyPtID][RateID]; /* TODO by page */ - - pRaInfo->NscDown += pRaInfo->RTY[0] * RETRY_PENALTY[PenaltyID1][0]; - pRaInfo->NscDown += pRaInfo->RTY[1] * RETRY_PENALTY[PenaltyID1][1]; - pRaInfo->NscDown += pRaInfo->RTY[2] * RETRY_PENALTY[PenaltyID1][2]; - pRaInfo->NscDown += pRaInfo->RTY[3] * RETRY_PENALTY[PenaltyID1][3]; - pRaInfo->NscDown += pRaInfo->RTY[4] * RETRY_PENALTY[PenaltyID1][4]; - if (pRaInfo->NscDown > (pRaInfo->TOTAL * RETRY_PENALTY[PenaltyID1][5])) - pRaInfo->NscDown -= pRaInfo->TOTAL * RETRY_PENALTY[PenaltyID1][5]; - else - pRaInfo->NscDown = 0; - - /* rate up */ - PenaltyID2 = RETRY_PENALTY_UP_IDX[RateID]; - pRaInfo->NscUp += pRaInfo->RTY[0] * RETRY_PENALTY[PenaltyID2][0]; - pRaInfo->NscUp += pRaInfo->RTY[1] * RETRY_PENALTY[PenaltyID2][1]; - pRaInfo->NscUp += pRaInfo->RTY[2] * RETRY_PENALTY[PenaltyID2][2]; - pRaInfo->NscUp += pRaInfo->RTY[3] * RETRY_PENALTY[PenaltyID2][3]; - pRaInfo->NscUp += pRaInfo->RTY[4] * RETRY_PENALTY[PenaltyID2][4]; - if (pRaInfo->NscUp > (pRaInfo->TOTAL * RETRY_PENALTY[PenaltyID2][5])) - pRaInfo->NscUp -= pRaInfo->TOTAL * RETRY_PENALTY[PenaltyID2][5]; - else - pRaInfo->NscUp = 0; - - if ((pRaInfo->NscDown < N_THRESHOLD_LOW[RateID]) || - (pRaInfo->DROP > DROPING_NECESSARY[RateID])) - odm_RateDown_8188E(dm_odm, pRaInfo); - else if (pRaInfo->NscUp > N_THRESHOLD_HIGH[RateID]) - odm_RateUp_8188E(dm_odm, pRaInfo); - - if (pRaInfo->DecisionRate > pRaInfo->HighestRate) - pRaInfo->DecisionRate = pRaInfo->HighestRate; - - if ((pRaInfo->DecisionRate) == (pRaInfo->PreRate)) - DynamicTxRPTTimingCounter += 1; - else - DynamicTxRPTTimingCounter = 0; - - if (DynamicTxRPTTimingCounter >= 4) { - odm_SetTxRPTTiming_8188E(dm_odm, pRaInfo, 1); - DynamicTxRPTTimingCounter = 0; - } - - pRaInfo->PreRate = pRaInfo->DecisionRate; /* YJ, add, 120120 */ - - odm_ResetRaCounter_8188E(pRaInfo); - } -} - -static int odm_ARFBRefresh_8188E(struct odm_dm_struct *dm_odm, struct odm_ra_info *pRaInfo) -{ /* Wilson 2011/10/26 */ - u32 MaskFromReg; - s8 i; - int res; - - switch (pRaInfo->RateID) { - case RATR_INX_WIRELESS_NGB: - pRaInfo->RAUseRate = (pRaInfo->RateMask) & 0x0f8ff015; - break; - case RATR_INX_WIRELESS_NG: - pRaInfo->RAUseRate = (pRaInfo->RateMask) & 0x0f8ff010; - break; - case RATR_INX_WIRELESS_NB: - pRaInfo->RAUseRate = (pRaInfo->RateMask) & 0x0f8ff005; - break; - case RATR_INX_WIRELESS_N: - pRaInfo->RAUseRate = (pRaInfo->RateMask) & 0x0f8ff000; - break; - case RATR_INX_WIRELESS_GB: - pRaInfo->RAUseRate = (pRaInfo->RateMask) & 0x00000ff5; - break; - case RATR_INX_WIRELESS_G: - pRaInfo->RAUseRate = (pRaInfo->RateMask) & 0x00000ff0; - break; - case RATR_INX_WIRELESS_B: - pRaInfo->RAUseRate = (pRaInfo->RateMask) & 0x0000000d; - break; - case 12: - res = rtw_read32(dm_odm->Adapter, REG_ARFR0, &MaskFromReg); - if (res) - return res; - - pRaInfo->RAUseRate = (pRaInfo->RateMask) & MaskFromReg; - break; - case 13: - res = rtw_read32(dm_odm->Adapter, REG_ARFR1, &MaskFromReg); - if (res) - return res; - - pRaInfo->RAUseRate = (pRaInfo->RateMask) & MaskFromReg; - break; - case 14: - res = rtw_read32(dm_odm->Adapter, REG_ARFR2, &MaskFromReg); - if (res) - return res; - - pRaInfo->RAUseRate = (pRaInfo->RateMask) & MaskFromReg; - break; - case 15: - res = rtw_read32(dm_odm->Adapter, REG_ARFR3, &MaskFromReg); - if (res) - return res; - - pRaInfo->RAUseRate = (pRaInfo->RateMask) & MaskFromReg; - break; - default: - pRaInfo->RAUseRate = (pRaInfo->RateMask); - break; - } - /* Highest rate */ - if (pRaInfo->RAUseRate) { - for (i = RATESIZE; i >= 0; i--) { - if ((pRaInfo->RAUseRate) & BIT(i)) { - pRaInfo->HighestRate = i; - break; - } - } - } else { - pRaInfo->HighestRate = 0; - } - /* Lowest rate */ - if (pRaInfo->RAUseRate) { - for (i = 0; i < RATESIZE; i++) { - if ((pRaInfo->RAUseRate) & BIT(i)) { - pRaInfo->LowestRate = i; - break; - } - } - } else { - pRaInfo->LowestRate = 0; - } - if (pRaInfo->HighestRate > 0x13) - pRaInfo->PTModeSS = 3; - else if (pRaInfo->HighestRate > 0x0b) - pRaInfo->PTModeSS = 2; - else if (pRaInfo->HighestRate > 0x03) - pRaInfo->PTModeSS = 1; - else - pRaInfo->PTModeSS = 0; - - if (pRaInfo->DecisionRate > pRaInfo->HighestRate) - pRaInfo->DecisionRate = pRaInfo->HighestRate; - - return 0; -} - -static void odm_PTTryState_8188E(struct odm_ra_info *pRaInfo) -{ - pRaInfo->PTTryState = 0; - switch (pRaInfo->PTModeSS) { - case 3: - if (pRaInfo->DecisionRate >= 0x19) - pRaInfo->PTTryState = 1; - break; - case 2: - if (pRaInfo->DecisionRate >= 0x11) - pRaInfo->PTTryState = 1; - break; - case 1: - if (pRaInfo->DecisionRate >= 0x0a) - pRaInfo->PTTryState = 1; - break; - case 0: - if (pRaInfo->DecisionRate >= 0x03) - pRaInfo->PTTryState = 1; - break; - default: - pRaInfo->PTTryState = 0; - break; - } - - if (pRaInfo->RssiStaRA < 48) { - pRaInfo->PTStage = 0; - } else if (pRaInfo->PTTryState == 1) { - if ((pRaInfo->PTStopCount >= 10) || - (pRaInfo->PTPreRssi > pRaInfo->RssiStaRA + 5) || - (pRaInfo->PTPreRssi < pRaInfo->RssiStaRA - 5) || - (pRaInfo->DecisionRate != pRaInfo->PTPreRate)) { - if (pRaInfo->PTStage == 0) - pRaInfo->PTStage = 1; - else if (pRaInfo->PTStage == 1) - pRaInfo->PTStage = 3; - else - pRaInfo->PTStage = 5; - - pRaInfo->PTPreRssi = pRaInfo->RssiStaRA; - pRaInfo->PTStopCount = 0; - } else { - pRaInfo->RAstage = 0; - pRaInfo->PTStopCount++; - } - } else { - pRaInfo->PTStage = 0; - pRaInfo->RAstage = 0; - } - pRaInfo->PTPreRate = pRaInfo->DecisionRate; -} - -static void odm_PTDecision_8188E(struct odm_ra_info *pRaInfo) -{ - u8 j; - u8 temp_stage; - u32 numsc; - u32 num_total; - u8 stage_id; - - numsc = 0; - num_total = pRaInfo->TOTAL * PT_PENALTY[5]; - for (j = 0; j <= 4; j++) { - numsc += pRaInfo->RTY[j] * PT_PENALTY[j]; - if (numsc > num_total) - break; - } - - j = j >> 1; - temp_stage = (pRaInfo->PTStage + 1) >> 1; - if (temp_stage > j) - stage_id = temp_stage - j; - else - stage_id = 0; - - pRaInfo->PTSmoothFactor = (pRaInfo->PTSmoothFactor >> 1) + (pRaInfo->PTSmoothFactor >> 2) + stage_id * 16 + 2; - if (pRaInfo->PTSmoothFactor > 192) - pRaInfo->PTSmoothFactor = 192; - stage_id = pRaInfo->PTSmoothFactor >> 6; - temp_stage = stage_id * 2; - if (temp_stage != 0) - temp_stage -= 1; - if (pRaInfo->DROP > 3) - temp_stage = 0; - pRaInfo->PTStage = temp_stage; -} - -static void -odm_RATxRPTTimerSetting( - struct odm_dm_struct *dm_odm, - u16 minRptTime -) -{ - if (dm_odm->CurrminRptTime != minRptTime) { - rtw_rpt_timer_cfg_cmd(dm_odm->Adapter, minRptTime); - dm_odm->CurrminRptTime = minRptTime; - } -} - -int ODM_RAInfo_Init(struct odm_dm_struct *dm_odm, u8 macid) -{ - struct odm_ra_info *pRaInfo = &dm_odm->RAInfo[macid]; - u8 WirelessMode = 0xFF; /* invalid value */ - u8 max_rate_idx = 0x13; /* MCS7 */ - if (dm_odm->pWirelessMode) - WirelessMode = *dm_odm->pWirelessMode; - - if (WirelessMode != 0xFF) { - if (WirelessMode & ODM_WM_N24G) - max_rate_idx = 0x13; - else if (WirelessMode & ODM_WM_G) - max_rate_idx = 0x0b; - else if (WirelessMode & ODM_WM_B) - max_rate_idx = 0x03; - } - - pRaInfo->DecisionRate = max_rate_idx; - pRaInfo->PreRate = max_rate_idx; - pRaInfo->HighestRate = max_rate_idx; - pRaInfo->LowestRate = 0; - pRaInfo->RateID = 0; - pRaInfo->RateMask = 0xffffffff; - pRaInfo->RssiStaRA = 0; - pRaInfo->PreRssiStaRA = 0; - pRaInfo->SGIEnable = 0; - pRaInfo->RAUseRate = 0xffffffff; - pRaInfo->NscDown = (N_THRESHOLD_HIGH[0x13] + N_THRESHOLD_LOW[0x13]) / 2; - pRaInfo->NscUp = (N_THRESHOLD_HIGH[0x13] + N_THRESHOLD_LOW[0x13]) / 2; - pRaInfo->RateSGI = 0; - pRaInfo->Active = 1; /* Active is not used at present. by page, 110819 */ - pRaInfo->RptTime = 0x927c; - pRaInfo->DROP = 0; - pRaInfo->RTY[0] = 0; - pRaInfo->RTY[1] = 0; - pRaInfo->RTY[2] = 0; - pRaInfo->RTY[3] = 0; - pRaInfo->RTY[4] = 0; - pRaInfo->TOTAL = 0; - pRaInfo->RAWaitingCounter = 0; - pRaInfo->RAPendingCounter = 0; - pRaInfo->PTActive = 1; /* Active when this STA is use */ - pRaInfo->PTTryState = 0; - pRaInfo->PTStage = 5; /* Need to fill into HW_PWR_STATUS */ - pRaInfo->PTSmoothFactor = 192; - pRaInfo->PTStopCount = 0; - pRaInfo->PTPreRate = 0; - pRaInfo->PTPreRssi = 0; - pRaInfo->PTModeSS = 0; - pRaInfo->RAstage = 0; - return 0; -} - -int ODM_RAInfo_Init_all(struct odm_dm_struct *dm_odm) -{ - u8 macid = 0; - - dm_odm->CurrminRptTime = 0; - - for (macid = 0; macid < ODM_ASSOCIATE_ENTRY_NUM; macid++) - ODM_RAInfo_Init(dm_odm, macid); - - return 0; -} - -u8 ODM_RA_GetShortGI_8188E(struct odm_dm_struct *dm_odm, u8 macid) -{ - if ((NULL == dm_odm) || (macid >= ODM_ASSOCIATE_ENTRY_NUM)) - return 0; - return dm_odm->RAInfo[macid].RateSGI; -} - -u8 ODM_RA_GetDecisionRate_8188E(struct odm_dm_struct *dm_odm, u8 macid) -{ - u8 DecisionRate = 0; - - if ((NULL == dm_odm) || (macid >= ODM_ASSOCIATE_ENTRY_NUM)) - return 0; - DecisionRate = (dm_odm->RAInfo[macid].DecisionRate); - return DecisionRate; -} - -u8 ODM_RA_GetHwPwrStatus_8188E(struct odm_dm_struct *dm_odm, u8 macid) -{ - u8 PTStage = 5; - - if ((NULL == dm_odm) || (macid >= ODM_ASSOCIATE_ENTRY_NUM)) - return 0; - PTStage = (dm_odm->RAInfo[macid].PTStage); - return PTStage; -} - -void ODM_RA_UpdateRateInfo_8188E(struct odm_dm_struct *dm_odm, u8 macid, u8 RateID, u32 RateMask, u8 SGIEnable) -{ - struct odm_ra_info *pRaInfo = NULL; - - if ((NULL == dm_odm) || (macid >= ODM_ASSOCIATE_ENTRY_NUM)) - return; - - pRaInfo = &dm_odm->RAInfo[macid]; - pRaInfo->RateID = RateID; - pRaInfo->RateMask = RateMask; - pRaInfo->SGIEnable = SGIEnable; - odm_ARFBRefresh_8188E(dm_odm, pRaInfo); -} - -void ODM_RA_SetRSSI_8188E(struct odm_dm_struct *dm_odm, u8 macid, u8 Rssi) -{ - struct odm_ra_info *pRaInfo = NULL; - - if ((NULL == dm_odm) || (macid >= ODM_ASSOCIATE_ENTRY_NUM)) - return; - - pRaInfo = &dm_odm->RAInfo[macid]; - pRaInfo->RssiStaRA = Rssi; -} - -void ODM_RA_Set_TxRPT_Time(struct odm_dm_struct *dm_odm, u16 minRptTime) -{ - rtw_write16(dm_odm->Adapter, REG_TX_RPT_TIME, minRptTime); -} - -void ODM_RA_TxRPT2Handle_8188E(struct odm_dm_struct *dm_odm, u8 *TxRPT_Buf, u16 TxRPT_Len, u32 macid_entry0, u32 macid_entry1) -{ - struct odm_ra_info *pRAInfo = NULL; - u8 MacId = 0; - u8 *pBuffer = NULL; - u32 valid = 0, ItemNum = 0; - u16 minRptTime = 0x927c; - - ItemNum = TxRPT_Len >> 3; - pBuffer = TxRPT_Buf; - - do { - if (MacId >= ODM_ASSOCIATE_ENTRY_NUM) - valid = 0; - else if (MacId >= 32) - valid = (1 << (MacId - 32)) & macid_entry1; - else - valid = (1 << MacId) & macid_entry0; - - pRAInfo = &dm_odm->RAInfo[MacId]; - if (valid) { - pRAInfo->RTY[0] = le16_to_cpup((__le16 *)pBuffer); - pRAInfo->RTY[1] = pBuffer[2]; - pRAInfo->RTY[2] = pBuffer[3]; - pRAInfo->RTY[3] = pBuffer[4]; - pRAInfo->RTY[4] = pBuffer[5]; - pRAInfo->DROP = pBuffer[6]; - pRAInfo->TOTAL = pRAInfo->RTY[0] + pRAInfo->RTY[1] + - pRAInfo->RTY[2] + pRAInfo->RTY[3] + - pRAInfo->RTY[4] + pRAInfo->DROP; - if (pRAInfo->TOTAL != 0) { - if (pRAInfo->PTActive) { - if (pRAInfo->RAstage < 5) - odm_RateDecision_8188E(dm_odm, pRAInfo); - else if (pRAInfo->RAstage == 5) /* Power training try state */ - odm_PTTryState_8188E(pRAInfo); - else /* RAstage == 6 */ - odm_PTDecision_8188E(pRAInfo); - - /* Stage_RA counter */ - if (pRAInfo->RAstage <= 5) - pRAInfo->RAstage++; - else - pRAInfo->RAstage = 0; - } else { - odm_RateDecision_8188E(dm_odm, pRAInfo); - } - } - } - - if (minRptTime > pRAInfo->RptTime) - minRptTime = pRAInfo->RptTime; - - pBuffer += TX_RPT2_ITEM_SIZE; - MacId++; - } while (MacId < ItemNum); - - odm_RATxRPTTimerSetting(dm_odm, minRptTime); -} diff --git a/drivers/staging/r8188eu/hal/HalHWImg8188E_BB.c b/drivers/staging/r8188eu/hal/HalHWImg8188E_BB.c deleted file mode 100644 index 23b7205722b5..000000000000 --- a/drivers/staging/r8188eu/hal/HalHWImg8188E_BB.c +++ /dev/null @@ -1,733 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#include "../include/rtw_iol.h" - -#define read_next_pair(array, v1, v2, i) \ - do { \ - i += 2; \ - v1 = array[i]; \ - v2 = array[i + 1]; \ - } while (0) - -static bool CheckCondition(const u32 condition, const u32 hex) -{ - u32 _interface = (hex & 0x0000FF00) >> 8; - u32 _platform = (hex & 0x00FF0000) >> 16; - u32 cond = condition; - - if (condition == 0xCDCDCDCD) - return true; - - cond = condition & 0x0000FF00; - cond = cond >> 8; - if ((_interface & cond) == 0 && cond != 0x07) - return false; - - cond = condition & 0x00FF0000; - cond = cond >> 16; - if ((_platform & cond) == 0 && cond != 0x0F) - return false; - return true; -} - -/****************************************************************************** -* AGC_TAB_1T.TXT -******************************************************************************/ - -static u32 array_agc_tab_1t_8188e[] = { - 0xC78, 0xFB000001, - 0xC78, 0xFB010001, - 0xC78, 0xFB020001, - 0xC78, 0xFB030001, - 0xC78, 0xFB040001, - 0xC78, 0xFB050001, - 0xC78, 0xFA060001, - 0xC78, 0xF9070001, - 0xC78, 0xF8080001, - 0xC78, 0xF7090001, - 0xC78, 0xF60A0001, - 0xC78, 0xF50B0001, - 0xC78, 0xF40C0001, - 0xC78, 0xF30D0001, - 0xC78, 0xF20E0001, - 0xC78, 0xF10F0001, - 0xC78, 0xF0100001, - 0xC78, 0xEF110001, - 0xC78, 0xEE120001, - 0xC78, 0xED130001, - 0xC78, 0xEC140001, - 0xC78, 0xEB150001, - 0xC78, 0xEA160001, - 0xC78, 0xE9170001, - 0xC78, 0xE8180001, - 0xC78, 0xE7190001, - 0xC78, 0xE61A0001, - 0xC78, 0xE51B0001, - 0xC78, 0xE41C0001, - 0xC78, 0xE31D0001, - 0xC78, 0xE21E0001, - 0xC78, 0xE11F0001, - 0xC78, 0x8A200001, - 0xC78, 0x89210001, - 0xC78, 0x88220001, - 0xC78, 0x87230001, - 0xC78, 0x86240001, - 0xC78, 0x85250001, - 0xC78, 0x84260001, - 0xC78, 0x83270001, - 0xC78, 0x82280001, - 0xC78, 0x6B290001, - 0xC78, 0x6A2A0001, - 0xC78, 0x692B0001, - 0xC78, 0x682C0001, - 0xC78, 0x672D0001, - 0xC78, 0x662E0001, - 0xC78, 0x652F0001, - 0xC78, 0x64300001, - 0xC78, 0x63310001, - 0xC78, 0x62320001, - 0xC78, 0x61330001, - 0xC78, 0x46340001, - 0xC78, 0x45350001, - 0xC78, 0x44360001, - 0xC78, 0x43370001, - 0xC78, 0x42380001, - 0xC78, 0x41390001, - 0xC78, 0x403A0001, - 0xC78, 0x403B0001, - 0xC78, 0x403C0001, - 0xC78, 0x403D0001, - 0xC78, 0x403E0001, - 0xC78, 0x403F0001, - 0xC78, 0xFB400001, - 0xC78, 0xFB410001, - 0xC78, 0xFB420001, - 0xC78, 0xFB430001, - 0xC78, 0xFB440001, - 0xC78, 0xFB450001, - 0xC78, 0xFB460001, - 0xC78, 0xFB470001, - 0xC78, 0xFB480001, - 0xC78, 0xFA490001, - 0xC78, 0xF94A0001, - 0xC78, 0xF84B0001, - 0xC78, 0xF74C0001, - 0xC78, 0xF64D0001, - 0xC78, 0xF54E0001, - 0xC78, 0xF44F0001, - 0xC78, 0xF3500001, - 0xC78, 0xF2510001, - 0xC78, 0xF1520001, - 0xC78, 0xF0530001, - 0xC78, 0xEF540001, - 0xC78, 0xEE550001, - 0xC78, 0xED560001, - 0xC78, 0xEC570001, - 0xC78, 0xEB580001, - 0xC78, 0xEA590001, - 0xC78, 0xE95A0001, - 0xC78, 0xE85B0001, - 0xC78, 0xE75C0001, - 0xC78, 0xE65D0001, - 0xC78, 0xE55E0001, - 0xC78, 0xE45F0001, - 0xC78, 0xE3600001, - 0xC78, 0xE2610001, - 0xC78, 0xC3620001, - 0xC78, 0xC2630001, - 0xC78, 0xC1640001, - 0xC78, 0x8B650001, - 0xC78, 0x8A660001, - 0xC78, 0x89670001, - 0xC78, 0x88680001, - 0xC78, 0x87690001, - 0xC78, 0x866A0001, - 0xC78, 0x856B0001, - 0xC78, 0x846C0001, - 0xC78, 0x676D0001, - 0xC78, 0x666E0001, - 0xC78, 0x656F0001, - 0xC78, 0x64700001, - 0xC78, 0x63710001, - 0xC78, 0x62720001, - 0xC78, 0x61730001, - 0xC78, 0x60740001, - 0xC78, 0x46750001, - 0xC78, 0x45760001, - 0xC78, 0x44770001, - 0xC78, 0x43780001, - 0xC78, 0x42790001, - 0xC78, 0x417A0001, - 0xC78, 0x407B0001, - 0xC78, 0x407C0001, - 0xC78, 0x407D0001, - 0xC78, 0x407E0001, - 0xC78, 0x407F0001, -}; - -static void odm_ConfigBB_AGC_8188E(struct odm_dm_struct *pDM_Odm, u32 Addr, u32 Bitmask, u32 Data) -{ - rtl8188e_PHY_SetBBReg(pDM_Odm->Adapter, Addr, Bitmask, Data); - /* Add 1us delay between BB/RF register setting. */ - udelay(1); -} - -int ODM_ReadAndConfig_AGC_TAB_1T_8188E(struct odm_dm_struct *dm_odm) -{ - u32 hex = 0; - u32 i = 0; - u32 arraylen = ARRAY_SIZE(array_agc_tab_1t_8188e); - u32 *array = array_agc_tab_1t_8188e; - bool biol = false; - struct adapter *adapter = dm_odm->Adapter; - struct xmit_frame *pxmit_frame = NULL; - u8 bndy_cnt = 1; - - hex += ODM_ITRF_USB << 8; - hex += ODM_CE << 16; - hex += 0xFF000000; - biol = rtw_IOL_applied(adapter); - - if (biol) { - pxmit_frame = rtw_IOL_accquire_xmit_frame(adapter); - if (!pxmit_frame) { - pr_info("rtw_IOL_accquire_xmit_frame failed\n"); - return -ENOMEM; - } - } - - for (i = 0; i < arraylen; i += 2) { - u32 v1 = array[i]; - u32 v2 = array[i + 1]; - - /* This (offset, data) pair meets the condition. */ - if (v1 < 0xCDCDCDCD) { - if (biol) { - if (rtw_IOL_cmd_boundary_handle(pxmit_frame)) - bndy_cnt++; - rtw_IOL_append_WD_cmd(pxmit_frame, (u16)v1, v2, bMaskDWord); - } else { - odm_ConfigBB_AGC_8188E(dm_odm, v1, bMaskDWord, v2); - } - continue; - } else { - /* This line is the start line of branch. */ - if (!CheckCondition(array[i], hex)) { - /* Discard the following (offset, data) pairs. */ - read_next_pair(array, v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && i < arraylen - 2) - read_next_pair(array, v1, v2, i); - i -= 2; /* prevent from for-loop += 2 */ - } else { /* Configure matched pairs and skip to end of if-else. */ - read_next_pair(array, v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && i < arraylen - 2) { - if (biol) { - if (rtw_IOL_cmd_boundary_handle(pxmit_frame)) - bndy_cnt++; - rtw_IOL_append_WD_cmd(pxmit_frame, (u16)v1, v2, bMaskDWord); - } else { - odm_ConfigBB_AGC_8188E(dm_odm, v1, bMaskDWord, v2); - } - read_next_pair(array, v1, v2, i); - } - - while (v2 != 0xDEAD && i < arraylen - 2) - read_next_pair(array, v1, v2, i); - } - } - } - if (biol) { - if (!rtl8188e_IOL_exec_cmds_sync(dm_odm->Adapter, pxmit_frame, 1000, bndy_cnt)) { - printk("~~~ %s IOL_exec_cmds Failed !!!\n", __func__); - return -1; - } - } - return 0; -} - -/****************************************************************************** -* PHY_REG_1T.TXT -******************************************************************************/ - -static u32 array_phy_reg_1t_8188e[] = { - 0x800, 0x80040000, - 0x804, 0x00000003, - 0x808, 0x0000FC00, - 0x80C, 0x0000000A, - 0x810, 0x10001331, - 0x814, 0x020C3D10, - 0x818, 0x02200385, - 0x81C, 0x00000000, - 0x820, 0x01000100, - 0x824, 0x00390204, - 0x828, 0x00000000, - 0x82C, 0x00000000, - 0x830, 0x00000000, - 0x834, 0x00000000, - 0x838, 0x00000000, - 0x83C, 0x00000000, - 0x840, 0x00010000, - 0x844, 0x00000000, - 0x848, 0x00000000, - 0x84C, 0x00000000, - 0x850, 0x00000000, - 0x854, 0x00000000, - 0x858, 0x569A11A9, - 0x85C, 0x01000014, - 0x860, 0x66F60110, - 0x864, 0x061F0649, - 0x868, 0x00000000, - 0x86C, 0x27272700, - 0x870, 0x07000760, - 0x874, 0x25004000, - 0x878, 0x00000808, - 0x87C, 0x00000000, - 0x880, 0xB0000C1C, - 0x884, 0x00000001, - 0x888, 0x00000000, - 0x88C, 0xCCC000C0, - 0x890, 0x00000800, - 0x894, 0xFFFFFFFE, - 0x898, 0x40302010, - 0x89C, 0x00706050, - 0x900, 0x00000000, - 0x904, 0x00000023, - 0x908, 0x00000000, - 0x90C, 0x81121111, - 0x910, 0x00000002, - 0x914, 0x00000201, - 0xA00, 0x00D047C8, - 0xA04, 0x80FF000C, - 0xA08, 0x8C838300, - 0xA0C, 0x2E7F120F, - 0xA10, 0x9500BB78, - 0xA14, 0x1114D028, - 0xA18, 0x00881117, - 0xA1C, 0x89140F00, - 0xA20, 0x1A1B0000, - 0xA24, 0x090E1317, - 0xA28, 0x00000204, - 0xA2C, 0x00D30000, - 0xA70, 0x101FBF00, - 0xA74, 0x00000007, - 0xA78, 0x00000900, - 0xA7C, 0x225B0606, - 0xA80, 0x218075B1, - 0xB2C, 0x80000000, - 0xC00, 0x48071D40, - 0xC04, 0x03A05611, - 0xC08, 0x000000E4, - 0xC0C, 0x6C6C6C6C, - 0xC10, 0x08800000, - 0xC14, 0x40000100, - 0xC18, 0x08800000, - 0xC1C, 0x40000100, - 0xC20, 0x00000000, - 0xC24, 0x00000000, - 0xC28, 0x00000000, - 0xC2C, 0x00000000, - 0xC30, 0x69E9AC47, - 0xC34, 0x469652AF, - 0xC38, 0x49795994, - 0xC3C, 0x0A97971C, - 0xC40, 0x1F7C403F, - 0xC44, 0x000100B7, - 0xC48, 0xEC020107, - 0xC4C, 0x007F037F, - 0xC50, 0x69553420, - 0xC54, 0x43BC0094, - 0xC58, 0x00013169, - 0xC5C, 0x00250492, - 0xC60, 0x00000000, - 0xC64, 0x7112848B, - 0xC68, 0x47C00BFF, - 0xC6C, 0x00000036, - 0xC70, 0x2C7F000D, - 0xC74, 0x020610DB, - 0xC78, 0x0000001F, - 0xC7C, 0x00B91612, - 0xC80, 0x390000E4, - 0xC84, 0x20F60000, - 0xC88, 0x40000100, - 0xC8C, 0x20200000, - 0xC90, 0x00091521, - 0xC94, 0x00000000, - 0xC98, 0x00121820, - 0xC9C, 0x00007F7F, - 0xCA0, 0x00000000, - 0xCA4, 0x000300A0, - 0xCA8, 0x00000000, - 0xCAC, 0x00000000, - 0xCB0, 0x00000000, - 0xCB4, 0x00000000, - 0xCB8, 0x00000000, - 0xCBC, 0x28000000, - 0xCC0, 0x00000000, - 0xCC4, 0x00000000, - 0xCC8, 0x00000000, - 0xCCC, 0x00000000, - 0xCD0, 0x00000000, - 0xCD4, 0x00000000, - 0xCD8, 0x64B22427, - 0xCDC, 0x00766932, - 0xCE0, 0x00222222, - 0xCE4, 0x00000000, - 0xCE8, 0x37644302, - 0xCEC, 0x2F97D40C, - 0xD00, 0x00000740, - 0xD04, 0x00020401, - 0xD08, 0x0000907F, - 0xD0C, 0x20010201, - 0xD10, 0xA0633333, - 0xD14, 0x3333BC43, - 0xD18, 0x7A8F5B6F, - 0xD2C, 0xCC979975, - 0xD30, 0x00000000, - 0xD34, 0x80608000, - 0xD38, 0x00000000, - 0xD3C, 0x00127353, - 0xD40, 0x00000000, - 0xD44, 0x00000000, - 0xD48, 0x00000000, - 0xD4C, 0x00000000, - 0xD50, 0x6437140A, - 0xD54, 0x00000000, - 0xD58, 0x00000282, - 0xD5C, 0x30032064, - 0xD60, 0x4653DE68, - 0xD64, 0x04518A3C, - 0xD68, 0x00002101, - 0xD6C, 0x2A201C16, - 0xD70, 0x1812362E, - 0xD74, 0x322C2220, - 0xD78, 0x000E3C24, - 0xE00, 0x2D2D2D2D, - 0xE04, 0x2D2D2D2D, - 0xE08, 0x0390272D, - 0xE10, 0x2D2D2D2D, - 0xE14, 0x2D2D2D2D, - 0xE18, 0x2D2D2D2D, - 0xE1C, 0x2D2D2D2D, - 0xE28, 0x00000000, - 0xE30, 0x1000DC1F, - 0xE34, 0x10008C1F, - 0xE38, 0x02140102, - 0xE3C, 0x681604C2, - 0xE40, 0x01007C00, - 0xE44, 0x01004800, - 0xE48, 0xFB000000, - 0xE4C, 0x000028D1, - 0xE50, 0x1000DC1F, - 0xE54, 0x10008C1F, - 0xE58, 0x02140102, - 0xE5C, 0x28160D05, - 0xE60, 0x00000008, - 0xE68, 0x001B25A4, - 0xE6C, 0x00C00014, - 0xE70, 0x00C00014, - 0xE74, 0x01000014, - 0xE78, 0x01000014, - 0xE7C, 0x01000014, - 0xE80, 0x01000014, - 0xE84, 0x00C00014, - 0xE88, 0x01000014, - 0xE8C, 0x00C00014, - 0xED0, 0x00C00014, - 0xED4, 0x00C00014, - 0xED8, 0x00C00014, - 0xEDC, 0x00000014, - 0xEE0, 0x00000014, - 0xEEC, 0x01C00014, - 0xF14, 0x00000003, - 0xF4C, 0x00000000, - 0xF00, 0x00000300, -}; - -static void odm_ConfigBB_PHY_8188E(struct odm_dm_struct *pDM_Odm, u32 Addr, u32 Bitmask, u32 Data) -{ - if (Addr == 0xfe) { - msleep(50); - } else if (Addr == 0xfd) { - mdelay(5); - } else if (Addr == 0xfc) { - mdelay(1); - } else if (Addr == 0xfb) { - udelay(50); - } else if (Addr == 0xfa) { - udelay(5); - } else if (Addr == 0xf9) { - udelay(1); - } else { - if (Addr == 0xa24) - pDM_Odm->RFCalibrateInfo.RegA24 = Data; - rtl8188e_PHY_SetBBReg(pDM_Odm->Adapter, Addr, Bitmask, Data); - - /* Add 1us delay between BB/RF register setting. */ - udelay(1); - } -} - -int ODM_ReadAndConfig_PHY_REG_1T_8188E(struct odm_dm_struct *dm_odm) -{ - u32 hex = 0; - u32 i = 0; - u32 arraylen = ARRAY_SIZE(array_phy_reg_1t_8188e); - u32 *array = array_phy_reg_1t_8188e; - bool biol = false; - struct adapter *adapter = dm_odm->Adapter; - struct xmit_frame *pxmit_frame = NULL; - u8 bndy_cnt = 1; - hex += ODM_ITRF_USB << 8; - hex += ODM_CE << 16; - hex += 0xFF000000; - biol = rtw_IOL_applied(adapter); - - if (biol) { - pxmit_frame = rtw_IOL_accquire_xmit_frame(adapter); - if (!pxmit_frame) { - pr_info("rtw_IOL_accquire_xmit_frame failed\n"); - return -ENOMEM; - } - } - - for (i = 0; i < arraylen; i += 2) { - u32 v1 = array[i]; - u32 v2 = array[i + 1]; - - /* This (offset, data) pair meets the condition. */ - if (v1 < 0xCDCDCDCD) { - if (biol) { - if (rtw_IOL_cmd_boundary_handle(pxmit_frame)) - bndy_cnt++; - if (v1 == 0xfe) { - rtw_IOL_append_DELAY_MS_cmd(pxmit_frame, 50); - } else if (v1 == 0xfd) { - rtw_IOL_append_DELAY_MS_cmd(pxmit_frame, 5); - } else if (v1 == 0xfc) { - rtw_IOL_append_DELAY_MS_cmd(pxmit_frame, 1); - } else if (v1 == 0xfb) { - rtw_IOL_append_DELAY_US_cmd(pxmit_frame, 50); - } else if (v1 == 0xfa) { - rtw_IOL_append_DELAY_US_cmd(pxmit_frame, 5); - } else if (v1 == 0xf9) { - rtw_IOL_append_DELAY_US_cmd(pxmit_frame, 1); - } else { - if (v1 == 0xa24) - dm_odm->RFCalibrateInfo.RegA24 = v2; - rtw_IOL_append_WD_cmd(pxmit_frame, (u16)v1, v2, bMaskDWord); - } - } else { - odm_ConfigBB_PHY_8188E(dm_odm, v1, bMaskDWord, v2); - } - continue; - } else { /* This line is the start line of branch. */ - if (!CheckCondition(array[i], hex)) { - /* Discard the following (offset, data) pairs. */ - read_next_pair(array, v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && i < arraylen - 2) - read_next_pair(array, v1, v2, i); - i -= 2; /* prevent from for-loop += 2 */ - } else { /* Configure matched pairs and skip to end of if-else. */ - read_next_pair(array, v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && i < arraylen - 2) { - if (biol) { - if (rtw_IOL_cmd_boundary_handle(pxmit_frame)) - bndy_cnt++; - if (v1 == 0xfe) { - rtw_IOL_append_DELAY_MS_cmd(pxmit_frame, 50); - } else if (v1 == 0xfd) { - rtw_IOL_append_DELAY_MS_cmd(pxmit_frame, 5); - } else if (v1 == 0xfc) { - rtw_IOL_append_DELAY_MS_cmd(pxmit_frame, 1); - } else if (v1 == 0xfb) { - rtw_IOL_append_DELAY_US_cmd(pxmit_frame, 50); - } else if (v1 == 0xfa) { - rtw_IOL_append_DELAY_US_cmd(pxmit_frame, 5); - } else if (v1 == 0xf9) { - rtw_IOL_append_DELAY_US_cmd(pxmit_frame, 1); - } else { - if (v1 == 0xa24) - dm_odm->RFCalibrateInfo.RegA24 = v2; - - rtw_IOL_append_WD_cmd(pxmit_frame, (u16)v1, v2, bMaskDWord); - } - } else { - odm_ConfigBB_PHY_8188E(dm_odm, v1, bMaskDWord, v2); - } - read_next_pair(array, v1, v2, i); - } - - while (v2 != 0xDEAD && i < arraylen - 2) - read_next_pair(array, v1, v2, i); - } - } - } - if (biol) { - if (!rtl8188e_IOL_exec_cmds_sync(dm_odm->Adapter, pxmit_frame, 1000, bndy_cnt)) { - pr_info("~~~ IOL Config %s Failed !!!\n", __func__); - return -1; - } - } - return 0; -} - -/****************************************************************************** -* PHY_REG_PG.TXT -******************************************************************************/ - -static u32 array_phy_reg_pg_8188e[] = { - 0xE00, 0xFFFFFFFF, 0x06070809, - 0xE04, 0xFFFFFFFF, 0x02020405, - 0xE08, 0x0000FF00, 0x00000006, - 0x86C, 0xFFFFFF00, 0x00020400, - 0xE10, 0xFFFFFFFF, 0x08090A0B, - 0xE14, 0xFFFFFFFF, 0x01030607, - 0xE18, 0xFFFFFFFF, 0x08090A0B, - 0xE1C, 0xFFFFFFFF, 0x01030607, - 0xE00, 0xFFFFFFFF, 0x00000000, - 0xE04, 0xFFFFFFFF, 0x00000000, - 0xE08, 0x0000FF00, 0x00000000, - 0x86C, 0xFFFFFF00, 0x00000000, - 0xE10, 0xFFFFFFFF, 0x00000000, - 0xE14, 0xFFFFFFFF, 0x00000000, - 0xE18, 0xFFFFFFFF, 0x00000000, - 0xE1C, 0xFFFFFFFF, 0x00000000, - 0xE00, 0xFFFFFFFF, 0x02020202, - 0xE04, 0xFFFFFFFF, 0x00020202, - 0xE08, 0x0000FF00, 0x00000000, - 0x86C, 0xFFFFFF00, 0x00000000, - 0xE10, 0xFFFFFFFF, 0x04040404, - 0xE14, 0xFFFFFFFF, 0x00020404, - 0xE18, 0xFFFFFFFF, 0x00000000, - 0xE1C, 0xFFFFFFFF, 0x00000000, - 0xE00, 0xFFFFFFFF, 0x02020202, - 0xE04, 0xFFFFFFFF, 0x00020202, - 0xE08, 0x0000FF00, 0x00000000, - 0x86C, 0xFFFFFF00, 0x00000000, - 0xE10, 0xFFFFFFFF, 0x04040404, - 0xE14, 0xFFFFFFFF, 0x00020404, - 0xE18, 0xFFFFFFFF, 0x00000000, - 0xE1C, 0xFFFFFFFF, 0x00000000, - 0xE00, 0xFFFFFFFF, 0x00000000, - 0xE04, 0xFFFFFFFF, 0x00000000, - 0xE08, 0x0000FF00, 0x00000000, - 0x86C, 0xFFFFFF00, 0x00000000, - 0xE10, 0xFFFFFFFF, 0x00000000, - 0xE14, 0xFFFFFFFF, 0x00000000, - 0xE18, 0xFFFFFFFF, 0x00000000, - 0xE1C, 0xFFFFFFFF, 0x00000000, - 0xE00, 0xFFFFFFFF, 0x02020202, - 0xE04, 0xFFFFFFFF, 0x00020202, - 0xE08, 0x0000FF00, 0x00000000, - 0x86C, 0xFFFFFF00, 0x00000000, - 0xE10, 0xFFFFFFFF, 0x04040404, - 0xE14, 0xFFFFFFFF, 0x00020404, - 0xE18, 0xFFFFFFFF, 0x00000000, - 0xE1C, 0xFFFFFFFF, 0x00000000, - 0xE00, 0xFFFFFFFF, 0x00000000, - 0xE04, 0xFFFFFFFF, 0x00000000, - 0xE08, 0x0000FF00, 0x00000000, - 0x86C, 0xFFFFFF00, 0x00000000, - 0xE10, 0xFFFFFFFF, 0x00000000, - 0xE14, 0xFFFFFFFF, 0x00000000, - 0xE18, 0xFFFFFFFF, 0x00000000, - 0xE1C, 0xFFFFFFFF, 0x00000000, - 0xE00, 0xFFFFFFFF, 0x00000000, - 0xE04, 0xFFFFFFFF, 0x00000000, - 0xE08, 0x0000FF00, 0x00000000, - 0x86C, 0xFFFFFF00, 0x00000000, - 0xE10, 0xFFFFFFFF, 0x00000000, - 0xE14, 0xFFFFFFFF, 0x00000000, - 0xE18, 0xFFFFFFFF, 0x00000000, - 0xE1C, 0xFFFFFFFF, 0x00000000, - 0xE00, 0xFFFFFFFF, 0x00000000, - 0xE04, 0xFFFFFFFF, 0x00000000, - 0xE08, 0x0000FF00, 0x00000000, - 0x86C, 0xFFFFFF00, 0x00000000, - 0xE10, 0xFFFFFFFF, 0x00000000, - 0xE14, 0xFFFFFFFF, 0x00000000, - 0xE18, 0xFFFFFFFF, 0x00000000, - 0xE1C, 0xFFFFFFFF, 0x00000000, - 0xE00, 0xFFFFFFFF, 0x00000000, - 0xE04, 0xFFFFFFFF, 0x00000000, - 0xE08, 0x0000FF00, 0x00000000, - 0x86C, 0xFFFFFF00, 0x00000000, - 0xE10, 0xFFFFFFFF, 0x00000000, - 0xE14, 0xFFFFFFFF, 0x00000000, - 0xE18, 0xFFFFFFFF, 0x00000000, - 0xE1C, 0xFFFFFFFF, 0x00000000, - 0xE00, 0xFFFFFFFF, 0x00000000, - 0xE04, 0xFFFFFFFF, 0x00000000, - 0xE08, 0x0000FF00, 0x00000000, - 0x86C, 0xFFFFFF00, 0x00000000, - 0xE10, 0xFFFFFFFF, 0x00000000, - 0xE14, 0xFFFFFFFF, 0x00000000, - 0xE18, 0xFFFFFFFF, 0x00000000, - 0xE1C, 0xFFFFFFFF, 0x00000000, - -}; - -static void odm_ConfigBB_PHY_REG_PG_8188E(struct odm_dm_struct *pDM_Odm, u32 Addr, u32 Bitmask, - u32 Data) -{ - if (Addr == 0xfe) - msleep(50); - else if (Addr == 0xfd) - mdelay(5); - else if (Addr == 0xfc) - mdelay(1); - else if (Addr == 0xfb) - udelay(50); - else if (Addr == 0xfa) - udelay(5); - else if (Addr == 0xf9) - udelay(1); - else - storePwrIndexDiffRateOffset(pDM_Odm->Adapter, Addr, Bitmask, Data); -} - -void ODM_ReadAndConfig_PHY_REG_PG_8188E(struct odm_dm_struct *dm_odm) -{ - u32 hex; - u32 i = 0; - u32 arraylen = ARRAY_SIZE(array_phy_reg_pg_8188e); - u32 *array = array_phy_reg_pg_8188e; - - hex = ODM_ITRF_USB << 8; - hex += (ODM_CE << 16) + 0xFF000000; - - for (i = 0; i < arraylen; i += 3) { - u32 v1 = array[i]; - u32 v2 = array[i + 1]; - u32 v3 = array[i + 2]; - - /* this line is a line of pure_body */ - if (v1 < 0xCDCDCDCD) { - odm_ConfigBB_PHY_REG_PG_8188E(dm_odm, v1, v2, v3); - continue; - } else { /* this line is the start of branch */ - if (!CheckCondition(array[i], hex)) { - /* don't need the hw_body */ - i += 2; /* skip the pair of expression */ - v1 = array[i]; - v2 = array[i + 1]; - v3 = array[i + 2]; - while (v2 != 0xDEAD) { - i += 3; - v1 = array[i]; - v2 = array[i + 1]; - v3 = array[i + 1]; - } - } - } - } -} diff --git a/drivers/staging/r8188eu/hal/HalHWImg8188E_MAC.c b/drivers/staging/r8188eu/hal/HalHWImg8188E_MAC.c deleted file mode 100644 index da71867bcca3..000000000000 --- a/drivers/staging/r8188eu/hal/HalHWImg8188E_MAC.c +++ /dev/null @@ -1,212 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#include "../include/rtw_iol.h" - -static bool Checkcondition(const u32 condition, const u32 hex) -{ - u32 _board = (hex & 0x000000FF); - u32 _interface = (hex & 0x0000FF00) >> 8; - u32 _platform = (hex & 0x00FF0000) >> 16; - u32 cond = condition; - - if (condition == 0xCDCDCDCD) - return true; - - cond = condition & 0x000000FF; - if ((_board == cond) && cond != 0x00) - return false; - - cond = condition & 0x0000FF00; - cond = cond >> 8; - if ((_interface & cond) == 0 && cond != 0x07) - return false; - - cond = condition & 0x00FF0000; - cond = cond >> 16; - if ((_platform & cond) == 0 && cond != 0x0F) - return false; - return true; -} - -/****************************************************************************** -* MAC_REG.TXT -******************************************************************************/ - -static u32 array_MAC_REG_8188E[] = { - 0x026, 0x00000041, - 0x027, 0x00000035, - 0x428, 0x0000000A, - 0x429, 0x00000010, - 0x430, 0x00000000, - 0x431, 0x00000001, - 0x432, 0x00000002, - 0x433, 0x00000004, - 0x434, 0x00000005, - 0x435, 0x00000006, - 0x436, 0x00000007, - 0x437, 0x00000008, - 0x438, 0x00000000, - 0x439, 0x00000000, - 0x43A, 0x00000001, - 0x43B, 0x00000002, - 0x43C, 0x00000004, - 0x43D, 0x00000005, - 0x43E, 0x00000006, - 0x43F, 0x00000007, - 0x440, 0x0000005D, - 0x441, 0x00000001, - 0x442, 0x00000000, - 0x444, 0x00000015, - 0x445, 0x000000F0, - 0x446, 0x0000000F, - 0x447, 0x00000000, - 0x458, 0x00000041, - 0x459, 0x000000A8, - 0x45A, 0x00000072, - 0x45B, 0x000000B9, - 0x460, 0x00000066, - 0x461, 0x00000066, - 0x480, 0x00000008, - 0x4C8, 0x000000FF, - 0x4C9, 0x00000008, - 0x4CC, 0x000000FF, - 0x4CD, 0x000000FF, - 0x4CE, 0x00000001, - 0x4D3, 0x00000001, - 0x500, 0x00000026, - 0x501, 0x000000A2, - 0x502, 0x0000002F, - 0x503, 0x00000000, - 0x504, 0x00000028, - 0x505, 0x000000A3, - 0x506, 0x0000005E, - 0x507, 0x00000000, - 0x508, 0x0000002B, - 0x509, 0x000000A4, - 0x50A, 0x0000005E, - 0x50B, 0x00000000, - 0x50C, 0x0000004F, - 0x50D, 0x000000A4, - 0x50E, 0x00000000, - 0x50F, 0x00000000, - 0x512, 0x0000001C, - 0x514, 0x0000000A, - 0x516, 0x0000000A, - 0x525, 0x0000004F, - 0x550, 0x00000010, - 0x551, 0x00000010, - 0x559, 0x00000002, - 0x55D, 0x000000FF, - 0x605, 0x00000030, - 0x608, 0x0000000E, - 0x609, 0x0000002A, - 0x620, 0x000000FF, - 0x621, 0x000000FF, - 0x622, 0x000000FF, - 0x623, 0x000000FF, - 0x624, 0x000000FF, - 0x625, 0x000000FF, - 0x626, 0x000000FF, - 0x627, 0x000000FF, - 0x652, 0x00000020, - 0x63C, 0x0000000A, - 0x63D, 0x0000000A, - 0x63E, 0x0000000E, - 0x63F, 0x0000000E, - 0x640, 0x00000040, - 0x66E, 0x00000005, - 0x700, 0x00000021, - 0x701, 0x00000043, - 0x702, 0x00000065, - 0x703, 0x00000087, - 0x708, 0x00000021, - 0x709, 0x00000043, - 0x70A, 0x00000065, - 0x70B, 0x00000087, -}; - -static void odm_ConfigMAC_8188E(struct odm_dm_struct *pDM_Odm, u32 Addr, u8 Data) -{ - rtw_write8(pDM_Odm->Adapter, Addr, Data); -} - -int ODM_ReadAndConfig_MAC_REG_8188E(struct odm_dm_struct *dm_odm) -{ - #define READ_NEXT_PAIR(v1, v2, i) do { i += 2; v1 = array[i]; v2 = array[i + 1]; } while (0) - - u32 hex = 0; - u32 i; - u32 array_len = ARRAY_SIZE(array_MAC_REG_8188E); - u32 *array = array_MAC_REG_8188E; - bool biol = false; - - struct adapter *adapt = dm_odm->Adapter; - struct xmit_frame *pxmit_frame = NULL; - u8 bndy_cnt = 1; - hex += ODM_ITRF_USB << 8; - hex += ODM_CE << 16; - hex += 0xFF000000; - - biol = rtw_IOL_applied(adapt); - - if (biol) { - pxmit_frame = rtw_IOL_accquire_xmit_frame(adapt); - if (!pxmit_frame) { - pr_info("rtw_IOL_accquire_xmit_frame failed\n"); - return -ENOMEM; - } - } - - for (i = 0; i < array_len; i += 2) { - u32 v1 = array[i]; - u32 v2 = array[i + 1]; - - /* This (offset, data) pair meets the condition. */ - if (v1 < 0xCDCDCDCD) { - if (biol) { - if (rtw_IOL_cmd_boundary_handle(pxmit_frame)) - bndy_cnt++; - rtw_IOL_append_WB_cmd(pxmit_frame, (u16)v1, (u8)v2, 0xFF); - } else { - odm_ConfigMAC_8188E(dm_odm, v1, (u8)v2); - } - continue; - } else { /* This line is the start line of branch. */ - if (!Checkcondition(array[i], hex)) { - /* Discard the following (offset, data) pairs. */ - READ_NEXT_PAIR(v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && i < array_len - 2) { - READ_NEXT_PAIR(v1, v2, i); - } - i -= 2; /* prevent from for-loop += 2 */ - } else { /* Configure matched pairs and skip to end of if-else. */ - READ_NEXT_PAIR(v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && i < array_len - 2) { - if (biol) { - if (rtw_IOL_cmd_boundary_handle(pxmit_frame)) - bndy_cnt++; - rtw_IOL_append_WB_cmd(pxmit_frame, (u16)v1, (u8)v2, 0xFF); - } else { - odm_ConfigMAC_8188E(dm_odm, v1, (u8)v2); - } - - READ_NEXT_PAIR(v1, v2, i); - } - while (v2 != 0xDEAD && i < array_len - 2) - READ_NEXT_PAIR(v1, v2, i); - } - } - } - if (biol) { - if (!rtl8188e_IOL_exec_cmds_sync(dm_odm->Adapter, pxmit_frame, 1000, bndy_cnt)) { - pr_info("~~~ MAC IOL_exec_cmds Failed !!!\n"); - return -1; - } - } - return 0; -} diff --git a/drivers/staging/r8188eu/hal/HalHWImg8188E_RF.c b/drivers/staging/r8188eu/hal/HalHWImg8188E_RF.c deleted file mode 100644 index a4c3d3d149f7..000000000000 --- a/drivers/staging/r8188eu/hal/HalHWImg8188E_RF.c +++ /dev/null @@ -1,269 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#include "../include/rtw_iol.h" - -static bool CheckCondition(const u32 Condition, const u32 Hex) -{ - u32 _interface = (Hex & 0x0000FF00) >> 8; - u32 _platform = (Hex & 0x00FF0000) >> 16; - u32 cond = Condition; - - if (Condition == 0xCDCDCDCD) - return true; - - cond = Condition & 0x0000FF00; - cond = cond >> 8; - if ((_interface & cond) == 0 && cond != 0x07) - return false; - - cond = Condition & 0x00FF0000; - cond = cond >> 16; - if ((_platform & cond) == 0 && cond != 0x0F) - return false; - return true; -} - -/****************************************************************************** -* RadioA_1T.TXT -******************************************************************************/ - -static u32 Array_RadioA_1T_8188E[] = { - 0x000, 0x00030000, - 0x008, 0x00084000, - 0x018, 0x00000407, - 0x019, 0x00000012, - 0x01E, 0x00080009, - 0x01F, 0x00000880, - 0x02F, 0x0001A060, - 0x03F, 0x00000000, - 0x042, 0x000060C0, - 0x057, 0x000D0000, - 0x058, 0x000BE180, - 0x067, 0x00001552, - 0x083, 0x00000000, - 0x0B0, 0x000FF8FC, - 0x0B1, 0x00054400, - 0x0B2, 0x000CCC19, - 0x0B4, 0x00043003, - 0x0B6, 0x0004953E, - 0x0B7, 0x0001C718, - 0x0B8, 0x000060FF, - 0x0B9, 0x00080001, - 0x0BA, 0x00040000, - 0x0BB, 0x00000400, - 0x0BF, 0x000C0000, - 0x0C2, 0x00002400, - 0x0C3, 0x00000009, - 0x0C4, 0x00040C91, - 0x0C5, 0x00099999, - 0x0C6, 0x000000A3, - 0x0C7, 0x00088820, - 0x0C8, 0x00076C06, - 0x0C9, 0x00000000, - 0x0CA, 0x00080000, - 0x0DF, 0x00000180, - 0x0EF, 0x000001A0, - 0x051, 0x0006B27D, - 0xFF0F041F, 0xABCD, - 0x052, 0x0007E4DD, - 0xCDCDCDCD, 0xCDCD, - 0x052, 0x0007E49D, - 0xFF0F041F, 0xDEAD, - 0x053, 0x00000073, - 0x056, 0x00051FF3, - 0x035, 0x00000086, - 0x035, 0x00000186, - 0x035, 0x00000286, - 0x036, 0x00001C25, - 0x036, 0x00009C25, - 0x036, 0x00011C25, - 0x036, 0x00019C25, - 0x0B6, 0x00048538, - 0x018, 0x00000C07, - 0x05A, 0x0004BD00, - 0x019, 0x000739D0, - 0x034, 0x0000ADF3, - 0x034, 0x00009DF0, - 0x034, 0x00008DED, - 0x034, 0x00007DEA, - 0x034, 0x00006DE7, - 0x034, 0x000054EE, - 0x034, 0x000044EB, - 0x034, 0x000034E8, - 0x034, 0x0000246B, - 0x034, 0x00001468, - 0x034, 0x0000006D, - 0x000, 0x00030159, - 0x084, 0x00068200, - 0x086, 0x000000CE, - 0x087, 0x00048A00, - 0x08E, 0x00065540, - 0x08F, 0x00088000, - 0x0EF, 0x000020A0, - 0x03B, 0x000F02B0, - 0x03B, 0x000EF7B0, - 0x03B, 0x000D4FB0, - 0x03B, 0x000CF060, - 0x03B, 0x000B0090, - 0x03B, 0x000A0080, - 0x03B, 0x00090080, - 0x03B, 0x0008F780, - 0x03B, 0x000722B0, - 0x03B, 0x0006F7B0, - 0x03B, 0x00054FB0, - 0x03B, 0x0004F060, - 0x03B, 0x00030090, - 0x03B, 0x00020080, - 0x03B, 0x00010080, - 0x03B, 0x0000F780, - 0x0EF, 0x000000A0, - 0x000, 0x00010159, - 0x018, 0x0000F407, - 0xFFE, 0x00000000, - 0xFFE, 0x00000000, - 0x01F, 0x00080003, - 0xFFE, 0x00000000, - 0xFFE, 0x00000000, - 0x01E, 0x00000001, - 0x01F, 0x00080000, - 0x000, 0x00033E60, -}; - -static void odm_ConfigRFReg_8188E(struct odm_dm_struct *pDM_Odm, u32 Addr, - u32 Data, u32 RegAddr) -{ - if (Addr == 0xffe) { - msleep(50); - } else if (Addr == 0xfd) { - mdelay(5); - } else if (Addr == 0xfc) { - mdelay(1); - } else if (Addr == 0xfb) { - udelay(50); - } else if (Addr == 0xfa) { - udelay(5); - } else if (Addr == 0xf9) { - udelay(1); - } else { - rtl8188e_PHY_SetRFReg(pDM_Odm->Adapter, RegAddr, bRFRegOffsetMask, Data); - /* Add 1us delay between BB/RF register setting. */ - udelay(1); - } -} - -static void odm_ConfigRF_RadioA_8188E(struct odm_dm_struct *pDM_Odm, u32 Addr, u32 Data) -{ - u32 content = 0x1000; /* RF_Content: radioa_txt */ - u32 maskforPhySet = (u32)(content & 0xE000); - - odm_ConfigRFReg_8188E(pDM_Odm, Addr, Data, Addr | maskforPhySet); -} - -int ODM_ReadAndConfig_RadioA_1T_8188E(struct odm_dm_struct *pDM_Odm) -{ - #define READ_NEXT_PAIR(v1, v2, i) do \ - { i += 2; v1 = Array[i]; \ - v2 = Array[i + 1]; } while (0) - - u32 hex = 0; - u32 i = 0; - u32 ArrayLen = ARRAY_SIZE(Array_RadioA_1T_8188E); - u32 *Array = Array_RadioA_1T_8188E; - bool biol = false; - struct adapter *Adapter = pDM_Odm->Adapter; - struct xmit_frame *pxmit_frame = NULL; - u8 bndy_cnt = 1; - - hex += ODM_ITRF_USB << 8; - hex += ODM_CE << 16; - hex += 0xFF000000; - biol = rtw_IOL_applied(Adapter); - - if (biol) { - pxmit_frame = rtw_IOL_accquire_xmit_frame(Adapter); - if (!pxmit_frame) { - pr_info("rtw_IOL_accquire_xmit_frame failed\n"); - return -ENOMEM; - } - } - - for (i = 0; i < ArrayLen; i += 2) { - u32 v1 = Array[i]; - u32 v2 = Array[i + 1]; - - /* This (offset, data) pair meets the condition. */ - if (v1 < 0xCDCDCDCD) { - if (biol) { - if (rtw_IOL_cmd_boundary_handle(pxmit_frame)) - bndy_cnt++; - - if (v1 == 0xffe) - rtw_IOL_append_DELAY_MS_cmd(pxmit_frame, 50); - else if (v1 == 0xfd) - rtw_IOL_append_DELAY_MS_cmd(pxmit_frame, 5); - else if (v1 == 0xfc) - rtw_IOL_append_DELAY_MS_cmd(pxmit_frame, 1); - else if (v1 == 0xfb) - rtw_IOL_append_DELAY_US_cmd(pxmit_frame, 50); - else if (v1 == 0xfa) - rtw_IOL_append_DELAY_US_cmd(pxmit_frame, 5); - else if (v1 == 0xf9) - rtw_IOL_append_DELAY_US_cmd(pxmit_frame, 1); - else - rtw_IOL_append_WRF_cmd(pxmit_frame, RF_PATH_A, (u16)v1, v2, bRFRegOffsetMask); - } else { - odm_ConfigRF_RadioA_8188E(pDM_Odm, v1, v2); - } - continue; - } else { /* This line is the start line of branch. */ - if (!CheckCondition(Array[i], hex)) { - /* Discard the following (offset, data) pairs. */ - READ_NEXT_PAIR(v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && i < ArrayLen - 2) - READ_NEXT_PAIR(v1, v2, i); - i -= 2; /* prevent from for-loop += 2 */ - } else { /* Configure matched pairs and skip to end of if-else. */ - READ_NEXT_PAIR(v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && i < ArrayLen - 2) { - if (biol) { - if (rtw_IOL_cmd_boundary_handle(pxmit_frame)) - bndy_cnt++; - - if (v1 == 0xffe) - rtw_IOL_append_DELAY_MS_cmd(pxmit_frame, 50); - else if (v1 == 0xfd) - rtw_IOL_append_DELAY_MS_cmd(pxmit_frame, 5); - else if (v1 == 0xfc) - rtw_IOL_append_DELAY_MS_cmd(pxmit_frame, 1); - else if (v1 == 0xfb) - rtw_IOL_append_DELAY_US_cmd(pxmit_frame, 50); - else if (v1 == 0xfa) - rtw_IOL_append_DELAY_US_cmd(pxmit_frame, 5); - else if (v1 == 0xf9) - rtw_IOL_append_DELAY_US_cmd(pxmit_frame, 1); - else - rtw_IOL_append_WRF_cmd(pxmit_frame, RF_PATH_A, (u16)v1, v2, bRFRegOffsetMask); - } else { - odm_ConfigRF_RadioA_8188E(pDM_Odm, v1, v2); - } - READ_NEXT_PAIR(v1, v2, i); - } - - while (v2 != 0xDEAD && i < ArrayLen - 2) - READ_NEXT_PAIR(v1, v2, i); - } - } - } - if (biol) { - if (!rtl8188e_IOL_exec_cmds_sync(pDM_Odm->Adapter, pxmit_frame, 1000, bndy_cnt)) { - pr_info("~~~ IOL Config %s Failed !!!\n", __func__); - return -1; - } - } - return 0; -} diff --git a/drivers/staging/r8188eu/hal/HalPhyRf_8188e.c b/drivers/staging/r8188eu/hal/HalPhyRf_8188e.c deleted file mode 100644 index 26e710ef5134..000000000000 --- a/drivers/staging/r8188eu/hal/HalPhyRf_8188e.c +++ /dev/null @@ -1,900 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#include "../include/drv_types.h" - -/*---------------------------Define Local Constant---------------------------*/ -/* 2010/04/25 MH Define the max tx power tracking tx agc power. */ -#define ODM_TXPWRTRACK_MAX_IDX_88E 6 - -/*---------------------------Define Local Constant---------------------------*/ - -/* 3============================================================ */ -/* 3 Tx Power Tracking */ -/* 3============================================================ */ -/*----------------------------------------------------------------------------- - * Function: ODM_TxPwrTrackAdjust88E() - * - * Overview: 88E we can not write 0xc80/c94/c4c/ 0xa2x. Instead of write TX agc. - * No matter OFDM & CCK use the same method. - * - * Input: NONE - * - * Output: NONE - * - * Return: NONE - * - * Revised History: - * When Who Remark - * 04/23/2012 MHC Create Version 0. - * 04/23/2012 MHC Adjust TX agc directly not throughput BB digital. - * - *---------------------------------------------------------------------------*/ -void ODM_TxPwrTrackAdjust88E(struct odm_dm_struct *dm_odm, u8 Type,/* 0 = OFDM, 1 = CCK */ - u8 *pDirection, /* 1 = +(increase) 2 = -(decrease) */ - u32 *pOutWriteVal /* Tx tracking CCK/OFDM BB swing index adjust */ - ) -{ - u8 pwr_value = 0; - /* Tx power tracking BB swing table. */ - /* The base index = 12. +((12-n)/2)dB 13~?? = decrease tx pwr by -((n-12)/2)dB */ - if (Type == 0) { /* For OFDM afjust */ - if (dm_odm->BbSwingIdxOfdm <= dm_odm->BbSwingIdxOfdmBase) { - *pDirection = 1; - pwr_value = (dm_odm->BbSwingIdxOfdmBase - dm_odm->BbSwingIdxOfdm); - } else { - *pDirection = 2; - pwr_value = (dm_odm->BbSwingIdxOfdm - dm_odm->BbSwingIdxOfdmBase); - } - } else if (Type == 1) { /* For CCK adjust. */ - if (dm_odm->BbSwingIdxCck <= dm_odm->BbSwingIdxCckBase) { - *pDirection = 1; - pwr_value = (dm_odm->BbSwingIdxCckBase - dm_odm->BbSwingIdxCck); - } else { - *pDirection = 2; - pwr_value = (dm_odm->BbSwingIdxCck - dm_odm->BbSwingIdxCckBase); - } - } - - /* */ - /* 2012/04/25 MH According to Ed/Luke.Lees estimate for EVM the max tx power tracking */ - /* need to be less than 6 power index for 88E. */ - /* */ - if (pwr_value >= ODM_TXPWRTRACK_MAX_IDX_88E && *pDirection == 1) - pwr_value = ODM_TXPWRTRACK_MAX_IDX_88E; - - *pOutWriteVal = pwr_value | (pwr_value << 8) | (pwr_value << 16) | (pwr_value << 24); -} /* ODM_TxPwrTrackAdjust88E */ - -/*----------------------------------------------------------------------------- - * Function: odm_TxPwrTrackSetPwr88E() - * - * Overview: 88E change all channel tx power according to flag. - * OFDM & CCK are all different. - * - * Input: NONE - * - * Output: NONE - * - * Return: NONE - * - * Revised History: - * When Who Remark - * 04/23/2012 MHC Create Version 0. - * - *---------------------------------------------------------------------------*/ -static void odm_TxPwrTrackSetPwr88E(struct odm_dm_struct *dm_odm) -{ - if (dm_odm->BbSwingFlagOfdm || dm_odm->BbSwingFlagCck) { - PHY_SetTxPowerLevel8188E(dm_odm->Adapter, *dm_odm->pChannel); - dm_odm->BbSwingFlagOfdm = false; - dm_odm->BbSwingFlagCck = false; - } -} /* odm_TxPwrTrackSetPwr88E */ - -/* 091212 chiyokolin */ -void -odm_TXPowerTrackingCallback_ThermalMeter_8188E( - struct adapter *Adapter - ) -{ - struct hal_data_8188e *pHalData = &Adapter->haldata; - u8 ThermalValue = 0, delta, delta_LCK, delta_IQK, offset; - u8 ThermalValue_AVG_count = 0; - u32 ThermalValue_AVG = 0; - s32 ele_D, TempCCk; - s8 OFDM_index, CCK_index = 0; - s8 OFDM_index_old = 0, CCK_index_old = 0; - u32 i = 0, j = 0; - - u8 OFDM_min_index = 6; /* OFDM BB Swing should be less than +3.0dB, which is required by Arthur */ - s8 OFDM_index_mapping[2][index_mapping_NUM_88E] = { - {0, 0, 2, 3, 4, 4, /* 2.4G, decrease power */ - 5, 6, 7, 7, 8, 9, - 10, 10, 11}, /* For lower temperature, 20120220 updated on 20120220. */ - {0, 0, -1, -2, -3, -4, /* 2.4G, increase power */ - -4, -4, -4, -5, -7, -8, - -9, -9, -10}, - }; - u8 Thermal_mapping[2][index_mapping_NUM_88E] = { - {0, 2, 4, 6, 8, 10, /* 2.4G, decrease power */ - 12, 14, 16, 18, 20, 22, - 24, 26, 27}, - {0, 2, 4, 6, 8, 10, /* 2.4G,, increase power */ - 12, 14, 16, 18, 20, 22, - 25, 25, 25}, - }; - struct odm_dm_struct *dm_odm = &pHalData->odmpriv; - - /* 2012/04/25 MH Add for tx power tracking to set tx power in tx agc for 88E. */ - odm_TxPwrTrackSetPwr88E(dm_odm); - - /* RFCalibrateInfo.RegA24 will be initialized when ODM HW configuring, but MP configures with para files. */ - dm_odm->RFCalibrateInfo.RegA24 = 0x090e1317; - - ThermalValue = (u8)rtl8188e_PHY_QueryRFReg(Adapter, RF_T_METER_88E, 0xfc00); /* 0x42: RF Reg[15:10] 88E */ - - if (ThermalValue) { - /* Query OFDM path A default setting */ - ele_D = rtl8188e_PHY_QueryBBReg(Adapter, rOFDM0_XATxIQImbalance, bMaskDWord) & bMaskOFDM_D; - for (i = 0; i < OFDM_TABLE_SIZE_92D; i++) { /* find the index */ - if (ele_D == (OFDMSwingTable[i] & bMaskOFDM_D)) { - OFDM_index_old = (u8)i; - dm_odm->BbSwingIdxOfdmBase = (u8)i; - break; - } - } - - /* Query CCK default setting From 0xa24 */ - TempCCk = dm_odm->RFCalibrateInfo.RegA24; - - for (i = 0; i < CCK_TABLE_SIZE; i++) { - if (memcmp((void *)&TempCCk, (void *)&cck_swing_table[i][2], 4)) { - CCK_index_old = (u8)i; - dm_odm->BbSwingIdxCckBase = (u8)i; - break; - } - } - - if (!dm_odm->RFCalibrateInfo.ThermalValue) { - dm_odm->RFCalibrateInfo.ThermalValue = pHalData->EEPROMThermalMeter; - dm_odm->RFCalibrateInfo.ThermalValue_LCK = ThermalValue; - dm_odm->RFCalibrateInfo.ThermalValue_IQK = ThermalValue; - - dm_odm->RFCalibrateInfo.OFDM_index = OFDM_index_old; - dm_odm->RFCalibrateInfo.CCK_index = CCK_index_old; - } - - /* calculate average thermal meter */ - dm_odm->RFCalibrateInfo.ThermalValue_AVG[dm_odm->RFCalibrateInfo.ThermalValue_AVG_index] = ThermalValue; - dm_odm->RFCalibrateInfo.ThermalValue_AVG_index++; - if (dm_odm->RFCalibrateInfo.ThermalValue_AVG_index == AVG_THERMAL_NUM_88E) - dm_odm->RFCalibrateInfo.ThermalValue_AVG_index = 0; - - for (i = 0; i < AVG_THERMAL_NUM_88E; i++) { - if (dm_odm->RFCalibrateInfo.ThermalValue_AVG[i]) { - ThermalValue_AVG += dm_odm->RFCalibrateInfo.ThermalValue_AVG[i]; - ThermalValue_AVG_count++; - } - } - - if (ThermalValue_AVG_count) - ThermalValue = (u8)(ThermalValue_AVG / ThermalValue_AVG_count); - - if (dm_odm->RFCalibrateInfo.bReloadtxpowerindex) { - delta = ThermalValue > pHalData->EEPROMThermalMeter ? - (ThermalValue - pHalData->EEPROMThermalMeter) : - (pHalData->EEPROMThermalMeter - ThermalValue); - dm_odm->RFCalibrateInfo.bReloadtxpowerindex = false; - dm_odm->RFCalibrateInfo.bDoneTxpower = false; - } else if (dm_odm->RFCalibrateInfo.bDoneTxpower) { - delta = (ThermalValue > dm_odm->RFCalibrateInfo.ThermalValue) ? - (ThermalValue - dm_odm->RFCalibrateInfo.ThermalValue) : - (dm_odm->RFCalibrateInfo.ThermalValue - ThermalValue); - } else { - delta = ThermalValue > pHalData->EEPROMThermalMeter ? - (ThermalValue - pHalData->EEPROMThermalMeter) : - (pHalData->EEPROMThermalMeter - ThermalValue); - } - delta_LCK = (ThermalValue > dm_odm->RFCalibrateInfo.ThermalValue_LCK) ? - (ThermalValue - dm_odm->RFCalibrateInfo.ThermalValue_LCK) : - (dm_odm->RFCalibrateInfo.ThermalValue_LCK - ThermalValue); - delta_IQK = (ThermalValue > dm_odm->RFCalibrateInfo.ThermalValue_IQK) ? - (ThermalValue - dm_odm->RFCalibrateInfo.ThermalValue_IQK) : - (dm_odm->RFCalibrateInfo.ThermalValue_IQK - ThermalValue); - - if ((delta_LCK >= 8)) { /* Delta temperature is equal to or larger than 20 centigrade. */ - dm_odm->RFCalibrateInfo.ThermalValue_LCK = ThermalValue; - PHY_LCCalibrate_8188E(Adapter); - } - - if (delta > 0 && dm_odm->RFCalibrateInfo.TxPowerTrackControl) { - delta = ThermalValue > pHalData->EEPROMThermalMeter ? - (ThermalValue - pHalData->EEPROMThermalMeter) : - (pHalData->EEPROMThermalMeter - ThermalValue); - /* calculate new OFDM / CCK offset */ - if (ThermalValue > pHalData->EEPROMThermalMeter) - j = 1; - else - j = 0; - for (offset = 0; offset < index_mapping_NUM_88E; offset++) { - if (delta < Thermal_mapping[j][offset]) { - if (offset != 0) - offset--; - break; - } - } - if (offset >= index_mapping_NUM_88E) - offset = index_mapping_NUM_88E - 1; - OFDM_index = dm_odm->RFCalibrateInfo.OFDM_index + OFDM_index_mapping[j][offset]; - CCK_index = dm_odm->RFCalibrateInfo.CCK_index + OFDM_index_mapping[j][offset]; - - if (OFDM_index > OFDM_TABLE_SIZE_92D - 1) - OFDM_index = OFDM_TABLE_SIZE_92D - 1; - else if (OFDM_index < OFDM_min_index) - OFDM_index = OFDM_min_index; - - if (CCK_index > CCK_TABLE_SIZE - 1) - CCK_index = CCK_TABLE_SIZE - 1; - else if (CCK_index < 0) - CCK_index = 0; - - /* 2 temporarily remove bNOPG */ - /* Config by SwingTable */ - if (dm_odm->RFCalibrateInfo.TxPowerTrackControl) { - dm_odm->RFCalibrateInfo.bDoneTxpower = true; - - /* Revse TX power table. */ - dm_odm->BbSwingIdxOfdm = (u8)OFDM_index; - dm_odm->BbSwingIdxCck = (u8)CCK_index; - - if (dm_odm->BbSwingIdxOfdmCurrent != dm_odm->BbSwingIdxOfdm) { - dm_odm->BbSwingIdxOfdmCurrent = dm_odm->BbSwingIdxOfdm; - dm_odm->BbSwingFlagOfdm = true; - } - - if (dm_odm->BbSwingIdxCckCurrent != dm_odm->BbSwingIdxCck) { - dm_odm->BbSwingIdxCckCurrent = dm_odm->BbSwingIdxCck; - dm_odm->BbSwingFlagCck = true; - } - } - } - - if (delta_IQK >= 8) { /* Delta temperature is equal to or larger than 20 centigrade. */ - dm_odm->RFCalibrateInfo.ThermalValue_IQK = ThermalValue; - PHY_IQCalibrate_8188E(Adapter, false); - } - /* update thermal meter value */ - if (dm_odm->RFCalibrateInfo.TxPowerTrackControl) - dm_odm->RFCalibrateInfo.ThermalValue = ThermalValue; - } -} - -/* 1 7. IQK */ -#define MAX_TOLERANCE 5 -#define IQK_DELAY_TIME 1 /* ms */ - -static u8 /* bit0 = 1 => Tx OK, bit1 = 1 => Rx OK */ -phy_PathA_IQK_8188E(struct adapter *adapt) -{ - u32 regeac, regE94, regE9C; - u8 result = 0x00; - - /* 1 Tx IQK */ - /* path-A IQK setting */ - rtl8188e_PHY_SetBBReg(adapt, rTx_IQK_Tone_A, bMaskDWord, 0x10008c1c); - rtl8188e_PHY_SetBBReg(adapt, rRx_IQK_Tone_A, bMaskDWord, 0x30008c1c); - rtl8188e_PHY_SetBBReg(adapt, rTx_IQK_PI_A, bMaskDWord, 0x8214032a); - rtl8188e_PHY_SetBBReg(adapt, rRx_IQK_PI_A, bMaskDWord, 0x28160000); - - /* LO calibration setting */ - rtl8188e_PHY_SetBBReg(adapt, rIQK_AGC_Rsp, bMaskDWord, 0x00462911); - - /* One shot, path A LOK & IQK */ - rtl8188e_PHY_SetBBReg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf9000000); - rtl8188e_PHY_SetBBReg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf8000000); - - /* delay x ms */ - /* PlatformStallExecution(IQK_DELAY_TIME_88E*1000); */ - mdelay(IQK_DELAY_TIME_88E); - - /* Check failed */ - regeac = rtl8188e_PHY_QueryBBReg(adapt, rRx_Power_After_IQK_A_2, bMaskDWord); - regE94 = rtl8188e_PHY_QueryBBReg(adapt, rTx_Power_Before_IQK_A, bMaskDWord); - regE9C = rtl8188e_PHY_QueryBBReg(adapt, rTx_Power_After_IQK_A, bMaskDWord); - - if (!(regeac & BIT(28)) && - (((regE94 & 0x03FF0000) >> 16) != 0x142) && - (((regE9C & 0x03FF0000) >> 16) != 0x42)) - result |= 0x01; - return result; -} - -static u8 /* bit0 = 1 => Tx OK, bit1 = 1 => Rx OK */ -phy_PathA_RxIQK(struct adapter *adapt) -{ - u32 regeac, regE94, regE9C, regEA4, u4tmp; - u8 result = 0x00; - - /* 1 Get TXIMR setting */ - /* modify RXIQK mode table */ - rtl8188e_PHY_SetBBReg(adapt, rFPGA0_IQK, bMaskDWord, 0x00000000); - rtl8188e_PHY_SetRFReg(adapt, RF_WE_LUT, bRFRegOffsetMask, 0x800a0); - rtl8188e_PHY_SetRFReg(adapt, RF_RCK_OS, bRFRegOffsetMask, 0x30000); - rtl8188e_PHY_SetRFReg(adapt, RF_TXPA_G1, bRFRegOffsetMask, 0x0000f); - rtl8188e_PHY_SetRFReg(adapt, RF_TXPA_G2, bRFRegOffsetMask, 0xf117B); - - /* PA,PAD off */ - rtl8188e_PHY_SetRFReg(adapt, 0xdf, bRFRegOffsetMask, 0x980); - rtl8188e_PHY_SetRFReg(adapt, 0x56, bRFRegOffsetMask, 0x51000); - - rtl8188e_PHY_SetBBReg(adapt, rFPGA0_IQK, bMaskDWord, 0x80800000); - - /* IQK setting */ - rtl8188e_PHY_SetBBReg(adapt, rTx_IQK, bMaskDWord, 0x01007c00); - rtl8188e_PHY_SetBBReg(adapt, rRx_IQK, bMaskDWord, 0x81004800); - - /* path-A IQK setting */ - rtl8188e_PHY_SetBBReg(adapt, rTx_IQK_Tone_A, bMaskDWord, 0x10008c1c); - rtl8188e_PHY_SetBBReg(adapt, rRx_IQK_Tone_A, bMaskDWord, 0x30008c1c); - rtl8188e_PHY_SetBBReg(adapt, rTx_IQK_PI_A, bMaskDWord, 0x82160c1f); - rtl8188e_PHY_SetBBReg(adapt, rRx_IQK_PI_A, bMaskDWord, 0x28160000); - - /* LO calibration setting */ - rtl8188e_PHY_SetBBReg(adapt, rIQK_AGC_Rsp, bMaskDWord, 0x0046a911); - - /* One shot, path A LOK & IQK */ - rtl8188e_PHY_SetBBReg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf9000000); - rtl8188e_PHY_SetBBReg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf8000000); - - /* delay x ms */ - mdelay(IQK_DELAY_TIME_88E); - - /* Check failed */ - regeac = rtl8188e_PHY_QueryBBReg(adapt, rRx_Power_After_IQK_A_2, bMaskDWord); - regE94 = rtl8188e_PHY_QueryBBReg(adapt, rTx_Power_Before_IQK_A, bMaskDWord); - regE9C = rtl8188e_PHY_QueryBBReg(adapt, rTx_Power_After_IQK_A, bMaskDWord); - - if (!(regeac & BIT(28)) && - (((regE94 & 0x03FF0000) >> 16) != 0x142) && - (((regE9C & 0x03FF0000) >> 16) != 0x42)) - result |= 0x01; - else /* if Tx not OK, ignore Rx */ - return result; - - u4tmp = 0x80007C00 | (regE94 & 0x3FF0000) | ((regE9C & 0x3FF0000) >> 16); - rtl8188e_PHY_SetBBReg(adapt, rTx_IQK, bMaskDWord, u4tmp); - - /* 1 RX IQK */ - /* modify RXIQK mode table */ - rtl8188e_PHY_SetBBReg(adapt, rFPGA0_IQK, bMaskDWord, 0x00000000); - rtl8188e_PHY_SetRFReg(adapt, RF_WE_LUT, bRFRegOffsetMask, 0x800a0); - rtl8188e_PHY_SetRFReg(adapt, RF_RCK_OS, bRFRegOffsetMask, 0x30000); - rtl8188e_PHY_SetRFReg(adapt, RF_TXPA_G1, bRFRegOffsetMask, 0x0000f); - rtl8188e_PHY_SetRFReg(adapt, RF_TXPA_G2, bRFRegOffsetMask, 0xf7ffa); - rtl8188e_PHY_SetBBReg(adapt, rFPGA0_IQK, bMaskDWord, 0x80800000); - - /* IQK setting */ - rtl8188e_PHY_SetBBReg(adapt, rRx_IQK, bMaskDWord, 0x01004800); - - /* path-A IQK setting */ - rtl8188e_PHY_SetBBReg(adapt, rTx_IQK_Tone_A, bMaskDWord, 0x38008c1c); - rtl8188e_PHY_SetBBReg(adapt, rRx_IQK_Tone_A, bMaskDWord, 0x18008c1c); - rtl8188e_PHY_SetBBReg(adapt, rTx_IQK_PI_A, bMaskDWord, 0x82160c05); - rtl8188e_PHY_SetBBReg(adapt, rRx_IQK_PI_A, bMaskDWord, 0x28160c1f); - - /* LO calibration setting */ - rtl8188e_PHY_SetBBReg(adapt, rIQK_AGC_Rsp, bMaskDWord, 0x0046a911); - - /* One shot, path A LOK & IQK */ - rtl8188e_PHY_SetBBReg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf9000000); - rtl8188e_PHY_SetBBReg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf8000000); - - /* delay x ms */ - /* PlatformStallExecution(IQK_DELAY_TIME_88E*1000); */ - mdelay(IQK_DELAY_TIME_88E); - - /* Check failed */ - regeac = rtl8188e_PHY_QueryBBReg(adapt, rRx_Power_After_IQK_A_2, bMaskDWord); - regE94 = rtl8188e_PHY_QueryBBReg(adapt, rTx_Power_Before_IQK_A, bMaskDWord); - regE9C = rtl8188e_PHY_QueryBBReg(adapt, rTx_Power_After_IQK_A, bMaskDWord); - regEA4 = rtl8188e_PHY_QueryBBReg(adapt, rRx_Power_Before_IQK_A_2, bMaskDWord); - - /* reload RF 0xdf */ - rtl8188e_PHY_SetBBReg(adapt, rFPGA0_IQK, bMaskDWord, 0x00000000); - rtl8188e_PHY_SetRFReg(adapt, 0xdf, bRFRegOffsetMask, 0x180); - - if (!(regeac & BIT(27)) && /* if Tx is OK, check whether Rx is OK */ - (((regEA4 & 0x03FF0000) >> 16) != 0x132) && - (((regeac & 0x03FF0000) >> 16) != 0x36)) - result |= 0x02; - - return result; -} - -static void patha_fill_iqk(struct adapter *adapt, bool iqkok, s32 result[][8], u8 final_candidate, bool txonly) -{ - u32 Oldval_0, X, TX0_A, reg; - s32 Y, TX0_C; - - if (final_candidate == 0xFF) { - return; - } else if (iqkok) { - Oldval_0 = (rtl8188e_PHY_QueryBBReg(adapt, rOFDM0_XATxIQImbalance, bMaskDWord) >> 22) & 0x3FF; - - X = result[final_candidate][0]; - if ((X & 0x00000200) != 0) - X = X | 0xFFFFFC00; - TX0_A = (X * Oldval_0) >> 8; - rtl8188e_PHY_SetBBReg(adapt, rOFDM0_XATxIQImbalance, 0x3FF, TX0_A); - - rtl8188e_PHY_SetBBReg(adapt, rOFDM0_ECCAThreshold, BIT(31), ((X * Oldval_0 >> 7) & 0x1)); - - Y = result[final_candidate][1]; - if ((Y & 0x00000200) != 0) - Y = Y | 0xFFFFFC00; - - TX0_C = (Y * Oldval_0) >> 8; - rtl8188e_PHY_SetBBReg(adapt, rOFDM0_XCTxAFE, 0xF0000000, ((TX0_C & 0x3C0) >> 6)); - rtl8188e_PHY_SetBBReg(adapt, rOFDM0_XATxIQImbalance, 0x003F0000, (TX0_C & 0x3F)); - - rtl8188e_PHY_SetBBReg(adapt, rOFDM0_ECCAThreshold, BIT(29), ((Y * Oldval_0 >> 7) & 0x1)); - - if (txonly) - return; - - reg = result[final_candidate][2]; - rtl8188e_PHY_SetBBReg(adapt, rOFDM0_XARxIQImbalance, 0x3FF, reg); - - reg = result[final_candidate][3] & 0x3F; - rtl8188e_PHY_SetBBReg(adapt, rOFDM0_XARxIQImbalance, 0xFC00, reg); - - reg = (result[final_candidate][3] >> 6) & 0xF; - rtl8188e_PHY_SetBBReg(adapt, rOFDM0_RxIQExtAnta, 0xF0000000, reg); - } -} - -void _PHY_SaveADDARegisters(struct adapter *adapt, u32 *ADDAReg, u32 *ADDABackup, u32 RegisterNum) -{ - u32 i; - - for (i = 0; i < RegisterNum; i++) { - ADDABackup[i] = rtl8188e_PHY_QueryBBReg(adapt, ADDAReg[i], bMaskDWord); - } -} - -/* FIXME: return an error to caller */ -static void _PHY_SaveMACRegisters( - struct adapter *adapt, - u32 *MACReg, - u32 *MACBackup - ) -{ - u32 i; - int res; - - for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++) { - u8 reg; - - res = rtw_read8(adapt, MACReg[i], ®); - if (res) - return; - - MACBackup[i] = reg; - } - - res = rtw_read32(adapt, MACReg[i], MACBackup + i); - (void)res; -} - -static void reload_adda_reg(struct adapter *adapt, u32 *ADDAReg, u32 *ADDABackup, u32 RegiesterNum) -{ - u32 i; - - for (i = 0; i < RegiesterNum; i++) - rtl8188e_PHY_SetBBReg(adapt, ADDAReg[i], bMaskDWord, ADDABackup[i]); -} - -static void -_PHY_ReloadMACRegisters( - struct adapter *adapt, - u32 *MACReg, - u32 *MACBackup - ) -{ - u32 i; - - for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++) - rtw_write8(adapt, MACReg[i], (u8)MACBackup[i]); - - rtw_write32(adapt, MACReg[i], MACBackup[i]); -} - -static void -_PHY_PathADDAOn( - struct adapter *adapt, - u32 *ADDAReg) -{ - u32 i; - - rtl8188e_PHY_SetBBReg(adapt, ADDAReg[0], bMaskDWord, 0x0b1b25a0); - - for (i = 1; i < IQK_ADDA_REG_NUM; i++) - rtl8188e_PHY_SetBBReg(adapt, ADDAReg[i], bMaskDWord, 0x0bdb25a0); -} - -void -_PHY_MACSettingCalibration( - struct adapter *adapt, - u32 *MACReg, - u32 *MACBackup - ) -{ - u32 i = 0; - - rtw_write8(adapt, MACReg[i], 0x3F); - - for (i = 1; i < (IQK_MAC_REG_NUM - 1); i++) - rtw_write8(adapt, MACReg[i], (u8)(MACBackup[i] & (~BIT(3)))); - - rtw_write8(adapt, MACReg[i], (u8)(MACBackup[i] & (~BIT(5)))); -} - -static void _PHY_PIModeSwitch( - struct adapter *adapt, - bool PIMode - ) -{ - u32 mode; - - mode = PIMode ? 0x01000100 : 0x01000000; - rtl8188e_PHY_SetBBReg(adapt, rFPGA0_XA_HSSIParameter1, bMaskDWord, mode); - rtl8188e_PHY_SetBBReg(adapt, rFPGA0_XB_HSSIParameter1, bMaskDWord, mode); -} - -static bool phy_SimularityCompare_8188E( - struct adapter *adapt, - s32 resulta[][8], - u8 c1, - u8 c2 - ) -{ - u32 i, j, diff, sim_bitmap, bound = 0; - u8 final_candidate[2] = {0xFF, 0xFF}; /* for path A and path B */ - bool result = true; - s32 tmp1 = 0, tmp2 = 0; - - bound = 4; - sim_bitmap = 0; - - for (i = 0; i < bound; i++) { - if ((i == 1) || (i == 3) || (i == 5) || (i == 7)) { - if ((resulta[c1][i] & 0x00000200) != 0) - tmp1 = resulta[c1][i] | 0xFFFFFC00; - else - tmp1 = resulta[c1][i]; - - if ((resulta[c2][i] & 0x00000200) != 0) - tmp2 = resulta[c2][i] | 0xFFFFFC00; - else - tmp2 = resulta[c2][i]; - } else { - tmp1 = resulta[c1][i]; - tmp2 = resulta[c2][i]; - } - - diff = abs(tmp1 - tmp2); - - if (diff > MAX_TOLERANCE) { - if ((i == 2 || i == 6) && !sim_bitmap) { - if (resulta[c1][i] + resulta[c1][i + 1] == 0) - final_candidate[(i / 4)] = c2; - else if (resulta[c2][i] + resulta[c2][i + 1] == 0) - final_candidate[(i / 4)] = c1; - else - sim_bitmap = sim_bitmap | (1 << i); - } else { - sim_bitmap = sim_bitmap | (1 << i); - } - } - } - - if (sim_bitmap == 0) { - for (i = 0; i < (bound / 4); i++) { - if (final_candidate[i] != 0xFF) { - for (j = i * 4; j < (i + 1) * 4 - 2; j++) - resulta[3][j] = resulta[final_candidate[i]][j]; - result = false; - } - } - return result; - } else { - if (!(sim_bitmap & 0x03)) { /* path A TX OK */ - for (i = 0; i < 2; i++) - resulta[3][i] = resulta[c1][i]; - } - if (!(sim_bitmap & 0x0c)) { /* path A RX OK */ - for (i = 2; i < 4; i++) - resulta[3][i] = resulta[c1][i]; - } - - if (!(sim_bitmap & 0x30)) { /* path B TX OK */ - for (i = 4; i < 6; i++) - resulta[3][i] = resulta[c1][i]; - } - - if (!(sim_bitmap & 0xc0)) { /* path B RX OK */ - for (i = 6; i < 8; i++) - resulta[3][i] = resulta[c1][i]; - } - return false; - } -} - -static void phy_IQCalibrate_8188E(struct adapter *adapt, s32 result[][8], u8 t) -{ - struct hal_data_8188e *pHalData = &adapt->haldata; - struct odm_dm_struct *dm_odm = &pHalData->odmpriv; - u32 i; - u8 PathAOK; - u32 ADDA_REG[IQK_ADDA_REG_NUM] = { - rFPGA0_XCD_SwitchControl, rBlue_Tooth, - rRx_Wait_CCA, rTx_CCK_RFON, - rTx_CCK_BBON, rTx_OFDM_RFON, - rTx_OFDM_BBON, rTx_To_Rx, - rTx_To_Tx, rRx_CCK, - rRx_OFDM, rRx_Wait_RIFS, - rRx_TO_Rx, rStandby, - rSleep, rPMPD_ANAEN }; - u32 IQK_MAC_REG[IQK_MAC_REG_NUM] = { - REG_TXPAUSE, REG_BCN_CTRL, - REG_BCN_CTRL_1, REG_GPIO_MUXCFG}; - - /* since 92C & 92D have the different define in IQK_BB_REG */ - u32 IQK_BB_REG_92C[IQK_BB_REG_NUM] = { - rOFDM0_TRxPathEnable, rOFDM0_TRMuxPar, - rFPGA0_XCD_RFInterfaceSW, rConfig_AntA, rConfig_AntB, - rFPGA0_XAB_RFInterfaceSW, rFPGA0_XA_RFInterfaceOE, - rFPGA0_XB_RFInterfaceOE, rFPGA0_RFMOD - }; - u32 retryCount = 2; - /* Note: IQ calibration must be performed after loading */ - /* PHY_REG.txt , and radio_a, radio_b.txt */ - - if (t == 0) { - /* Save ADDA parameters, turn Path A ADDA on */ - _PHY_SaveADDARegisters(adapt, ADDA_REG, dm_odm->RFCalibrateInfo.ADDA_backup, IQK_ADDA_REG_NUM); - _PHY_SaveMACRegisters(adapt, IQK_MAC_REG, dm_odm->RFCalibrateInfo.IQK_MAC_backup); - _PHY_SaveADDARegisters(adapt, IQK_BB_REG_92C, dm_odm->RFCalibrateInfo.IQK_BB_backup, IQK_BB_REG_NUM); - } - - _PHY_PathADDAOn(adapt, ADDA_REG); - if (t == 0) - dm_odm->RFCalibrateInfo.bRfPiEnable = (u8)rtl8188e_PHY_QueryBBReg(adapt, rFPGA0_XA_HSSIParameter1, BIT(8)); - - if (!dm_odm->RFCalibrateInfo.bRfPiEnable) { - /* Switch BB to PI mode to do IQ Calibration. */ - _PHY_PIModeSwitch(adapt, true); - } - - /* BB setting */ - rtl8188e_PHY_SetBBReg(adapt, rFPGA0_RFMOD, BIT(24), 0x00); - rtl8188e_PHY_SetBBReg(adapt, rOFDM0_TRxPathEnable, bMaskDWord, 0x03a05600); - rtl8188e_PHY_SetBBReg(adapt, rOFDM0_TRMuxPar, bMaskDWord, 0x000800e4); - rtl8188e_PHY_SetBBReg(adapt, rFPGA0_XCD_RFInterfaceSW, bMaskDWord, 0x22204000); - - rtl8188e_PHY_SetBBReg(adapt, rFPGA0_XAB_RFInterfaceSW, BIT(10), 0x01); - rtl8188e_PHY_SetBBReg(adapt, rFPGA0_XAB_RFInterfaceSW, BIT(26), 0x01); - rtl8188e_PHY_SetBBReg(adapt, rFPGA0_XA_RFInterfaceOE, BIT(10), 0x00); - rtl8188e_PHY_SetBBReg(adapt, rFPGA0_XB_RFInterfaceOE, BIT(10), 0x00); - - /* MAC settings */ - _PHY_MACSettingCalibration(adapt, IQK_MAC_REG, dm_odm->RFCalibrateInfo.IQK_MAC_backup); - - /* Page B init */ - /* AP or IQK */ - rtl8188e_PHY_SetBBReg(adapt, rConfig_AntA, bMaskDWord, 0x0f600000); - - - /* IQ calibration setting */ - rtl8188e_PHY_SetBBReg(adapt, rFPGA0_IQK, bMaskDWord, 0x80800000); - rtl8188e_PHY_SetBBReg(adapt, rTx_IQK, bMaskDWord, 0x01007c00); - rtl8188e_PHY_SetBBReg(adapt, rRx_IQK, bMaskDWord, 0x81004800); - - for (i = 0; i < retryCount; i++) { - PathAOK = phy_PathA_IQK_8188E(adapt); - if (PathAOK == 0x01) { - result[t][0] = (rtl8188e_PHY_QueryBBReg(adapt, rTx_Power_Before_IQK_A, bMaskDWord) & 0x3FF0000) >> 16; - result[t][1] = (rtl8188e_PHY_QueryBBReg(adapt, rTx_Power_After_IQK_A, bMaskDWord) & 0x3FF0000) >> 16; - break; - } - } - - for (i = 0; i < retryCount; i++) { - PathAOK = phy_PathA_RxIQK(adapt); - if (PathAOK == 0x03) { - result[t][2] = (rtl8188e_PHY_QueryBBReg(adapt, rRx_Power_Before_IQK_A_2, bMaskDWord) & 0x3FF0000) >> 16; - result[t][3] = (rtl8188e_PHY_QueryBBReg(adapt, rRx_Power_After_IQK_A_2, bMaskDWord) & 0x3FF0000) >> 16; - break; - } - } - - /* Back to BB mode, load original value */ - rtl8188e_PHY_SetBBReg(adapt, rFPGA0_IQK, bMaskDWord, 0); - - if (t != 0) { - if (!dm_odm->RFCalibrateInfo.bRfPiEnable) { - /* Switch back BB to SI mode after finish IQ Calibration. */ - _PHY_PIModeSwitch(adapt, false); - } - - /* Reload ADDA power saving parameters */ - reload_adda_reg(adapt, ADDA_REG, dm_odm->RFCalibrateInfo.ADDA_backup, IQK_ADDA_REG_NUM); - - /* Reload MAC parameters */ - _PHY_ReloadMACRegisters(adapt, IQK_MAC_REG, dm_odm->RFCalibrateInfo.IQK_MAC_backup); - - reload_adda_reg(adapt, IQK_BB_REG_92C, dm_odm->RFCalibrateInfo.IQK_BB_backup, IQK_BB_REG_NUM); - - /* Restore RX initial gain */ - rtl8188e_PHY_SetBBReg(adapt, rFPGA0_XA_LSSIParameter, bMaskDWord, 0x00032ed3); - - /* load 0xe30 IQC default value */ - rtl8188e_PHY_SetBBReg(adapt, rTx_IQK_Tone_A, bMaskDWord, 0x01008c00); - rtl8188e_PHY_SetBBReg(adapt, rRx_IQK_Tone_A, bMaskDWord, 0x01008c00); - } -} - -static void phy_LCCalibrate_8188E(struct adapter *adapt) -{ - u8 tmpreg; - u32 RF_Amode = 0, LC_Cal; - int res; - - /* Check continuous TX and Packet TX */ - res = rtw_read8(adapt, 0xd03, &tmpreg); - if (res) - return; - - if ((tmpreg & 0x70) != 0) /* Deal with contisuous TX case */ - rtw_write8(adapt, 0xd03, tmpreg & 0x8F); /* disable all continuous TX */ - else /* Deal with Packet TX case */ - rtw_write8(adapt, REG_TXPAUSE, 0xFF); /* block all queues */ - - if ((tmpreg & 0x70) != 0) { - /* 1. Read original RF mode */ - /* Path-A */ - RF_Amode = rtl8188e_PHY_QueryRFReg(adapt, RF_AC, bMask12Bits); - - /* 2. Set RF mode = standby mode */ - /* Path-A */ - rtl8188e_PHY_SetRFReg(adapt, RF_AC, bMask12Bits, (RF_Amode & 0x8FFFF) | 0x10000); - } - - /* 3. Read RF reg18 */ - LC_Cal = rtl8188e_PHY_QueryRFReg(adapt, RF_CHNLBW, bMask12Bits); - - /* 4. Set LC calibration begin bit15 */ - rtl8188e_PHY_SetRFReg(adapt, RF_CHNLBW, bMask12Bits, LC_Cal | 0x08000); - - msleep(100); - - /* Restore original situation */ - if ((tmpreg & 0x70) != 0) { - /* Deal with continuous TX case */ - /* Path-A */ - rtw_write8(adapt, 0xd03, tmpreg); - rtl8188e_PHY_SetRFReg(adapt, RF_AC, bMask12Bits, RF_Amode); - } else { - /* Deal with Packet TX case */ - rtw_write8(adapt, REG_TXPAUSE, 0x00); - } -} - -void PHY_IQCalibrate_8188E(struct adapter *adapt, bool recovery) -{ - struct hal_data_8188e *pHalData = &adapt->haldata; - struct odm_dm_struct *dm_odm = &pHalData->odmpriv; - s32 result[4][8]; /* last is final result */ - u8 i, final_candidate; - bool pathaok; - s32 RegE94, RegE9C, RegEA4, RegEB4, RegEBC; - bool is12simular, is13simular, is23simular; - u32 IQK_BB_REG_92C[IQK_BB_REG_NUM] = { - rOFDM0_XARxIQImbalance, rOFDM0_XBRxIQImbalance, - rOFDM0_ECCAThreshold, rOFDM0_AGCRSSITable, - rOFDM0_XATxIQImbalance, rOFDM0_XBTxIQImbalance, - rOFDM0_XCTxAFE, rOFDM0_XDTxAFE, - rOFDM0_RxIQExtAnta}; - - if (recovery) { - reload_adda_reg(adapt, IQK_BB_REG_92C, dm_odm->RFCalibrateInfo.IQK_BB_backup_recover, 9); - return; - } - - for (i = 0; i < 8; i++) { - result[0][i] = 0; - result[1][i] = 0; - result[2][i] = 0; - if ((i == 0) || (i == 2) || (i == 4) || (i == 6)) - result[3][i] = 0x100; - else - result[3][i] = 0; - } - final_candidate = 0xff; - pathaok = false; - is12simular = false; - is23simular = false; - is13simular = false; - - for (i = 0; i < 3; i++) { - phy_IQCalibrate_8188E(adapt, result, i); - - if (i == 1) { - is12simular = phy_SimularityCompare_8188E(adapt, result, 0, 1); - if (is12simular) { - final_candidate = 0; - break; - } - } - - if (i == 2) { - is13simular = phy_SimularityCompare_8188E(adapt, result, 0, 2); - if (is13simular) { - final_candidate = 0; - - break; - } - is23simular = phy_SimularityCompare_8188E(adapt, result, 1, 2); - if (is23simular) { - final_candidate = 1; - } else { - final_candidate = 3; - } - } - } - - for (i = 0; i < 4; i++) { - RegE94 = result[i][0]; - RegE9C = result[i][1]; - RegEA4 = result[i][2]; - RegEB4 = result[i][4]; - RegEBC = result[i][5]; - } - - if (final_candidate != 0xff) { - RegE94 = result[final_candidate][0]; - RegE9C = result[final_candidate][1]; - RegEA4 = result[final_candidate][2]; - RegEB4 = result[final_candidate][4]; - RegEBC = result[final_candidate][5]; - dm_odm->RFCalibrateInfo.RegE94 = RegE94; - dm_odm->RFCalibrateInfo.RegE9C = RegE9C; - dm_odm->RFCalibrateInfo.RegEB4 = RegEB4; - dm_odm->RFCalibrateInfo.RegEBC = RegEBC; - pathaok = true; - } else { - dm_odm->RFCalibrateInfo.RegE94 = 0x100; - dm_odm->RFCalibrateInfo.RegEB4 = 0x100; /* X default value */ - dm_odm->RFCalibrateInfo.RegE9C = 0x0; - dm_odm->RFCalibrateInfo.RegEBC = 0x0; /* Y default value */ - } - if (RegE94 != 0) - patha_fill_iqk(adapt, pathaok, result, final_candidate, (RegEA4 == 0)); - - _PHY_SaveADDARegisters(adapt, IQK_BB_REG_92C, dm_odm->RFCalibrateInfo.IQK_BB_backup_recover, 9); -} - -void PHY_LCCalibrate_8188E(struct adapter *adapt) -{ - u32 timeout = 2000, timecount = 0; - struct hal_data_8188e *pHalData = &adapt->haldata; - struct odm_dm_struct *dm_odm = &pHalData->odmpriv; - - while (*dm_odm->pbScanInProcess && timecount < timeout) { - mdelay(50); - timecount += 50; - } - - phy_LCCalibrate_8188E(adapt); -} diff --git a/drivers/staging/r8188eu/hal/HalPwrSeqCmd.c b/drivers/staging/r8188eu/hal/HalPwrSeqCmd.c deleted file mode 100644 index 6c0b1368383d..000000000000 --- a/drivers/staging/r8188eu/hal/HalPwrSeqCmd.c +++ /dev/null @@ -1,149 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#include "../include/HalPwrSeqCmd.h" - -#define PWR_CMD_WRITE 0x01 - /* offset: the read register offset */ - /* msk: the mask of the write bits */ - /* value: write value */ - /* note: driver shall implement this cmd by read & msk after write */ - -#define PWR_CMD_POLLING 0x02 - /* offset: the read register offset */ - /* msk: the mask of the polled value */ - /* value: the value to be polled, masked by the msd field. */ - /* note: driver shall implement this cmd by */ - /* do{ */ - /* if ( (Read(offset) & msk) == (value & msk) ) */ - /* break; */ - /* } while (not timeout); */ - -#define PWR_CMD_DELAY 0x03 - /* offset: the value to delay (in us) */ - /* msk: N/A */ - /* value: N/A */ - -struct wl_pwr_cfg { - u16 offset; - u8 cmd:4; - u8 msk; - u8 value; -}; - -#define GET_PWR_CFG_OFFSET(__PWR_CMD) __PWR_CMD.offset -#define GET_PWR_CFG_CMD(__PWR_CMD) __PWR_CMD.cmd -#define GET_PWR_CFG_MASK(__PWR_CMD) __PWR_CMD.msk -#define GET_PWR_CFG_VALUE(__PWR_CMD) __PWR_CMD.value - -static struct wl_pwr_cfg rtl8188E_power_on_flow[] = { - { 0x0006, PWR_CMD_POLLING, BIT(1), BIT(1) }, - { 0x0002, PWR_CMD_WRITE, BIT(0) | BIT(1), 0 }, /* reset BB */ - { 0x0026, PWR_CMD_WRITE, BIT(7), BIT(7) }, /* schmitt trigger */ - { 0x0005, PWR_CMD_WRITE, BIT(7), 0 }, /* disable HWPDN (control by DRV)*/ - { 0x0005, PWR_CMD_WRITE, BIT(4) | BIT(3), 0 }, /* disable WL suspend*/ - { 0x0005, PWR_CMD_WRITE, BIT(0), BIT(0) }, - { 0x0005, PWR_CMD_POLLING, BIT(0), 0 }, - { 0x0023, PWR_CMD_WRITE, BIT(4), 0 }, -}; - -static struct wl_pwr_cfg rtl8188E_card_disable_flow[] = { - { 0x001F, PWR_CMD_WRITE, 0xFF, 0 }, /* turn off RF */ - { 0x0023, PWR_CMD_WRITE, BIT(4), BIT(4) }, /* LDO Sleep mode */ - { 0x0005, PWR_CMD_WRITE, BIT(1), BIT(1) }, /* turn off MAC by HW state machine */ - { 0x0005, PWR_CMD_POLLING, BIT(1), 0 }, - { 0x0026, PWR_CMD_WRITE, BIT(7), BIT(7) }, /* schmitt trigger */ - { 0x0005, PWR_CMD_WRITE, BIT(3) | BIT(4), BIT(3) }, /* enable WL suspend */ - { 0x0007, PWR_CMD_WRITE, 0xFF, 0 }, /* enable bandgap mbias in suspend */ - { 0x0041, PWR_CMD_WRITE, BIT(4), 0 }, /* Clear SIC_EN register */ - { 0xfe10, PWR_CMD_WRITE, BIT(4), BIT(4) }, /* Set USB suspend enable local register */ -}; - -/* This is used by driver for LPSRadioOff Procedure, not for FW LPS Step */ -static struct wl_pwr_cfg rtl8188E_enter_lps_flow[] = { - { 0x0522, PWR_CMD_WRITE, 0xFF, 0x7F },/* Tx Pause */ - { 0x05F8, PWR_CMD_POLLING, 0xFF, 0 }, /* Should be zero if no packet is transmitted */ - { 0x05F9, PWR_CMD_POLLING, 0xFF, 0 }, /* Should be zero if no packet is transmitted */ - { 0x05FA, PWR_CMD_POLLING, 0xFF, 0 }, /* Should be zero if no packet is transmitted */ - { 0x05FB, PWR_CMD_POLLING, 0xFF, 0 }, /* Should be zero if no packet is transmitted */ - { 0x0002, PWR_CMD_WRITE, BIT(0), 0 }, /* CCK and OFDM are disabled, clocks are gated */ - { 0x0002, PWR_CMD_DELAY, 0, 0 }, - { 0x0100, PWR_CMD_WRITE, 0xFF, 0x3F }, /* Reset MAC TRX */ - { 0x0101, PWR_CMD_WRITE, BIT(1), 0 }, /* check if removed later */ - { 0x0553, PWR_CMD_WRITE, BIT(5), BIT(5) }, /* Respond TxOK to scheduler */ -}; - -u8 HalPwrSeqCmdParsing(struct adapter *padapter, enum r8188eu_pwr_seq seq) -{ - struct wl_pwr_cfg pwrcfgcmd = {0}; - struct wl_pwr_cfg *pwrseqcmd; - u8 poll_bit = false; - u8 idx, num_steps; - u8 value = 0; - u32 offset = 0; - u32 poll_count = 0; /* polling autoload done. */ - u32 max_poll_count = 5000; - int res; - - switch (seq) { - case PWR_ON_FLOW: - pwrseqcmd = rtl8188E_power_on_flow; - num_steps = ARRAY_SIZE(rtl8188E_power_on_flow); - break; - case DISABLE_FLOW: - pwrseqcmd = rtl8188E_card_disable_flow; - num_steps = ARRAY_SIZE(rtl8188E_card_disable_flow); - break; - case LPS_ENTER_FLOW: - pwrseqcmd = rtl8188E_enter_lps_flow; - num_steps = ARRAY_SIZE(rtl8188E_enter_lps_flow); - break; - default: - return false; - } - - for (idx = 0; idx < num_steps; idx++) { - pwrcfgcmd = pwrseqcmd[idx]; - - switch (GET_PWR_CFG_CMD(pwrcfgcmd)) { - case PWR_CMD_WRITE: - offset = GET_PWR_CFG_OFFSET(pwrcfgcmd); - - /* Read the value from system register */ - res = rtw_read8(padapter, offset, &value); - if (res) - return false; - - value &= ~(GET_PWR_CFG_MASK(pwrcfgcmd)); - value |= (GET_PWR_CFG_VALUE(pwrcfgcmd) & GET_PWR_CFG_MASK(pwrcfgcmd)); - - /* Write the value back to system register */ - rtw_write8(padapter, offset, value); - break; - case PWR_CMD_POLLING: - poll_bit = false; - offset = GET_PWR_CFG_OFFSET(pwrcfgcmd); - do { - res = rtw_read8(padapter, offset, &value); - if (res) - return false; - - value &= GET_PWR_CFG_MASK(pwrcfgcmd); - if (value == (GET_PWR_CFG_VALUE(pwrcfgcmd) & GET_PWR_CFG_MASK(pwrcfgcmd))) - poll_bit = true; - else - udelay(10); - - if (poll_count++ > max_poll_count) - return false; - } while (!poll_bit); - break; - case PWR_CMD_DELAY: - udelay(GET_PWR_CFG_OFFSET(pwrcfgcmd)); - break; - default: - break; - } - } - return true; -} diff --git a/drivers/staging/r8188eu/hal/hal_com.c b/drivers/staging/r8188eu/hal/hal_com.c deleted file mode 100644 index 33967eb3c0d0..000000000000 --- a/drivers/staging/r8188eu/hal/hal_com.c +++ /dev/null @@ -1,139 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#include "../include/osdep_service.h" -#include "../include/drv_types.h" - -#include "../include/hal_intf.h" -#include "../include/hal_com.h" -#include "../include/rtl8188e_hal.h" - -#define _HAL_INIT_C_ - -#define CHAN_PLAN_HW 0x80 - -u8 /* return the final channel plan decision */ -hal_com_get_channel_plan(struct adapter *padapter, u8 hw_channel_plan, - u8 sw_channel_plan, u8 def_channel_plan, - bool load_fail) -{ - u8 sw_cfg; - u8 chnlplan; - - sw_cfg = true; - if (!load_fail) { - if (!rtw_is_channel_plan_valid(sw_channel_plan)) - sw_cfg = false; - if (hw_channel_plan & CHAN_PLAN_HW) - sw_cfg = false; - } - - if (sw_cfg) - chnlplan = sw_channel_plan; - else - chnlplan = hw_channel_plan & (~CHAN_PLAN_HW); - - if (!rtw_is_channel_plan_valid(chnlplan)) - chnlplan = def_channel_plan; - - return chnlplan; -} - -u8 MRateToHwRate(u8 rate) -{ - u8 ret = DESC_RATE1M; - - switch (rate) { - /* CCK and OFDM non-HT rates */ - case IEEE80211_CCK_RATE_1MB: - ret = DESC_RATE1M; - break; - case IEEE80211_CCK_RATE_2MB: - ret = DESC_RATE2M; - break; - case IEEE80211_CCK_RATE_5MB: - ret = DESC_RATE5_5M; - break; - case IEEE80211_CCK_RATE_11MB: - ret = DESC_RATE11M; - break; - case IEEE80211_OFDM_RATE_6MB: - ret = DESC_RATE6M; - break; - case IEEE80211_OFDM_RATE_9MB: - ret = DESC_RATE9M; - break; - case IEEE80211_OFDM_RATE_12MB: - ret = DESC_RATE12M; - break; - case IEEE80211_OFDM_RATE_18MB: - ret = DESC_RATE18M; - break; - case IEEE80211_OFDM_RATE_24MB: - ret = DESC_RATE24M; - break; - case IEEE80211_OFDM_RATE_36MB: - ret = DESC_RATE36M; - break; - case IEEE80211_OFDM_RATE_48MB: - ret = DESC_RATE48M; - break; - case IEEE80211_OFDM_RATE_54MB: - ret = DESC_RATE54M; - break; - default: - break; - } - return ret; -} - -void HalSetBrateCfg(struct adapter *adapt, u8 *brates, u16 *rate_cfg) -{ - u8 i, is_brate, brate; - - for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) { - is_brate = brates[i] & IEEE80211_BASIC_RATE_MASK; - brate = brates[i] & 0x7f; - - if (is_brate) { - switch (brate) { - case IEEE80211_CCK_RATE_1MB: - *rate_cfg |= RATE_1M; - break; - case IEEE80211_CCK_RATE_2MB: - *rate_cfg |= RATE_2M; - break; - case IEEE80211_CCK_RATE_5MB: - *rate_cfg |= RATE_5_5M; - break; - case IEEE80211_CCK_RATE_11MB: - *rate_cfg |= RATE_11M; - break; - case IEEE80211_OFDM_RATE_6MB: - *rate_cfg |= RATE_6M; - break; - case IEEE80211_OFDM_RATE_9MB: - *rate_cfg |= RATE_9M; - break; - case IEEE80211_OFDM_RATE_12MB: - *rate_cfg |= RATE_12M; - break; - case IEEE80211_OFDM_RATE_18MB: - *rate_cfg |= RATE_18M; - break; - case IEEE80211_OFDM_RATE_24MB: - *rate_cfg |= RATE_24M; - break; - case IEEE80211_OFDM_RATE_36MB: - *rate_cfg |= RATE_36M; - break; - case IEEE80211_OFDM_RATE_48MB: - *rate_cfg |= RATE_48M; - break; - case IEEE80211_OFDM_RATE_54MB: - *rate_cfg |= RATE_54M; - break; - } - } - } -} diff --git a/drivers/staging/r8188eu/hal/hal_intf.c b/drivers/staging/r8188eu/hal/hal_intf.c deleted file mode 100644 index 13790e32f11c..000000000000 --- a/drivers/staging/r8188eu/hal/hal_intf.c +++ /dev/null @@ -1,50 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2007 - 2012 Realtek Corporation. */ - -#define _HAL_INTF_C_ -#include "../include/osdep_service.h" -#include "../include/drv_types.h" -#include "../include/hal_intf.h" - -uint rtw_hal_init(struct adapter *adapt) -{ - adapt->hw_init_completed = false; - - if (rtl8188eu_hal_init(adapt) != _SUCCESS) - return _FAIL; - - adapt->hw_init_completed = true; - - if (adapt->registrypriv.notch_filter == 1) - hal_notch_filter_8188e(adapt, 1); - - return _SUCCESS; -} - -uint rtw_hal_deinit(struct adapter *adapt) -{ - uint status = _SUCCESS; - - status = rtl8188eu_hal_deinit(adapt); - - if (status == _SUCCESS) - adapt->hw_init_completed = false; - - return status; -} - -void rtw_hal_update_ra_mask(struct adapter *adapt, u32 mac_id, u8 rssi_level) -{ - struct mlme_priv *pmlmepriv = &adapt->mlmepriv; - - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - struct sta_info *psta = NULL; - struct sta_priv *pstapriv = &adapt->stapriv; - if (mac_id >= 2) - psta = pstapriv->sta_aid[(mac_id - 1) - 1]; - if (psta) - add_RATid(adapt, psta, 0);/* todo: based on rssi_level*/ - } else { - UpdateHalRAMask8188EUsb(adapt, mac_id, rssi_level); - } -} diff --git a/drivers/staging/r8188eu/hal/odm.c b/drivers/staging/r8188eu/hal/odm.c deleted file mode 100644 index 94f9b125d860..000000000000 --- a/drivers/staging/r8188eu/hal/odm.c +++ /dev/null @@ -1,821 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#include "../include/drv_types.h" - -/* avoid to warn in FreeBSD ==> To DO modify */ -static u32 EDCAParam[HT_IOT_PEER_MAX][3] = { - /* UL DL */ - {0x5ea42b, 0x5ea42b, 0x5ea42b}, /* 0:unknown AP */ - {0xa44f, 0x5ea44f, 0x5e431c}, /* 1:realtek AP */ - {0x5ea42b, 0x5ea42b, 0x5ea42b}, /* 2:unknown AP => realtek_92SE */ - {0x5ea32b, 0x5ea42b, 0x5e4322}, /* 3:broadcom AP */ - {0x5ea422, 0x00a44f, 0x00a44f}, /* 4:ralink AP */ - {0x5ea322, 0x00a630, 0x00a44f}, /* 5:atheros AP */ - {0x5e4322, 0x5e4322, 0x5e4322},/* 6:cisco AP */ - {0x5ea44f, 0x00a44f, 0x5ea42b}, /* 8:marvell AP */ - {0x5ea42b, 0x5ea42b, 0x5ea42b}, /* 10:unknown AP=> 92U AP */ - {0x5ea42b, 0xa630, 0x5e431c}, /* 11:airgocap AP */ -}; - -/* Global var */ -u32 OFDMSwingTable[OFDM_TABLE_SIZE_92D] = { - 0x7f8001fe, /* 0, +6.0dB */ - 0x788001e2, /* 1, +5.5dB */ - 0x71c001c7, /* 2, +5.0dB */ - 0x6b8001ae, /* 3, +4.5dB */ - 0x65400195, /* 4, +4.0dB */ - 0x5fc0017f, /* 5, +3.5dB */ - 0x5a400169, /* 6, +3.0dB */ - 0x55400155, /* 7, +2.5dB */ - 0x50800142, /* 8, +2.0dB */ - 0x4c000130, /* 9, +1.5dB */ - 0x47c0011f, /* 10, +1.0dB */ - 0x43c0010f, /* 11, +0.5dB */ - 0x40000100, /* 12, +0dB */ - 0x3c8000f2, /* 13, -0.5dB */ - 0x390000e4, /* 14, -1.0dB */ - 0x35c000d7, /* 15, -1.5dB */ - 0x32c000cb, /* 16, -2.0dB */ - 0x300000c0, /* 17, -2.5dB */ - 0x2d4000b5, /* 18, -3.0dB */ - 0x2ac000ab, /* 19, -3.5dB */ - 0x288000a2, /* 20, -4.0dB */ - 0x26000098, /* 21, -4.5dB */ - 0x24000090, /* 22, -5.0dB */ - 0x22000088, /* 23, -5.5dB */ - 0x20000080, /* 24, -6.0dB */ - 0x1e400079, /* 25, -6.5dB */ - 0x1c800072, /* 26, -7.0dB */ - 0x1b00006c, /* 27. -7.5dB */ - 0x19800066, /* 28, -8.0dB */ - 0x18000060, /* 29, -8.5dB */ - 0x16c0005b, /* 30, -9.0dB */ - 0x15800056, /* 31, -9.5dB */ - 0x14400051, /* 32, -10.0dB */ - 0x1300004c, /* 33, -10.5dB */ - 0x12000048, /* 34, -11.0dB */ - 0x11000044, /* 35, -11.5dB */ - 0x10000040, /* 36, -12.0dB */ - 0x0f00003c,/* 37, -12.5dB */ - 0x0e400039,/* 38, -13.0dB */ - 0x0d800036,/* 39, -13.5dB */ - 0x0cc00033,/* 40, -14.0dB */ - 0x0c000030,/* 41, -14.5dB */ - 0x0b40002d,/* 42, -15.0dB */ -}; - -u8 cck_swing_table[CCK_TABLE_SIZE][8] = { - {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04}, /* 0, +0dB */ - {0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04}, /* 1, -0.5dB */ - {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, /* 2, -1.0dB */ - {0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03}, /* 3, -1.5dB */ - {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, /* 4, -2.0dB */ - {0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03}, /* 5, -2.5dB */ - {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, /* 6, -3.0dB */ - {0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03}, /* 7, -3.5dB */ - {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, /* 8, -4.0dB */ - {0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02}, /* 9, -4.5dB */ - {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, /* 10, -5.0dB */ - {0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02}, /* 11, -5.5dB */ - {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, /* 12, -6.0dB */ - {0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02}, /* 13, -6.5dB */ - {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, /* 14, -7.0dB */ - {0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02}, /* 15, -7.5dB */ - {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, /* 16, -8.0dB */ - {0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02}, /* 17, -8.5dB */ - {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, /* 18, -9.0dB */ - {0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 19, -9.5dB */ - {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 20, -10.0dB */ - {0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 21, -10.5dB */ - {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 22, -11.0dB */ - {0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01}, /* 23, -11.5dB */ - {0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01}, /* 24, -12.0dB */ - {0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01}, /* 25, -12.5dB */ - {0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01}, /* 26, -13.0dB */ - {0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 27, -13.5dB */ - {0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 28, -14.0dB */ - {0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 29, -14.5dB */ - {0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 30, -15.0dB */ - {0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01}, /* 31, -15.5dB */ - {0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01} /* 32, -16.0dB */ -}; - -#define RxDefaultAnt1 0x65a9 -#define RxDefaultAnt2 0x569a - -static void odm_DIGInit(struct odm_dm_struct *pDM_Odm) -{ - struct rtw_dig *pDM_DigTable = &pDM_Odm->DM_DigTable; - struct adapter *adapter = pDM_Odm->Adapter; - - pDM_DigTable->CurIGValue = (u8)rtl8188e_PHY_QueryBBReg(adapter, ODM_REG_IGI_A_11N, ODM_BIT_IGI_11N); - pDM_DigTable->rx_gain_range_max = DM_DIG_MAX_NIC; - pDM_DigTable->rx_gain_range_min = DM_DIG_MIN_NIC; - pDM_DigTable->CurCCK_CCAThres = 0x83; - pDM_DigTable->ForbiddenIGI = DM_DIG_MIN_NIC; - pDM_DigTable->LargeFAHit = 0; - pDM_DigTable->Recover_cnt = 0; - pDM_DigTable->DIG_Dynamic_MIN_0 = DM_DIG_MIN_NIC; - pDM_DigTable->bMediaConnect_0 = false; - - /* To Initialize pDM_Odm->bDMInitialGainEnable == false to avoid DIG error */ - pDM_Odm->bDMInitialGainEnable = true; -} - -static void odm_DIG(struct odm_dm_struct *pDM_Odm) -{ - struct rtw_dig *pDM_DigTable = &pDM_Odm->DM_DigTable; - struct false_alarm_stats *pFalseAlmCnt = &pDM_Odm->FalseAlmCnt; - u8 DIG_Dynamic_MIN; - u8 DIG_MaxOfMin; - bool FirstConnect, FirstDisConnect; - u8 dm_dig_max, dm_dig_min; - u8 CurrentIGI = pDM_DigTable->CurIGValue; - - if (*pDM_Odm->pbScanInProcess) - return; - - /* add by Neil Chen to avoid PSD is processing */ - if (!pDM_Odm->bDMInitialGainEnable) - return; - - DIG_Dynamic_MIN = pDM_DigTable->DIG_Dynamic_MIN_0; - FirstConnect = (pDM_Odm->bLinked) && (!pDM_DigTable->bMediaConnect_0); - FirstDisConnect = (!pDM_Odm->bLinked) && (pDM_DigTable->bMediaConnect_0); - - /* 1 Boundary Decision */ - dm_dig_max = DM_DIG_MAX_NIC; - dm_dig_min = DM_DIG_MIN_NIC; - DIG_MaxOfMin = DM_DIG_MAX_AP; - - if (pDM_Odm->bLinked) { - /* 2 8723A Series, offset need to be 10 */ - /* 2 Modify DIG upper bound */ - if ((pDM_Odm->RSSI_Min + 20) > dm_dig_max) - pDM_DigTable->rx_gain_range_max = dm_dig_max; - else if ((pDM_Odm->RSSI_Min + 20) < dm_dig_min) - pDM_DigTable->rx_gain_range_max = dm_dig_min; - else - pDM_DigTable->rx_gain_range_max = pDM_Odm->RSSI_Min + 20; - /* 2 Modify DIG lower bound */ - if (pDM_Odm->bOneEntryOnly) { - if (pDM_Odm->RSSI_Min < dm_dig_min) - DIG_Dynamic_MIN = dm_dig_min; - else if (pDM_Odm->RSSI_Min > DIG_MaxOfMin) - DIG_Dynamic_MIN = DIG_MaxOfMin; - else - DIG_Dynamic_MIN = pDM_Odm->RSSI_Min; - } else if (pDM_Odm->SupportAbility & ODM_BB_ANT_DIV) { - /* 1 Lower Bound for 88E AntDiv */ - if (pDM_Odm->AntDivType == CG_TRX_HW_ANTDIV) - DIG_Dynamic_MIN = (u8)pDM_DigTable->AntDiv_RSSI_max; - } else { - DIG_Dynamic_MIN = dm_dig_min; - } - } else { - pDM_DigTable->rx_gain_range_max = dm_dig_max; - DIG_Dynamic_MIN = dm_dig_min; - } - - /* 1 Modify DIG lower bound, deal with abnormally large false alarm */ - if (pFalseAlmCnt->Cnt_all > 10000) { - if (pDM_DigTable->LargeFAHit != 3) - pDM_DigTable->LargeFAHit++; - if (pDM_DigTable->ForbiddenIGI < CurrentIGI) { - pDM_DigTable->ForbiddenIGI = CurrentIGI; - pDM_DigTable->LargeFAHit = 1; - } - - if (pDM_DigTable->LargeFAHit >= 3) { - if ((pDM_DigTable->ForbiddenIGI + 1) > pDM_DigTable->rx_gain_range_max) - pDM_DigTable->rx_gain_range_min = pDM_DigTable->rx_gain_range_max; - else - pDM_DigTable->rx_gain_range_min = (pDM_DigTable->ForbiddenIGI + 1); - pDM_DigTable->Recover_cnt = 3600; /* 3600=2hr */ - } - - } else { - /* Recovery mechanism for IGI lower bound */ - if (pDM_DigTable->Recover_cnt != 0) { - pDM_DigTable->Recover_cnt--; - } else { - if (pDM_DigTable->LargeFAHit < 3) { - if ((pDM_DigTable->ForbiddenIGI - 1) < DIG_Dynamic_MIN) { /* DM_DIG_MIN) */ - pDM_DigTable->ForbiddenIGI = DIG_Dynamic_MIN; /* DM_DIG_MIN; */ - pDM_DigTable->rx_gain_range_min = DIG_Dynamic_MIN; /* DM_DIG_MIN; */ - } else { - pDM_DigTable->ForbiddenIGI--; - pDM_DigTable->rx_gain_range_min = (pDM_DigTable->ForbiddenIGI + 1); - } - } else { - pDM_DigTable->LargeFAHit = 0; - } - } - } - - /* 1 Adjust initial gain by false alarm */ - if (pDM_Odm->bLinked) { - if (FirstConnect) { - CurrentIGI = pDM_Odm->RSSI_Min; - } else { - if (pFalseAlmCnt->Cnt_all > DM_DIG_FA_TH2) - CurrentIGI = CurrentIGI + 4;/* pDM_DigTable->CurIGValue = pDM_DigTable->PreIGValue+2; */ - else if (pFalseAlmCnt->Cnt_all > DM_DIG_FA_TH1) - CurrentIGI = CurrentIGI + 2;/* pDM_DigTable->CurIGValue = pDM_DigTable->PreIGValue+1; */ - else if (pFalseAlmCnt->Cnt_all < DM_DIG_FA_TH0) - CurrentIGI = CurrentIGI - 2;/* pDM_DigTable->CurIGValue =pDM_DigTable->PreIGValue-1; */ - } - } else { - if (FirstDisConnect) { - CurrentIGI = pDM_DigTable->rx_gain_range_min; - } else { - /* 2012.03.30 LukeLee: enable DIG before link but with very high thresholds */ - if (pFalseAlmCnt->Cnt_all > 10000) - CurrentIGI = CurrentIGI + 2;/* pDM_DigTable->CurIGValue = pDM_DigTable->PreIGValue+2; */ - else if (pFalseAlmCnt->Cnt_all > 8000) - CurrentIGI = CurrentIGI + 1;/* pDM_DigTable->CurIGValue = pDM_DigTable->PreIGValue+1; */ - else if (pFalseAlmCnt->Cnt_all < 500) - CurrentIGI = CurrentIGI - 1;/* pDM_DigTable->CurIGValue =pDM_DigTable->PreIGValue-1; */ - } - } - /* 1 Check initial gain by upper/lower bound */ - if (CurrentIGI > pDM_DigTable->rx_gain_range_max) - CurrentIGI = pDM_DigTable->rx_gain_range_max; - if (CurrentIGI < pDM_DigTable->rx_gain_range_min) - CurrentIGI = pDM_DigTable->rx_gain_range_min; - - /* 2 High power RSSI threshold */ - - ODM_Write_DIG(pDM_Odm, CurrentIGI);/* ODM_Write_DIG(pDM_Odm, pDM_DigTable->CurIGValue); */ - pDM_DigTable->bMediaConnect_0 = pDM_Odm->bLinked; - pDM_DigTable->DIG_Dynamic_MIN_0 = DIG_Dynamic_MIN; -} - -static void odm_CommonInfoSelfInit(struct odm_dm_struct *pDM_Odm) -{ - struct adapter *adapter = pDM_Odm->Adapter; - - pDM_Odm->bCckHighPower = (bool)rtl8188e_PHY_QueryBBReg(adapter, 0x824, BIT(9)); - pDM_Odm->RFPathRxEnable = (u8)rtl8188e_PHY_QueryBBReg(adapter, 0xc04, 0x0F); -} - -static void odm_CommonInfoSelfUpdate(struct odm_dm_struct *pDM_Odm) -{ - u8 EntryCnt = 0; - u8 i; - struct sta_info *pEntry; - - if (*pDM_Odm->pBandWidth == HT_CHANNEL_WIDTH_40) { - if (*pDM_Odm->pSecChOffset == 1) - pDM_Odm->ControlChannel = *pDM_Odm->pChannel - 2; - else if (*pDM_Odm->pSecChOffset == 2) - pDM_Odm->ControlChannel = *pDM_Odm->pChannel + 2; - } else { - pDM_Odm->ControlChannel = *pDM_Odm->pChannel; - } - - for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) { - pEntry = pDM_Odm->pODM_StaInfo[i]; - if (IS_STA_VALID(pEntry)) - EntryCnt++; - } - if (EntryCnt == 1) - pDM_Odm->bOneEntryOnly = true; - else - pDM_Odm->bOneEntryOnly = false; -} - -static void odm_RateAdaptiveMaskInit(struct odm_dm_struct *pDM_Odm) -{ - struct odm_rate_adapt *pOdmRA = &pDM_Odm->RateAdaptive; - - pOdmRA->RATRState = DM_RATR_STA_INIT; - pOdmRA->HighRSSIThresh = 50; - pOdmRA->LowRSSIThresh = 20; -} - -static void odm_RefreshRateAdaptiveMask(struct odm_dm_struct *pDM_Odm) -{ - u8 i; - struct adapter *pAdapter = pDM_Odm->Adapter; - - if (pAdapter->bDriverStopped) - return; - - for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) { - struct sta_info *pstat = pDM_Odm->pODM_StaInfo[i]; - - if (IS_STA_VALID(pstat)) { - if (ODM_RAStateCheck(pDM_Odm, pstat->rssi_stat.UndecoratedSmoothedPWDB, false, &pstat->rssi_level)) - rtw_hal_update_ra_mask(pAdapter, i, pstat->rssi_level); - } - } -} - -static void odm_DynamicBBPowerSavingInit(struct odm_dm_struct *pDM_Odm) -{ - struct rtl_ps *pDM_PSTable = &pDM_Odm->DM_PSTable; - - pDM_PSTable->pre_rf_state = RF_MAX; - pDM_PSTable->cur_rf_state = RF_MAX; - pDM_PSTable->initialize = 0; -} - -static void odm_FalseAlarmCounterStatistics(struct odm_dm_struct *pDM_Odm) -{ - u32 ret_value; - struct false_alarm_stats *FalseAlmCnt = &pDM_Odm->FalseAlmCnt; - struct adapter *adapter = pDM_Odm->Adapter; - - /* hold ofdm counter */ - rtl8188e_PHY_SetBBReg(adapter, ODM_REG_OFDM_FA_HOLDC_11N, BIT(31), 1); /* hold page C counter */ - rtl8188e_PHY_SetBBReg(adapter, ODM_REG_OFDM_FA_RSTD_11N, BIT(31), 1); /* hold page D counter */ - - ret_value = rtl8188e_PHY_QueryBBReg(adapter, ODM_REG_OFDM_FA_TYPE1_11N, bMaskDWord); - FalseAlmCnt->Cnt_Fast_Fsync = (ret_value & 0xffff); - FalseAlmCnt->Cnt_SB_Search_fail = ((ret_value & 0xffff0000) >> 16); - ret_value = rtl8188e_PHY_QueryBBReg(adapter, ODM_REG_OFDM_FA_TYPE2_11N, bMaskDWord); - FalseAlmCnt->Cnt_OFDM_CCA = (ret_value & 0xffff); - FalseAlmCnt->Cnt_Parity_Fail = ((ret_value & 0xffff0000) >> 16); - ret_value = rtl8188e_PHY_QueryBBReg(adapter, ODM_REG_OFDM_FA_TYPE3_11N, bMaskDWord); - FalseAlmCnt->Cnt_Rate_Illegal = (ret_value & 0xffff); - FalseAlmCnt->Cnt_Crc8_fail = ((ret_value & 0xffff0000) >> 16); - ret_value = rtl8188e_PHY_QueryBBReg(adapter, ODM_REG_OFDM_FA_TYPE4_11N, bMaskDWord); - FalseAlmCnt->Cnt_Mcs_fail = (ret_value & 0xffff); - - FalseAlmCnt->Cnt_Ofdm_fail = FalseAlmCnt->Cnt_Parity_Fail + FalseAlmCnt->Cnt_Rate_Illegal + - FalseAlmCnt->Cnt_Crc8_fail + FalseAlmCnt->Cnt_Mcs_fail + - FalseAlmCnt->Cnt_Fast_Fsync + FalseAlmCnt->Cnt_SB_Search_fail; - - ret_value = rtl8188e_PHY_QueryBBReg(adapter, ODM_REG_SC_CNT_11N, bMaskDWord); - FalseAlmCnt->Cnt_BW_LSC = (ret_value & 0xffff); - FalseAlmCnt->Cnt_BW_USC = ((ret_value & 0xffff0000) >> 16); - - /* hold cck counter */ - rtl8188e_PHY_SetBBReg(adapter, ODM_REG_CCK_FA_RST_11N, BIT(12), 1); - rtl8188e_PHY_SetBBReg(adapter, ODM_REG_CCK_FA_RST_11N, BIT(14), 1); - - ret_value = rtl8188e_PHY_QueryBBReg(adapter, ODM_REG_CCK_FA_LSB_11N, bMaskByte0); - FalseAlmCnt->Cnt_Cck_fail = ret_value; - ret_value = rtl8188e_PHY_QueryBBReg(adapter, ODM_REG_CCK_FA_MSB_11N, bMaskByte3); - FalseAlmCnt->Cnt_Cck_fail += (ret_value & 0xff) << 8; - - ret_value = rtl8188e_PHY_QueryBBReg(adapter, ODM_REG_CCK_CCA_CNT_11N, bMaskDWord); - FalseAlmCnt->Cnt_CCK_CCA = ((ret_value & 0xFF) << 8) | ((ret_value & 0xFF00) >> 8); - - FalseAlmCnt->Cnt_all = (FalseAlmCnt->Cnt_Fast_Fsync + - FalseAlmCnt->Cnt_SB_Search_fail + - FalseAlmCnt->Cnt_Parity_Fail + - FalseAlmCnt->Cnt_Rate_Illegal + - FalseAlmCnt->Cnt_Crc8_fail + - FalseAlmCnt->Cnt_Mcs_fail + - FalseAlmCnt->Cnt_Cck_fail); - - FalseAlmCnt->Cnt_CCA_all = FalseAlmCnt->Cnt_OFDM_CCA + FalseAlmCnt->Cnt_CCK_CCA; -} - -static void odm_CCKPacketDetectionThresh(struct odm_dm_struct *pDM_Odm) -{ - u8 CurCCK_CCAThres; - struct false_alarm_stats *FalseAlmCnt = &pDM_Odm->FalseAlmCnt; - - if (pDM_Odm->bLinked) { - if (pDM_Odm->RSSI_Min > 25) { - CurCCK_CCAThres = 0xcd; - } else if ((pDM_Odm->RSSI_Min <= 25) && (pDM_Odm->RSSI_Min > 10)) { - CurCCK_CCAThres = 0x83; - } else { - if (FalseAlmCnt->Cnt_Cck_fail > 1000) - CurCCK_CCAThres = 0x83; - else - CurCCK_CCAThres = 0x40; - } - } else { - if (FalseAlmCnt->Cnt_Cck_fail > 1000) - CurCCK_CCAThres = 0x83; - else - CurCCK_CCAThres = 0x40; - } - ODM_Write_CCK_CCA_Thres(pDM_Odm, CurCCK_CCAThres); -} - -static void FindMinimumRSSI(struct adapter *pAdapter) -{ - struct hal_data_8188e *pHalData = &pAdapter->haldata; - struct dm_priv *pdmpriv = &pHalData->dmpriv; - struct mlme_priv *pmlmepriv = &pAdapter->mlmepriv; - - /* 1 1.Determine the minimum RSSI */ - if (!check_fwstate(pmlmepriv, _FW_LINKED) && - pdmpriv->EntryMinUndecoratedSmoothedPWDB == 0) - pdmpriv->MinUndecoratedPWDBForDM = 0; - - pdmpriv->MinUndecoratedPWDBForDM = pdmpriv->EntryMinUndecoratedSmoothedPWDB; -} - -static void odm_RSSIMonitorCheck(struct odm_dm_struct *pDM_Odm) -{ - struct adapter *Adapter = pDM_Odm->Adapter; - struct hal_data_8188e *pHalData = &Adapter->haldata; - struct dm_priv *pdmpriv = &pHalData->dmpriv; - int i; - int tmpEntryMaxPWDB = 0, tmpEntryMinPWDB = 0xff; - u8 sta_cnt = 0; - u32 PWDB_rssi[NUM_STA] = {0};/* 0~15]:MACID, [16~31]:PWDB_rssi */ - struct sta_info *psta; - - if (!(pDM_Odm->SupportAbility & ODM_BB_RSSI_MONITOR)) - return; - - if (!check_fwstate(&Adapter->mlmepriv, _FW_LINKED)) - return; - - for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) { - psta = pDM_Odm->pODM_StaInfo[i]; - if (IS_STA_VALID(psta) && - (psta->state & WIFI_ASOC_STATE) && - !is_broadcast_ether_addr(psta->hwaddr) && - memcmp(psta->hwaddr, myid(&Adapter->eeprompriv), ETH_ALEN)) { - if (psta->rssi_stat.UndecoratedSmoothedPWDB < tmpEntryMinPWDB) - tmpEntryMinPWDB = psta->rssi_stat.UndecoratedSmoothedPWDB; - - if (psta->rssi_stat.UndecoratedSmoothedPWDB > tmpEntryMaxPWDB) - tmpEntryMaxPWDB = psta->rssi_stat.UndecoratedSmoothedPWDB; - if (psta->rssi_stat.UndecoratedSmoothedPWDB != (-1)) - PWDB_rssi[sta_cnt++] = (psta->mac_id | (psta->rssi_stat.UndecoratedSmoothedPWDB << 16)); - } - } - - for (i = 0; i < sta_cnt; i++) { - if (PWDB_rssi[i] != (0)) { - if (pHalData->fw_ractrl) { - /* Report every sta's RSSI to FW */ - } else { - ODM_RA_SetRSSI_8188E( - &pHalData->odmpriv, (PWDB_rssi[i] & 0xFF), (u8)((PWDB_rssi[i] >> 16) & 0xFF)); - } - } - } - - if (tmpEntryMinPWDB != 0xff) /* If associated entry is found */ - pdmpriv->EntryMinUndecoratedSmoothedPWDB = tmpEntryMinPWDB; - else - pdmpriv->EntryMinUndecoratedSmoothedPWDB = 0; - - FindMinimumRSSI(Adapter); - pHalData->odmpriv.RSSI_Min = pdmpriv->MinUndecoratedPWDBForDM; -} - -static void odm_TXPowerTrackingThermalMeterInit(struct odm_dm_struct *pDM_Odm) -{ - pDM_Odm->RFCalibrateInfo.TxPowerTrackControl = true; -} - -static void odm_InitHybridAntDiv(struct odm_dm_struct *pDM_Odm) -{ - if (!(pDM_Odm->SupportAbility & ODM_BB_ANT_DIV)) - return; - - ODM_AntennaDiversityInit_88E(pDM_Odm); -} - -static void odm_HwAntDiv(struct odm_dm_struct *pDM_Odm) -{ - if (!(pDM_Odm->SupportAbility & ODM_BB_ANT_DIV)) - return; - - ODM_AntennaDiversity_88E(pDM_Odm); -} - -static void ODM_EdcaTurboInit(struct odm_dm_struct *pDM_Odm) -{ - struct adapter *Adapter = pDM_Odm->Adapter; - pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA = false; - pDM_Odm->DM_EDCA_Table.bIsCurRDLState = false; - Adapter->recvpriv.bIsAnyNonBEPkts = false; -} - -static void odm_EdcaTurboCheck(struct odm_dm_struct *pDM_Odm) -{ - struct adapter *Adapter = pDM_Odm->Adapter; - u32 trafficIndex; - u32 edca_param; - u64 cur_tx_bytes = 0; - u64 cur_rx_bytes = 0; - u8 bbtchange = false; - struct hal_data_8188e *pHalData = &Adapter->haldata; - struct xmit_priv *pxmitpriv = &Adapter->xmitpriv; - struct recv_priv *precvpriv = &Adapter->recvpriv; - struct registry_priv *pregpriv = &Adapter->registrypriv; - struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - if (pregpriv->wifi_spec == 1) - goto dm_CheckEdcaTurbo_EXIT; - - if (pmlmeinfo->assoc_AP_vendor >= HT_IOT_PEER_MAX) - goto dm_CheckEdcaTurbo_EXIT; - - /* Check if the status needs to be changed. */ - if ((bbtchange) || (!precvpriv->bIsAnyNonBEPkts)) { - cur_tx_bytes = pxmitpriv->tx_bytes - pxmitpriv->last_tx_bytes; - cur_rx_bytes = precvpriv->rx_bytes - precvpriv->last_rx_bytes; - - /* traffic, TX or RX */ - if ((pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_RALINK) || - (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_ATHEROS)) { - if (cur_tx_bytes > (cur_rx_bytes << 2)) { - /* Uplink TP is present. */ - trafficIndex = UP_LINK; - } else { - /* Balance TP is present. */ - trafficIndex = DOWN_LINK; - } - } else { - if (cur_rx_bytes > (cur_tx_bytes << 2)) { - /* Downlink TP is present. */ - trafficIndex = DOWN_LINK; - } else { - /* Balance TP is present. */ - trafficIndex = UP_LINK; - } - } - - if ((pDM_Odm->DM_EDCA_Table.prv_traffic_idx != trafficIndex) || (!pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA)) { - if ((pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_CISCO) && (pmlmeext->cur_wireless_mode & WIRELESS_11_24N)) - edca_param = EDCAParam[pmlmeinfo->assoc_AP_vendor][trafficIndex]; - else - edca_param = EDCAParam[HT_IOT_PEER_UNKNOWN][trafficIndex]; - - rtw_write32(Adapter, REG_EDCA_BE_PARAM, edca_param); - - pDM_Odm->DM_EDCA_Table.prv_traffic_idx = trafficIndex; - } - - pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA = true; - } else { - /* Turn Off EDCA turbo here. */ - /* Restore original EDCA according to the declaration of AP. */ - if (pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA) { - rtw_write32(Adapter, REG_EDCA_BE_PARAM, pHalData->AcParam_BE); - pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA = false; - } - } - -dm_CheckEdcaTurbo_EXIT: - /* Set variables for next time. */ - precvpriv->bIsAnyNonBEPkts = false; - pxmitpriv->last_tx_bytes = pxmitpriv->tx_bytes; - precvpriv->last_rx_bytes = precvpriv->rx_bytes; -} - -/* 2011/09/21 MH Add to describe different team necessary resource allocate?? */ -void ODM_DMInit(struct odm_dm_struct *pDM_Odm) -{ - /* 2012.05.03 Luke: For all IC series */ - odm_CommonInfoSelfInit(pDM_Odm); - odm_DIGInit(pDM_Odm); - odm_RateAdaptiveMaskInit(pDM_Odm); - - odm_DynamicBBPowerSavingInit(pDM_Odm); - odm_TXPowerTrackingThermalMeterInit(pDM_Odm); - ODM_EdcaTurboInit(pDM_Odm); - ODM_RAInfo_Init_all(pDM_Odm); - if ((pDM_Odm->AntDivType == CG_TRX_HW_ANTDIV) || - (pDM_Odm->AntDivType == CGCS_RX_HW_ANTDIV) || - (pDM_Odm->AntDivType == CG_TRX_SMART_ANTDIV)) - odm_InitHybridAntDiv(pDM_Odm); -} - -/* 2011/09/20 MH This is the entry pointer for all team to execute HW out source DM. */ -/* You can not add any dummy function here, be care, you can only use DM structure */ -/* to perform any new ODM_DM. */ -void ODM_DMWatchdog(struct odm_dm_struct *pDM_Odm) -{ - /* 2012.05.03 Luke: For all IC series */ - odm_CommonInfoSelfUpdate(pDM_Odm); - odm_FalseAlarmCounterStatistics(pDM_Odm); - odm_RSSIMonitorCheck(pDM_Odm); - - odm_DIG(pDM_Odm); - odm_CCKPacketDetectionThresh(pDM_Odm); - - if (*pDM_Odm->pbPowerSaving) - return; - - odm_RefreshRateAdaptiveMask(pDM_Odm); - - if ((pDM_Odm->AntDivType == CG_TRX_HW_ANTDIV) || - (pDM_Odm->AntDivType == CGCS_RX_HW_ANTDIV) || - (pDM_Odm->AntDivType == CG_TRX_SMART_ANTDIV)) - odm_HwAntDiv(pDM_Odm); - - ODM_TXPowerTrackingCheck(pDM_Odm); - odm_EdcaTurboCheck(pDM_Odm); -} - -/* Init /.. Fixed HW value. Only init time. */ -void ODM_CmnInfoInit(struct odm_dm_struct *pDM_Odm, enum odm_common_info_def CmnInfo, u32 Value) -{ - /* This section is used for init value */ - switch (CmnInfo) { - /* Fixed ODM value. */ - case ODM_CMNINFO_MP_TEST_CHIP: - pDM_Odm->bIsMPChip = (u8)Value; - break; - case ODM_CMNINFO_RF_ANTENNA_TYPE: - pDM_Odm->AntDivType = (u8)Value; - break; - default: - /* do nothing */ - break; - } - - /* Tx power tracking BB swing table. */ - /* The base index = 12. +((12-n)/2)dB 13~?? = decrease tx pwr by -((n-12)/2)dB */ - pDM_Odm->BbSwingIdxOfdm = 12; /* Set defalut value as index 12. */ - pDM_Odm->BbSwingIdxOfdmCurrent = 12; - pDM_Odm->BbSwingFlagOfdm = false; -} - -void ODM_Write_DIG(struct odm_dm_struct *pDM_Odm, u8 CurrentIGI) -{ - struct rtw_dig *pDM_DigTable = &pDM_Odm->DM_DigTable; - struct adapter *adapter = pDM_Odm->Adapter; - - if (pDM_DigTable->CurIGValue != CurrentIGI) { - rtl8188e_PHY_SetBBReg(adapter, ODM_REG_IGI_A_11N, ODM_BIT_IGI_11N, CurrentIGI); - pDM_DigTable->CurIGValue = CurrentIGI; - } -} - -void ODM_Write_CCK_CCA_Thres(struct odm_dm_struct *pDM_Odm, u8 CurCCK_CCAThres) -{ - struct rtw_dig *pDM_DigTable = &pDM_Odm->DM_DigTable; - - if (pDM_DigTable->CurCCK_CCAThres != CurCCK_CCAThres) /* modify by Guo.Mingzhi 2012-01-03 */ - rtw_write8(pDM_Odm->Adapter, ODM_REG_CCK_CCA_11N, CurCCK_CCAThres); - pDM_DigTable->CurCCK_CCAThres = CurCCK_CCAThres; -} - -void ODM_RF_Saving(struct odm_dm_struct *pDM_Odm, u8 bForceInNormal) -{ - struct rtl_ps *pDM_PSTable = &pDM_Odm->DM_PSTable; - struct adapter *adapter = pDM_Odm->Adapter; - u8 Rssi_Up_bound = 30; - u8 Rssi_Low_bound = 25; - - if (pDM_PSTable->initialize == 0) { - pDM_PSTable->reg_874 = (rtl8188e_PHY_QueryBBReg(adapter, 0x874, bMaskDWord) & 0x1CC000) >> 14; - pDM_PSTable->reg_c70 = (rtl8188e_PHY_QueryBBReg(adapter, 0xc70, bMaskDWord) & BIT(3)) >> 3; - pDM_PSTable->reg_85c = (rtl8188e_PHY_QueryBBReg(adapter, 0x85c, bMaskDWord) & 0xFF000000) >> 24; - pDM_PSTable->reg_a74 = (rtl8188e_PHY_QueryBBReg(adapter, 0xa74, bMaskDWord) & 0xF000) >> 12; - pDM_PSTable->initialize = 1; - } - - if (!bForceInNormal) { - if (pDM_Odm->RSSI_Min != 0xFF) { - if (pDM_PSTable->pre_rf_state == RF_Normal) { - if (pDM_Odm->RSSI_Min >= Rssi_Up_bound) - pDM_PSTable->cur_rf_state = RF_Save; - else - pDM_PSTable->cur_rf_state = RF_Normal; - } else { - if (pDM_Odm->RSSI_Min <= Rssi_Low_bound) - pDM_PSTable->cur_rf_state = RF_Normal; - else - pDM_PSTable->cur_rf_state = RF_Save; - } - } else { - pDM_PSTable->cur_rf_state = RF_MAX; - } - } else { - pDM_PSTable->cur_rf_state = RF_Normal; - } - - if (pDM_PSTable->pre_rf_state != pDM_PSTable->cur_rf_state) { - if (pDM_PSTable->cur_rf_state == RF_Save) { - rtl8188e_PHY_SetBBReg(adapter, 0x874, 0x1C0000, 0x2); /* Reg874[20:18]=3'b010 */ - rtl8188e_PHY_SetBBReg(adapter, 0xc70, BIT(3), 0); /* RegC70[3]=1'b0 */ - rtl8188e_PHY_SetBBReg(adapter, 0x85c, 0xFF000000, 0x63); /* Reg85C[31:24]=0x63 */ - rtl8188e_PHY_SetBBReg(adapter, 0x874, 0xC000, 0x2); /* Reg874[15:14]=2'b10 */ - rtl8188e_PHY_SetBBReg(adapter, 0xa74, 0xF000, 0x3); /* RegA75[7:4]=0x3 */ - rtl8188e_PHY_SetBBReg(adapter, 0x818, BIT(28), 0x0); /* Reg818[28]=1'b0 */ - rtl8188e_PHY_SetBBReg(adapter, 0x818, BIT(28), 0x1); /* Reg818[28]=1'b1 */ - } else { - rtl8188e_PHY_SetBBReg(adapter, 0x874, 0x1CC000, pDM_PSTable->reg_874); - rtl8188e_PHY_SetBBReg(adapter, 0xc70, BIT(3), pDM_PSTable->reg_c70); - rtl8188e_PHY_SetBBReg(adapter, 0x85c, 0xFF000000, pDM_PSTable->reg_85c); - rtl8188e_PHY_SetBBReg(adapter, 0xa74, 0xF000, pDM_PSTable->reg_a74); - rtl8188e_PHY_SetBBReg(adapter, 0x818, BIT(28), 0x0); - } - pDM_PSTable->pre_rf_state = pDM_PSTable->cur_rf_state; - } -} - -u32 ODM_Get_Rate_Bitmap(struct odm_dm_struct *pDM_Odm, u32 macid, u32 ra_mask, u8 rssi_level) -{ - struct sta_info *pEntry; - u32 rate_bitmap = 0x0fffffff; - u8 WirelessMode; - - pEntry = pDM_Odm->pODM_StaInfo[macid]; - if (!IS_STA_VALID(pEntry)) - return ra_mask; - - WirelessMode = pEntry->wireless_mode; - - switch (WirelessMode) { - case ODM_WM_B: - if (ra_mask & 0x0000000c) /* 11M or 5.5M enable */ - rate_bitmap = 0x0000000d; - else - rate_bitmap = 0x0000000f; - break; - case (ODM_WM_B | ODM_WM_G): - if (rssi_level == DM_RATR_STA_HIGH) - rate_bitmap = 0x00000f00; - else if (rssi_level == DM_RATR_STA_MIDDLE) - rate_bitmap = 0x00000ff0; - else - rate_bitmap = 0x00000ff5; - break; - case (ODM_WM_B | ODM_WM_G | ODM_WM_N24G): - if (rssi_level == DM_RATR_STA_HIGH) { - rate_bitmap = 0x000f0000; - } else if (rssi_level == DM_RATR_STA_MIDDLE) { - rate_bitmap = 0x000ff000; - } else { - if (*pDM_Odm->pBandWidth == HT_CHANNEL_WIDTH_40) - rate_bitmap = 0x000ff015; - else - rate_bitmap = 0x000ff005; - } - break; - default: - /* case WIRELESS_11_24N: */ - rate_bitmap = 0x0fffffff; - break; - } - - return rate_bitmap; -} - -/* Return Value: bool */ -/* - true: RATRState is changed. */ -bool ODM_RAStateCheck(struct odm_dm_struct *pDM_Odm, s32 RSSI, bool bForceUpdate, u8 *pRATRState) -{ - struct odm_rate_adapt *pRA = &pDM_Odm->RateAdaptive; - const u8 GoUpGap = 5; - u8 HighRSSIThreshForRA = pRA->HighRSSIThresh; - u8 LowRSSIThreshForRA = pRA->LowRSSIThresh; - u8 RATRState; - - /* Threshold Adjustment: */ - /* when RSSI state trends to go up one or two levels, make sure RSSI is high enough. */ - /* Here GoUpGap is added to solve the boundary's level alternation issue. */ - switch (*pRATRState) { - case DM_RATR_STA_INIT: - case DM_RATR_STA_HIGH: - break; - case DM_RATR_STA_MIDDLE: - HighRSSIThreshForRA += GoUpGap; - break; - case DM_RATR_STA_LOW: - HighRSSIThreshForRA += GoUpGap; - LowRSSIThreshForRA += GoUpGap; - break; - default: - break; - } - - /* Decide RATRState by RSSI. */ - if (RSSI > HighRSSIThreshForRA) - RATRState = DM_RATR_STA_HIGH; - else if (RSSI > LowRSSIThreshForRA) - RATRState = DM_RATR_STA_MIDDLE; - else - RATRState = DM_RATR_STA_LOW; - - if (*pRATRState != RATRState || bForceUpdate) { - *pRATRState = RATRState; - return true; - } - return false; -} - -void ODM_TXPowerTrackingCheck(struct odm_dm_struct *pDM_Odm) -{ - struct adapter *Adapter = pDM_Odm->Adapter; - - if (!pDM_Odm->RFCalibrateInfo.TM_Trigger) { /* at least delay 1 sec */ - rtl8188e_PHY_SetRFReg(Adapter, RF_T_METER_88E, BIT(17) | BIT(16), 0x03); - - pDM_Odm->RFCalibrateInfo.TM_Trigger = 1; - return; - } else { - odm_TXPowerTrackingCallback_ThermalMeter_8188E(Adapter); - pDM_Odm->RFCalibrateInfo.TM_Trigger = 0; - } -} diff --git a/drivers/staging/r8188eu/hal/odm_HWConfig.c b/drivers/staging/r8188eu/hal/odm_HWConfig.c deleted file mode 100644 index 38f357e8aeda..000000000000 --- a/drivers/staging/r8188eu/hal/odm_HWConfig.c +++ /dev/null @@ -1,349 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#include "../include/drv_types.h" - -static u8 odm_query_rxpwrpercentage(s8 antpower) -{ - if ((antpower <= -100) || (antpower >= 20)) - return 0; - else if (antpower >= 0) - return 100; - else - return 100 + antpower; -} - -static s32 odm_signal_scale_mapping(struct odm_dm_struct *dm_odm, s32 currsig) -{ - s32 retsig; - - if (currsig >= 51 && currsig <= 100) - retsig = 100; - else if (currsig >= 41 && currsig <= 50) - retsig = 80 + ((currsig - 40) * 2); - else if (currsig >= 31 && currsig <= 40) - retsig = 66 + (currsig - 30); - else if (currsig >= 21 && currsig <= 30) - retsig = 54 + (currsig - 20); - else if (currsig >= 10 && currsig <= 20) - retsig = 42 + (((currsig - 10) * 2) / 3); - else if (currsig >= 5 && currsig <= 9) - retsig = 22 + (((currsig - 5) * 3) / 2); - else if (currsig >= 1 && currsig <= 4) - retsig = 6 + (((currsig - 1) * 3) / 2); - else - retsig = currsig; - - return retsig; -} - -static u8 odm_evm_db_to_percentage(s8 value) -{ - /* -33dB~0dB to 0%~99% */ - s8 ret_val = clamp(-value, 0, 33) * 3; - - if (ret_val == 99) - ret_val = 100; - - return ret_val; -} - -static void odm_RxPhyStatus92CSeries_Parsing(struct odm_dm_struct *dm_odm, - struct phy_info *pPhyInfo, - u8 *pPhyStatus, - struct odm_per_pkt_info *pPktinfo, - struct adapter *adapt) -{ - u8 i, Max_spatial_stream; - s8 rx_pwr[4], rx_pwr_all = 0; - u8 EVM, PWDB_ALL = 0; - u8 RSSI, total_rssi = 0; - u8 isCCKrate = 0; - u8 rf_rx_num = 0; - u8 cck_highpwr = 0; - u8 LNA_idx, VGA_idx; - - struct phy_status_rpt *pPhyStaRpt = (struct phy_status_rpt *)pPhyStatus; - - isCCKrate = pPktinfo->Rate >= DESC92C_RATE1M && pPktinfo->Rate <= DESC92C_RATE11M; - - if (isCCKrate) { - u8 cck_agc_rpt; - - /* (1)Hardware does not provide RSSI for CCK */ - /* (2)PWDB, Average PWDB calculated by hardware (for rate adaptive) */ - - cck_highpwr = dm_odm->bCckHighPower; - - cck_agc_rpt = pPhyStaRpt->cck_agc_rpt_ofdm_cfosho_a; - - /* 2011.11.28 LukeLee: 88E use different LNA & VGA gain table */ - /* The RSSI formula should be modified according to the gain table */ - /* In 88E, cck_highpwr is always set to 1 */ - LNA_idx = ((cck_agc_rpt & 0xE0) >> 5); - VGA_idx = (cck_agc_rpt & 0x1F); - switch (LNA_idx) { - case 7: - if (VGA_idx <= 27) - rx_pwr_all = -100 + 2 * (27 - VGA_idx); /* VGA_idx = 27~2 */ - else - rx_pwr_all = -100; - break; - case 6: - rx_pwr_all = -48 + 2 * (2 - VGA_idx); /* VGA_idx = 2~0 */ - break; - case 5: - rx_pwr_all = -42 + 2 * (7 - VGA_idx); /* VGA_idx = 7~5 */ - break; - case 4: - rx_pwr_all = -36 + 2 * (7 - VGA_idx); /* VGA_idx = 7~4 */ - break; - case 3: - rx_pwr_all = -24 + 2 * (7 - VGA_idx); /* VGA_idx = 7~0 */ - break; - case 2: - if (cck_highpwr) - rx_pwr_all = -12 + 2 * (5 - VGA_idx); /* VGA_idx = 5~0 */ - else - rx_pwr_all = -6 + 2 * (5 - VGA_idx); - break; - case 1: - rx_pwr_all = 8 - 2 * VGA_idx; - break; - case 0: - rx_pwr_all = 14 - 2 * VGA_idx; - break; - default: - break; - } - rx_pwr_all += 6; - PWDB_ALL = odm_query_rxpwrpercentage(rx_pwr_all); - if (!cck_highpwr) { - if (PWDB_ALL >= 80) - PWDB_ALL = ((PWDB_ALL - 80) << 1) + ((PWDB_ALL - 80) >> 1) + 80; - else if ((PWDB_ALL <= 78) && (PWDB_ALL >= 20)) - PWDB_ALL += 3; - if (PWDB_ALL > 100) - PWDB_ALL = 100; - } - - pPhyInfo->RxPWDBAll = PWDB_ALL; - pPhyInfo->recvpower = rx_pwr_all; - /* (3) Get Signal Quality (EVM) */ - if (pPktinfo->bPacketMatchBSSID) { - u8 SQ, SQ_rpt; - - if (pPhyInfo->RxPWDBAll > 40) { - SQ = 100; - } else { - SQ_rpt = pPhyStaRpt->cck_sig_qual_ofdm_pwdb_all; - - if (SQ_rpt > 64) - SQ = 0; - else if (SQ_rpt < 20) - SQ = 100; - else - SQ = ((64 - SQ_rpt) * 100) / 44; - } - pPhyInfo->SignalQuality = SQ; - } - } else { /* is OFDM rate */ - /* (1)Get RSSI for HT rate */ - - for (i = RF_PATH_A; i < RF_PATH_MAX; i++) { - /* 2008/01/30 MH we will judge RF RX path now. */ - if (dm_odm->RFPathRxEnable & BIT(i)) - rf_rx_num++; - - rx_pwr[i] = ((pPhyStaRpt->path_agc[i].gain & 0x3F) * 2) - 110; - if (i == RF_PATH_A) - adapt->signal_strength = rx_pwr[i]; - - pPhyInfo->RxPwr[i] = rx_pwr[i]; - - /* Translate DBM to percentage. */ - RSSI = odm_query_rxpwrpercentage(rx_pwr[i]); - total_rssi += RSSI; - - pPhyInfo->RxMIMOSignalStrength[i] = (u8)RSSI; - - /* Get Rx snr value in DB */ - dm_odm->PhyDbgInfo.RxSNRdB[i] = (s32)(pPhyStaRpt->path_rxsnr[i] / 2); - } - /* (2)PWDB, Average PWDB calculated by hardware (for rate adaptive) */ - rx_pwr_all = (((pPhyStaRpt->cck_sig_qual_ofdm_pwdb_all) >> 1) & 0x7f) - 110; - - PWDB_ALL = odm_query_rxpwrpercentage(rx_pwr_all); - - pPhyInfo->RxPWDBAll = PWDB_ALL; - pPhyInfo->RxPower = rx_pwr_all; - pPhyInfo->recvpower = rx_pwr_all; - - /* (3)EVM of HT rate */ - if (pPktinfo->Rate >= DESC92C_RATEMCS8 && pPktinfo->Rate <= DESC92C_RATEMCS15) - Max_spatial_stream = 2; /* both spatial stream make sense */ - else - Max_spatial_stream = 1; /* only spatial stream 1 makes sense */ - - for (i = 0; i < Max_spatial_stream; i++) { - /* Do not use shift operation like "rx_evmX >>= 1" because the compilor of free build environment */ - /* fill most significant bit to "zero" when doing shifting operation which may change a negative */ - /* value to positive one, then the dbm value (which is supposed to be negative) is not correct anymore. */ - EVM = odm_evm_db_to_percentage((pPhyStaRpt->stream_rxevm[i])); /* dbm */ - - if (pPktinfo->bPacketMatchBSSID) { - if (i == RF_PATH_A) /* Fill value in RFD, Get the first spatial stream only */ - pPhyInfo->SignalQuality = (u8)(EVM & 0xff); - } - } - } - /* UI BSS List signal strength(in percentage), make it good looking, from 0~100. */ - /* It is assigned to the BSS List in GetValueFromBeaconOrProbeRsp(). */ - if (isCCKrate) { - pPhyInfo->SignalStrength = (u8)(odm_signal_scale_mapping(dm_odm, PWDB_ALL));/* PWDB_ALL; */ - } else { - if (rf_rx_num != 0) - pPhyInfo->SignalStrength = (u8)(odm_signal_scale_mapping(dm_odm, total_rssi /= rf_rx_num)); - } - - /* For 88E HW Antenna Diversity */ - dm_odm->DM_FatTable.antsel_rx_keep_0 = pPhyStaRpt->ant_sel; - dm_odm->DM_FatTable.antsel_rx_keep_1 = pPhyStaRpt->ant_sel_b; - dm_odm->DM_FatTable.antsel_rx_keep_2 = pPhyStaRpt->antsel_rx_keep_2; -} - -static void odm_Process_RSSIForDM(struct odm_dm_struct *dm_odm, - struct phy_info *pPhyInfo, - struct odm_per_pkt_info *pPktinfo) -{ - s32 UndecoratedSmoothedPWDB, UndecoratedSmoothedCCK; - s32 UndecoratedSmoothedOFDM, RSSI_Ave; - u8 isCCKrate = 0; - u8 RSSI_max, RSSI_min, i; - u32 OFDM_pkt = 0; - u32 Weighting = 0; - struct sta_info *pEntry; - u8 antsel_tr_mux; - struct fast_ant_train *pDM_FatTable = &dm_odm->DM_FatTable; - - if (pPktinfo->StationID == 0xFF) - return; - pEntry = dm_odm->pODM_StaInfo[pPktinfo->StationID]; - if (!IS_STA_VALID(pEntry)) - return; - if ((!pPktinfo->bPacketMatchBSSID)) - return; - - isCCKrate = pPktinfo->Rate >= DESC92C_RATE1M && pPktinfo->Rate <= DESC92C_RATE11M; - - /* Smart Antenna Debug Message------------------ */ - if ((dm_odm->AntDivType == CG_TRX_HW_ANTDIV) || (dm_odm->AntDivType == CGCS_RX_HW_ANTDIV)) { - if (pPktinfo->bPacketToSelf || pPktinfo->bPacketBeacon) { - antsel_tr_mux = (pDM_FatTable->antsel_rx_keep_2 << 2) | - (pDM_FatTable->antsel_rx_keep_1 << 1) | pDM_FatTable->antsel_rx_keep_0; - ODM_AntselStatistics_88E(dm_odm, antsel_tr_mux, pPktinfo->StationID, pPhyInfo->RxPWDBAll); - } - } - - /* Smart Antenna Debug Message------------------ */ - - UndecoratedSmoothedCCK = pEntry->rssi_stat.UndecoratedSmoothedCCK; - UndecoratedSmoothedOFDM = pEntry->rssi_stat.UndecoratedSmoothedOFDM; - UndecoratedSmoothedPWDB = pEntry->rssi_stat.UndecoratedSmoothedPWDB; - - if (pPktinfo->bPacketToSelf || pPktinfo->bPacketBeacon) { - if (!isCCKrate) { /* ofdm rate */ - if (pPhyInfo->RxMIMOSignalStrength[RF_PATH_B] == 0) { - RSSI_Ave = pPhyInfo->RxMIMOSignalStrength[RF_PATH_A]; - } else { - if (pPhyInfo->RxMIMOSignalStrength[RF_PATH_A] > pPhyInfo->RxMIMOSignalStrength[RF_PATH_B]) { - RSSI_max = pPhyInfo->RxMIMOSignalStrength[RF_PATH_A]; - RSSI_min = pPhyInfo->RxMIMOSignalStrength[RF_PATH_B]; - } else { - RSSI_max = pPhyInfo->RxMIMOSignalStrength[RF_PATH_B]; - RSSI_min = pPhyInfo->RxMIMOSignalStrength[RF_PATH_A]; - } - if ((RSSI_max - RSSI_min) < 3) - RSSI_Ave = RSSI_max; - else if ((RSSI_max - RSSI_min) < 6) - RSSI_Ave = RSSI_max - 1; - else if ((RSSI_max - RSSI_min) < 10) - RSSI_Ave = RSSI_max - 2; - else - RSSI_Ave = RSSI_max - 3; - } - - /* 1 Process OFDM RSSI */ - if (UndecoratedSmoothedOFDM <= 0) { /* initialize */ - UndecoratedSmoothedOFDM = pPhyInfo->RxPWDBAll; - } else { - if (pPhyInfo->RxPWDBAll > (u32)UndecoratedSmoothedOFDM) { - UndecoratedSmoothedOFDM = - (((UndecoratedSmoothedOFDM) * (Rx_Smooth_Factor - 1)) + - (RSSI_Ave)) / (Rx_Smooth_Factor); - UndecoratedSmoothedOFDM = UndecoratedSmoothedOFDM + 1; - } else { - UndecoratedSmoothedOFDM = - (((UndecoratedSmoothedOFDM) * (Rx_Smooth_Factor - 1)) + - (RSSI_Ave)) / (Rx_Smooth_Factor); - } - } - - pEntry->rssi_stat.PacketMap = (pEntry->rssi_stat.PacketMap << 1) | BIT(0); - - } else { - RSSI_Ave = pPhyInfo->RxPWDBAll; - - /* 1 Process CCK RSSI */ - if (UndecoratedSmoothedCCK <= 0) { /* initialize */ - UndecoratedSmoothedCCK = pPhyInfo->RxPWDBAll; - } else { - if (pPhyInfo->RxPWDBAll > (u32)UndecoratedSmoothedCCK) { - UndecoratedSmoothedCCK = - ((UndecoratedSmoothedCCK * (Rx_Smooth_Factor - 1)) + - pPhyInfo->RxPWDBAll) / Rx_Smooth_Factor; - UndecoratedSmoothedCCK = UndecoratedSmoothedCCK + 1; - } else { - UndecoratedSmoothedCCK = - ((UndecoratedSmoothedCCK * (Rx_Smooth_Factor - 1)) + - pPhyInfo->RxPWDBAll) / Rx_Smooth_Factor; - } - } - pEntry->rssi_stat.PacketMap = pEntry->rssi_stat.PacketMap << 1; - } - /* 2011.07.28 LukeLee: modified to prevent unstable CCK RSSI */ - if (pEntry->rssi_stat.ValidBit >= 64) - pEntry->rssi_stat.ValidBit = 64; - else - pEntry->rssi_stat.ValidBit++; - - for (i = 0; i < pEntry->rssi_stat.ValidBit; i++) - OFDM_pkt += (u8)(pEntry->rssi_stat.PacketMap >> i) & BIT(0); - - if (pEntry->rssi_stat.ValidBit == 64) { - Weighting = ((OFDM_pkt << 4) > 64) ? 64 : (OFDM_pkt << 4); - UndecoratedSmoothedPWDB = (Weighting * UndecoratedSmoothedOFDM + (64 - Weighting) * UndecoratedSmoothedCCK) >> 6; - } else { - if (pEntry->rssi_stat.ValidBit != 0) - UndecoratedSmoothedPWDB = (OFDM_pkt * UndecoratedSmoothedOFDM + - (pEntry->rssi_stat.ValidBit - OFDM_pkt) * - UndecoratedSmoothedCCK) / pEntry->rssi_stat.ValidBit; - else - UndecoratedSmoothedPWDB = 0; - } - pEntry->rssi_stat.UndecoratedSmoothedCCK = UndecoratedSmoothedCCK; - pEntry->rssi_stat.UndecoratedSmoothedOFDM = UndecoratedSmoothedOFDM; - pEntry->rssi_stat.UndecoratedSmoothedPWDB = UndecoratedSmoothedPWDB; - } -} - -/* Endianness before calling this API */ -void ODM_PhyStatusQuery(struct odm_dm_struct *dm_odm, - struct phy_info *pPhyInfo, - u8 *pPhyStatus, - struct odm_per_pkt_info *pPktinfo, - struct adapter *adapt) -{ - odm_RxPhyStatus92CSeries_Parsing(dm_odm, pPhyInfo, pPhyStatus, pPktinfo, adapt); - odm_Process_RSSIForDM(dm_odm, pPhyInfo, pPktinfo); -} diff --git a/drivers/staging/r8188eu/hal/odm_RTL8188E.c b/drivers/staging/r8188eu/hal/odm_RTL8188E.c deleted file mode 100644 index f3f4074d4316..000000000000 --- a/drivers/staging/r8188eu/hal/odm_RTL8188E.c +++ /dev/null @@ -1,264 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#include "../include/drv_types.h" - -static void odm_RX_HWAntDivInit(struct odm_dm_struct *dm_odm) -{ - struct adapter *adapter = dm_odm->Adapter; - u32 value32; - - /* MAC Setting */ - value32 = rtl8188e_PHY_QueryBBReg(adapter, ODM_REG_ANTSEL_PIN_11N, bMaskDWord); - rtl8188e_PHY_SetBBReg(adapter, ODM_REG_ANTSEL_PIN_11N, bMaskDWord, value32 | (BIT(23) | BIT(25))); /* Reg4C[25]=1, Reg4C[23]=1 for pin output */ - /* Pin Settings */ - rtl8188e_PHY_SetBBReg(adapter, ODM_REG_PIN_CTRL_11N, BIT(9) | BIT(8), 0);/* Reg870[8]=1'b0, Reg870[9]=1'b0 antsel antselb by HW */ - rtl8188e_PHY_SetBBReg(adapter, ODM_REG_RX_ANT_CTRL_11N, BIT(10), 0); /* Reg864[10]=1'b0 antsel2 by HW */ - rtl8188e_PHY_SetBBReg(adapter, ODM_REG_LNA_SWITCH_11N, BIT(22), 1); /* Regb2c[22]=1'b0 disable CS/CG switch */ - rtl8188e_PHY_SetBBReg(adapter, ODM_REG_LNA_SWITCH_11N, BIT(31), 1); /* Regb2c[31]=1'b1 output at CG only */ - /* OFDM Settings */ - rtl8188e_PHY_SetBBReg(adapter, ODM_REG_ANTDIV_PARA1_11N, bMaskDWord, 0x000000a0); - /* CCK Settings */ - rtl8188e_PHY_SetBBReg(adapter, ODM_REG_BB_PWR_SAV4_11N, BIT(7), 1); /* Fix CCK PHY status report issue */ - rtl8188e_PHY_SetBBReg(adapter, ODM_REG_CCK_ANTDIV_PARA2_11N, BIT(4), 1); /* CCK complete HW AntDiv within 64 samples */ - ODM_UpdateRxIdleAnt_88E(dm_odm, MAIN_ANT); - rtl8188e_PHY_SetBBReg(adapter, ODM_REG_ANT_MAPPING1_11N, 0xFFFF, 0x0201); /* antenna mapping table */ -} - -static void odm_TRX_HWAntDivInit(struct odm_dm_struct *dm_odm) -{ - struct adapter *adapter = dm_odm->Adapter; - u32 value32; - - /* MAC Setting */ - value32 = rtl8188e_PHY_QueryBBReg(adapter, ODM_REG_ANTSEL_PIN_11N, bMaskDWord); - rtl8188e_PHY_SetBBReg(adapter, ODM_REG_ANTSEL_PIN_11N, bMaskDWord, value32 | (BIT(23) | BIT(25))); /* Reg4C[25]=1, Reg4C[23]=1 for pin output */ - /* Pin Settings */ - rtl8188e_PHY_SetBBReg(adapter, ODM_REG_PIN_CTRL_11N, BIT(9) | BIT(8), 0);/* Reg870[8]=1'b0, Reg870[9]=1'b0 antsel antselb by HW */ - rtl8188e_PHY_SetBBReg(adapter, ODM_REG_RX_ANT_CTRL_11N, BIT(10), 0); /* Reg864[10]=1'b0 antsel2 by HW */ - rtl8188e_PHY_SetBBReg(adapter, ODM_REG_LNA_SWITCH_11N, BIT(22), 0); /* Regb2c[22]=1'b0 disable CS/CG switch */ - rtl8188e_PHY_SetBBReg(adapter, ODM_REG_LNA_SWITCH_11N, BIT(31), 1); /* Regb2c[31]=1'b1 output at CG only */ - /* OFDM Settings */ - rtl8188e_PHY_SetBBReg(adapter, ODM_REG_ANTDIV_PARA1_11N, bMaskDWord, 0x000000a0); - /* CCK Settings */ - rtl8188e_PHY_SetBBReg(adapter, ODM_REG_BB_PWR_SAV4_11N, BIT(7), 1); /* Fix CCK PHY status report issue */ - rtl8188e_PHY_SetBBReg(adapter, ODM_REG_CCK_ANTDIV_PARA2_11N, BIT(4), 1); /* CCK complete HW AntDiv within 64 samples */ - /* Tx Settings */ - rtl8188e_PHY_SetBBReg(adapter, ODM_REG_TX_ANT_CTRL_11N, BIT(21), 0); /* Reg80c[21]=1'b0 from TX Reg */ - ODM_UpdateRxIdleAnt_88E(dm_odm, MAIN_ANT); - - /* antenna mapping table */ - if (!dm_odm->bIsMPChip) { /* testchip */ - rtl8188e_PHY_SetBBReg(adapter, ODM_REG_RX_DEFUALT_A_11N, BIT(10) | BIT(9) | BIT(8), 1); /* Reg858[10:8]=3'b001 */ - rtl8188e_PHY_SetBBReg(adapter, ODM_REG_RX_DEFUALT_A_11N, BIT(13) | BIT(12) | BIT(11), 2); /* Reg858[13:11]=3'b010 */ - } else { /* MPchip */ - rtl8188e_PHY_SetBBReg(adapter, ODM_REG_ANT_MAPPING1_11N, bMaskDWord, 0x0201); /* Reg914=3'b010, Reg915=3'b001 */ - } -} - -static void odm_FastAntTrainingInit(struct odm_dm_struct *dm_odm) -{ - struct adapter *adapter = dm_odm->Adapter; - u32 value32; - - /* MAC Setting */ - value32 = rtl8188e_PHY_QueryBBReg(adapter, 0x4c, bMaskDWord); - rtl8188e_PHY_SetBBReg(adapter, 0x4c, bMaskDWord, value32 | (BIT(23) | BIT(25))); /* Reg4C[25]=1, Reg4C[23]=1 for pin output */ - value32 = rtl8188e_PHY_QueryBBReg(adapter, 0x7B4, bMaskDWord); - rtl8188e_PHY_SetBBReg(adapter, 0x7b4, bMaskDWord, value32 | (BIT(16) | BIT(17))); /* Reg7B4[16]=1 enable antenna training, Reg7B4[17]=1 enable A2 match */ - - /* Match MAC ADDR */ - rtl8188e_PHY_SetBBReg(adapter, 0x7b4, 0xFFFF, 0); - rtl8188e_PHY_SetBBReg(adapter, 0x7b0, bMaskDWord, 0); - - rtl8188e_PHY_SetBBReg(adapter, 0x870, BIT(9) | BIT(8), 0);/* Reg870[8]=1'b0, Reg870[9]=1'b0 antsel antselb by HW */ - rtl8188e_PHY_SetBBReg(adapter, 0x864, BIT(10), 0); /* Reg864[10]=1'b0 antsel2 by HW */ - rtl8188e_PHY_SetBBReg(adapter, 0xb2c, BIT(22), 0); /* Regb2c[22]=1'b0 disable CS/CG switch */ - rtl8188e_PHY_SetBBReg(adapter, 0xb2c, BIT(31), 1); /* Regb2c[31]=1'b1 output at CG only */ - rtl8188e_PHY_SetBBReg(adapter, 0xca4, bMaskDWord, 0x000000a0); - - if (!dm_odm->bIsMPChip) { /* testchip */ - rtl8188e_PHY_SetBBReg(adapter, 0x858, BIT(10) | BIT(9) | BIT(8), 1); /* Reg858[10:8]=3'b001 */ - rtl8188e_PHY_SetBBReg(adapter, 0x858, BIT(13) | BIT(12) | BIT(11), 2); /* Reg858[13:11]=3'b010 */ - } else { /* MPchip */ - rtl8188e_PHY_SetBBReg(adapter, 0x914, bMaskByte0, 1); - rtl8188e_PHY_SetBBReg(adapter, 0x914, bMaskByte1, 2); - } - - /* Default Ant Setting when no fast training */ - rtl8188e_PHY_SetBBReg(adapter, 0x80c, BIT(21), 1); /* Reg80c[21]=1'b1 from TX Info */ - rtl8188e_PHY_SetBBReg(adapter, 0x864, BIT(5) | BIT(4) | BIT(3), 0); /* Default RX */ - rtl8188e_PHY_SetBBReg(adapter, 0x864, BIT(8) | BIT(7) | BIT(6), 1); /* Optional RX */ - - /* Enter Training state */ - rtl8188e_PHY_SetBBReg(adapter, 0x864, BIT(2) | BIT(1) | BIT(0), 1); - rtl8188e_PHY_SetBBReg(adapter, 0xc50, BIT(7), 1); /* RegC50[7]=1'b1 enable HW AntDiv */ -} - -void ODM_AntennaDiversityInit_88E(struct odm_dm_struct *dm_odm) -{ - if (dm_odm->AntDivType == CGCS_RX_HW_ANTDIV) - odm_RX_HWAntDivInit(dm_odm); - else if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) - odm_TRX_HWAntDivInit(dm_odm); - else if (dm_odm->AntDivType == CG_TRX_SMART_ANTDIV) - odm_FastAntTrainingInit(dm_odm); -} - -void ODM_UpdateRxIdleAnt_88E(struct odm_dm_struct *dm_odm, u8 Ant) -{ - struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable; - struct adapter *adapter = dm_odm->Adapter; - u32 DefaultAnt, OptionalAnt; - - if (dm_fat_tbl->RxIdleAnt != Ant) { - if (Ant == MAIN_ANT) { - DefaultAnt = (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) ? MAIN_ANT_CG_TRX : MAIN_ANT_CGCS_RX; - OptionalAnt = (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) ? AUX_ANT_CG_TRX : AUX_ANT_CGCS_RX; - } else { - DefaultAnt = (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) ? AUX_ANT_CG_TRX : AUX_ANT_CGCS_RX; - OptionalAnt = (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) ? MAIN_ANT_CG_TRX : MAIN_ANT_CGCS_RX; - } - - if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) { - rtl8188e_PHY_SetBBReg(adapter, ODM_REG_RX_ANT_CTRL_11N, BIT(5) | BIT(4) | BIT(3), DefaultAnt); /* Default RX */ - rtl8188e_PHY_SetBBReg(adapter, ODM_REG_RX_ANT_CTRL_11N, BIT(8) | BIT(7) | BIT(6), OptionalAnt); /* Optional RX */ - rtl8188e_PHY_SetBBReg(adapter, ODM_REG_ANTSEL_CTRL_11N, BIT(14) | BIT(13) | BIT(12), DefaultAnt); /* Default TX */ - rtl8188e_PHY_SetBBReg(adapter, ODM_REG_RESP_TX_11N, BIT(6) | BIT(7), DefaultAnt); /* Resp Tx */ - } else if (dm_odm->AntDivType == CGCS_RX_HW_ANTDIV) { - rtl8188e_PHY_SetBBReg(adapter, ODM_REG_RX_ANT_CTRL_11N, BIT(5) | BIT(4) | BIT(3), DefaultAnt); /* Default RX */ - rtl8188e_PHY_SetBBReg(adapter, ODM_REG_RX_ANT_CTRL_11N, BIT(8) | BIT(7) | BIT(6), OptionalAnt); /* Optional RX */ - } - } - dm_fat_tbl->RxIdleAnt = Ant; - if (Ant != MAIN_ANT) - pr_info("RxIdleAnt=AUX_ANT\n"); -} - -static void odm_UpdateTxAnt_88E(struct odm_dm_struct *dm_odm, u8 Ant, u32 MacId) -{ - struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable; - u8 TargetAnt; - - if (Ant == MAIN_ANT) - TargetAnt = MAIN_ANT_CG_TRX; - else - TargetAnt = AUX_ANT_CG_TRX; - dm_fat_tbl->antsel_a[MacId] = TargetAnt & BIT(0); - dm_fat_tbl->antsel_b[MacId] = (TargetAnt & BIT(1)) >> 1; - dm_fat_tbl->antsel_c[MacId] = (TargetAnt & BIT(2)) >> 2; -} - -void ODM_SetTxAntByTxInfo_88E(struct odm_dm_struct *dm_odm, u8 *pDesc, u8 macId) -{ - struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable; - - if ((dm_odm->AntDivType == CG_TRX_HW_ANTDIV) || (dm_odm->AntDivType == CG_TRX_SMART_ANTDIV)) { - SET_TX_DESC_ANTSEL_A_88E(pDesc, dm_fat_tbl->antsel_a[macId]); - SET_TX_DESC_ANTSEL_B_88E(pDesc, dm_fat_tbl->antsel_b[macId]); - SET_TX_DESC_ANTSEL_C_88E(pDesc, dm_fat_tbl->antsel_c[macId]); - } -} - -void ODM_AntselStatistics_88E(struct odm_dm_struct *dm_odm, u8 antsel_tr_mux, u32 MacId, u8 RxPWDBAll) -{ - struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable; - if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) { - if (antsel_tr_mux == MAIN_ANT_CG_TRX) { - dm_fat_tbl->MainAnt_Sum[MacId] += RxPWDBAll; - dm_fat_tbl->MainAnt_Cnt[MacId]++; - } else { - dm_fat_tbl->AuxAnt_Sum[MacId] += RxPWDBAll; - dm_fat_tbl->AuxAnt_Cnt[MacId]++; - } - } else if (dm_odm->AntDivType == CGCS_RX_HW_ANTDIV) { - if (antsel_tr_mux == MAIN_ANT_CGCS_RX) { - dm_fat_tbl->MainAnt_Sum[MacId] += RxPWDBAll; - dm_fat_tbl->MainAnt_Cnt[MacId]++; - } else { - dm_fat_tbl->AuxAnt_Sum[MacId] += RxPWDBAll; - dm_fat_tbl->AuxAnt_Cnt[MacId]++; - } - } -} - -static void odm_HWAntDiv(struct odm_dm_struct *dm_odm) -{ - u32 i, MinRSSI = 0xFF, AntDivMaxRSSI = 0, MaxRSSI = 0, LocalMinRSSI, LocalMaxRSSI; - u32 Main_RSSI, Aux_RSSI; - u8 RxIdleAnt = 0, TargetAnt = 7; - struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable; - struct rtw_dig *pDM_DigTable = &dm_odm->DM_DigTable; - struct sta_info *pEntry; - - for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) { - pEntry = dm_odm->pODM_StaInfo[i]; - if (IS_STA_VALID(pEntry)) { - /* 2 Calculate RSSI per Antenna */ - Main_RSSI = (dm_fat_tbl->MainAnt_Cnt[i] != 0) ? (dm_fat_tbl->MainAnt_Sum[i] / dm_fat_tbl->MainAnt_Cnt[i]) : 0; - Aux_RSSI = (dm_fat_tbl->AuxAnt_Cnt[i] != 0) ? (dm_fat_tbl->AuxAnt_Sum[i] / dm_fat_tbl->AuxAnt_Cnt[i]) : 0; - TargetAnt = (Main_RSSI >= Aux_RSSI) ? MAIN_ANT : AUX_ANT; - /* 2 Select MaxRSSI for DIG */ - LocalMaxRSSI = max(Main_RSSI, Aux_RSSI); - if ((LocalMaxRSSI > AntDivMaxRSSI) && (LocalMaxRSSI < 40)) - AntDivMaxRSSI = LocalMaxRSSI; - if (LocalMaxRSSI > MaxRSSI) - MaxRSSI = LocalMaxRSSI; - - /* 2 Select RX Idle Antenna */ - if ((dm_fat_tbl->RxIdleAnt == MAIN_ANT) && (Main_RSSI == 0)) - Main_RSSI = Aux_RSSI; - else if ((dm_fat_tbl->RxIdleAnt == AUX_ANT) && (Aux_RSSI == 0)) - Aux_RSSI = Main_RSSI; - - LocalMinRSSI = min(Main_RSSI, Aux_RSSI); - if (LocalMinRSSI < MinRSSI) { - MinRSSI = LocalMinRSSI; - RxIdleAnt = TargetAnt; - } - /* 2 Select TRX Antenna */ - if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) - odm_UpdateTxAnt_88E(dm_odm, TargetAnt, i); - } - dm_fat_tbl->MainAnt_Sum[i] = 0; - dm_fat_tbl->AuxAnt_Sum[i] = 0; - dm_fat_tbl->MainAnt_Cnt[i] = 0; - dm_fat_tbl->AuxAnt_Cnt[i] = 0; - } - - /* 2 Set RX Idle Antenna */ - ODM_UpdateRxIdleAnt_88E(dm_odm, RxIdleAnt); - - pDM_DigTable->AntDiv_RSSI_max = AntDivMaxRSSI; - pDM_DigTable->RSSI_max = MaxRSSI; -} - -void ODM_AntennaDiversity_88E(struct odm_dm_struct *dm_odm) -{ - struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable; - struct adapter *adapter = dm_odm->Adapter; - - if (!(dm_odm->SupportAbility & ODM_BB_ANT_DIV)) - return; - if (!dm_odm->bLinked) { - if (dm_fat_tbl->bBecomeLinked) { - rtl8188e_PHY_SetBBReg(adapter, ODM_REG_IGI_A_11N, BIT(7), 0); /* RegC50[7]=1'b1 enable HW AntDiv */ - rtl8188e_PHY_SetBBReg(adapter, ODM_REG_CCK_ANTDIV_PARA1_11N, BIT(15), 0); /* Enable CCK AntDiv */ - if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) - rtl8188e_PHY_SetBBReg(adapter, ODM_REG_TX_ANT_CTRL_11N, BIT(21), 0); /* Reg80c[21]=1'b0 from TX Reg */ - dm_fat_tbl->bBecomeLinked = dm_odm->bLinked; - } - return; - } else { - if (!dm_fat_tbl->bBecomeLinked) { - /* Because HW AntDiv is disabled before Link, we enable HW AntDiv after link */ - rtl8188e_PHY_SetBBReg(adapter, ODM_REG_IGI_A_11N, BIT(7), 1); /* RegC50[7]=1'b1 enable HW AntDiv */ - rtl8188e_PHY_SetBBReg(adapter, ODM_REG_CCK_ANTDIV_PARA1_11N, BIT(15), 1); /* Enable CCK AntDiv */ - if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) - rtl8188e_PHY_SetBBReg(adapter, ODM_REG_TX_ANT_CTRL_11N, BIT(21), 1); /* Reg80c[21]=1'b1 from TX Info */ - dm_fat_tbl->bBecomeLinked = dm_odm->bLinked; - } - } - if ((dm_odm->AntDivType == CG_TRX_HW_ANTDIV) || (dm_odm->AntDivType == CGCS_RX_HW_ANTDIV)) - odm_HWAntDiv(dm_odm); -} diff --git a/drivers/staging/r8188eu/hal/rtl8188e_cmd.c b/drivers/staging/r8188eu/hal/rtl8188e_cmd.c deleted file mode 100644 index 788904d4655c..000000000000 --- a/drivers/staging/r8188eu/hal/rtl8188e_cmd.c +++ /dev/null @@ -1,694 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#define _RTL8188E_CMD_C_ - -#include "../include/osdep_service.h" -#include "../include/drv_types.h" -#include "../include/rtw_ioctl_set.h" - -#include "../include/rtl8188e_hal.h" - -#define RTL88E_MAX_H2C_BOX_NUMS 4 -#define RTL88E_MAX_CMD_LEN 7 -#define RTL88E_MESSAGE_BOX_SIZE 4 -#define RTL88E_EX_MESSAGE_BOX_SIZE 4 - -static u8 _is_fw_read_cmd_down(struct adapter *adapt, u8 msgbox_num) -{ - u8 read_down = false, reg; - int retry_cnts = 100; - int res; - - u8 valid; - - do { - res = rtw_read8(adapt, REG_HMETFR, ®); - if (res) - continue; - - valid = reg & BIT(msgbox_num); - if (0 == valid) - read_down = true; - } while ((!read_down) && (retry_cnts--)); - - return read_down; -} - -/***************************************** -* H2C Msg format : -* 0x1DF - 0x1D0 -*| 31 - 8 | 7-5 4 - 0 | -*| h2c_msg |Class_ID CMD_ID | -* -* Extend 0x1FF - 0x1F0 -*|31 - 0 | -*|ext_msg| -******************************************/ -static s32 FillH2CCmd_88E(struct adapter *adapt, u8 ElementID, u32 CmdLen, u8 *pCmdBuffer) -{ - u8 bcmd_down = false; - s32 retry_cnts = 100; - u8 h2c_box_num; - u32 msgbox_addr; - u32 msgbox_ex_addr; - struct hal_data_8188e *haldata = &adapt->haldata; - u8 cmd_idx, ext_cmd_len; - u32 h2c_cmd = 0; - u32 h2c_cmd_ex = 0; - - if (!adapt->bFWReady) - return _FAIL; - - if (!pCmdBuffer || CmdLen > RTL88E_MAX_CMD_LEN || adapt->bSurpriseRemoved) - return _FAIL; - - /* pay attention to if race condition happened in H2C cmd setting. */ - do { - h2c_box_num = haldata->LastHMEBoxNum; - - if (!_is_fw_read_cmd_down(adapt, h2c_box_num)) - return _FAIL; - - *(u8 *)(&h2c_cmd) = ElementID; - - if (CmdLen <= 3) { - memcpy((u8 *)(&h2c_cmd) + 1, pCmdBuffer, CmdLen); - } else { - memcpy((u8 *)(&h2c_cmd) + 1, pCmdBuffer, 3); - ext_cmd_len = CmdLen - 3; - memcpy((u8 *)(&h2c_cmd_ex), pCmdBuffer + 3, ext_cmd_len); - - /* Write Ext command */ - msgbox_ex_addr = REG_HMEBOX_EXT_0 + (h2c_box_num * RTL88E_EX_MESSAGE_BOX_SIZE); - for (cmd_idx = 0; cmd_idx < ext_cmd_len; cmd_idx++) { - rtw_write8(adapt, msgbox_ex_addr + cmd_idx, *((u8 *)(&h2c_cmd_ex) + cmd_idx)); - } - } - /* Write command */ - msgbox_addr = REG_HMEBOX_0 + (h2c_box_num * RTL88E_MESSAGE_BOX_SIZE); - for (cmd_idx = 0; cmd_idx < RTL88E_MESSAGE_BOX_SIZE; cmd_idx++) { - rtw_write8(adapt, msgbox_addr + cmd_idx, *((u8 *)(&h2c_cmd) + cmd_idx)); - } - bcmd_down = true; - - haldata->LastHMEBoxNum = (h2c_box_num + 1) % RTL88E_MAX_H2C_BOX_NUMS; - - } while ((!bcmd_down) && (retry_cnts--)); - - return _SUCCESS; -} - -u8 rtl8188e_set_raid_cmd(struct adapter *adapt, u32 mask) -{ - u8 buf[3]; - u8 res = _SUCCESS; - struct hal_data_8188e *haldata = &adapt->haldata; - - if (haldata->fw_ractrl) { - __le32 lmask; - - memset(buf, 0, 3); - lmask = cpu_to_le32(mask); - memcpy(buf, &lmask, 3); - - FillH2CCmd_88E(adapt, H2C_DM_MACID_CFG, 3, buf); - } else { - res = _FAIL; - } - - return res; -} - -/* bitmap[0:27] = tx_rate_bitmap */ -/* bitmap[28:31]= Rate Adaptive id */ -/* arg[0:4] = macid */ -/* arg[5] = Short GI */ -void rtl8188e_Add_RateATid(struct adapter *pAdapter, u32 bitmap, u8 arg, u8 rssi_level) -{ - struct hal_data_8188e *haldata = &pAdapter->haldata; - - u8 macid, raid, short_gi_rate = false; - - macid = arg & 0x1f; - - raid = (bitmap >> 28) & 0x0f; - bitmap &= 0x0fffffff; - - if (rssi_level != DM_RATR_STA_INIT) - bitmap = ODM_Get_Rate_Bitmap(&haldata->odmpriv, macid, bitmap, rssi_level); - - bitmap |= ((raid << 28) & 0xf0000000); - - short_gi_rate = (arg & BIT(5)) ? true : false; - - raid = (bitmap >> 28) & 0x0f; - - bitmap &= 0x0fffffff; - - ODM_RA_UpdateRateInfo_8188E(&haldata->odmpriv, macid, raid, bitmap, short_gi_rate); -} - -void rtl8188e_set_FwPwrMode_cmd(struct adapter *adapt, u8 Mode) -{ - struct setpwrmode_parm H2CSetPwrMode; - struct pwrctrl_priv *pwrpriv = &adapt->pwrctrlpriv; - u8 RLBM = 0; /* 0:Min, 1:Max, 2:User define */ - - switch (Mode) { - case PS_MODE_ACTIVE: - H2CSetPwrMode.Mode = 0; - break; - case PS_MODE_MIN: - H2CSetPwrMode.Mode = 1; - break; - case PS_MODE_MAX: - RLBM = 1; - H2CSetPwrMode.Mode = 1; - break; - case PS_MODE_DTIM: - RLBM = 2; - H2CSetPwrMode.Mode = 1; - break; - case PS_MODE_UAPSD_WMM: - H2CSetPwrMode.Mode = 2; - break; - default: - H2CSetPwrMode.Mode = 0; - break; - } - - H2CSetPwrMode.SmartPS_RLBM = (((pwrpriv->smart_ps << 4) & 0xf0) | (RLBM & 0x0f)); - - H2CSetPwrMode.AwakeInterval = 1; - - H2CSetPwrMode.bAllQueueUAPSD = adapt->registrypriv.uapsd_enable; - - if (Mode > 0) - H2CSetPwrMode.PwrState = 0x00;/* AllON(0x0C), RFON(0x04), RFOFF(0x00) */ - else - H2CSetPwrMode.PwrState = 0x0C;/* AllON(0x0C), RFON(0x04), RFOFF(0x00) */ - - FillH2CCmd_88E(adapt, H2C_PS_PWR_MODE, sizeof(H2CSetPwrMode), (u8 *)&H2CSetPwrMode); - -} - -void rtl8188e_set_FwMediaStatus_cmd(struct adapter *adapt, u16 mstatus_rpt) -{ - __le16 mst_rpt = cpu_to_le16(mstatus_rpt); - - FillH2CCmd_88E(adapt, H2C_COM_MEDIA_STATUS_RPT, sizeof(mst_rpt), (u8 *)&mst_rpt); -} - -static void ConstructBeacon(struct adapter *adapt, u8 *pframe, u32 *pLength) -{ - struct ieee80211_hdr *pwlanhdr; - __le16 *fctrl; - u32 rate_len, pktlen; - struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *cur_network = &pmlmeinfo->network; - - pwlanhdr = (struct ieee80211_hdr *)pframe; - - fctrl = &pwlanhdr->frame_control; - *(fctrl) = 0; - - eth_broadcast_addr(pwlanhdr->addr1); - memcpy(pwlanhdr->addr2, myid(&adapt->eeprompriv), ETH_ALEN); - memcpy(pwlanhdr->addr3, get_my_bssid(cur_network), ETH_ALEN); - - SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/); - SetFrameSubType(pframe, WIFI_BEACON); - - pframe += sizeof(struct ieee80211_hdr_3addr); - pktlen = sizeof(struct ieee80211_hdr_3addr); - - /* timestamp will be inserted by hardware */ - pframe += 8; - pktlen += 8; - - /* beacon interval: 2 bytes */ - memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2); - - pframe += 2; - pktlen += 2; - - /* capability info: 2 bytes */ - memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2); - - pframe += 2; - pktlen += 2; - - if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) { - pktlen += cur_network->IELength - sizeof(struct ndis_802_11_fixed_ie); - memcpy(pframe, cur_network->IEs + sizeof(struct ndis_802_11_fixed_ie), pktlen); - - goto _ConstructBeacon; - } - - /* below for ad-hoc mode */ - - /* SSID */ - pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pktlen); - - /* supported rates... */ - rate_len = rtw_get_rateset_len(cur_network->SupportedRates); - pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pktlen); - - /* DS parameter set */ - pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&cur_network->Configuration.DSConfig, &pktlen); - - if ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) { - u32 ATIMWindow; - /* IBSS Parameter Set... */ - ATIMWindow = 0; - pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pktlen); - } - - /* todo: ERP IE */ - - /* EXTERNDED SUPPORTED RATE */ - if (rate_len > 8) - pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pktlen); - - /* todo:HT for adhoc */ - -_ConstructBeacon: - - if ((pktlen + TXDESC_SIZE) > 512) - return; - - *pLength = pktlen; -} - -static void ConstructPSPoll(struct adapter *adapt, u8 *pframe, u32 *pLength) -{ - struct ieee80211_hdr *pwlanhdr; - struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - __le16 *fctrl; - - pwlanhdr = (struct ieee80211_hdr *)pframe; - - /* Frame control. */ - fctrl = &pwlanhdr->frame_control; - *(fctrl) = 0; - SetPwrMgt(fctrl); - SetFrameSubType(pframe, WIFI_PSPOLL); - - /* AID. */ - SetDuration(pframe, (pmlmeinfo->aid | 0xc000)); - - /* BSSID. */ - memcpy(pwlanhdr->addr1, get_my_bssid(&pmlmeinfo->network), ETH_ALEN); - - /* TA. */ - memcpy(pwlanhdr->addr2, myid(&adapt->eeprompriv), ETH_ALEN); - - *pLength = 16; -} - -static void ConstructNullFunctionData(struct adapter *adapt, u8 *pframe, - u32 *pLength, - u8 *StaAddr, - u8 bQoS, - u8 AC, - u8 bEosp, - u8 bForcePowerSave) -{ - struct ieee80211_hdr *pwlanhdr; - __le16 *fctrl; - u32 pktlen; - struct mlme_priv *pmlmepriv = &adapt->mlmepriv; - struct wlan_network *cur_network = &pmlmepriv->cur_network; - struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - pwlanhdr = (struct ieee80211_hdr *)pframe; - - fctrl = &pwlanhdr->frame_control; - *(fctrl) = 0; - if (bForcePowerSave) - SetPwrMgt(fctrl); - - switch (cur_network->network.InfrastructureMode) { - case Ndis802_11Infrastructure: - SetToDs(fctrl); - memcpy(pwlanhdr->addr1, get_my_bssid(&pmlmeinfo->network), ETH_ALEN); - memcpy(pwlanhdr->addr2, myid(&adapt->eeprompriv), ETH_ALEN); - memcpy(pwlanhdr->addr3, StaAddr, ETH_ALEN); - break; - case Ndis802_11APMode: - SetFrDs(fctrl); - memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN); - memcpy(pwlanhdr->addr2, get_my_bssid(&pmlmeinfo->network), ETH_ALEN); - memcpy(pwlanhdr->addr3, myid(&adapt->eeprompriv), ETH_ALEN); - break; - case Ndis802_11IBSS: - default: - memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN); - memcpy(pwlanhdr->addr2, myid(&adapt->eeprompriv), ETH_ALEN); - memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN); - break; - } - - SetSeqNum(pwlanhdr, 0); - - if (bQoS) { - struct ieee80211_qos_hdr *pwlanqoshdr; - - SetFrameSubType(pframe, WIFI_QOS_DATA_NULL); - - pwlanqoshdr = (struct ieee80211_qos_hdr *)pframe; - SetPriority(&pwlanqoshdr->qos_ctrl, AC); - SetEOSP(&pwlanqoshdr->qos_ctrl, bEosp); - - pktlen = sizeof(struct ieee80211_qos_hdr); - } else { - SetFrameSubType(pframe, WIFI_DATA_NULL); - - pktlen = sizeof(struct ieee80211_qos_hdr); - } - - *pLength = pktlen; -} - -static void ConstructProbeRsp(struct adapter *adapt, u8 *pframe, u32 *pLength, u8 *StaAddr, bool bHideSSID) -{ - struct ieee80211_hdr *pwlanhdr; - __le16 *fctrl; - u8 *mac, *bssid; - u32 pktlen; - struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *cur_network = &pmlmeinfo->network; - - pwlanhdr = (struct ieee80211_hdr *)pframe; - - mac = myid(&adapt->eeprompriv); - bssid = cur_network->MacAddress; - - fctrl = &pwlanhdr->frame_control; - *(fctrl) = 0; - memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN); - memcpy(pwlanhdr->addr2, mac, ETH_ALEN); - memcpy(pwlanhdr->addr3, bssid, ETH_ALEN); - - SetSeqNum(pwlanhdr, 0); - SetFrameSubType(fctrl, WIFI_PROBERSP); - - pktlen = sizeof(struct ieee80211_hdr_3addr); - pframe += pktlen; - - if (cur_network->IELength > MAX_IE_SZ) - return; - - memcpy(pframe, cur_network->IEs, cur_network->IELength); - pframe += cur_network->IELength; - pktlen += cur_network->IELength; - - *pLength = pktlen; -} - -/* To check if reserved page content is destroyed by beacon because beacon is too large. */ -/* 2010.06.23. Added by tynli. */ -void CheckFwRsvdPageContent(struct adapter *Adapter) -{ -} - -/* */ -/* Description: Fill the reserved packets that FW will use to RSVD page. */ -/* Now we just send 4 types packet to rsvd page. */ -/* (1)Beacon, (2)Ps-poll, (3)Null data, (4)ProbeRsp. */ -/* Input: */ -/* bDLFinished - false: At the first time we will send all the packets as a large packet to Hw, */ -/* so we need to set the packet length to total length. */ -/* true: At the second time, we should send the first packet (default:beacon) */ -/* to Hw again and set the length in descriptor to the real beacon length. */ -/* 2009.10.15 by tynli. */ -static void SetFwRsvdPagePkt(struct adapter *adapt, bool bDLFinished) -{ - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - struct xmit_priv *pxmitpriv; - struct mlme_ext_priv *pmlmeext; - struct mlme_ext_info *pmlmeinfo; - u32 BeaconLength = 0, ProbeRspLength = 0, PSPollLength; - u32 NullDataLength, QosNullLength; - u8 *ReservedPagePacket; - u8 PageNum, PageNeed, TxDescLen; - u16 BufIndex; - u32 TotalPacketLen; - struct rsvdpage_loc RsvdPageLoc; - - ReservedPagePacket = kzalloc(1000, GFP_KERNEL); - if (!ReservedPagePacket) - return; - - pxmitpriv = &adapt->xmitpriv; - pmlmeext = &adapt->mlmeextpriv; - pmlmeinfo = &pmlmeext->mlmext_info; - - TxDescLen = TXDESC_SIZE; - PageNum = 0; - - /* 3 (1) beacon * 2 pages */ - BufIndex = TXDESC_OFFSET; - ConstructBeacon(adapt, &ReservedPagePacket[BufIndex], &BeaconLength); - - /* When we count the first page size, we need to reserve description size for the RSVD */ - /* packet, it will be filled in front of the packet in TXPKTBUF. */ - PageNeed = (u8)PageNum_128(TxDescLen + BeaconLength); - /* To reserved 2 pages for beacon buffer. 2010.06.24. */ - if (PageNeed == 1) - PageNeed += 1; - PageNum += PageNeed; - - BufIndex += PageNeed * 128; - - /* 3 (2) ps-poll *1 page */ - RsvdPageLoc.LocPsPoll = PageNum; - ConstructPSPoll(adapt, &ReservedPagePacket[BufIndex], &PSPollLength); - rtl8188e_fill_fake_txdesc(adapt, &ReservedPagePacket[BufIndex - TxDescLen], PSPollLength, true, false); - - PageNeed = (u8)PageNum_128(TxDescLen + PSPollLength); - PageNum += PageNeed; - - BufIndex += PageNeed * 128; - - /* 3 (3) null data * 1 page */ - RsvdPageLoc.LocNullData = PageNum; - ConstructNullFunctionData(adapt, &ReservedPagePacket[BufIndex], &NullDataLength, get_my_bssid(&pmlmeinfo->network), false, 0, 0, false); - rtl8188e_fill_fake_txdesc(adapt, &ReservedPagePacket[BufIndex - TxDescLen], NullDataLength, false, false); - - PageNeed = (u8)PageNum_128(TxDescLen + NullDataLength); - PageNum += PageNeed; - - BufIndex += PageNeed * 128; - - /* 3 (4) probe response * 1page */ - RsvdPageLoc.LocProbeRsp = PageNum; - ConstructProbeRsp(adapt, &ReservedPagePacket[BufIndex], &ProbeRspLength, get_my_bssid(&pmlmeinfo->network), false); - rtl8188e_fill_fake_txdesc(adapt, &ReservedPagePacket[BufIndex - TxDescLen], ProbeRspLength, false, false); - - PageNeed = (u8)PageNum_128(TxDescLen + ProbeRspLength); - PageNum += PageNeed; - - BufIndex += PageNeed * 128; - - /* 3 (5) Qos null data */ - RsvdPageLoc.LocQosNull = PageNum; - ConstructNullFunctionData(adapt, &ReservedPagePacket[BufIndex], - &QosNullLength, get_my_bssid(&pmlmeinfo->network), true, 0, 0, false); - rtl8188e_fill_fake_txdesc(adapt, &ReservedPagePacket[BufIndex - TxDescLen], QosNullLength, false, false); - - PageNeed = (u8)PageNum_128(TxDescLen + QosNullLength); - PageNum += PageNeed; - - TotalPacketLen = BufIndex + QosNullLength; - pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (!pmgntframe) - goto exit; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib(adapt, pattrib); - pattrib->qsel = 0x10; - pattrib->last_txcmdsz = TotalPacketLen - TXDESC_OFFSET; - pattrib->pktlen = pattrib->last_txcmdsz; - memcpy(pmgntframe->buf_addr, ReservedPagePacket, TotalPacketLen); - - rtl8188eu_mgnt_xmit(adapt, pmgntframe); - - FillH2CCmd_88E(adapt, H2C_COM_RSVD_PAGE, sizeof(RsvdPageLoc), (u8 *)&RsvdPageLoc); - -exit: - kfree(ReservedPagePacket); -} - -void rtl8188e_set_FwJoinBssReport_cmd(struct adapter *adapt, u8 mstatus) -{ - struct hal_data_8188e *haldata = &adapt->haldata; - struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - bool bSendBeacon = false; - bool bcn_valid = false; - u8 DLBcnCount = 0; - u32 poll = 0; - u8 reg; - int res; - - if (mstatus == 1) { - /* We should set AID, correct TSF, HW seq enable before set JoinBssReport to Fw in 88/92C. */ - /* Suggested by filen. Added by tynli. */ - rtw_write16(adapt, REG_BCN_PSR_RPT, (0xC000 | pmlmeinfo->aid)); - /* Do not set TSF again here or vWiFi beacon DMA INT will not work. */ - - /* Set REG_CR bit 8. DMA beacon by SW. */ - haldata->RegCR_1 |= BIT(0); - rtw_write8(adapt, REG_CR + 1, haldata->RegCR_1); - - /* Disable Hw protection for a time which revserd for Hw sending beacon. */ - /* Fix download reserved page packet fail that access collision with the protection time. */ - /* 2010.05.11. Added by tynli. */ - res = rtw_read8(adapt, REG_BCN_CTRL, ®); - if (res) - return; - - rtw_write8(adapt, REG_BCN_CTRL, reg & (~BIT(3))); - - res = rtw_read8(adapt, REG_BCN_CTRL, ®); - if (res) - return; - - rtw_write8(adapt, REG_BCN_CTRL, reg | BIT(4)); - - if (haldata->RegFwHwTxQCtrl & BIT(6)) - bSendBeacon = true; - - /* Set FWHW_TXQ_CTRL 0x422[6]=0 to tell Hw the packet is not a real beacon frame. */ - rtw_write8(adapt, REG_FWHW_TXQ_CTRL + 2, (haldata->RegFwHwTxQCtrl & (~BIT(6)))); - haldata->RegFwHwTxQCtrl &= (~BIT(6)); - - clear_beacon_valid_bit(adapt); - DLBcnCount = 0; - poll = 0; - do { - /* download rsvd page. */ - SetFwRsvdPagePkt(adapt, false); - DLBcnCount++; - do { - yield(); - /* mdelay(10); */ - /* check rsvd page download OK. */ - bcn_valid = get_beacon_valid_bit(adapt); - poll++; - } while (!bcn_valid && (poll % 10) != 0 && !adapt->bSurpriseRemoved && !adapt->bDriverStopped); - } while (!bcn_valid && DLBcnCount <= 100 && !adapt->bSurpriseRemoved && !adapt->bDriverStopped); - - /* */ - /* We just can send the reserved page twice during the time that Tx thread is stopped (e.g. pnpsetpower) */ - /* because we need to free the Tx BCN Desc which is used by the first reserved page packet. */ - /* At run time, we cannot get the Tx Desc until it is released in TxHandleInterrupt() so we will return */ - /* the beacon TCB in the following code. 2011.11.23. by tynli. */ - /* */ - - /* Enable Bcn */ - res = rtw_read8(adapt, REG_BCN_CTRL, ®); - if (res) - return; - - rtw_write8(adapt, REG_BCN_CTRL, reg | BIT(3)); - - res = rtw_read8(adapt, REG_BCN_CTRL, ®); - if (res) - return; - - rtw_write8(adapt, REG_BCN_CTRL, reg & (~BIT(4))); - - /* To make sure that if there exists an adapter which would like to send beacon. */ - /* If exists, the origianl value of 0x422[6] will be 1, we should check this to */ - /* prevent from setting 0x422[6] to 0 after download reserved page, or it will cause */ - /* the beacon cannot be sent by HW. */ - /* 2010.06.23. Added by tynli. */ - if (bSendBeacon) { - rtw_write8(adapt, REG_FWHW_TXQ_CTRL + 2, (haldata->RegFwHwTxQCtrl | BIT(6))); - haldata->RegFwHwTxQCtrl |= BIT(6); - } - - /* Update RSVD page location H2C to Fw. */ - if (bcn_valid) - clear_beacon_valid_bit(adapt); - - /* Do not enable HW DMA BCN or it will cause Pcie interface hang by timing issue. 2011.11.24. by tynli. */ - /* Clear CR[8] or beacon packet will not be send to TxBuf anymore. */ - haldata->RegCR_1 &= (~BIT(0)); - rtw_write8(adapt, REG_CR + 1, haldata->RegCR_1); - } - -} - -void rtl8188e_set_p2p_ps_offload_cmd(struct adapter *adapt, u8 p2p_ps_state) -{ - struct hal_data_8188e *haldata = &adapt->haldata; - struct wifidirect_info *pwdinfo = &adapt->wdinfo; - struct P2P_PS_Offload_t *p2p_ps_offload = &haldata->p2p_ps_offload; - u8 i; - - switch (p2p_ps_state) { - case P2P_PS_DISABLE: - memset(p2p_ps_offload, 0, 1); - break; - case P2P_PS_ENABLE: - /* update CTWindow value. */ - if (pwdinfo->ctwindow > 0) { - p2p_ps_offload->CTWindow_En = 1; - rtw_write8(adapt, REG_P2P_CTWIN, pwdinfo->ctwindow); - } - - /* hw only support 2 set of NoA */ - for (i = 0; i < pwdinfo->noa_num; i++) { - /* To control the register setting for which NOA */ - rtw_write8(adapt, REG_NOA_DESC_SEL, (i << 4)); - if (i == 0) - p2p_ps_offload->NoA0_En = 1; - else - p2p_ps_offload->NoA1_En = 1; - - /* config P2P NoA Descriptor Register */ - rtw_write32(adapt, REG_NOA_DESC_DURATION, pwdinfo->noa_duration[i]); - rtw_write32(adapt, REG_NOA_DESC_INTERVAL, pwdinfo->noa_interval[i]); - rtw_write32(adapt, REG_NOA_DESC_START, pwdinfo->noa_start_time[i]); - rtw_write8(adapt, REG_NOA_DESC_COUNT, pwdinfo->noa_count[i]); - } - - if ((pwdinfo->opp_ps == 1) || (pwdinfo->noa_num > 0)) { - /* rst p2p circuit */ - rtw_write8(adapt, REG_DUAL_TSF_RST, BIT(4)); - - p2p_ps_offload->Offload_En = 1; - - if (pwdinfo->role == P2P_ROLE_GO) { - p2p_ps_offload->role = 1; - p2p_ps_offload->AllStaSleep = 0; - } else { - p2p_ps_offload->role = 0; - } - - p2p_ps_offload->discovery = 0; - } - break; - case P2P_PS_SCAN: - p2p_ps_offload->discovery = 1; - break; - case P2P_PS_SCAN_DONE: - p2p_ps_offload->discovery = 0; - pwdinfo->p2p_ps_state = P2P_PS_ENABLE; - break; - default: - break; - } - - FillH2CCmd_88E(adapt, H2C_PS_P2P_OFFLOAD, 1, (u8 *)p2p_ps_offload); -} diff --git a/drivers/staging/r8188eu/hal/rtl8188e_dm.c b/drivers/staging/r8188eu/hal/rtl8188e_dm.c deleted file mode 100644 index 0399872c4546..000000000000 --- a/drivers/staging/r8188eu/hal/rtl8188e_dm.c +++ /dev/null @@ -1,146 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -/* This file is for 92CE/92CU dynamic mechanism only */ -#define _RTL8188E_DM_C_ - -#include "../include/osdep_service.h" -#include "../include/drv_types.h" -#include "../include/rtl8188e_hal.h" - -/* Initialize GPIO setting registers */ -static void dm_InitGPIOSetting(struct adapter *Adapter) -{ - u8 tmp1byte; - int res; - - res = rtw_read8(Adapter, REG_GPIO_MUXCFG, &tmp1byte); - if (res) - return; - - tmp1byte &= (GPIOSEL_GPIO | ~GPIOSEL_ENBT); - - rtw_write8(Adapter, REG_GPIO_MUXCFG, tmp1byte); -} - -/* */ -/* functions */ -/* */ -static void Update_ODM_ComInfo_88E(struct adapter *Adapter) -{ - struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv; - struct mlme_priv *pmlmepriv = &Adapter->mlmepriv; - struct pwrctrl_priv *pwrctrlpriv = &Adapter->pwrctrlpriv; - struct hal_data_8188e *hal_data = &Adapter->haldata; - struct odm_dm_struct *dm_odm = &hal_data->odmpriv; - struct dm_priv *pdmpriv = &hal_data->dmpriv; - int i; - - pdmpriv->InitODMFlag = ODM_BB_RSSI_MONITOR; - if (hal_data->AntDivCfg) - pdmpriv->InitODMFlag |= ODM_BB_ANT_DIV; - - dm_odm->SupportAbility = pdmpriv->InitODMFlag; - - dm_odm->pWirelessMode = &pmlmeext->cur_wireless_mode; - dm_odm->pSecChOffset = &hal_data->nCur40MhzPrimeSC; - dm_odm->pBandWidth = &hal_data->CurrentChannelBW; - dm_odm->pChannel = &hal_data->CurrentChannel; - dm_odm->pbScanInProcess = &pmlmepriv->bScanInProcess; - dm_odm->pbPowerSaving = &pwrctrlpriv->bpower_saving; - - ODM_CmnInfoInit(dm_odm, ODM_CMNINFO_RF_ANTENNA_TYPE, hal_data->TRxAntDivType); - - for (i = 0; i < NUM_STA; i++) - dm_odm->pODM_StaInfo[i] = NULL; -} - -void rtl8188e_InitHalDm(struct adapter *Adapter) -{ - struct hal_data_8188e *hal_data = &Adapter->haldata; - struct odm_dm_struct *dm_odm = &hal_data->odmpriv; - - dm_InitGPIOSetting(Adapter); - Update_ODM_ComInfo_88E(Adapter); - ODM_DMInit(dm_odm); -} - -void rtl8188e_HalDmWatchDog(struct adapter *Adapter) -{ - u8 hw_init_completed = Adapter->hw_init_completed; - struct hal_data_8188e *hal_data = &Adapter->haldata; - struct mlme_priv *pmlmepriv = &Adapter->mlmepriv; - u8 bLinked = false; - - if (!hw_init_completed) - return; - - if ((check_fwstate(pmlmepriv, WIFI_AP_STATE)) || - (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE))) { - if (Adapter->stapriv.asoc_sta_count > 2) - bLinked = true; - } else {/* Station mode */ - if (check_fwstate(pmlmepriv, _FW_LINKED)) - bLinked = true; - } - - hal_data->odmpriv.bLinked = bLinked; - ODM_DMWatchdog(&hal_data->odmpriv); -} - -void rtl8188e_init_dm_priv(struct adapter *Adapter) -{ - struct hal_data_8188e *hal_data = &Adapter->haldata; - struct dm_priv *pdmpriv = &hal_data->dmpriv; - struct odm_dm_struct *dm_odm = &hal_data->odmpriv; - - memset(pdmpriv, 0, sizeof(struct dm_priv)); - memset(dm_odm, 0, sizeof(*dm_odm)); - - dm_odm->Adapter = Adapter; - ODM_CmnInfoInit(dm_odm, ODM_CMNINFO_MP_TEST_CHIP, IS_NORMAL_CHIP(hal_data->VersionID)); - ODM_CmnInfoInit(dm_odm, ODM_CMNINFO_RF_ANTENNA_TYPE, hal_data->TRxAntDivType); -} - -/* Add new function to reset the state of antenna diversity before link. */ -/* Compare RSSI for deciding antenna */ -void AntDivCompare8188E(struct adapter *Adapter, struct wlan_bssid_ex *dst, struct wlan_bssid_ex *src) -{ - struct hal_data_8188e *hal_data = &Adapter->haldata; - - if (0 != hal_data->AntDivCfg) { - /* select optimum_antenna for before linked =>For antenna diversity */ - if (dst->Rssi >= src->Rssi) {/* keep org parameter */ - src->Rssi = dst->Rssi; - src->PhyInfo.Optimum_antenna = dst->PhyInfo.Optimum_antenna; - } - } -} - -/* Add new function to reset the state of antenna diversity before link. */ -u8 AntDivBeforeLink8188E(struct adapter *Adapter) -{ - struct hal_data_8188e *hal_data = &Adapter->haldata; - struct odm_dm_struct *dm_odm = &hal_data->odmpriv; - struct sw_ant_switch *dm_swat_tbl = &dm_odm->DM_SWAT_Table; - struct mlme_priv *pmlmepriv = &Adapter->mlmepriv; - - /* Condition that does not need to use antenna diversity. */ - if (hal_data->AntDivCfg == 0) - return false; - - if (check_fwstate(pmlmepriv, _FW_LINKED)) - return false; - - if (dm_swat_tbl->SWAS_NoLink_State == 0) { - /* switch channel */ - dm_swat_tbl->SWAS_NoLink_State = 1; - dm_swat_tbl->CurAntenna = (dm_swat_tbl->CurAntenna == Antenna_A) ? Antenna_B : Antenna_A; - - rtw_antenna_select_cmd(Adapter, dm_swat_tbl->CurAntenna, false); - return true; - } else { - dm_swat_tbl->SWAS_NoLink_State = 0; - return false; - } -} diff --git a/drivers/staging/r8188eu/hal/rtl8188e_hal_init.c b/drivers/staging/r8188eu/hal/rtl8188e_hal_init.c deleted file mode 100644 index 73855bca76fe..000000000000 --- a/drivers/staging/r8188eu/hal/rtl8188e_hal_init.c +++ /dev/null @@ -1,922 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#define _HAL_INIT_C_ - -#include "../include/drv_types.h" -#include "../include/rtw_efuse.h" -#include "../include/rtl8188e_hal.h" -#include "../include/rtw_iol.h" -#include "../include/usb_ops.h" -#include "../include/rtw_fw.h" - -static void iol_mode_enable(struct adapter *padapter, u8 enable) -{ - u8 reg_0xf0 = 0; - int res; - - if (enable) { - /* Enable initial offload */ - res = rtw_read8(padapter, REG_SYS_CFG, ®_0xf0); - if (res) - return; - - rtw_write8(padapter, REG_SYS_CFG, reg_0xf0 | SW_OFFLOAD_EN); - - if (!padapter->bFWReady) - rtw_reset_8051(padapter); - - } else { - /* disable initial offload */ - res = rtw_read8(padapter, REG_SYS_CFG, ®_0xf0); - if (res) - return; - - rtw_write8(padapter, REG_SYS_CFG, reg_0xf0 & ~SW_OFFLOAD_EN); - } -} - -static s32 iol_execute(struct adapter *padapter, u8 control) -{ - s32 status = _FAIL; - u8 reg_0x88 = 0; - unsigned long timeout; - int res; - - control = control & 0x0f; - res = rtw_read8(padapter, REG_HMEBOX_E0, ®_0x88); - if (res) - return _FAIL; - - rtw_write8(padapter, REG_HMEBOX_E0, reg_0x88 | control); - - timeout = jiffies + msecs_to_jiffies(1000); - - do { - res = rtw_read8(padapter, REG_HMEBOX_E0, ®_0x88); - if (res) - continue; - - if (!(reg_0x88 & control)) - break; - - } while (time_before(jiffies, timeout)); - - res = rtw_read8(padapter, REG_HMEBOX_E0, ®_0x88); - if (res) - return _FAIL; - - status = (reg_0x88 & control) ? _FAIL : _SUCCESS; - if (reg_0x88 & control << 4) - status = _FAIL; - return status; -} - -static s32 iol_InitLLTTable(struct adapter *padapter, u8 txpktbuf_bndy) -{ - s32 rst = _SUCCESS; - iol_mode_enable(padapter, 1); - rtw_write8(padapter, REG_TDECTRL + 1, txpktbuf_bndy); - rst = iol_execute(padapter, CMD_INIT_LLT); - iol_mode_enable(padapter, 0); - return rst; -} - -static void -efuse_phymap_to_logical(u8 *phymap, u16 _size_byte, u8 *pbuf) -{ - u8 *efuseTbl = NULL; - u8 rtemp8; - u16 eFuse_Addr = 0; - u8 offset, wren; - u16 i, j; - u16 **eFuseWord = NULL; - u8 u1temp = 0; - - efuseTbl = kzalloc(EFUSE_MAP_LEN_88E, GFP_KERNEL); - if (!efuseTbl) - goto exit; - - eFuseWord = rtw_malloc2d(EFUSE_MAX_SECTION_88E, EFUSE_MAX_WORD_UNIT, sizeof(u16)); - if (!eFuseWord) - goto exit; - - /* 0. Refresh efuse init map as all oxFF. */ - for (i = 0; i < EFUSE_MAX_SECTION_88E; i++) - for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) - eFuseWord[i][j] = 0xFFFF; - - /* */ - /* 1. Read the first byte to check if efuse is empty!!! */ - /* */ - /* */ - rtemp8 = *(phymap + eFuse_Addr); - if (rtemp8 != 0xFF) { - eFuse_Addr++; - } else { - goto exit; - } - - /* */ - /* 2. Read real efuse content. Filter PG header and every section data. */ - /* */ - while ((rtemp8 != 0xFF) && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E)) { - /* Check PG header for section num. */ - if ((rtemp8 & 0x1F) == 0x0F) { /* extended header */ - u1temp = ((rtemp8 & 0xE0) >> 5); - rtemp8 = *(phymap + eFuse_Addr); - if ((rtemp8 & 0x0F) == 0x0F) { - eFuse_Addr++; - rtemp8 = *(phymap + eFuse_Addr); - - if (rtemp8 != 0xFF && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E)) - eFuse_Addr++; - continue; - } else { - offset = ((rtemp8 & 0xF0) >> 1) | u1temp; - wren = (rtemp8 & 0x0F); - eFuse_Addr++; - } - } else { - offset = ((rtemp8 >> 4) & 0x0f); - wren = (rtemp8 & 0x0f); - } - - if (offset < EFUSE_MAX_SECTION_88E) { - /* Get word enable value from PG header */ - for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) { - /* Check word enable condition in the section */ - if (!(wren & 0x01)) { - rtemp8 = *(phymap + eFuse_Addr); - eFuse_Addr++; - eFuseWord[offset][i] = (rtemp8 & 0xff); - if (eFuse_Addr >= EFUSE_REAL_CONTENT_LEN_88E) - break; - rtemp8 = *(phymap + eFuse_Addr); - eFuse_Addr++; - eFuseWord[offset][i] |= (((u16)rtemp8 << 8) & 0xff00); - - if (eFuse_Addr >= EFUSE_REAL_CONTENT_LEN_88E) - break; - } - wren >>= 1; - } - } - /* Read next PG header */ - rtemp8 = *(phymap + eFuse_Addr); - - if (rtemp8 != 0xFF && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E)) { - eFuse_Addr++; - } - } - - /* */ - /* 3. Collect 16 sections and 4 word unit into Efuse map. */ - /* */ - for (i = 0; i < EFUSE_MAX_SECTION_88E; i++) { - for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) { - efuseTbl[(i * 8) + (j * 2)] = (eFuseWord[i][j] & 0xff); - efuseTbl[(i * 8) + ((j * 2) + 1)] = ((eFuseWord[i][j] >> 8) & 0xff); - } - } - - /* */ - /* 4. Copy from Efuse map to output pointer memory!!! */ - /* */ - memcpy(pbuf, efuseTbl, _size_byte); - -exit: - kfree(efuseTbl); - kfree(eFuseWord); -} - -/* FIXME: add error handling in callers */ -static int efuse_read_phymap_from_txpktbuf( - struct adapter *adapter, - u8 *content, /* buffer to store efuse physical map */ - u16 *size /* for efuse content: the max byte to read. will update to byte read */ - ) -{ - unsigned long timeout; - __le32 lo32 = 0, hi32 = 0; - u16 len = 0, count = 0; - int i = 0, res; - u16 limit = *size; - u8 reg; - u8 *pos = content; - u32 reg32; - - rtw_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL, TXPKT_BUF_SELECT); - - while (1) { - rtw_write16(adapter, REG_PKTBUF_DBG_ADDR, i); - - rtw_write8(adapter, REG_TXPKTBUF_DBG, 0); - timeout = jiffies + msecs_to_jiffies(1000); - do { - res = rtw_read8(adapter, REG_TXPKTBUF_DBG, ®); - if (res) - continue; - - if (reg) - break; - - msleep(1); - } while (time_before(jiffies, timeout)); - - /* data from EEPROM needs to be in LE */ - res = rtw_read32(adapter, REG_PKTBUF_DBG_DATA_L, ®32); - if (res) - return res; - - lo32 = cpu_to_le32(reg32); - - res = rtw_read32(adapter, REG_PKTBUF_DBG_DATA_H, ®32); - if (res) - return res; - - hi32 = cpu_to_le32(reg32); - - if (i == 0) { - u16 reg; - - /* Although lenc is only used in a debug statement, - * do not remove it as the rtw_read16() call consumes - * 2 bytes from the EEPROM source. - */ - res = rtw_read16(adapter, REG_PKTBUF_DBG_DATA_L, ®); - if (res) - return res; - - len = le32_to_cpu(lo32) & 0x0000ffff; - - limit = (len - 2 < limit) ? len - 2 : limit; - - memcpy(pos, ((u8 *)&lo32) + 2, (limit >= count + 2) ? 2 : limit - count); - count += (limit >= count + 2) ? 2 : limit - count; - pos = content + count; - } else { - memcpy(pos, ((u8 *)&lo32), (limit >= count + 4) ? 4 : limit - count); - count += (limit >= count + 4) ? 4 : limit - count; - pos = content + count; - } - - if (limit > count && len - 2 > count) { - memcpy(pos, (u8 *)&hi32, (limit >= count + 4) ? 4 : limit - count); - count += (limit >= count + 4) ? 4 : limit - count; - pos = content + count; - } - - if (limit <= count || len - 2 <= count) - break; - i++; - } - rtw_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL, DISABLE_TRXPKT_BUF_ACCESS); - *size = count; - - return 0; -} - -static s32 iol_read_efuse(struct adapter *padapter, u16 size_byte, u8 *logical_map) -{ - s32 status = _FAIL; - u8 physical_map[512]; - u16 size = 512; - - rtw_write8(padapter, REG_TDECTRL + 1, 0); - memset(physical_map, 0xFF, 512); - rtw_write8(padapter, REG_PKT_BUFF_ACCESS_CTRL, TXPKT_BUF_SELECT); - status = iol_execute(padapter, CMD_READ_EFUSE_MAP); - if (status == _SUCCESS) - efuse_read_phymap_from_txpktbuf(padapter, physical_map, &size); - efuse_phymap_to_logical(physical_map, size_byte, logical_map); - return status; -} - -s32 rtl8188e_iol_efuse_patch(struct adapter *padapter) -{ - s32 result = _SUCCESS; - - if (rtw_IOL_applied(padapter)) { - iol_mode_enable(padapter, 1); - result = iol_execute(padapter, CMD_READ_EFUSE_MAP); - if (result == _SUCCESS) - result = iol_execute(padapter, CMD_EFUSE_PATCH); - - iol_mode_enable(padapter, 0); - } - return result; -} - -static s32 iol_ioconfig(struct adapter *padapter, u8 iocfg_bndy) -{ - s32 rst = _SUCCESS; - - rtw_write8(padapter, REG_TDECTRL + 1, iocfg_bndy); - rst = iol_execute(padapter, CMD_IOCONFIG); - return rst; -} - -int rtl8188e_IOL_exec_cmds_sync(struct adapter *adapter, struct xmit_frame *xmit_frame, u32 max_wating_ms, u32 bndy_cnt) -{ - struct pkt_attrib *pattrib = &xmit_frame->attrib; - u8 i; - int ret = _FAIL; - - if (rtw_IOL_append_END_cmd(xmit_frame) != _SUCCESS) - goto exit; - if (rtw_usb_bulk_size_boundary(adapter, TXDESC_SIZE + pattrib->last_txcmdsz)) { - if (rtw_IOL_append_END_cmd(xmit_frame) != _SUCCESS) - goto exit; - } - - dump_mgntframe_and_wait(adapter, xmit_frame, max_wating_ms); - - iol_mode_enable(adapter, 1); - for (i = 0; i < bndy_cnt; i++) { - u8 page_no = 0; - page_no = i * 2; - ret = iol_ioconfig(adapter, page_no); - if (ret != _SUCCESS) - break; - } - iol_mode_enable(adapter, 0); -exit: - /* restore BCN_HEAD */ - rtw_write8(adapter, REG_TDECTRL + 1, 0); - return ret; -} - -void rtl8188e_EfusePowerSwitch(struct adapter *pAdapter, u8 PwrState) -{ - u16 tmpV16; - int res; - - if (PwrState) { - rtw_write8(pAdapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_ON); - - /* 1.2V Power: From VDDON with Power Cut(0x0000h[15]), default valid */ - res = rtw_read16(pAdapter, REG_SYS_ISO_CTRL, &tmpV16); - if (res) - return; - - if (!(tmpV16 & PWC_EV12V)) { - tmpV16 |= PWC_EV12V; - rtw_write16(pAdapter, REG_SYS_ISO_CTRL, tmpV16); - } - /* Reset: 0x0000h[28], default valid */ - res = rtw_read16(pAdapter, REG_SYS_FUNC_EN, &tmpV16); - if (res) - return; - - if (!(tmpV16 & FEN_ELDR)) { - tmpV16 |= FEN_ELDR; - rtw_write16(pAdapter, REG_SYS_FUNC_EN, tmpV16); - } - - /* Clock: Gated(0x0008h[5]) 8M(0x0008h[1]) clock from ANA, default valid */ - res = rtw_read16(pAdapter, REG_SYS_CLKR, &tmpV16); - if (res) - return; - - if ((!(tmpV16 & LOADER_CLK_EN)) || (!(tmpV16 & ANA8M))) { - tmpV16 |= (LOADER_CLK_EN | ANA8M); - rtw_write16(pAdapter, REG_SYS_CLKR, tmpV16); - } - } else { - rtw_write8(pAdapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_OFF); - } -} - -static void Hal_EfuseReadEFuse88E(struct adapter *Adapter, - u16 _offset, - u16 _size_byte, - u8 *pbuf) -{ - u8 *efuseTbl = NULL; - u8 rtemp8[1]; - u16 eFuse_Addr = 0; - u8 offset, wren; - u16 i, j; - u16 **eFuseWord = NULL; - u16 efuse_utilized = 0; - u8 u1temp = 0; - - /* */ - /* Do NOT excess total size of EFuse table. Added by Roger, 2008.11.10. */ - /* */ - if ((_offset + _size_byte) > EFUSE_MAP_LEN_88E) /* total E-Fuse table is 512bytes */ - goto exit; - - efuseTbl = kzalloc(EFUSE_MAP_LEN_88E, GFP_KERNEL); - if (!efuseTbl) - goto exit; - - eFuseWord = rtw_malloc2d(EFUSE_MAX_SECTION_88E, EFUSE_MAX_WORD_UNIT, sizeof(u16)); - if (!eFuseWord) - goto exit; - - /* 0. Refresh efuse init map as all oxFF. */ - for (i = 0; i < EFUSE_MAX_SECTION_88E; i++) - for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) - eFuseWord[i][j] = 0xFFFF; - - /* */ - /* 1. Read the first byte to check if efuse is empty!!! */ - /* */ - /* */ - ReadEFuseByte(Adapter, eFuse_Addr, rtemp8); - if (*rtemp8 != 0xFF) { - efuse_utilized++; - eFuse_Addr++; - } else { - goto exit; - } - - /* */ - /* 2. Read real efuse content. Filter PG header and every section data. */ - /* */ - while ((*rtemp8 != 0xFF) && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E)) { - /* Check PG header for section num. */ - if ((*rtemp8 & 0x1F) == 0x0F) { /* extended header */ - u1temp = ((*rtemp8 & 0xE0) >> 5); - - ReadEFuseByte(Adapter, eFuse_Addr, rtemp8); - - if ((*rtemp8 & 0x0F) == 0x0F) { - eFuse_Addr++; - ReadEFuseByte(Adapter, eFuse_Addr, rtemp8); - - if (*rtemp8 != 0xFF && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E)) - eFuse_Addr++; - continue; - } else { - offset = ((*rtemp8 & 0xF0) >> 1) | u1temp; - wren = (*rtemp8 & 0x0F); - eFuse_Addr++; - } - } else { - offset = ((*rtemp8 >> 4) & 0x0f); - wren = (*rtemp8 & 0x0f); - } - - if (offset < EFUSE_MAX_SECTION_88E) { - /* Get word enable value from PG header */ - - for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) { - /* Check word enable condition in the section */ - if (!(wren & 0x01)) { - ReadEFuseByte(Adapter, eFuse_Addr, rtemp8); - eFuse_Addr++; - efuse_utilized++; - eFuseWord[offset][i] = (*rtemp8 & 0xff); - if (eFuse_Addr >= EFUSE_REAL_CONTENT_LEN_88E) - break; - ReadEFuseByte(Adapter, eFuse_Addr, rtemp8); - eFuse_Addr++; - efuse_utilized++; - eFuseWord[offset][i] |= (((u16)*rtemp8 << 8) & 0xff00); - if (eFuse_Addr >= EFUSE_REAL_CONTENT_LEN_88E) - break; - } - wren >>= 1; - } - } - - /* Read next PG header */ - ReadEFuseByte(Adapter, eFuse_Addr, rtemp8); - - if (*rtemp8 != 0xFF && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E)) { - efuse_utilized++; - eFuse_Addr++; - } - } - - /* 3. Collect 16 sections and 4 word unit into Efuse map. */ - for (i = 0; i < EFUSE_MAX_SECTION_88E; i++) { - for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) { - efuseTbl[(i * 8) + (j * 2)] = (eFuseWord[i][j] & 0xff); - efuseTbl[(i * 8) + ((j * 2) + 1)] = ((eFuseWord[i][j] >> 8) & 0xff); - } - } - - /* 4. Copy from Efuse map to output pointer memory!!! */ - for (i = 0; i < _size_byte; i++) - pbuf[i] = efuseTbl[_offset + i]; - -exit: - kfree(efuseTbl); - kfree(eFuseWord); -} - -void rtl8188e_ReadEFuse(struct adapter *Adapter, u16 _size_byte, u8 *pbuf) -{ - int ret = _FAIL; - if (rtw_IOL_applied(Adapter)) { - rtl8188eu_InitPowerOn(Adapter); - - iol_mode_enable(Adapter, 1); - ret = iol_read_efuse(Adapter, _size_byte, pbuf); - iol_mode_enable(Adapter, 0); - - if (_SUCCESS == ret) - return; - } - - Hal_EfuseReadEFuse88E(Adapter, 0, _size_byte, pbuf); -} - -static void dump_chip_info(struct adapter *adapter, struct HAL_VERSION chip_vers) -{ - struct net_device *netdev = adapter->pnetdev; - char *cut = NULL; - char buf[25]; - - switch (chip_vers.CUTVersion) { - case A_CUT_VERSION: - cut = "A_CUT"; - break; - case B_CUT_VERSION: - cut = "B_CUT"; - break; - case C_CUT_VERSION: - cut = "C_CUT"; - break; - case D_CUT_VERSION: - cut = "D_CUT"; - break; - case E_CUT_VERSION: - cut = "E_CUT"; - break; - default: - snprintf(buf, sizeof(buf), "UNKNOWN_CUT(%d)", chip_vers.CUTVersion); - cut = buf; - break; - } - - netdev_dbg(netdev, "Chip Version Info: CHIP_8188E_%s_%s_%s_1T1R_RomVer(%d)\n", - IS_NORMAL_CHIP(chip_vers) ? "Normal_Chip" : "Test_Chip", - IS_CHIP_VENDOR_TSMC(chip_vers) ? "TSMC" : "UMC", - cut, 0); -} - -void rtl8188e_read_chip_version(struct adapter *padapter) -{ - u32 value32; - struct HAL_VERSION ChipVersion; - struct hal_data_8188e *pHalData = &padapter->haldata; - int res; - - res = rtw_read32(padapter, REG_SYS_CFG, &value32); - if (res) - return; - - ChipVersion.ChipType = ((value32 & RTL_ID) ? TEST_CHIP : NORMAL_CHIP); - - ChipVersion.VendorType = ((value32 & VENDOR_ID) ? CHIP_VENDOR_UMC : CHIP_VENDOR_TSMC); - ChipVersion.CUTVersion = (value32 & CHIP_VER_RTL_MASK) >> CHIP_VER_RTL_SHIFT; /* IC version (CUT) */ - - dump_chip_info(padapter, ChipVersion); - - pHalData->VersionID = ChipVersion; -} - -void rtl8188e_SetHalODMVar(struct adapter *Adapter, void *pValue1, bool bSet) -{ - struct hal_data_8188e *pHalData = &Adapter->haldata; - struct odm_dm_struct *podmpriv = &pHalData->odmpriv; - struct sta_info *psta = (struct sta_info *)pValue1; - - if (bSet) { - podmpriv->pODM_StaInfo[psta->mac_id] = psta; - ODM_RAInfo_Init(podmpriv, psta->mac_id); - } else { - podmpriv->pODM_StaInfo[psta->mac_id] = NULL; - } -} - -void hal_notch_filter_8188e(struct adapter *adapter, bool enable) -{ - int res; - u8 reg; - - res = rtw_read8(adapter, rOFDM0_RxDSP + 1, ®); - if (res) - return; - - if (enable) - rtw_write8(adapter, rOFDM0_RxDSP + 1, reg | BIT(1)); - else - rtw_write8(adapter, rOFDM0_RxDSP + 1, reg & ~BIT(1)); -} - -/* */ -/* */ -/* LLT R/W/Init function */ -/* */ -/* */ -static s32 _LLTWrite(struct adapter *padapter, u32 address, u32 data) -{ - s32 count; - u32 value = _LLT_INIT_ADDR(address) | _LLT_INIT_DATA(data) | _LLT_OP(_LLT_WRITE_ACCESS); - u16 LLTReg = REG_LLT_INIT; - int res; - - rtw_write32(padapter, LLTReg, value); - - /* polling */ - for (count = 0; count <= POLLING_LLT_THRESHOLD; count++) { - res = rtw_read32(padapter, LLTReg, &value); - if (res) - continue; - - if (_LLT_NO_ACTIVE == _LLT_OP_VALUE(value)) - break; - } - - return count > POLLING_LLT_THRESHOLD ? _FAIL : _SUCCESS; -} - -s32 InitLLTTable(struct adapter *padapter, u8 txpktbuf_bndy) -{ - s32 status = _FAIL; - u32 i; - u32 Last_Entry_Of_TxPktBuf = LAST_ENTRY_OF_TX_PKT_BUFFER;/* 176, 22k */ - - if (rtw_IOL_applied(padapter)) { - status = iol_InitLLTTable(padapter, txpktbuf_bndy); - } else { - for (i = 0; i < (txpktbuf_bndy - 1); i++) { - status = _LLTWrite(padapter, i, i + 1); - if (_SUCCESS != status) - return status; - } - - /* end of list */ - status = _LLTWrite(padapter, (txpktbuf_bndy - 1), 0xFF); - if (_SUCCESS != status) - return status; - - /* Make the other pages as ring buffer */ - /* This ring buffer is used as beacon buffer if we config this MAC as two MAC transfer. */ - /* Otherwise used as local loopback buffer. */ - for (i = txpktbuf_bndy; i < Last_Entry_Of_TxPktBuf; i++) { - status = _LLTWrite(padapter, i, (i + 1)); - if (_SUCCESS != status) - return status; - } - - /* Let last entry point to the start entry of ring buffer */ - status = _LLTWrite(padapter, Last_Entry_Of_TxPktBuf, txpktbuf_bndy); - if (_SUCCESS != status) { - return status; - } - } - - return status; -} - -void Hal_EfuseParseIDCode88E(struct adapter *padapter, u8 *hwinfo) -{ - struct eeprom_priv *pEEPROM = &padapter->eeprompriv; - struct net_device *netdev = padapter->pnetdev; - u16 EEPROMId; - - /* Check 0x8129 again for making sure autoload status!! */ - EEPROMId = le16_to_cpu(*((__le16 *)hwinfo)); - if (EEPROMId != RTL_EEPROM_ID) { - pr_err("EEPROM ID(%#x) is invalid!!\n", EEPROMId); - pEEPROM->bautoload_fail_flag = true; - } else { - pEEPROM->bautoload_fail_flag = false; - } - - netdev_dbg(netdev, "EEPROM ID = 0x%04x\n", EEPROMId); -} - -static void Hal_ReadPowerValueFromPROM_8188E(struct txpowerinfo24g *pwrInfo24G, u8 *PROMContent, bool AutoLoadFail) -{ - u32 rfPath, eeAddr = EEPROM_TX_PWR_INX_88E, group, TxCount = 0; - - memset(pwrInfo24G, 0, sizeof(struct txpowerinfo24g)); - - if (AutoLoadFail) { - for (rfPath = 0; rfPath < RF_PATH_MAX; rfPath++) { - /* 2.4G default value */ - for (group = 0; group < MAX_CHNL_GROUP_24G; group++) { - pwrInfo24G->IndexCCK_Base[rfPath][group] = EEPROM_DEFAULT_24G_INDEX; - pwrInfo24G->IndexBW40_Base[rfPath][group] = EEPROM_DEFAULT_24G_INDEX; - } - for (TxCount = 0; TxCount < MAX_TX_COUNT; TxCount++) { - if (TxCount == 0) { - pwrInfo24G->BW20_Diff[rfPath][0] = EEPROM_DEFAULT_24G_HT20_DIFF; - pwrInfo24G->OFDM_Diff[rfPath][0] = EEPROM_DEFAULT_24G_OFDM_DIFF; - } else { - pwrInfo24G->BW20_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF; - pwrInfo24G->BW40_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF; - pwrInfo24G->CCK_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF; - pwrInfo24G->OFDM_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF; - } - } - } - return; - } - - for (rfPath = 0; rfPath < RF_PATH_MAX; rfPath++) { - /* 2.4G default value */ - for (group = 0; group < MAX_CHNL_GROUP_24G; group++) { - pwrInfo24G->IndexCCK_Base[rfPath][group] = PROMContent[eeAddr++]; - if (pwrInfo24G->IndexCCK_Base[rfPath][group] == 0xFF) - pwrInfo24G->IndexCCK_Base[rfPath][group] = EEPROM_DEFAULT_24G_INDEX; - } - for (group = 0; group < MAX_CHNL_GROUP_24G - 1; group++) { - pwrInfo24G->IndexBW40_Base[rfPath][group] = PROMContent[eeAddr++]; - if (pwrInfo24G->IndexBW40_Base[rfPath][group] == 0xFF) - pwrInfo24G->IndexBW40_Base[rfPath][group] = EEPROM_DEFAULT_24G_INDEX; - } - for (TxCount = 0; TxCount < MAX_TX_COUNT; TxCount++) { - if (TxCount == 0) { - pwrInfo24G->BW40_Diff[rfPath][TxCount] = 0; - if (PROMContent[eeAddr] == 0xFF) { - pwrInfo24G->BW20_Diff[rfPath][TxCount] = EEPROM_DEFAULT_24G_HT20_DIFF; - } else { - pwrInfo24G->BW20_Diff[rfPath][TxCount] = (PROMContent[eeAddr] & 0xf0) >> 4; - if (pwrInfo24G->BW20_Diff[rfPath][TxCount] & BIT(3)) /* 4bit sign number to 8 bit sign number */ - pwrInfo24G->BW20_Diff[rfPath][TxCount] |= 0xF0; - } - - if (PROMContent[eeAddr] == 0xFF) { - pwrInfo24G->OFDM_Diff[rfPath][TxCount] = EEPROM_DEFAULT_24G_OFDM_DIFF; - } else { - pwrInfo24G->OFDM_Diff[rfPath][TxCount] = (PROMContent[eeAddr] & 0x0f); - if (pwrInfo24G->OFDM_Diff[rfPath][TxCount] & BIT(3)) /* 4bit sign number to 8 bit sign number */ - pwrInfo24G->OFDM_Diff[rfPath][TxCount] |= 0xF0; - } - pwrInfo24G->CCK_Diff[rfPath][TxCount] = 0; - eeAddr++; - } else { - if (PROMContent[eeAddr] == 0xFF) { - pwrInfo24G->BW40_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF; - } else { - pwrInfo24G->BW40_Diff[rfPath][TxCount] = (PROMContent[eeAddr] & 0xf0) >> 4; - if (pwrInfo24G->BW40_Diff[rfPath][TxCount] & BIT(3)) /* 4bit sign number to 8 bit sign number */ - pwrInfo24G->BW40_Diff[rfPath][TxCount] |= 0xF0; - } - - if (PROMContent[eeAddr] == 0xFF) { - pwrInfo24G->BW20_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF; - } else { - pwrInfo24G->BW20_Diff[rfPath][TxCount] = (PROMContent[eeAddr] & 0x0f); - if (pwrInfo24G->BW20_Diff[rfPath][TxCount] & BIT(3)) /* 4bit sign number to 8 bit sign number */ - pwrInfo24G->BW20_Diff[rfPath][TxCount] |= 0xF0; - } - eeAddr++; - - if (PROMContent[eeAddr] == 0xFF) { - pwrInfo24G->OFDM_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF; - } else { - pwrInfo24G->OFDM_Diff[rfPath][TxCount] = (PROMContent[eeAddr] & 0xf0) >> 4; - if (pwrInfo24G->OFDM_Diff[rfPath][TxCount] & BIT(3)) /* 4bit sign number to 8 bit sign number */ - pwrInfo24G->OFDM_Diff[rfPath][TxCount] |= 0xF0; - } - - if (PROMContent[eeAddr] == 0xFF) { - pwrInfo24G->CCK_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF; - } else { - pwrInfo24G->CCK_Diff[rfPath][TxCount] = (PROMContent[eeAddr] & 0x0f); - if (pwrInfo24G->CCK_Diff[rfPath][TxCount] & BIT(3)) /* 4bit sign number to 8 bit sign number */ - pwrInfo24G->CCK_Diff[rfPath][TxCount] |= 0xF0; - } - eeAddr++; - } - } - } -} - -static void hal_get_chnl_group_88e(u8 chnl, u8 *group) -{ - if (chnl < 3) /* Channel 1-2 */ - *group = 0; - else if (chnl < 6) /* Channel 3-5 */ - *group = 1; - else if (chnl < 9) /* Channel 6-8 */ - *group = 2; - else if (chnl < 12) /* Channel 9-11 */ - *group = 3; - else if (chnl < 14) /* Channel 12-13 */ - *group = 4; - else if (chnl == 14) /* Channel 14 */ - *group = 5; -} - -void Hal_ReadPowerSavingMode88E(struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail) -{ - if (AutoLoadFail) - padapter->pwrctrlpriv.bSupportRemoteWakeup = false; - else - /* hw power down mode selection , 0:rf-off / 1:power down */ - - /* decide hw if support remote wakeup function */ - /* if hw supported, 8051 (SIE) will generate WeakUP signal(D+/D- toggle) when autoresume */ - padapter->pwrctrlpriv.bSupportRemoteWakeup = (hwinfo[EEPROM_USB_OPTIONAL_FUNCTION0] & BIT(1)) ? true : false; -} - -void Hal_ReadTxPowerInfo88E(struct adapter *padapter, u8 *PROMContent, bool AutoLoadFail) -{ - struct hal_data_8188e *pHalData = &padapter->haldata; - struct txpowerinfo24g pwrInfo24G; - u8 ch, group; - u8 TxCount; - - Hal_ReadPowerValueFromPROM_8188E(&pwrInfo24G, PROMContent, AutoLoadFail); - - for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++) { - hal_get_chnl_group_88e(ch, &group); - - pHalData->Index24G_CCK_Base[ch] = pwrInfo24G.IndexCCK_Base[0][group]; - if (ch == 14) - pHalData->Index24G_BW40_Base[ch] = pwrInfo24G.IndexBW40_Base[0][4]; - else - pHalData->Index24G_BW40_Base[ch] = pwrInfo24G.IndexBW40_Base[0][group]; - } - for (TxCount = 0; TxCount < MAX_TX_COUNT; TxCount++) { - pHalData->OFDM_24G_Diff[TxCount] = pwrInfo24G.OFDM_Diff[0][TxCount]; - pHalData->BW20_24G_Diff[TxCount] = pwrInfo24G.BW20_Diff[0][TxCount]; - } - - /* 2010/10/19 MH Add Regulator recognize for CU. */ - if (!AutoLoadFail) { - pHalData->EEPROMRegulatory = (PROMContent[EEPROM_RF_BOARD_OPTION_88E] & 0x7); /* bit0~2 */ - if (PROMContent[EEPROM_RF_BOARD_OPTION_88E] == 0xFF) - pHalData->EEPROMRegulatory = (EEPROM_DEFAULT_BOARD_OPTION & 0x7); /* bit0~2 */ - } else { - pHalData->EEPROMRegulatory = 0; - } -} - -void Hal_EfuseParseXtal_8188E(struct adapter *pAdapter, u8 *hwinfo, bool AutoLoadFail) -{ - struct hal_data_8188e *pHalData = &pAdapter->haldata; - - if (!AutoLoadFail) { - pHalData->CrystalCap = hwinfo[EEPROM_XTAL_88E]; - if (pHalData->CrystalCap == 0xFF) - pHalData->CrystalCap = EEPROM_Default_CrystalCap_88E; - } else { - pHalData->CrystalCap = EEPROM_Default_CrystalCap_88E; - } -} - -void rtl8188e_EfuseParseChnlPlan(struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail) -{ - padapter->mlmepriv.ChannelPlan = - hal_com_get_channel_plan(padapter, - hwinfo ? hwinfo[EEPROM_ChannelPlan_88E] : 0xFF, - padapter->registrypriv.channel_plan, - RT_CHANNEL_DOMAIN_WORLD_WIDE_13, AutoLoadFail); -} - -void Hal_ReadAntennaDiversity88E(struct adapter *pAdapter, u8 *PROMContent, bool AutoLoadFail) -{ - struct hal_data_8188e *pHalData = &pAdapter->haldata; - struct registry_priv *registry_par = &pAdapter->registrypriv; - - if (!AutoLoadFail) { - /* Antenna Diversity setting. */ - if (registry_par->antdiv_cfg == 2) { /* 2:By EFUSE */ - pHalData->AntDivCfg = (PROMContent[EEPROM_RF_BOARD_OPTION_88E] & 0x18) >> 3; - if (PROMContent[EEPROM_RF_BOARD_OPTION_88E] == 0xFF) - pHalData->AntDivCfg = (EEPROM_DEFAULT_BOARD_OPTION & 0x18) >> 3; - } else { - pHalData->AntDivCfg = registry_par->antdiv_cfg; /* 0:OFF , 1:ON, 2:By EFUSE */ - } - - if (registry_par->antdiv_type == 0) { - /* If TRxAntDivType is AUTO in advanced setting, use EFUSE value instead. */ - pHalData->TRxAntDivType = PROMContent[EEPROM_RF_ANTENNA_OPT_88E]; - if (pHalData->TRxAntDivType == 0xFF) - pHalData->TRxAntDivType = CG_TRX_HW_ANTDIV; /* For 88EE, 1Tx and 1RxCG are fixed.(1Ant, Tx and RxCG are both on aux port) */ - } else { - pHalData->TRxAntDivType = registry_par->antdiv_type; - } - - if (pHalData->TRxAntDivType == CG_TRX_HW_ANTDIV || pHalData->TRxAntDivType == CGCS_RX_HW_ANTDIV) - pHalData->AntDivCfg = 1; /* 0xC1[3] is ignored. */ - } else { - pHalData->AntDivCfg = 0; - } -} - -void Hal_ReadThermalMeter_88E(struct adapter *Adapter, u8 *PROMContent, bool AutoloadFail) -{ - struct hal_data_8188e *pHalData = &Adapter->haldata; - - /* ThermalMeter from EEPROM */ - if (!AutoloadFail) - pHalData->EEPROMThermalMeter = PROMContent[EEPROM_THERMAL_METER_88E]; - else - pHalData->EEPROMThermalMeter = EEPROM_Default_ThermalMeter_88E; - - if (pHalData->EEPROMThermalMeter == 0xff || AutoloadFail) - pHalData->EEPROMThermalMeter = EEPROM_Default_ThermalMeter_88E; -} diff --git a/drivers/staging/r8188eu/hal/rtl8188e_phycfg.c b/drivers/staging/r8188eu/hal/rtl8188e_phycfg.c deleted file mode 100644 index f4edf4a8f5c2..000000000000 --- a/drivers/staging/r8188eu/hal/rtl8188e_phycfg.c +++ /dev/null @@ -1,705 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#define _RTL8188E_PHYCFG_C_ - -#include "../include/osdep_service.h" -#include "../include/drv_types.h" -#include "../include/rtw_iol.h" -#include "../include/rtl8188e_hal.h" - -/* */ -/* 1. BB register R/W API */ -/* */ - -/* Get shifted position of the bit mask */ -static u32 phy_calculate_bit_shift(u32 bitmask) -{ - u32 i = ffs(bitmask); - - return i ? i - 1 : 32; -} - -/** -* Function: PHY_QueryBBReg -* -* Overview: Read "sepcific bits" from BB register -* -* Input: -* struct adapter *Adapter, -* u32 RegAddr, The target address to be readback -* u32 BitMask The target bit position in the target address -* to be readback -* Output: None -* Return: u32 Data The readback register value -* Note: This function is equal to "GetRegSetting" in PHY programming guide -*/ -u32 -rtl8188e_PHY_QueryBBReg( - struct adapter *Adapter, - u32 RegAddr, - u32 BitMask - ) -{ - u32 ReturnValue = 0, OriginalValue, BitShift; - int res; - - res = rtw_read32(Adapter, RegAddr, &OriginalValue); - if (res) - return 0; - - BitShift = phy_calculate_bit_shift(BitMask); - ReturnValue = (OriginalValue & BitMask) >> BitShift; - return ReturnValue; -} - -/** -* Function: PHY_SetBBReg -* -* Overview: Write "Specific bits" to BB register (page 8~) -* -* Input: -* struct adapter *Adapter, -* u32 RegAddr, The target address to be modified -* u32 BitMask The target bit position in the target address -* to be modified -* u32 Data The new register value in the target bit position -* of the target address -* -* Output: None -* Return: None -* Note: This function is equal to "PutRegSetting" in PHY programming guide -*/ - -void rtl8188e_PHY_SetBBReg(struct adapter *Adapter, u32 RegAddr, u32 BitMask, u32 Data) -{ - u32 OriginalValue, BitShift; - int res; - - if (BitMask != bMaskDWord) { /* if not "double word" write */ - res = rtw_read32(Adapter, RegAddr, &OriginalValue); - if (res) - return; - - BitShift = phy_calculate_bit_shift(BitMask); - Data = ((OriginalValue & (~BitMask)) | (Data << BitShift)); - } - - rtw_write32(Adapter, RegAddr, Data); -} - -/* */ -/* 2. RF register R/W API */ -/* */ -/** -* Function: phy_RFSerialRead -* -* Overview: Read register from RF chips -* -* Input: -* struct adapter *Adapter, -* u32 Offset, The target address to be read -* -* Output: None -* Return: u32 reback value -* Note: Threre are three types of serial operations: -* 1. Software serial write -* 2. Hardware LSSI-Low Speed Serial Interface -* 3. Hardware HSSI-High speed -* serial write. Driver need to implement (1) and (2). -* This function is equal to the combination of RF_ReadReg() and RFLSSIRead() -*/ -static u32 -phy_RFSerialRead( - struct adapter *Adapter, - u32 Offset - ) -{ - u32 retValue = 0; - struct hal_data_8188e *pHalData = &Adapter->haldata; - struct bb_reg_def *pPhyReg = &pHalData->PHYRegDef; - u32 NewOffset; - u32 tmplong, tmplong2; - u8 RfPiEnable = 0; - /* */ - /* Make sure RF register offset is correct */ - /* */ - Offset &= 0xff; - - /* */ - /* Switch page for 8256 RF IC */ - /* */ - NewOffset = Offset; - - /* For 92S LSSI Read RFLSSIRead */ - /* For RF A/B write 0x824/82c(does not work in the future) */ - /* We must use 0x824 for RF A and B to execute read trigger */ - tmplong = rtl8188e_PHY_QueryBBReg(Adapter, rFPGA0_XA_HSSIParameter2, bMaskDWord); - tmplong2 = tmplong; - - tmplong2 = (tmplong2 & (~bLSSIReadAddress)) | (NewOffset << 23) | bLSSIReadEdge; /* T65 RF */ - - rtl8188e_PHY_SetBBReg(Adapter, rFPGA0_XA_HSSIParameter2, bMaskDWord, tmplong & (~bLSSIReadEdge)); - udelay(10);/* PlatformStallExecution(10); */ - - rtl8188e_PHY_SetBBReg(Adapter, pPhyReg->rfHSSIPara2, bMaskDWord, tmplong2); - udelay(100);/* PlatformStallExecution(100); */ - - udelay(10);/* PlatformStallExecution(10); */ - - RfPiEnable = (u8)rtl8188e_PHY_QueryBBReg(Adapter, rFPGA0_XA_HSSIParameter1, BIT(8)); - - if (RfPiEnable) { /* Read from BBreg8b8, 12 bits for 8190, 20bits for T65 RF */ - retValue = rtl8188e_PHY_QueryBBReg(Adapter, pPhyReg->rfLSSIReadBackPi, bLSSIReadBackData); - } else { /* Read from BBreg8a0, 12 bits for 8190, 20 bits for T65 RF */ - retValue = rtl8188e_PHY_QueryBBReg(Adapter, pPhyReg->rfLSSIReadBack, bLSSIReadBackData); - } - return retValue; -} - -/** -* Function: phy_RFSerialWrite -* -* Overview: Write data to RF register (page 8~) -* -* Input: -* struct adapter *Adapter, -* enum rf_radio_path eRFPath, Radio path of A/B/C/D -* u32 Offset, The target address to be read -* u32 Data The new register Data in the target bit position -* of the target to be read -* -* Output: None -* Return: None -* Note: Threre are three types of serial operations: -* 1. Software serial write -* 2. Hardware LSSI-Low Speed Serial Interface -* 3. Hardware HSSI-High speed -* serial write. Driver need to implement (1) and (2). -* This function is equal to the combination of RF_ReadReg() and RFLSSIRead() - * - * Note: For RF8256 only - * The total count of RTL8256(Zebra4) register is around 36 bit it only employs - * 4-bit RF address. RTL8256 uses "register mode control bit" (Reg00[12], Reg00[10]) - * to access register address bigger than 0xf. See "Appendix-4 in PHY Configuration - * programming guide" for more details. - * Thus, we define a sub-finction for RTL8526 register address conversion - * =========================================================== - * Register Mode RegCTL[1] RegCTL[0] Note - * (Reg00[12]) (Reg00[10]) - * =========================================================== - * Reg_Mode0 0 x Reg 0 ~15(0x0 ~ 0xf) - * ------------------------------------------------------------------ - * Reg_Mode1 1 0 Reg 16 ~30(0x1 ~ 0xf) - * ------------------------------------------------------------------ - * Reg_Mode2 1 1 Reg 31 ~ 45(0x1 ~ 0xf) - * ------------------------------------------------------------------ - * - * 2008/09/02 MH Add 92S RF definition - * - * - * -*/ -static void -phy_RFSerialWrite( - struct adapter *Adapter, - u32 Offset, - u32 Data - ) -{ - u32 DataAndAddr = 0; - struct hal_data_8188e *pHalData = &Adapter->haldata; - struct bb_reg_def *pPhyReg = &pHalData->PHYRegDef; - u32 NewOffset; - - /* 2009/06/17 MH We can not execute IO for power save or other accident mode. */ - - Offset &= 0xff; - - /* */ - /* Switch page for 8256 RF IC */ - /* */ - NewOffset = Offset; - - /* */ - /* Put write addr in [5:0] and write data in [31:16] */ - /* */ - DataAndAddr = ((NewOffset << 20) | (Data & 0x000fffff)) & 0x0fffffff; /* T65 RF */ - - /* */ - /* Write Operation */ - /* */ - rtl8188e_PHY_SetBBReg(Adapter, pPhyReg->rf3wireOffset, bMaskDWord, DataAndAddr); -} - -/** -* Function: PHY_QueryRFReg -* -* Overview: Query "Specific bits" to RF register (page 8~) -* -* Input: -* struct adapter *Adapter, -* u32 RegAddr, The target address to be read -* u32 BitMask The target bit position in the target address -* to be read -* -* Output: None -* Return: u32 Readback value -* Note: This function is equal to "GetRFRegSetting" in PHY programming guide -*/ -u32 rtl8188e_PHY_QueryRFReg(struct adapter *Adapter, u32 RegAddr, u32 BitMask) -{ - u32 Original_Value, Readback_Value, BitShift; - - Original_Value = phy_RFSerialRead(Adapter, RegAddr); - - BitShift = phy_calculate_bit_shift(BitMask); - Readback_Value = (Original_Value & BitMask) >> BitShift; - return Readback_Value; -} - -/** -* Function: PHY_SetRFReg -* -* Overview: Write "Specific bits" to RF register (page 8~) -* -* Input: -* struct adapter *Adapter, -* u32 RegAddr, The target address to be modified -* u32 BitMask The target bit position in the target address -* to be modified -* u32 Data The new register Data in the target bit position -* of the target address -* -* Output: None -* Return: None -* Note: This function is equal to "PutRFRegSetting" in PHY programming guide -*/ -void -rtl8188e_PHY_SetRFReg( - struct adapter *Adapter, - u32 RegAddr, - u32 BitMask, - u32 Data - ) -{ - u32 Original_Value, BitShift; - - /* RF data is 12 bits only */ - if (BitMask != bRFRegOffsetMask) { - Original_Value = phy_RFSerialRead(Adapter, RegAddr); - BitShift = phy_calculate_bit_shift(BitMask); - Data = ((Original_Value & (~BitMask)) | (Data << BitShift)); - } - - phy_RFSerialWrite(Adapter, RegAddr, Data); -} - -/* */ -/* 3. Initial MAC/BB/RF config by reading MAC/BB/RF txt. */ -/* */ - -/*----------------------------------------------------------------------------- - * Function: PHY_MACConfig8192C - * - * Overview: Condig MAC by header file or parameter file. - * - * Input: NONE - * - * Output: NONE - * - * Return: NONE - * - * Revised History: - * When Who Remark - * 08/12/2008 MHC Create Version 0. - * - *---------------------------------------------------------------------------*/ -int PHY_MACConfig8188E(struct adapter *Adapter) -{ - struct hal_data_8188e *pHalData = &Adapter->haldata; - int err; - - /* */ - /* Config MAC */ - /* */ - err = ODM_ReadAndConfig_MAC_REG_8188E(&pHalData->odmpriv); - - /* 2010.07.13 AMPDU aggregation number B */ - rtw_write16(Adapter, REG_MAX_AGGR_NUM, MAX_AGGR_NUM); - - return err; -} - -/** -* Function: phy_InitBBRFRegisterDefinition -* -* Overview: Initialize Register definition offset for Radio Path A/B/C/D -* -* Input: -* struct adapter *Adapter, -* -* Output: None -* Return: None -* Note: The initialization value is constant and it should never be changes -*/ -static void -phy_InitBBRFRegisterDefinition( - struct adapter *Adapter -) -{ - struct hal_data_8188e *pHalData = &Adapter->haldata; - - /* RF Interface Sowrtware Control */ - pHalData->PHYRegDef.rfintfs = rFPGA0_XAB_RFInterfaceSW; /* 16 LSBs if read 32-bit from 0x870 */ - - /* RF Interface Readback Value */ - pHalData->PHYRegDef.rfintfi = rFPGA0_XAB_RFInterfaceRB; /* 16 LSBs if read 32-bit from 0x8E0 */ - - /* RF Interface Output (and Enable) */ - pHalData->PHYRegDef.rfintfo = rFPGA0_XA_RFInterfaceOE; /* 16 LSBs if read 32-bit from 0x860 */ - - /* RF Interface (Output and) Enable */ - pHalData->PHYRegDef.rfintfe = rFPGA0_XA_RFInterfaceOE; /* 16 MSBs if read 32-bit from 0x860 (16-bit for 0x862) */ - - /* Addr of LSSI. Write RF register by driver */ - pHalData->PHYRegDef.rf3wireOffset = rFPGA0_XA_LSSIParameter; /* LSSI Parameter */ - - /* RF parameter */ - pHalData->PHYRegDef.rfLSSI_Select = rFPGA0_XAB_RFParameter; /* BB Band Select */ - - /* Tx AGC Gain Stage (same for all path. Should we remove this?) */ - pHalData->PHYRegDef.rfTxGainStage = rFPGA0_TxGainStage; /* Tx gain stage */ - - /* Transceiver A~D HSSI Parameter-1 */ - pHalData->PHYRegDef.rfHSSIPara1 = rFPGA0_XA_HSSIParameter1; /* wire control parameter1 */ - - /* Transceiver A~D HSSI Parameter-2 */ - pHalData->PHYRegDef.rfHSSIPara2 = rFPGA0_XA_HSSIParameter2; /* wire control parameter2 */ - - /* RF switch Control */ - pHalData->PHYRegDef.rfSwitchControl = rFPGA0_XAB_SwitchControl; /* TR/Ant switch control */ - - /* AGC control 1 */ - pHalData->PHYRegDef.rfAGCControl1 = rOFDM0_XAAGCCore1; - - /* AGC control 2 */ - pHalData->PHYRegDef.rfAGCControl2 = rOFDM0_XAAGCCore2; - - /* RX AFE control 1 */ - pHalData->PHYRegDef.rfRxIQImbalance = rOFDM0_XARxIQImbalance; - - /* RX AFE control 1 */ - pHalData->PHYRegDef.rfRxAFE = rOFDM0_XARxAFE; - - /* Tx AFE control 1 */ - pHalData->PHYRegDef.rfTxIQImbalance = rOFDM0_XATxIQImbalance; - - /* Tx AFE control 2 */ - pHalData->PHYRegDef.rfTxAFE = rOFDM0_XATxAFE; - - /* Transceiver LSSI Readback SI mode */ - pHalData->PHYRegDef.rfLSSIReadBack = rFPGA0_XA_LSSIReadBack; - - /* Transceiver LSSI Readback PI mode */ - pHalData->PHYRegDef.rfLSSIReadBackPi = TransceiverA_HSPI_Readback; -} - -void storePwrIndexDiffRateOffset(struct adapter *Adapter, u32 RegAddr, u32 BitMask, u32 Data) -{ - struct hal_data_8188e *pHalData = &Adapter->haldata; - - if (RegAddr == rTxAGC_A_Rate18_06) - pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][0] = Data; - if (RegAddr == rTxAGC_A_Rate54_24) - pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][1] = Data; - if (RegAddr == rTxAGC_A_CCK1_Mcs32) - pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][6] = Data; - if (RegAddr == rTxAGC_B_CCK11_A_CCK2_11 && BitMask == 0xffffff00) - pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][7] = Data; - if (RegAddr == rTxAGC_A_Mcs03_Mcs00) - pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][2] = Data; - if (RegAddr == rTxAGC_A_Mcs07_Mcs04) - pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][3] = Data; - if (RegAddr == rTxAGC_A_Mcs11_Mcs08) - pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][4] = Data; - if (RegAddr == rTxAGC_A_Mcs15_Mcs12) { - pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][5] = Data; - pHalData->pwrGroupCnt++; - } - if (RegAddr == rTxAGC_B_Rate18_06) - pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][8] = Data; - if (RegAddr == rTxAGC_B_Rate54_24) - pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][9] = Data; - if (RegAddr == rTxAGC_B_CCK1_55_Mcs32) - pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][14] = Data; - if (RegAddr == rTxAGC_B_CCK11_A_CCK2_11 && BitMask == 0x000000ff) - pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][15] = Data; - if (RegAddr == rTxAGC_B_Mcs03_Mcs00) - pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][10] = Data; - if (RegAddr == rTxAGC_B_Mcs07_Mcs04) - pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][11] = Data; - if (RegAddr == rTxAGC_B_Mcs11_Mcs08) - pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][12] = Data; - if (RegAddr == rTxAGC_B_Mcs15_Mcs12) - pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][13] = Data; -} - -static int phy_BB8188E_Config_ParaFile(struct adapter *Adapter) -{ - struct eeprom_priv *pEEPROM = &Adapter->eeprompriv; - struct hal_data_8188e *pHalData = &Adapter->haldata; - int err; - - /* */ - /* 1. Read PHY_REG.TXT BB INIT!! */ - /* We will separate as 88C / 92C according to chip version */ - /* */ - err = ODM_ReadAndConfig_PHY_REG_1T_8188E(&pHalData->odmpriv); - if (err) - return err; - - /* 2. If EEPROM or EFUSE autoload OK, We must config by PHY_REG_PG.txt */ - if (!pEEPROM->bautoload_fail_flag) { - pHalData->pwrGroupCnt = 0; - ODM_ReadAndConfig_PHY_REG_PG_8188E(&pHalData->odmpriv); - } - - /* 3. BB AGC table Initialization */ - err = ODM_ReadAndConfig_AGC_TAB_1T_8188E(&pHalData->odmpriv); - if (err) - return err; - - return 0; -} - -int -PHY_BBConfig8188E( - struct adapter *Adapter - ) -{ - struct hal_data_8188e *pHalData = &Adapter->haldata; - u16 RegVal; - u8 CrystalCap; - int err; - - phy_InitBBRFRegisterDefinition(Adapter); - - /* Enable BB and RF */ - err = rtw_read16(Adapter, REG_SYS_FUNC_EN, &RegVal); - if (err) - return err; - - rtw_write16(Adapter, REG_SYS_FUNC_EN, (u16)(RegVal | BIT(13) | BIT(0) | BIT(1))); - - /* 20090923 Joseph: Advised by Steven and Jenyu. Power sequence before init RF. */ - - rtw_write8(Adapter, REG_RF_CTRL, RF_EN | RF_RSTB | RF_SDMRSTB); - - rtw_write8(Adapter, REG_SYS_FUNC_EN, FEN_USBA | FEN_USBD | FEN_BB_GLB_RSTn | FEN_BBRSTB); - - /* Config BB and AGC */ - err = phy_BB8188E_Config_ParaFile(Adapter); - - /* write 0x24[16:11] = 0x24[22:17] = CrystalCap */ - CrystalCap = pHalData->CrystalCap & 0x3F; - rtl8188e_PHY_SetBBReg(Adapter, REG_AFE_XTAL_CTRL, 0x7ff800, (CrystalCap | (CrystalCap << 6))); - - return err; -} - -static void getTxPowerIndex88E(struct adapter *Adapter, u8 channel, u8 *cckPowerLevel, - u8 *ofdmPowerLevel, u8 *BW20PowerLevel, - u8 *BW40PowerLevel) -{ - struct hal_data_8188e *pHalData = &Adapter->haldata; - u8 index = (channel - 1); - - /* 1. CCK */ - cckPowerLevel[RF_PATH_A] = pHalData->Index24G_CCK_Base[index]; - /* 2. OFDM */ - ofdmPowerLevel[RF_PATH_A] = pHalData->Index24G_BW40_Base[index] + - pHalData->OFDM_24G_Diff[RF_PATH_A]; - /* 1. BW20 */ - BW20PowerLevel[RF_PATH_A] = pHalData->Index24G_BW40_Base[index] + - pHalData->BW20_24G_Diff[RF_PATH_A]; - /* 2. BW40 */ - BW40PowerLevel[RF_PATH_A] = pHalData->Index24G_BW40_Base[index]; -} - -/*----------------------------------------------------------------------------- - * Function: SetTxPowerLevel8190() - * - * Overview: This function is export to "HalCommon" moudule - * We must consider RF path later!!!!!!! - * - * Input: struct adapter *Adapter - * u8 channel - * - * Output: NONE - * - * Return: NONE - * 2008/11/04 MHC We remove EEPROM_93C56. - * We need to move CCX relative code to independet file. - * 2009/01/21 MHC Support new EEPROM format from SD3 requirement. - * - *---------------------------------------------------------------------------*/ -void -PHY_SetTxPowerLevel8188E( - struct adapter *Adapter, - u8 channel - ) -{ - u8 cckPowerLevel[MAX_TX_COUNT] = {0}; - u8 ofdmPowerLevel[MAX_TX_COUNT] = {0};/* [0]:RF-A, [1]:RF-B */ - u8 BW20PowerLevel[MAX_TX_COUNT] = {0}; - u8 BW40PowerLevel[MAX_TX_COUNT] = {0}; - - getTxPowerIndex88E(Adapter, channel, &cckPowerLevel[0], &ofdmPowerLevel[0], &BW20PowerLevel[0], &BW40PowerLevel[0]); - - rtl8188e_PHY_RF6052SetCckTxPower(Adapter, &cckPowerLevel[0]); - rtl8188e_PHY_RF6052SetOFDMTxPower(Adapter, &ofdmPowerLevel[0], &BW20PowerLevel[0], &BW40PowerLevel[0], channel); -} - -/*----------------------------------------------------------------------------- - * Function: PHY_SetBWModeCallback8192C() - * - * Overview: Timer callback function for SetSetBWMode - * - * Input: PRT_TIMER pTimer - * - * Output: NONE - * - * Return: NONE - * - * Note: (1) We do not take j mode into consideration now - * (2) Will two workitem of "switch channel" and "switch channel bandwidth" run - * concurrently? - *---------------------------------------------------------------------------*/ -static void -_PHY_SetBWMode92C( - struct adapter *Adapter -) -{ - struct hal_data_8188e *pHalData = &Adapter->haldata; - u8 regBwOpMode; - u8 regRRSR_RSC; - int res; - - if (Adapter->bDriverStopped) - return; - - /* 3 */ - /* 3<1>Set MAC register */ - /* 3 */ - - res = rtw_read8(Adapter, REG_BWOPMODE, ®BwOpMode); - if (res) - return; - - res = rtw_read8(Adapter, REG_RRSR + 2, ®RRSR_RSC); - if (res) - return; - - switch (pHalData->CurrentChannelBW) { - case HT_CHANNEL_WIDTH_20: - regBwOpMode |= BW_OPMODE_20MHZ; - /* 2007/02/07 Mark by Emily because we have not verify whether this register works */ - rtw_write8(Adapter, REG_BWOPMODE, regBwOpMode); - break; - case HT_CHANNEL_WIDTH_40: - regBwOpMode &= ~BW_OPMODE_20MHZ; - /* 2007/02/07 Mark by Emily because we have not verify whether this register works */ - rtw_write8(Adapter, REG_BWOPMODE, regBwOpMode); - regRRSR_RSC = (regRRSR_RSC & 0x90) | (pHalData->nCur40MhzPrimeSC << 5); - rtw_write8(Adapter, REG_RRSR + 2, regRRSR_RSC); - break; - default: - break; - } - - /* 3 */ - /* 3 <2>Set PHY related register */ - /* 3 */ - switch (pHalData->CurrentChannelBW) { - /* 20 MHz channel*/ - case HT_CHANNEL_WIDTH_20: - rtl8188e_PHY_SetBBReg(Adapter, rFPGA0_RFMOD, bRFMOD, 0x0); - rtl8188e_PHY_SetBBReg(Adapter, rFPGA1_RFMOD, bRFMOD, 0x0); - break; - /* 40 MHz channel*/ - case HT_CHANNEL_WIDTH_40: - rtl8188e_PHY_SetBBReg(Adapter, rFPGA0_RFMOD, bRFMOD, 0x1); - rtl8188e_PHY_SetBBReg(Adapter, rFPGA1_RFMOD, bRFMOD, 0x1); - /* Set Control channel to upper or lower. These settings are required only for 40MHz */ - rtl8188e_PHY_SetBBReg(Adapter, rCCK0_System, bCCKSideBand, (pHalData->nCur40MhzPrimeSC >> 1)); - rtl8188e_PHY_SetBBReg(Adapter, rOFDM1_LSTF, 0xC00, pHalData->nCur40MhzPrimeSC); - rtl8188e_PHY_SetBBReg(Adapter, 0x818, (BIT(26) | BIT(27)), - (pHalData->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1); - break; - default: - break; - } - /* Skip over setting of J-mode in BB register here. Default value is "None J mode". Emily 20070315 */ - - rtl8188e_PHY_RF6052SetBandwidth(Adapter, pHalData->CurrentChannelBW); -} - - /*----------------------------------------------------------------------------- - * Function: SetBWMode8190Pci() - * - * Overview: This function is export to "HalCommon" moudule - * - * Input: struct adapter *Adapter - * enum ht_channel_width Bandwidth 20M or 40M - * - * Output: NONE - * - * Return: NONE - * - * Note: We do not take j mode into consideration now - *---------------------------------------------------------------------------*/ -void PHY_SetBWMode8188E(struct adapter *Adapter, enum ht_channel_width Bandwidth, /* 20M or 40M */ - unsigned char Offset) /* Upper, Lower, or Don't care */ -{ - struct hal_data_8188e *pHalData = &Adapter->haldata; - enum ht_channel_width tmpBW = pHalData->CurrentChannelBW; - - pHalData->CurrentChannelBW = Bandwidth; - - pHalData->nCur40MhzPrimeSC = Offset; - - if ((!Adapter->bDriverStopped) && (!Adapter->bSurpriseRemoved)) - _PHY_SetBWMode92C(Adapter); - else - pHalData->CurrentChannelBW = tmpBW; -} - -static void _PHY_SwChnl8192C(struct adapter *Adapter, u8 channel) -{ - u32 param1, param2; - struct hal_data_8188e *pHalData = &Adapter->haldata; - - /* s1. pre common command - CmdID_SetTxPowerLevel */ - PHY_SetTxPowerLevel8188E(Adapter, channel); - - /* s2. RF dependent command - CmdID_RF_WriteReg, param1=RF_CHNLBW, param2=channel */ - param1 = RF_CHNLBW; - param2 = channel; - pHalData->RfRegChnlVal = ((pHalData->RfRegChnlVal & 0xfffffc00) | param2); - rtl8188e_PHY_SetRFReg(Adapter, param1, bRFRegOffsetMask, pHalData->RfRegChnlVal); -} - -void PHY_SwChnl8188E(struct adapter *Adapter, u8 channel) -{ - /* Call after initialization */ - struct hal_data_8188e *pHalData = &Adapter->haldata; - - if (channel == 0) - channel = 1; - - if ((!Adapter->bDriverStopped) && (!Adapter->bSurpriseRemoved)) { - pHalData->CurrentChannel = channel; - _PHY_SwChnl8192C(Adapter, channel); - } -} diff --git a/drivers/staging/r8188eu/hal/rtl8188e_rf6052.c b/drivers/staging/r8188eu/hal/rtl8188e_rf6052.c deleted file mode 100644 index 1988fb6e780a..000000000000 --- a/drivers/staging/r8188eu/hal/rtl8188e_rf6052.c +++ /dev/null @@ -1,405 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -/****************************************************************************** - * - * - * Module: rtl8192c_rf6052.c ( Source C File) - * - * Note: Provide RF 6052 series relative API. - * - * Function: - * - * Export: - * - * Abbrev: - * - * History: - * Data Who Remark - * - * 09/25/2008 MHC Create initial version. - * 11/05/2008 MHC Add API for tw power setting. - * - * -******************************************************************************/ - -#define _RTL8188E_RF6052_C_ - -#include "../include/osdep_service.h" -#include "../include/drv_types.h" -#include "../include/rtl8188e_hal.h" - -/*----------------------------------------------------------------------------- - * Function: PHY_RF6052SetBandwidth() - * - * Overview: This function is called by SetBWModeCallback8190Pci() only - * - * Input: struct adapter *Adapter - * WIRELESS_BANDWIDTH_E Bandwidth 20M or 40M - * - * Output: NONE - * - * Return: NONE - * - * Note: For RF type 0222D - *---------------------------------------------------------------------------*/ -void rtl8188e_PHY_RF6052SetBandwidth(struct adapter *Adapter, - enum ht_channel_width Bandwidth) -{ - struct hal_data_8188e *pHalData = &Adapter->haldata; - - switch (Bandwidth) { - case HT_CHANNEL_WIDTH_20: - pHalData->RfRegChnlVal = ((pHalData->RfRegChnlVal & 0xfffff3ff) | BIT(10) | BIT(11)); - rtl8188e_PHY_SetRFReg(Adapter, RF_CHNLBW, bRFRegOffsetMask, pHalData->RfRegChnlVal); - break; - case HT_CHANNEL_WIDTH_40: - pHalData->RfRegChnlVal = ((pHalData->RfRegChnlVal & 0xfffff3ff) | BIT(10)); - rtl8188e_PHY_SetRFReg(Adapter, RF_CHNLBW, bRFRegOffsetMask, pHalData->RfRegChnlVal); - break; - default: - break; - } -} - -/*----------------------------------------------------------------------------- - * Function: PHY_RF6052SetCckTxPower - * - * Overview: - * - * Input: NONE - * - * Output: NONE - * - * Return: NONE - * - * Revised History: - * When Who Remark - * 11/05/2008 MHC Simulate 8192series.. - * - *---------------------------------------------------------------------------*/ - -void -rtl8188e_PHY_RF6052SetCckTxPower( - struct adapter *Adapter, - u8 *pPowerlevel) -{ - struct hal_data_8188e *pHalData = &Adapter->haldata; - struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv; - u32 TxAGC[2] = {0, 0}, tmpval = 0, pwrtrac_value; - u8 idx1, idx2; - u8 *ptr; - u8 direction; - - if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) { - TxAGC[RF_PATH_A] = 0x3f3f3f3f; - TxAGC[RF_PATH_B] = 0x3f3f3f3f; - - for (idx1 = RF_PATH_A; idx1 <= RF_PATH_B; idx1++) { - TxAGC[idx1] = - pPowerlevel[idx1] | (pPowerlevel[idx1] << 8) | - (pPowerlevel[idx1] << 16) | (pPowerlevel[idx1] << 24); - } - } else { - for (idx1 = RF_PATH_A; idx1 <= RF_PATH_B; idx1++) { - TxAGC[idx1] = - pPowerlevel[idx1] | (pPowerlevel[idx1] << 8) | - (pPowerlevel[idx1] << 16) | (pPowerlevel[idx1] << 24); - } - if (pHalData->EEPROMRegulatory == 0) { - tmpval = (pHalData->MCSTxPowerLevelOriginalOffset[0][6]) + - (pHalData->MCSTxPowerLevelOriginalOffset[0][7] << 8); - TxAGC[RF_PATH_A] += tmpval; - - tmpval = (pHalData->MCSTxPowerLevelOriginalOffset[0][14]) + - (pHalData->MCSTxPowerLevelOriginalOffset[0][15] << 24); - TxAGC[RF_PATH_B] += tmpval; - } - } - for (idx1 = RF_PATH_A; idx1 <= RF_PATH_B; idx1++) { - ptr = (u8 *)(&TxAGC[idx1]); - for (idx2 = 0; idx2 < 4; idx2++) { - if (*ptr > RF6052_MAX_TX_PWR) - *ptr = RF6052_MAX_TX_PWR; - ptr++; - } - } - ODM_TxPwrTrackAdjust88E(&pHalData->odmpriv, 1, &direction, &pwrtrac_value); - - if (direction == 1) { - /* Increase TX power */ - TxAGC[0] += pwrtrac_value; - TxAGC[1] += pwrtrac_value; - } else if (direction == 2) { - /* Decrease TX power */ - TxAGC[0] -= pwrtrac_value; - TxAGC[1] -= pwrtrac_value; - } - - /* rf-A cck tx power */ - tmpval = TxAGC[RF_PATH_A] & 0xff; - rtl8188e_PHY_SetBBReg(Adapter, rTxAGC_A_CCK1_Mcs32, bMaskByte1, tmpval); - tmpval = TxAGC[RF_PATH_A] >> 8; - rtl8188e_PHY_SetBBReg(Adapter, rTxAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval); - - /* rf-B cck tx power */ - tmpval = TxAGC[RF_PATH_B] >> 24; - rtl8188e_PHY_SetBBReg(Adapter, rTxAGC_B_CCK11_A_CCK2_11, bMaskByte0, tmpval); - tmpval = TxAGC[RF_PATH_B] & 0x00ffffff; - rtl8188e_PHY_SetBBReg(Adapter, rTxAGC_B_CCK1_55_Mcs32, 0xffffff00, tmpval); -} /* PHY_RF6052SetCckTxPower */ - -/* */ -/* powerbase0 for OFDM rates */ -/* powerbase1 for HT MCS rates */ -/* */ -static void getpowerbase88e(struct adapter *Adapter, u8 *pPowerLevelOFDM, - u8 *pPowerLevelBW20, u8 *pPowerLevelBW40, u8 Channel, u32 *OfdmBase, u32 *MCSBase) -{ - struct hal_data_8188e *pHalData = &Adapter->haldata; - u32 powerBase0, powerBase1; - u8 i; - - for (i = 0; i < 2; i++) { - powerBase0 = pPowerLevelOFDM[i]; - - powerBase0 = (powerBase0 << 24) | (powerBase0 << 16) | (powerBase0 << 8) | powerBase0; - *(OfdmBase + i) = powerBase0; - } - - /* Check HT20 to HT40 diff */ - if (pHalData->CurrentChannelBW == HT_CHANNEL_WIDTH_20) - powerBase1 = pPowerLevelBW20[0]; - else - powerBase1 = pPowerLevelBW40[0]; - powerBase1 = (powerBase1 << 24) | (powerBase1 << 16) | (powerBase1 << 8) | powerBase1; - *MCSBase = powerBase1; -} - -static void get_rx_power_val_by_reg(struct adapter *Adapter, u8 Channel, - u8 index, u32 *powerBase0, u32 *powerBase1, - u32 *pOutWriteVal) -{ - struct hal_data_8188e *pHalData = &Adapter->haldata; - u8 i, chnlGroup = 0, pwr_diff_limit[4], customer_pwr_limit; - s8 pwr_diff = 0; - u32 writeVal, customer_limit, rf; - u8 Regulatory = pHalData->EEPROMRegulatory; - - /* Index 0 & 1= legacy OFDM, 2-5=HT_MCS rate */ - - for (rf = 0; rf < 2; rf++) { - switch (Regulatory) { - case 0: /* Realtek better performance */ - /* increase power diff defined by Realtek for large power */ - chnlGroup = 0; - writeVal = pHalData->MCSTxPowerLevelOriginalOffset[chnlGroup][index + (rf ? 8 : 0)] + - ((index < 2) ? powerBase0[rf] : powerBase1[rf]); - break; - case 1: /* Realtek regulatory */ - /* increase power diff defined by Realtek for regulatory */ - if (pHalData->pwrGroupCnt == 1) - chnlGroup = 0; - if (pHalData->pwrGroupCnt >= MAX_PG_GROUP) { - if (Channel < 3) /* Channel 1-2 */ - chnlGroup = 0; - else if (Channel < 6) /* Channel 3-5 */ - chnlGroup = 1; - else if (Channel < 9) /* Channel 6-8 */ - chnlGroup = 2; - else if (Channel < 12) /* Channel 9-11 */ - chnlGroup = 3; - else if (Channel < 14) /* Channel 12-13 */ - chnlGroup = 4; - else if (Channel == 14) /* Channel 14 */ - chnlGroup = 5; - } - writeVal = pHalData->MCSTxPowerLevelOriginalOffset[chnlGroup][index + (rf ? 8 : 0)] + - ((index < 2) ? powerBase0[rf] : powerBase1[rf]); - break; - case 2: /* Better regulatory */ - /* don't increase any power diff */ - writeVal = ((index < 2) ? powerBase0[rf] : powerBase1[rf]); - break; - case 3: /* Customer defined power diff. */ - /* increase power diff defined by customer. */ - chnlGroup = 0; - - if (index < 2) - pwr_diff = pHalData->TxPwrLegacyHtDiff[rf][Channel - 1]; - else if (pHalData->CurrentChannelBW == HT_CHANNEL_WIDTH_20) - pwr_diff = pHalData->TxPwrHt20Diff[rf][Channel - 1]; - - if (pHalData->CurrentChannelBW == HT_CHANNEL_WIDTH_40) - customer_pwr_limit = pHalData->PwrGroupHT40[rf][Channel - 1]; - else - customer_pwr_limit = pHalData->PwrGroupHT20[rf][Channel - 1]; - - if (pwr_diff >= customer_pwr_limit) - pwr_diff = 0; - else - pwr_diff = customer_pwr_limit - pwr_diff; - - for (i = 0; i < 4; i++) { - pwr_diff_limit[i] = (u8)((pHalData->MCSTxPowerLevelOriginalOffset[chnlGroup][index + (rf ? 8 : 0)] & (0x7f << (i * 8))) >> (i * 8)); - - if (pwr_diff_limit[i] > pwr_diff) - pwr_diff_limit[i] = pwr_diff; - } - customer_limit = (pwr_diff_limit[3] << 24) | (pwr_diff_limit[2] << 16) | - (pwr_diff_limit[1] << 8) | (pwr_diff_limit[0]); - writeVal = customer_limit + ((index < 2) ? powerBase0[rf] : powerBase1[rf]); - break; - default: - chnlGroup = 0; - writeVal = pHalData->MCSTxPowerLevelOriginalOffset[chnlGroup][index + (rf ? 8 : 0)] + - ((index < 2) ? powerBase0[rf] : powerBase1[rf]); - break; - } - - *(pOutWriteVal + rf) = writeVal; - } -} -static void writeOFDMPowerReg88E(struct adapter *Adapter, u8 index, u32 *pValue) -{ - u16 regoffset_a[6] = { - rTxAGC_A_Rate18_06, rTxAGC_A_Rate54_24, - rTxAGC_A_Mcs03_Mcs00, rTxAGC_A_Mcs07_Mcs04, - rTxAGC_A_Mcs11_Mcs08, rTxAGC_A_Mcs15_Mcs12}; - u16 regoffset_b[6] = { - rTxAGC_B_Rate18_06, rTxAGC_B_Rate54_24, - rTxAGC_B_Mcs03_Mcs00, rTxAGC_B_Mcs07_Mcs04, - rTxAGC_B_Mcs11_Mcs08, rTxAGC_B_Mcs15_Mcs12}; - u8 i, rf, pwr_val[4]; - u32 writeVal; - u16 regoffset; - - for (rf = 0; rf < 2; rf++) { - writeVal = pValue[rf]; - for (i = 0; i < 4; i++) { - pwr_val[i] = (u8)((writeVal & (0x7f << (i * 8))) >> (i * 8)); - if (pwr_val[i] > RF6052_MAX_TX_PWR) - pwr_val[i] = RF6052_MAX_TX_PWR; - } - writeVal = (pwr_val[3] << 24) | (pwr_val[2] << 16) | (pwr_val[1] << 8) | pwr_val[0]; - - if (rf == 0) - regoffset = regoffset_a[index]; - else - regoffset = regoffset_b[index]; - - rtl8188e_PHY_SetBBReg(Adapter, regoffset, bMaskDWord, writeVal); - - /* 201005115 Joseph: Set Tx Power diff for Tx power training mechanism. */ - if (regoffset == rTxAGC_A_Mcs07_Mcs04 || regoffset == rTxAGC_B_Mcs07_Mcs04) { - writeVal = pwr_val[3]; - if (regoffset == rTxAGC_A_Mcs15_Mcs12 || regoffset == rTxAGC_A_Mcs07_Mcs04) - regoffset = 0xc90; - if (regoffset == rTxAGC_B_Mcs15_Mcs12 || regoffset == rTxAGC_B_Mcs07_Mcs04) - regoffset = 0xc98; - for (i = 0; i < 3; i++) { - if (i != 2) - writeVal = (writeVal > 8) ? (writeVal - 8) : 0; - else - writeVal = (writeVal > 6) ? (writeVal - 6) : 0; - rtw_write8(Adapter, (u32)(regoffset + i), (u8)writeVal); - } - } - } -} - -/*----------------------------------------------------------------------------- - * Function: PHY_RF6052SetOFDMTxPower - * - * Overview: For legacy and HY OFDM, we must read EEPROM TX power index for - * different channel and read original value in TX power register area from - * 0xe00. We increase offset and original value to be correct tx pwr. - * - * Input: NONE - * - * Output: NONE - * - * Return: NONE - * - * Revised History: - * When Who Remark - * 11/05/2008 MHC Simulate 8192 series method. - * 01/06/2009 MHC 1. Prevent Path B tx power overflow or underflow dure to - * A/B pwr difference or legacy/HT pwr diff. - * 2. We concern with path B legacy/HT OFDM difference. - * 01/22/2009 MHC Support new EPRO format from SD3. - * - *---------------------------------------------------------------------------*/ - -void -rtl8188e_PHY_RF6052SetOFDMTxPower( - struct adapter *Adapter, - u8 *pPowerLevelOFDM, - u8 *pPowerLevelBW20, - u8 *pPowerLevelBW40, - u8 Channel) -{ - struct hal_data_8188e *pHalData = &Adapter->haldata; - u32 writeVal[2], powerBase0[2], powerBase1[2], pwrtrac_value; - u8 direction; - u8 index = 0; - - getpowerbase88e(Adapter, pPowerLevelOFDM, pPowerLevelBW20, pPowerLevelBW40, Channel, &powerBase0[0], &powerBase1[0]); - - /* 2012/04/23 MH According to power tracking value, we need to revise OFDM tx power. */ - /* This is ued to fix unstable power tracking mode. */ - ODM_TxPwrTrackAdjust88E(&pHalData->odmpriv, 0, &direction, &pwrtrac_value); - - for (index = 0; index < 6; index++) { - get_rx_power_val_by_reg(Adapter, Channel, index, - &powerBase0[0], &powerBase1[0], - &writeVal[0]); - - if (direction == 1) { - writeVal[0] += pwrtrac_value; - writeVal[1] += pwrtrac_value; - } else if (direction == 2) { - writeVal[0] -= pwrtrac_value; - writeVal[1] -= pwrtrac_value; - } - writeOFDMPowerReg88E(Adapter, index, &writeVal[0]); - } -} - -int phy_RF6052_Config_ParaFile(struct adapter *Adapter) -{ - struct bb_reg_def *pPhyReg; - struct hal_data_8188e *pHalData = &Adapter->haldata; - u32 u4RegValue = 0; - int err; - - /* Initialize RF */ - - pPhyReg = &pHalData->PHYRegDef; - - /*----Store original RFENV control type----*/ - u4RegValue = rtl8188e_PHY_QueryBBReg(Adapter, pPhyReg->rfintfs, bRFSI_RFENV); - - /*----Set RF_ENV enable----*/ - rtl8188e_PHY_SetBBReg(Adapter, pPhyReg->rfintfe, bRFSI_RFENV << 16, 0x1); - udelay(1);/* PlatformStallExecution(1); */ - - /*----Set RF_ENV output high----*/ - rtl8188e_PHY_SetBBReg(Adapter, pPhyReg->rfintfo, bRFSI_RFENV, 0x1); - udelay(1);/* PlatformStallExecution(1); */ - - /* Set bit number of Address and Data for RF register */ - rtl8188e_PHY_SetBBReg(Adapter, pPhyReg->rfHSSIPara2, b3WireAddressLength, 0x0); /* Set 1 to 4 bits for 8255 */ - udelay(1);/* PlatformStallExecution(1); */ - - rtl8188e_PHY_SetBBReg(Adapter, pPhyReg->rfHSSIPara2, b3WireDataLength, 0x0); /* Set 0 to 12 bits for 8255 */ - udelay(1);/* PlatformStallExecution(1); */ - - /*----Initialize RF fom connfiguration file----*/ - err = ODM_ReadAndConfig_RadioA_1T_8188E(&pHalData->odmpriv); - - /*----Restore RFENV control type----*/; - rtl8188e_PHY_SetBBReg(Adapter, pPhyReg->rfintfs, bRFSI_RFENV, u4RegValue); - - return err; -} diff --git a/drivers/staging/r8188eu/hal/rtl8188e_rxdesc.c b/drivers/staging/r8188eu/hal/rtl8188e_rxdesc.c deleted file mode 100644 index d1ac2960f1c4..000000000000 --- a/drivers/staging/r8188eu/hal/rtl8188e_rxdesc.c +++ /dev/null @@ -1,161 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#define _RTL8188E_REDESC_C_ - -#include "../include/osdep_service.h" -#include "../include/drv_types.h" -#include "../include/rtl8188e_hal.h" - -static void process_rssi(struct adapter *padapter, struct recv_frame *prframe) -{ - struct rx_pkt_attrib *pattrib = &prframe->attrib; - struct signal_stat *signal_stat = &padapter->recvpriv.signal_strength_data; - - if (signal_stat->update_req) { - signal_stat->total_num = 0; - signal_stat->total_val = 0; - signal_stat->update_req = 0; - } - - signal_stat->total_num++; - signal_stat->total_val += pattrib->phy_info.SignalStrength; - signal_stat->avg_val = signal_stat->total_val / signal_stat->total_num; -} /* Process_UI_RSSI_8192C */ - -static void process_link_qual(struct adapter *padapter, struct recv_frame *prframe) -{ - struct rx_pkt_attrib *pattrib; - struct signal_stat *signal_stat; - - if (!prframe || !padapter) - return; - - pattrib = &prframe->attrib; - signal_stat = &padapter->recvpriv.signal_qual_data; - - if (signal_stat->update_req) { - signal_stat->total_num = 0; - signal_stat->total_val = 0; - signal_stat->update_req = 0; - } - - signal_stat->total_num++; - signal_stat->total_val += pattrib->phy_info.SignalQuality; - signal_stat->avg_val = signal_stat->total_val / signal_stat->total_num; -} - -static void rtl8188e_process_phy_info(struct adapter *padapter, void *prframe) -{ - struct recv_frame *precvframe = (struct recv_frame *)prframe; - - /* Check RSSI */ - process_rssi(padapter, precvframe); - /* Check EVM */ - process_link_qual(padapter, precvframe); -} - -void update_recvframe_attrib_88e(struct recv_frame *precvframe, struct recv_stat *prxstat) -{ - struct rx_pkt_attrib *pattrib = &precvframe->attrib; - memset(pattrib, 0, sizeof(struct rx_pkt_attrib)); - - pattrib->crc_err = (le32_to_cpu(prxstat->rxdw0) >> 14) & 0x1; - - pattrib->pkt_rpt_type = (le32_to_cpu(prxstat->rxdw3) >> 14) & 0x3; - - if (pattrib->pkt_rpt_type == NORMAL_RX) { - pattrib->pkt_len = le32_to_cpu(prxstat->rxdw0) & 0x00003fff; - pattrib->icv_err = (le32_to_cpu(prxstat->rxdw0) >> 15) & 0x1; - pattrib->drvinfo_sz = ((le32_to_cpu(prxstat->rxdw0) >> 16) & 0xf) * 8; - pattrib->encrypt = (u8)((le32_to_cpu(prxstat->rxdw0) >> 20) & 0x7); - pattrib->qos = (le32_to_cpu(prxstat->rxdw0) >> 23) & 0x1; - pattrib->shift_sz = (le32_to_cpu(prxstat->rxdw0) >> 24) & 0x3; - pattrib->physt = (le32_to_cpu(prxstat->rxdw0) >> 26) & 0x1; - pattrib->bdecrypted = (le32_to_cpu(prxstat->rxdw0) & BIT(27)) ? 0 : 1; - - pattrib->priority = (le32_to_cpu(prxstat->rxdw1) >> 8) & 0xf; - pattrib->amsdu = (le32_to_cpu(prxstat->rxdw1) >> 13) & 0x1; - pattrib->mdata = (le32_to_cpu(prxstat->rxdw1) >> 26) & 0x1; - pattrib->mfrag = (le32_to_cpu(prxstat->rxdw1) >> 27) & 0x1; - - pattrib->seq_num = le32_to_cpu(prxstat->rxdw2) & 0x00000fff; - pattrib->frag_num = (le32_to_cpu(prxstat->rxdw2) >> 12) & 0xf; - - pattrib->mcs_rate = le32_to_cpu(prxstat->rxdw3) & 0x3f; - pattrib->rxht = (le32_to_cpu(prxstat->rxdw3) >> 6) & 0x1; - - } else if (pattrib->pkt_rpt_type == TX_REPORT1) { /* CCX */ - pattrib->pkt_len = TX_RPT1_PKT_LEN; - } else if (pattrib->pkt_rpt_type == TX_REPORT2) { - pattrib->pkt_len = le32_to_cpu(prxstat->rxdw0) & 0x3FF; - - pattrib->MacIDValidEntry[0] = le32_to_cpu(prxstat->rxdw4); - pattrib->MacIDValidEntry[1] = le32_to_cpu(prxstat->rxdw5); - - } else if (pattrib->pkt_rpt_type == HIS_REPORT) { - pattrib->pkt_len = le32_to_cpu(prxstat->rxdw0) & 0x00003fff; - } -} - -/* - * Notice: - * Before calling this function, - * precvframe->rx_data should be ready! - */ -void update_recvframe_phyinfo_88e(struct recv_frame *precvframe, struct phy_stat *pphy_status) -{ - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)precvframe->rx_data; - struct adapter *padapter = precvframe->adapter; - struct rx_pkt_attrib *pattrib = &precvframe->attrib; - struct hal_data_8188e *pHalData = &padapter->haldata; - struct phy_info *pPHYInfo = &pattrib->phy_info; - u8 *wlanhdr = precvframe->rx_data; - struct odm_per_pkt_info pkt_info; - u8 *sa = NULL; - struct sta_priv *pstapriv; - struct sta_info *psta; - - pkt_info.bPacketMatchBSSID = ((!ieee80211_is_ctl(hdr->frame_control)) && - !pattrib->icv_err && !pattrib->crc_err && - !memcmp(get_hdr_bssid(wlanhdr), - get_bssid(&padapter->mlmepriv), ETH_ALEN)); - - pkt_info.bPacketToSelf = pkt_info.bPacketMatchBSSID && - ether_addr_equal(ieee80211_get_DA(hdr), - myid(&padapter->eeprompriv)); - - pkt_info.bPacketBeacon = pkt_info.bPacketMatchBSSID && - ieee80211_is_beacon(hdr->frame_control); - if (pkt_info.bPacketBeacon) { - if (check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE)) - sa = padapter->mlmepriv.cur_network.network.MacAddress; - /* to do Ad-hoc */ - } else { - sa = ieee80211_get_SA(hdr); - } - - pstapriv = &padapter->stapriv; - pkt_info.StationID = 0xFF; - psta = rtw_get_stainfo(pstapriv, sa); - if (psta) - pkt_info.StationID = psta->mac_id; - pkt_info.Rate = pattrib->mcs_rate; - - ODM_PhyStatusQuery(&pHalData->odmpriv, pPHYInfo, (u8 *)pphy_status, &(pkt_info), padapter); - - precvframe->psta = NULL; - if (pkt_info.bPacketMatchBSSID && - (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE))) { - if (psta) { - precvframe->psta = psta; - rtl8188e_process_phy_info(padapter, precvframe); - } - } else if (pkt_info.bPacketToSelf || pkt_info.bPacketBeacon) { - if (check_fwstate(&padapter->mlmepriv, WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE)) { - if (psta) - precvframe->psta = psta; - } - rtl8188e_process_phy_info(padapter, precvframe); - } -} diff --git a/drivers/staging/r8188eu/hal/rtl8188eu_xmit.c b/drivers/staging/r8188eu/hal/rtl8188eu_xmit.c deleted file mode 100644 index 3ffab4953a5c..000000000000 --- a/drivers/staging/r8188eu/hal/rtl8188eu_xmit.c +++ /dev/null @@ -1,627 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#define _RTL8188E_XMIT_C_ -#include "../include/osdep_service.h" -#include "../include/drv_types.h" -#include "../include/wifi.h" -#include "../include/osdep_intf.h" -#include "../include/usb_ops.h" -#include "../include/rtl8188e_hal.h" - -static void rtl8188eu_cal_txdesc_chksum(struct tx_desc *ptxdesc) -{ - u16 *usptr = (u16 *)ptxdesc; - u32 count = 16; /* (32 bytes / 2 bytes per XOR) => 16 times */ - u32 index; - u16 checksum = 0; - - /* Clear first */ - ptxdesc->txdw7 &= cpu_to_le32(0xffff0000); - - for (index = 0; index < count; index++) - checksum = checksum ^ le16_to_cpu(*(__le16 *)(usptr + index)); - ptxdesc->txdw7 |= cpu_to_le32(0x0000ffff & checksum); -} - -/* Description: In normal chip, we should send some packet to Hw which will be used by Fw */ -/* in FW LPS mode. The function is to fill the Tx descriptor of this packets, then */ -/* Fw can tell Hw to send these packet derectly. */ -void rtl8188e_fill_fake_txdesc(struct adapter *adapt, u8 *desc, u32 BufferLen, u8 ispspoll, u8 is_btqosnull) -{ - struct tx_desc *ptxdesc; - - /* Clear all status */ - ptxdesc = (struct tx_desc *)desc; - memset(desc, 0, TXDESC_SIZE); - - /* offset 0 */ - ptxdesc->txdw0 |= cpu_to_le32(OWN | FSG | LSG); /* own, bFirstSeg, bLastSeg; */ - - ptxdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE + OFFSET_SZ) << OFFSET_SHT) & 0x00ff0000); /* 32 bytes for TX Desc */ - - ptxdesc->txdw0 |= cpu_to_le32(BufferLen & 0x0000ffff); /* Buffer size + command header */ - - /* offset 4 */ - ptxdesc->txdw1 |= cpu_to_le32((QSLT_MGNT << QSEL_SHT) & 0x00001f00); /* Fixed queue of Mgnt queue */ - - /* Set NAVUSEHDR to prevent Ps-poll AId filed to be changed to error vlaue by Hw. */ - if (ispspoll) { - ptxdesc->txdw1 |= cpu_to_le32(NAVUSEHDR); - } else { - ptxdesc->txdw4 |= cpu_to_le32(BIT(7)); /* Hw set sequence number */ - ptxdesc->txdw3 |= cpu_to_le32((8 << 28)); /* set bit3 to 1. Suugested by TimChen. 2009.12.29. */ - } - - if (is_btqosnull) - ptxdesc->txdw2 |= cpu_to_le32(BIT(23)); /* BT NULL */ - - /* offset 16 */ - ptxdesc->txdw4 |= cpu_to_le32(BIT(8));/* driver uses rate */ - - /* USB interface drop packet if the checksum of descriptor isn't correct. */ - /* Using this checksum can let hardware recovery from packet bulk out error (e.g. Cancel URC, Bulk out error.). */ - rtl8188eu_cal_txdesc_chksum(ptxdesc); -} - -static void fill_txdesc_sectype(struct pkt_attrib *pattrib, struct tx_desc *ptxdesc) -{ - if ((pattrib->encrypt > 0) && !pattrib->bswenc) { - switch (pattrib->encrypt) { - /* SEC_TYPE : 0:NO_ENC,1:WEP40/TKIP,2:WAPI,3:AES */ - case _WEP40_: - case _WEP104_: - ptxdesc->txdw1 |= cpu_to_le32((0x01 << SEC_TYPE_SHT) & 0x00c00000); - ptxdesc->txdw2 |= cpu_to_le32(0x7 << AMPDU_DENSITY_SHT); - break; - case _TKIP_: - case _TKIP_WTMIC_: - ptxdesc->txdw1 |= cpu_to_le32((0x01 << SEC_TYPE_SHT) & 0x00c00000); - ptxdesc->txdw2 |= cpu_to_le32(0x7 << AMPDU_DENSITY_SHT); - break; - case _AES_: - ptxdesc->txdw1 |= cpu_to_le32((0x03 << SEC_TYPE_SHT) & 0x00c00000); - ptxdesc->txdw2 |= cpu_to_le32(0x7 << AMPDU_DENSITY_SHT); - break; - case _NO_PRIVACY_: - default: - break; - } - } -} - -static void fill_txdesc_vcs(struct pkt_attrib *pattrib, __le32 *pdw) -{ - switch (pattrib->vcs_mode) { - case RTS_CTS: - *pdw |= cpu_to_le32(RTS_EN); - break; - case CTS_TO_SELF: - *pdw |= cpu_to_le32(CTS_2_SELF); - break; - case NONE_VCS: - default: - break; - } - if (pattrib->vcs_mode) { - *pdw |= cpu_to_le32(HW_RTS_EN); - /* Set RTS BW */ - if (pattrib->ht_en) { - *pdw |= (pattrib->bwmode & HT_CHANNEL_WIDTH_40) ? cpu_to_le32(BIT(27)) : 0; - - if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER) - *pdw |= cpu_to_le32((0x01 << 28) & 0x30000000); - else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER) - *pdw |= cpu_to_le32((0x02 << 28) & 0x30000000); - else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE) - *pdw |= 0; - else - *pdw |= cpu_to_le32((0x03 << 28) & 0x30000000); - } - } -} - -static void fill_txdesc_phy(struct pkt_attrib *pattrib, __le32 *pdw) -{ - if (pattrib->ht_en) { - *pdw |= (pattrib->bwmode & HT_CHANNEL_WIDTH_40) ? cpu_to_le32(BIT(25)) : 0; - - if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER) - *pdw |= cpu_to_le32((0x01 << DATA_SC_SHT) & 0x003f0000); - else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER) - *pdw |= cpu_to_le32((0x02 << DATA_SC_SHT) & 0x003f0000); - else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE) - *pdw |= 0; - else - *pdw |= cpu_to_le32((0x03 << DATA_SC_SHT) & 0x003f0000); - } -} - -static s32 update_txdesc(struct xmit_frame *pxmitframe, u8 *pmem, s32 sz) -{ - uint qsel; - u8 data_rate, pwr_status, offset; - struct adapter *adapt = pxmitframe->padapter; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct hal_data_8188e *haldata = &adapt->haldata; - struct tx_desc *ptxdesc = (struct tx_desc *)pmem; - struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - memset(ptxdesc, 0, sizeof(struct tx_desc)); - - /* 4 offset 0 */ - ptxdesc->txdw0 |= cpu_to_le32(OWN | FSG | LSG); - ptxdesc->txdw0 |= cpu_to_le32(sz & 0x0000ffff);/* update TXPKTSIZE */ - - offset = TXDESC_SIZE + OFFSET_SZ; - - ptxdesc->txdw0 |= cpu_to_le32(((offset) << OFFSET_SHT) & 0x00ff0000);/* 32 bytes for TX Desc */ - - if (is_multicast_ether_addr(pattrib->ra)) - ptxdesc->txdw0 |= cpu_to_le32(BMC); - - /* pkt_offset, unit:8 bytes padding */ - if (pxmitframe->pkt_offset > 0) - ptxdesc->txdw1 |= cpu_to_le32((pxmitframe->pkt_offset << 26) & 0x7c000000); - - /* driver uses rate */ - ptxdesc->txdw4 |= cpu_to_le32(USERATE);/* rate control always by driver */ - - if ((pxmitframe->frame_tag & 0x0f) == DATA_FRAMETAG) { - /* offset 4 */ - ptxdesc->txdw1 |= cpu_to_le32(pattrib->mac_id & 0x3F); - - qsel = (uint)(pattrib->qsel & 0x0000001f); - ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00); - - ptxdesc->txdw1 |= cpu_to_le32((pattrib->raid << RATE_ID_SHT) & 0x000F0000); - - fill_txdesc_sectype(pattrib, ptxdesc); - - if (pattrib->ampdu_en) { - ptxdesc->txdw2 |= cpu_to_le32(AGG_EN);/* AGG EN */ - ptxdesc->txdw6 = cpu_to_le32(0x6666f800); - } else { - ptxdesc->txdw2 |= cpu_to_le32(AGG_BK);/* AGG BK */ - } - - /* offset 8 */ - - /* offset 12 */ - ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum << SEQ_SHT) & 0x0FFF0000); - - /* offset 16 , offset 20 */ - if (pattrib->qos_en) - ptxdesc->txdw4 |= cpu_to_le32(QOS);/* QoS */ - - /* offset 20 */ - if (pxmitframe->agg_num > 1) - ptxdesc->txdw5 |= cpu_to_le32((pxmitframe->agg_num << USB_TXAGG_NUM_SHT) & 0xFF000000); - - if ((pattrib->ether_type != 0x888e) && - (pattrib->ether_type != 0x0806) && - (pattrib->ether_type != 0x88b4) && - (pattrib->dhcp_pkt != 1)) { - /* Non EAP & ARP & DHCP type data packet */ - - fill_txdesc_vcs(pattrib, &ptxdesc->txdw4); - fill_txdesc_phy(pattrib, &ptxdesc->txdw4); - - ptxdesc->txdw4 |= cpu_to_le32(0x00000008);/* RTS Rate=24M */ - ptxdesc->txdw5 |= cpu_to_le32(0x0001ff00);/* DATA/RTS Rate FB LMT */ - - if (pattrib->ht_en) { - if (ODM_RA_GetShortGI_8188E(&haldata->odmpriv, pattrib->mac_id)) - ptxdesc->txdw5 |= cpu_to_le32(SGI);/* SGI */ - } - data_rate = ODM_RA_GetDecisionRate_8188E(&haldata->odmpriv, pattrib->mac_id); - ptxdesc->txdw5 |= cpu_to_le32(data_rate & 0x3F); - pwr_status = ODM_RA_GetHwPwrStatus_8188E(&haldata->odmpriv, pattrib->mac_id); - ptxdesc->txdw4 |= cpu_to_le32((pwr_status & 0x7) << PWR_STATUS_SHT); - } else { - /* EAP data packet and ARP packet and DHCP. */ - /* Use the 1M data rate to send the EAP/ARP packet. */ - /* This will maybe make the handshake smooth. */ - ptxdesc->txdw2 |= cpu_to_le32(AGG_BK);/* AGG BK */ - if (pmlmeinfo->preamble_mode == PREAMBLE_SHORT) - ptxdesc->txdw4 |= cpu_to_le32(BIT(24));/* DATA_SHORT */ - ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate(pmlmeext->tx_rate)); - } - } else if ((pxmitframe->frame_tag & 0x0f) == MGNT_FRAMETAG) { - /* offset 4 */ - ptxdesc->txdw1 |= cpu_to_le32(pattrib->mac_id & 0x3f); - - qsel = (uint)(pattrib->qsel & 0x0000001f); - ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00); - - ptxdesc->txdw1 |= cpu_to_le32((pattrib->raid << RATE_ID_SHT) & 0x000f0000); - - /* offset 8 */ - /* CCX-TXRPT ack for xmit mgmt frames. */ - if (pxmitframe->ack_report) - ptxdesc->txdw2 |= cpu_to_le32(BIT(19)); - - /* offset 12 */ - ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum << SEQ_SHT) & 0x0FFF0000); - - /* offset 20 */ - ptxdesc->txdw5 |= cpu_to_le32(RTY_LMT_EN);/* retry limit enable */ - if (pattrib->retry_ctrl) - ptxdesc->txdw5 |= cpu_to_le32(0x00180000);/* retry limit = 6 */ - else - ptxdesc->txdw5 |= cpu_to_le32(0x00300000);/* retry limit = 12 */ - - ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate(pmlmeext->tx_rate)); - } else if ((pxmitframe->frame_tag & 0x0f) != TXAGG_FRAMETAG) { - /* offset 4 */ - ptxdesc->txdw1 |= cpu_to_le32((4) & 0x3f);/* CAM_ID(MAC_ID) */ - - ptxdesc->txdw1 |= cpu_to_le32((6 << RATE_ID_SHT) & 0x000f0000);/* raid */ - - /* offset 8 */ - - /* offset 12 */ - ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum << SEQ_SHT) & 0x0fff0000); - - /* offset 20 */ - ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate(pmlmeext->tx_rate)); - } - - /* 2009.11.05. tynli_test. Suggested by SD4 Filen for FW LPS. */ - /* (1) The sequence number of each non-Qos frame / broadcast / multicast / */ - /* mgnt frame should be controlled by Hw because Fw will also send null data */ - /* which we cannot control when Fw LPS enable. */ - /* --> default enable non-Qos data sequense number. 2010.06.23. by tynli. */ - /* (2) Enable HW SEQ control for beacon packet, because we use Hw beacon. */ - /* (3) Use HW Qos SEQ to control the seq num of Ext port non-Qos packets. */ - /* 2010.06.23. Added by tynli. */ - if (!pattrib->qos_en) { - ptxdesc->txdw3 |= cpu_to_le32(EN_HWSEQ); /* Hw set sequence number */ - ptxdesc->txdw4 |= cpu_to_le32(HW_SSN); /* Hw set sequence number */ - } - - ODM_SetTxAntByTxInfo_88E(&haldata->odmpriv, pmem, pattrib->mac_id); - - rtl8188eu_cal_txdesc_chksum(ptxdesc); - return 0; -} - -/* for non-agg data frame or management frame */ -static s32 rtw_dump_xframe(struct adapter *adapt, struct xmit_frame *pxmitframe) -{ - s32 ret = _SUCCESS; - s32 inner_ret = _SUCCESS; - int t, sz, w_sz, pull = 0; - u8 *mem_addr; - u32 ff_hwaddr; - struct xmit_buf *pxmitbuf = pxmitframe->pxmitbuf; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct xmit_priv *pxmitpriv = &adapt->xmitpriv; - struct security_priv *psecuritypriv = &adapt->securitypriv; - if ((pxmitframe->frame_tag == DATA_FRAMETAG) && - (pxmitframe->attrib.ether_type != 0x0806) && - (pxmitframe->attrib.ether_type != 0x888e) && - (pxmitframe->attrib.ether_type != 0x88b4) && - (pxmitframe->attrib.dhcp_pkt != 1)) - rtw_issue_addbareq_cmd(adapt, pxmitframe); - mem_addr = pxmitframe->buf_addr; - - for (t = 0; t < pattrib->nr_frags; t++) { - if (inner_ret != _SUCCESS && ret == _SUCCESS) - ret = _FAIL; - - if (t != (pattrib->nr_frags - 1)) { - sz = pxmitpriv->frag_len; - sz = sz - 4 - (psecuritypriv->sw_encrypt ? 0 : pattrib->icv_len); - } else { - /* no frag */ - sz = pattrib->last_txcmdsz; - } - - pull = update_txdesc(pxmitframe, mem_addr, sz); - - if (pull) { - mem_addr += PACKET_OFFSET_SZ; /* pull txdesc head */ - pxmitframe->buf_addr = mem_addr; - w_sz = sz + TXDESC_SIZE; - } else { - w_sz = sz + TXDESC_SIZE + PACKET_OFFSET_SZ; - } - ff_hwaddr = rtw_get_ff_hwaddr(pxmitframe); - - inner_ret = rtw_write_port(adapt, ff_hwaddr, w_sz, (unsigned char *)pxmitbuf); - - rtw_count_tx_stats(adapt, pxmitframe, sz); - - mem_addr += w_sz; - - mem_addr = PTR_ALIGN(mem_addr, 4); - } - - rtw_free_xmitframe(pxmitpriv, pxmitframe); - - if (ret != _SUCCESS) - rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_UNKNOWN); - - return ret; -} - -static u32 xmitframe_need_length(struct xmit_frame *pxmitframe) -{ - struct pkt_attrib *pattrib = &pxmitframe->attrib; - - u32 len = 0; - - /* no consider fragement */ - len = pattrib->hdrlen + pattrib->iv_len + - SNAP_SIZE + sizeof(u16) + - pattrib->pktlen + - ((pattrib->bswenc) ? pattrib->icv_len : 0); - - if (pattrib->encrypt == _TKIP_) - len += 8; - - return len; -} - -bool rtl8188eu_xmitframe_complete(struct adapter *adapt) -{ - struct xmit_priv *pxmitpriv = &adapt->xmitpriv; - struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(adapt); - struct xmit_frame *pxmitframe = NULL; - struct xmit_frame *pfirstframe = NULL; - struct xmit_buf *pxmitbuf; - - /* aggregate variable */ - struct hw_xmit *phwxmit; - struct sta_info *psta = NULL; - struct tx_servq *ptxservq = NULL; - struct list_head *xmitframe_plist = NULL, *xmitframe_phead = NULL; - - u32 pbuf; /* next pkt address */ - u32 pbuf_tail; /* last pkt tail */ - u32 len; /* packet length, except TXDESC_SIZE and PKT_OFFSET */ - - u32 bulksize; - u8 desc_cnt; - u32 bulkptr; - - /* dump frame variable */ - u32 ff_hwaddr; - - if (pdvobjpriv->pusbdev->speed == USB_SPEED_HIGH) - bulksize = USB_HIGH_SPEED_BULK_SIZE; - else - bulksize = USB_FULL_SPEED_BULK_SIZE; - - pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv); - if (!pxmitbuf) - return false; - - pxmitframe = rtw_dequeue_xframe(pxmitpriv, pxmitpriv->hwxmits); - if (!pxmitframe) { - /* no more xmit frame, release xmit buffer */ - rtw_free_xmitbuf(pxmitpriv, pxmitbuf); - return false; - } - - pxmitframe->pxmitbuf = pxmitbuf; - pxmitframe->buf_addr = pxmitbuf->pbuf; - pxmitbuf->priv_data = pxmitframe; - - pxmitframe->agg_num = 1; /* alloc xmitframe should assign to 1. */ - pxmitframe->pkt_offset = 1; /* first frame of aggregation, reserve offset */ - - rtw_xmitframe_coalesce(adapt, pxmitframe->pkt, pxmitframe); - - /* always return ndis_packet after rtw_xmitframe_coalesce */ - rtw_xmit_complete(adapt, pxmitframe); - - /* 3 2. aggregate same priority and same DA(AP or STA) frames */ - pfirstframe = pxmitframe; - len = xmitframe_need_length(pfirstframe) + TXDESC_SIZE + (pfirstframe->pkt_offset * PACKET_OFFSET_SZ); - pbuf_tail = len; - pbuf = round_up(pbuf_tail, 8); - - /* check pkt amount in one bulk */ - desc_cnt = 0; - bulkptr = bulksize; - if (pbuf < bulkptr) { - desc_cnt++; - } else { - desc_cnt = 0; - bulkptr = ((pbuf / bulksize) + 1) * bulksize; /* round to next bulksize */ - } - - /* dequeue same priority packet from station tx queue */ - psta = pfirstframe->attrib.psta; - switch (pfirstframe->attrib.priority) { - case 1: - case 2: - ptxservq = &psta->sta_xmitpriv.bk_q; - phwxmit = pxmitpriv->hwxmits + 3; - break; - case 4: - case 5: - ptxservq = &psta->sta_xmitpriv.vi_q; - phwxmit = pxmitpriv->hwxmits + 1; - break; - case 6: - case 7: - ptxservq = &psta->sta_xmitpriv.vo_q; - phwxmit = pxmitpriv->hwxmits; - break; - case 0: - case 3: - default: - ptxservq = &psta->sta_xmitpriv.be_q; - phwxmit = pxmitpriv->hwxmits + 2; - break; - } - spin_lock_bh(&pxmitpriv->lock); - - xmitframe_phead = &ptxservq->sta_pending; - xmitframe_plist = xmitframe_phead->next; - - while (xmitframe_phead != xmitframe_plist) { - pxmitframe = container_of(xmitframe_plist, struct xmit_frame, list); - xmitframe_plist = xmitframe_plist->next; - - pxmitframe->agg_num = 0; /* not first frame of aggregation */ - pxmitframe->pkt_offset = 0; /* not first frame of aggregation, no need to reserve offset */ - - len = xmitframe_need_length(pxmitframe) + TXDESC_SIZE + (pxmitframe->pkt_offset * PACKET_OFFSET_SZ); - - if (pbuf + len > MAX_XMITBUF_SZ) { - pxmitframe->agg_num = 1; - pxmitframe->pkt_offset = 1; - break; - } - list_del_init(&pxmitframe->list); - ptxservq->qcnt--; - phwxmit->accnt--; - - pxmitframe->buf_addr = pxmitbuf->pbuf + pbuf; - - rtw_xmitframe_coalesce(adapt, pxmitframe->pkt, pxmitframe); - /* always return ndis_packet after rtw_xmitframe_coalesce */ - rtw_xmit_complete(adapt, pxmitframe); - - /* (len - TXDESC_SIZE) == pxmitframe->attrib.last_txcmdsz */ - update_txdesc(pxmitframe, pxmitframe->buf_addr, pxmitframe->attrib.last_txcmdsz); - - /* don't need xmitframe any more */ - rtw_free_xmitframe(pxmitpriv, pxmitframe); - - /* handle pointer and stop condition */ - pbuf_tail = pbuf + len; - pbuf = round_up(pbuf_tail, 8); - - pfirstframe->agg_num++; - if (MAX_TX_AGG_PACKET_NUMBER == pfirstframe->agg_num) - break; - - if (pbuf < bulkptr) { - desc_cnt++; - if (desc_cnt == USB_TXAGG_DESC_NUM) - break; - } else { - desc_cnt = 0; - bulkptr = ((pbuf / bulksize) + 1) * bulksize; - } - } /* end while (aggregate same priority and same DA(AP or STA) frames) */ - - if (list_empty(&ptxservq->sta_pending)) - list_del_init(&ptxservq->tx_pending); - - spin_unlock_bh(&pxmitpriv->lock); - if ((pfirstframe->attrib.ether_type != 0x0806) && - (pfirstframe->attrib.ether_type != 0x888e) && - (pfirstframe->attrib.ether_type != 0x88b4) && - (pfirstframe->attrib.dhcp_pkt != 1)) - rtw_issue_addbareq_cmd(adapt, pfirstframe); - /* 3 3. update first frame txdesc */ - if ((pbuf_tail % bulksize) == 0) { - /* remove pkt_offset */ - pbuf_tail -= PACKET_OFFSET_SZ; - pfirstframe->buf_addr += PACKET_OFFSET_SZ; - pfirstframe->pkt_offset--; - } - - update_txdesc(pfirstframe, pfirstframe->buf_addr, pfirstframe->attrib.last_txcmdsz); - - /* 3 4. write xmit buffer to USB FIFO */ - ff_hwaddr = rtw_get_ff_hwaddr(pfirstframe); - rtw_write_port(adapt, ff_hwaddr, pbuf_tail, (u8 *)pxmitbuf); - - /* 3 5. update statisitc */ - pbuf_tail -= (pfirstframe->agg_num * TXDESC_SIZE); - pbuf_tail -= (pfirstframe->pkt_offset * PACKET_OFFSET_SZ); - - rtw_count_tx_stats(adapt, pfirstframe, pbuf_tail); - - rtw_free_xmitframe(pxmitpriv, pfirstframe); - - return true; -} - -static s32 xmitframe_direct(struct adapter *adapt, struct xmit_frame *pxmitframe) -{ - s32 res = _SUCCESS; - - res = rtw_xmitframe_coalesce(adapt, pxmitframe->pkt, pxmitframe); - if (res == _SUCCESS) - rtw_dump_xframe(adapt, pxmitframe); - - return res; -} - -/* - * Return - * true dump packet directly - * false enqueue packet - */ -static s32 pre_xmitframe(struct adapter *adapt, struct xmit_frame *pxmitframe) -{ - s32 res; - struct xmit_buf *pxmitbuf = NULL; - struct xmit_priv *pxmitpriv = &adapt->xmitpriv; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct mlme_priv *pmlmepriv = &adapt->mlmepriv; - - spin_lock_bh(&pxmitpriv->lock); - - if (rtw_txframes_sta_ac_pending(adapt, pattrib) > 0) - goto enqueue; - - if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING)) - goto enqueue; - - pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv); - if (!pxmitbuf) - goto enqueue; - - spin_unlock_bh(&pxmitpriv->lock); - - pxmitframe->pxmitbuf = pxmitbuf; - pxmitframe->buf_addr = pxmitbuf->pbuf; - pxmitbuf->priv_data = pxmitframe; - - if (xmitframe_direct(adapt, pxmitframe) != _SUCCESS) { - rtw_free_xmitbuf(pxmitpriv, pxmitbuf); - rtw_free_xmitframe(pxmitpriv, pxmitframe); - } - - return true; - -enqueue: - res = rtw_xmit_classifier(adapt, pxmitframe); - spin_unlock_bh(&pxmitpriv->lock); - - if (res != _SUCCESS) { - rtw_free_xmitframe(pxmitpriv, pxmitframe); - - /* Trick, make the statistics correct */ - pxmitpriv->tx_pkts--; - pxmitpriv->tx_drop++; - return true; - } - - return false; -} - -s32 rtl8188eu_mgnt_xmit(struct adapter *adapt, struct xmit_frame *pmgntframe) -{ - return rtw_dump_xframe(adapt, pmgntframe); -} - -/* - * Return - * true dump packet directly ok - * false temporary can't transmit packets to hardware - */ -s32 rtl8188eu_hal_xmit(struct adapter *adapt, struct xmit_frame *pxmitframe) -{ - return pre_xmitframe(adapt, pxmitframe); -} diff --git a/drivers/staging/r8188eu/hal/usb_halinit.c b/drivers/staging/r8188eu/hal/usb_halinit.c deleted file mode 100644 index a1051ac1cac4..000000000000 --- a/drivers/staging/r8188eu/hal/usb_halinit.c +++ /dev/null @@ -1,1069 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#define _HCI_HAL_INIT_C_ - -#include "../include/osdep_service.h" -#include "../include/drv_types.h" -#include "../include/rtw_efuse.h" -#include "../include/rtw_fw.h" -#include "../include/rtl8188e_hal.h" -#include "../include/rtw_iol.h" -#include "../include/usb_ops.h" -#include "../include/usb_osintf.h" -#include "../include/HalPwrSeqCmd.h" - -static void one_out_pipe(struct adapter *adapter) -{ - struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(adapter); - - pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0];/* VO */ - pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[0];/* VI */ - pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[0];/* BE */ - pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[0];/* BK */ -} - -static void two_out_pipe(struct adapter *adapter, bool wifi_cfg) -{ - struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(adapter); - - /* 0:H, 1:L */ - - pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[0];/* VI */ - pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[1];/* BE */ - - if (wifi_cfg) { - pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[1];/* VO */ - pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[0];/* BK */ - } else { - pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0];/* VO */ - pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[1];/* BK */ - } -} - -static void three_out_pipe(struct adapter *adapter, bool wifi_cfg) -{ - struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(adapter); - - /* 0:H, 1:N, 2:L */ - - pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0];/* VO */ - pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[1];/* VI */ - pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[2];/* BE */ - - pdvobjpriv->Queue2Pipe[3] = wifi_cfg ? - pdvobjpriv->RtOutPipe[1] : pdvobjpriv->RtOutPipe[2];/* BK */ -} - -int rtl8188eu_interface_configure(struct adapter *adapt) -{ - struct registry_priv *pregistrypriv = &adapt->registrypriv; - struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(adapt); - struct hal_data_8188e *haldata = &adapt->haldata; - bool wifi_cfg = pregistrypriv->wifi_spec; - - pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0];/* BCN */ - pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0];/* MGT */ - pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0];/* HIGH */ - pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0];/* TXCMD */ - - switch (pdvobjpriv->RtNumOutPipes) { - case 3: - haldata->out_ep_extra_queues = TX_SELE_LQ | TX_SELE_NQ; - three_out_pipe(adapt, wifi_cfg); - break; - case 2: - haldata->out_ep_extra_queues = TX_SELE_NQ; - two_out_pipe(adapt, wifi_cfg); - break; - case 1: - one_out_pipe(adapt); - break; - default: - return -ENXIO; - } - - return 0; -} - -u32 rtl8188eu_InitPowerOn(struct adapter *adapt) -{ - u16 value16; - int res; - - /* HW Power on sequence */ - struct hal_data_8188e *haldata = &adapt->haldata; - if (haldata->bMacPwrCtrlOn) - return _SUCCESS; - - if (!HalPwrSeqCmdParsing(adapt, PWR_ON_FLOW)) - return _FAIL; - - /* Enable MAC DMA/WMAC/SCHEDULE/SEC block */ - /* Set CR bit10 to enable 32k calibration. Suggested by SD1 Gimmy. Added by tynli. 2011.08.31. */ - rtw_write16(adapt, REG_CR, 0x00); /* suggseted by zhouzhou, by page, 20111230 */ - - /* Enable MAC DMA/WMAC/SCHEDULE/SEC block */ - res = rtw_read16(adapt, REG_CR, &value16); - if (res) - return _FAIL; - - value16 |= (HCI_TXDMA_EN | HCI_RXDMA_EN | TXDMA_EN | RXDMA_EN - | PROTOCOL_EN | SCHEDULE_EN | ENSEC | CALTMR_EN); - /* for SDIO - Set CR bit10 to enable 32k calibration. Suggested by SD1 Gimmy. Added by tynli. 2011.08.31. */ - - rtw_write16(adapt, REG_CR, value16); - haldata->bMacPwrCtrlOn = true; - - return _SUCCESS; -} - -/* Shall USB interface init this? */ -static void _InitInterrupt(struct adapter *Adapter) -{ - u32 imr, imr_ex; - u8 usb_opt; - int res; - - /* HISR write one to clear */ - rtw_write32(Adapter, REG_HISR_88E, 0xFFFFFFFF); - /* HIMR - */ - imr = IMR_PSTIMEOUT_88E | IMR_TBDER_88E | IMR_CPWM_88E | IMR_CPWM2_88E; - rtw_write32(Adapter, REG_HIMR_88E, imr); - - imr_ex = IMR_TXERR_88E | IMR_RXERR_88E | IMR_TXFOVW_88E | IMR_RXFOVW_88E; - rtw_write32(Adapter, REG_HIMRE_88E, imr_ex); - - /* REG_USB_SPECIAL_OPTION - BIT(4) */ - /* 0; Use interrupt endpoint to upload interrupt pkt */ - /* 1; Use bulk endpoint to upload interrupt pkt, */ - res = rtw_read8(Adapter, REG_USB_SPECIAL_OPTION, &usb_opt); - if (res) - return; - - if (adapter_to_dvobj(Adapter)->pusbdev->speed == USB_SPEED_HIGH) - usb_opt = usb_opt | (INT_BULK_SEL); - else - usb_opt = usb_opt & (~INT_BULK_SEL); - - rtw_write8(Adapter, REG_USB_SPECIAL_OPTION, usb_opt); -} - -static void _InitQueueReservedPage(struct adapter *Adapter) -{ - struct hal_data_8188e *haldata = &Adapter->haldata; - struct registry_priv *pregistrypriv = &Adapter->registrypriv; - u8 numLQ = 0; - u8 numNQ = 0; - u8 numPubQ; - - if (pregistrypriv->wifi_spec) { - if (haldata->out_ep_extra_queues & TX_SELE_LQ) - numLQ = 0x1C; - - /* NOTE: This step shall be proceed before writing REG_RQPN. */ - if (haldata->out_ep_extra_queues & TX_SELE_NQ) - numNQ = 0x1C; - - rtw_write8(Adapter, REG_RQPN_NPQ, numNQ); - - numPubQ = 0xA8 - NUM_HQ - numLQ - numNQ; - - /* TX DMA */ - rtw_write32(Adapter, REG_RQPN, LD_RQPN | numPubQ << 16 | numLQ << 8 | NUM_HQ); - } else { - rtw_write16(Adapter, REG_RQPN_NPQ, 0x0000);/* Just follow MP Team,??? Georgia 03/28 */ - rtw_write16(Adapter, REG_RQPN_NPQ, 0x0d); - rtw_write32(Adapter, REG_RQPN, 0x808E000d);/* reserve 7 page for LPS */ - } -} - -static void _InitTxBufferBoundary(struct adapter *Adapter, u8 txpktbuf_bndy) -{ - rtw_write8(Adapter, REG_TXPKTBUF_BCNQ_BDNY, txpktbuf_bndy); - rtw_write8(Adapter, REG_TXPKTBUF_MGQ_BDNY, txpktbuf_bndy); - rtw_write8(Adapter, REG_TXPKTBUF_WMAC_LBK_BF_HD, txpktbuf_bndy); - rtw_write8(Adapter, REG_TRXFF_BNDY, txpktbuf_bndy); - rtw_write8(Adapter, REG_TDECTRL + 1, txpktbuf_bndy); -} - -static void _InitPageBoundary(struct adapter *Adapter) -{ - /* RX Page Boundary */ - /* */ - u16 rxff_bndy = MAX_RX_DMA_BUFFER_SIZE_88E - 1; - - rtw_write16(Adapter, (REG_TRXFF_BNDY + 2), rxff_bndy); -} - -static void _InitNormalChipRegPriority(struct adapter *Adapter, u16 beQ, - u16 bkQ, u16 viQ, u16 voQ, u16 mgtQ, - u16 hiQ) -{ - u16 value16; - int res; - - res = rtw_read16(Adapter, REG_TRXDMA_CTRL, &value16); - if (res) - return; - - value16 &= 0x7; - - value16 |= _TXDMA_BEQ_MAP(beQ) | _TXDMA_BKQ_MAP(bkQ) | - _TXDMA_VIQ_MAP(viQ) | _TXDMA_VOQ_MAP(voQ) | - _TXDMA_MGQ_MAP(mgtQ) | _TXDMA_HIQ_MAP(hiQ); - - rtw_write16(Adapter, REG_TRXDMA_CTRL, value16); -} - -static void _InitNormalChipTwoOutEpPriority(struct adapter *Adapter) -{ - struct registry_priv *pregistrypriv = &Adapter->registrypriv; - u16 bkQ, voQ; - - if (!pregistrypriv->wifi_spec) { - bkQ = QUEUE_NORMAL; - voQ = QUEUE_HIGH; - } else {/* for WMM ,CONFIG_OUT_EP_WIFI_MODE */ - bkQ = QUEUE_HIGH; - voQ = QUEUE_NORMAL; - } - _InitNormalChipRegPriority(Adapter, QUEUE_NORMAL, bkQ, QUEUE_HIGH, - voQ, QUEUE_HIGH, QUEUE_HIGH); -} - -static void _InitNormalChipThreeOutEpPriority(struct adapter *Adapter) -{ - struct registry_priv *pregistrypriv = &Adapter->registrypriv; - u16 beQ, bkQ, viQ, voQ, mgtQ, hiQ; - - if (!pregistrypriv->wifi_spec) {/* typical setting */ - beQ = QUEUE_LOW; - bkQ = QUEUE_LOW; - viQ = QUEUE_NORMAL; - voQ = QUEUE_HIGH; - mgtQ = QUEUE_HIGH; - hiQ = QUEUE_HIGH; - } else {/* for WMM */ - beQ = QUEUE_LOW; - bkQ = QUEUE_NORMAL; - viQ = QUEUE_NORMAL; - voQ = QUEUE_HIGH; - mgtQ = QUEUE_HIGH; - hiQ = QUEUE_HIGH; - } - _InitNormalChipRegPriority(Adapter, beQ, bkQ, viQ, voQ, mgtQ, hiQ); -} - -static void _InitQueuePriority(struct adapter *Adapter) -{ - struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(Adapter); - - switch (pdvobjpriv->RtNumOutPipes) { - case 1: - _InitNormalChipRegPriority(Adapter, QUEUE_HIGH, QUEUE_HIGH, QUEUE_HIGH, - QUEUE_HIGH, QUEUE_HIGH, QUEUE_HIGH); - break; - case 2: - _InitNormalChipTwoOutEpPriority(Adapter); - break; - case 3: - _InitNormalChipThreeOutEpPriority(Adapter); - break; - default: - break; - } -} - -static void _InitNetworkType(struct adapter *Adapter) -{ - u32 value32; - int res; - - res = rtw_read32(Adapter, REG_CR, &value32); - if (res) - return; - - /* TODO: use the other function to set network type */ - value32 = (value32 & ~MASK_NETTYPE) | _NETTYPE(NT_LINK_AP); - - rtw_write32(Adapter, REG_CR, value32); -} - -static void _InitTransferPageSize(struct adapter *Adapter) -{ - /* Tx page size is always 128. */ - - u8 value8; - value8 = _PSRX(PBP_128) | _PSTX(PBP_128); - rtw_write8(Adapter, REG_PBP, value8); -} - -static void _InitDriverInfoSize(struct adapter *Adapter, u8 drvInfoSize) -{ - rtw_write8(Adapter, REG_RX_DRVINFO_SZ, drvInfoSize); -} - -static void _InitWMACSetting(struct adapter *Adapter) -{ - u32 receive_config = RCR_AAP | RCR_APM | RCR_AM | RCR_AB | - RCR_CBSSID_DATA | RCR_CBSSID_BCN | - RCR_APP_ICV | RCR_AMF | RCR_HTC_LOC_CTRL | - RCR_APP_MIC | RCR_APP_PHYSTS; - - /* some REG_RCR will be modified later by phy_ConfigMACWithHeaderFile() */ - rtw_write32(Adapter, REG_RCR, receive_config); - - /* Accept all multicast address */ - rtw_write32(Adapter, REG_MAR, 0xFFFFFFFF); - rtw_write32(Adapter, REG_MAR + 4, 0xFFFFFFFF); -} - -static void _InitAdaptiveCtrl(struct adapter *Adapter) -{ - u16 value16; - u32 value32; - int res; - - /* Response Rate Set */ - res = rtw_read32(Adapter, REG_RRSR, &value32); - if (res) - return; - - value32 &= ~RATE_BITMAP_ALL; - value32 |= RATE_RRSR_CCK_ONLY_1M; - rtw_write32(Adapter, REG_RRSR, value32); - - /* CF-END Threshold */ - - /* SIFS (used in NAV) */ - value16 = _SPEC_SIFS_CCK(0x10) | _SPEC_SIFS_OFDM(0x10); - rtw_write16(Adapter, REG_SPEC_SIFS, value16); - - /* Retry Limit */ - value16 = _LRL(0x30) | _SRL(0x30); - rtw_write16(Adapter, REG_RL, value16); -} - -static void _InitEDCA(struct adapter *Adapter) -{ - /* Set Spec SIFS (used in NAV) */ - rtw_write16(Adapter, REG_SPEC_SIFS, 0x100a); - rtw_write16(Adapter, REG_MAC_SPEC_SIFS, 0x100a); - - /* Set SIFS for CCK */ - rtw_write16(Adapter, REG_SIFS_CTX, 0x100a); - - /* Set SIFS for OFDM */ - rtw_write16(Adapter, REG_SIFS_TRX, 0x100a); - - /* TXOP */ - rtw_write32(Adapter, REG_EDCA_BE_PARAM, 0x005EA42B); - rtw_write32(Adapter, REG_EDCA_BK_PARAM, 0x0000A44F); - rtw_write32(Adapter, REG_EDCA_VI_PARAM, 0x005EA324); - rtw_write32(Adapter, REG_EDCA_VO_PARAM, 0x002FA226); -} - -static void _InitRetryFunction(struct adapter *Adapter) -{ - u8 value8; - int res; - - res = rtw_read8(Adapter, REG_FWHW_TXQ_CTRL, &value8); - if (res) - return; - - value8 |= EN_AMPDU_RTY_NEW; - rtw_write8(Adapter, REG_FWHW_TXQ_CTRL, value8); - - /* Set ACK timeout */ - rtw_write8(Adapter, REG_ACKTO, 0x40); -} - -/*----------------------------------------------------------------------------- - * Function: usb_AggSettingTxUpdate() - * - * Overview: Separate TX/RX parameters update independent for TP detection and - * dynamic TX/RX aggreagtion parameters update. - * - * Input: struct adapter * - * - * Output/Return: NONE - * - * Revised History: - * When Who Remark - * 12/10/2010 MHC Separate to smaller function. - * - *---------------------------------------------------------------------------*/ -static void usb_AggSettingTxUpdate(struct adapter *Adapter) -{ - u32 value32; - int res; - - if (Adapter->registrypriv.wifi_spec) - return; - - res = rtw_read32(Adapter, REG_TDECTRL, &value32); - if (res) - return; - - value32 = value32 & ~(BLK_DESC_NUM_MASK << BLK_DESC_NUM_SHIFT); - value32 |= ((USB_TXAGG_DESC_NUM & BLK_DESC_NUM_MASK) << BLK_DESC_NUM_SHIFT); - - rtw_write32(Adapter, REG_TDECTRL, value32); -} - -/*----------------------------------------------------------------------------- - * Function: usb_AggSettingRxUpdate() - * - * Overview: Separate TX/RX parameters update independent for TP detection and - * dynamic TX/RX aggreagtion parameters update. - * - * Input: struct adapter * - * - * Output/Return: NONE - * - * Revised History: - * When Who Remark - * 12/10/2010 MHC Separate to smaller function. - * - *---------------------------------------------------------------------------*/ -static void -usb_AggSettingRxUpdate( - struct adapter *Adapter - ) -{ - u8 valueDMA; - u8 valueUSB; - int res; - - res = rtw_read8(Adapter, REG_TRXDMA_CTRL, &valueDMA); - if (res) - return; - - res = rtw_read8(Adapter, REG_USB_SPECIAL_OPTION, &valueUSB); - if (res) - return; - - valueDMA |= RXDMA_AGG_EN; - valueUSB &= ~USB_AGG_EN; - - rtw_write8(Adapter, REG_TRXDMA_CTRL, valueDMA); - rtw_write8(Adapter, REG_USB_SPECIAL_OPTION, valueUSB); - - rtw_write8(Adapter, REG_RXDMA_AGG_PG_TH, USB_RXAGG_PAGE_COUNT); - rtw_write8(Adapter, REG_RXDMA_AGG_PG_TH + 1, USB_RXAGG_PAGE_TIMEOUT); -} - -static void InitUsbAggregationSetting(struct adapter *Adapter) -{ - /* Tx aggregation setting */ - usb_AggSettingTxUpdate(Adapter); - - /* Rx aggregation setting */ - usb_AggSettingRxUpdate(Adapter); -} - -/* FIXME: add error handling in callers */ -static int _InitBeaconParameters(struct adapter *Adapter) -{ - struct hal_data_8188e *haldata = &Adapter->haldata; - int res; - - rtw_write16(Adapter, REG_BCN_CTRL, 0x1010); - - /* TODO: Remove these magic number */ - rtw_write16(Adapter, REG_TBTT_PROHIBIT, 0x6404);/* ms */ - rtw_write8(Adapter, REG_DRVERLYINT, DRIVER_EARLY_INT_TIME);/* 5ms */ - rtw_write8(Adapter, REG_BCNDMATIM, BCN_DMA_ATIME_INT_TIME); /* 2ms */ - - /* Suggested by designer timchen. Change beacon AIFS to the largest number */ - /* beacause test chip does not contension before sending beacon. by tynli. 2009.11.03 */ - rtw_write16(Adapter, REG_BCNTCFG, 0x660F); - - res = rtw_read8(Adapter, REG_FWHW_TXQ_CTRL + 2, &haldata->RegFwHwTxQCtrl); - if (res) - return res; - - res = rtw_read8(Adapter, REG_TBTT_PROHIBIT + 2, &haldata->RegReg542); - if (res) - return res; - - res = rtw_read8(Adapter, REG_CR + 1, &haldata->RegCR_1); - if (res) - return res; - - return 0; -} - -static void _BeaconFunctionEnable(struct adapter *Adapter) -{ - rtw_write8(Adapter, REG_BCN_CTRL, (BIT(4) | BIT(3) | BIT(1))); - - rtw_write8(Adapter, REG_RD_CTRL + 1, 0x6F); -} - -/* Set CCK and OFDM Block "ON" */ -static void _BBTurnOnBlock(struct adapter *Adapter) -{ - rtl8188e_PHY_SetBBReg(Adapter, rFPGA0_RFMOD, bCCKEn, 0x1); - rtl8188e_PHY_SetBBReg(Adapter, rFPGA0_RFMOD, bOFDMEn, 0x1); -} - -static void _InitAntenna_Selection(struct adapter *Adapter) -{ - struct hal_data_8188e *haldata = &Adapter->haldata; - int res; - u32 reg; - - if (haldata->AntDivCfg == 0) - return; - - res = rtw_read32(Adapter, REG_LEDCFG0, ®); - if (res) - return; - - rtw_write32(Adapter, REG_LEDCFG0, reg | BIT(23)); - rtl8188e_PHY_SetBBReg(Adapter, rFPGA0_XAB_RFParameter, BIT(13), 0x01); - - if (rtl8188e_PHY_QueryBBReg(Adapter, rFPGA0_XA_RFInterfaceOE, 0x300) == Antenna_A) - haldata->CurAntenna = Antenna_A; - else - haldata->CurAntenna = Antenna_B; -} - -static void hw_var_set_macaddr(struct adapter *Adapter, u8 *val) -{ - u8 idx = 0; - u32 reg_macid; - - reg_macid = REG_MACID; - - for (idx = 0; idx < 6; idx++) - rtw_write8(Adapter, (reg_macid + idx), val[idx]); -} - -u32 rtl8188eu_hal_init(struct adapter *Adapter) -{ - u8 value8 = 0; - u16 value16; - u32 status = _SUCCESS; - int res; - struct hal_data_8188e *haldata = &Adapter->haldata; - struct pwrctrl_priv *pwrctrlpriv = &Adapter->pwrctrlpriv; - struct registry_priv *pregistrypriv = &Adapter->registrypriv; - u32 reg; - - if (Adapter->pwrctrlpriv.bkeepfwalive) { - if (haldata->odmpriv.RFCalibrateInfo.bIQKInitialized) { - PHY_IQCalibrate_8188E(Adapter, true); - } else { - PHY_IQCalibrate_8188E(Adapter, false); - haldata->odmpriv.RFCalibrateInfo.bIQKInitialized = true; - } - - ODM_TXPowerTrackingCheck(&haldata->odmpriv); - PHY_LCCalibrate_8188E(Adapter); - - goto exit; - } - - status = rtl8188eu_InitPowerOn(Adapter); - if (status == _FAIL) - goto exit; - - /* Save target channel */ - haldata->CurrentChannel = 6;/* default set to 6 */ - - /* 2010/08/09 MH We need to check if we need to turnon or off RF after detecting */ - /* HW GPIO pin. Before PHY_RFConfig8192C. */ - /* 2010/08/26 MH If Efuse does not support sective suspend then disable the function. */ - - _InitQueueReservedPage(Adapter); - _InitQueuePriority(Adapter); - _InitPageBoundary(Adapter); - _InitTransferPageSize(Adapter); - - _InitTxBufferBoundary(Adapter, 0); - - status = rtl8188e_firmware_download(Adapter); - - if (status != _SUCCESS) { - Adapter->bFWReady = false; - haldata->fw_ractrl = false; - return status; - } else { - Adapter->bFWReady = true; - haldata->fw_ractrl = false; - } - /* Initialize firmware vars */ - Adapter->pwrctrlpriv.bFwCurrentInPSMode = false; - haldata->LastHMEBoxNum = 0; - - if (PHY_MACConfig8188E(Adapter)) - return _FAIL; - - /* */ - /* d. Initialize BB related configurations. */ - /* */ - if (PHY_BBConfig8188E(Adapter)) - return _FAIL; - - if (phy_RF6052_Config_ParaFile(Adapter)) - return _FAIL; - - status = rtl8188e_iol_efuse_patch(Adapter); - if (status == _FAIL) - goto exit; - - _InitTxBufferBoundary(Adapter, TX_PAGE_BOUNDARY_88E); - - status = InitLLTTable(Adapter, TX_PAGE_BOUNDARY_88E); - if (status == _FAIL) - goto exit; - - /* Get Rx PHY status in order to report RSSI and others. */ - _InitDriverInfoSize(Adapter, DRVINFO_SZ); - - _InitInterrupt(Adapter); - hw_var_set_macaddr(Adapter, Adapter->eeprompriv.mac_addr); - _InitNetworkType(Adapter);/* set msr */ - _InitWMACSetting(Adapter); - _InitAdaptiveCtrl(Adapter); - _InitEDCA(Adapter); - _InitRetryFunction(Adapter); - InitUsbAggregationSetting(Adapter); - _InitBeaconParameters(Adapter); - - /* */ - /* Init CR MACTXEN, MACRXEN after setting RxFF boundary REG_TRXFF_BNDY to patch */ - /* Hw bug which Hw initials RxFF boundary size to a value which is larger than the real Rx buffer size in 88E. */ - /* */ - /* Enable MACTXEN/MACRXEN block */ - res = rtw_read16(Adapter, REG_CR, &value16); - if (res) - return _FAIL; - - value16 |= (MACTXEN | MACRXEN); - rtw_write8(Adapter, REG_CR, value16); - - /* Enable TX Report */ - /* Enable Tx Report Timer */ - res = rtw_read8(Adapter, REG_TX_RPT_CTRL, &value8); - if (res) - return _FAIL; - - rtw_write8(Adapter, REG_TX_RPT_CTRL, (value8 | BIT(1) | BIT(0))); - /* Set MAX RPT MACID */ - rtw_write8(Adapter, REG_TX_RPT_CTRL + 1, 2);/* FOR sta mode ,0: bc/mc ,1:AP */ - /* Tx RPT Timer. Unit: 32us */ - rtw_write16(Adapter, REG_TX_RPT_TIME, 0xCdf0); - - rtw_write8(Adapter, REG_EARLY_MODE_CONTROL, 0); - - rtw_write16(Adapter, REG_PKT_VO_VI_LIFE_TIME, 0x0400); /* unit: 256us. 256ms */ - rtw_write16(Adapter, REG_PKT_BE_BK_LIFE_TIME, 0x0400); /* unit: 256us. 256ms */ - - /* Keep RfRegChnlVal for later use. */ - haldata->RfRegChnlVal = rtl8188e_PHY_QueryRFReg(Adapter, RF_CHNLBW, bRFRegOffsetMask); - - _BBTurnOnBlock(Adapter); - - invalidate_cam_all(Adapter); - - /* 2010/12/17 MH We need to set TX power according to EFUSE content at first. */ - PHY_SetTxPowerLevel8188E(Adapter, haldata->CurrentChannel); - -/* Move by Neo for USB SS to below setp */ -/* _RfPowerSave(Adapter); */ - - _InitAntenna_Selection(Adapter); - - /* */ - /* Disable BAR, suggested by Scott */ - /* 2010.04.09 add by hpfan */ - /* */ - rtw_write32(Adapter, REG_BAR_MODE_CTRL, 0x0201ffff); - - /* HW SEQ CTRL */ - /* set 0x0 to 0xFF by tynli. Default enable HW SEQ NUM. */ - rtw_write8(Adapter, REG_HWSEQ_CTRL, 0xFF); - - if (pregistrypriv->wifi_spec) - rtw_write16(Adapter, REG_FAST_EDCA_CTRL, 0); - - /* Nav limit , suggest by scott */ - rtw_write8(Adapter, 0x652, 0x0); - - rtl8188e_InitHalDm(Adapter); - - /* 2010/08/11 MH Merge from 8192SE for Minicard init. We need to confirm current radio status */ - /* and then decide to enable RF or not.!!!??? For Selective suspend mode. We may not */ - /* call initstruct adapter. May cause some problem?? */ - /* Fix the bug that Hw/Sw radio off before S3/S4, the RF off action will not be executed */ - /* in MgntActSet_RF_State() after wake up, because the value of haldata->eRFPowerState */ - /* is the same as eRfOff, we should change it to eRfOn after we config RF parameters. */ - /* Added by tynli. 2010.03.30. */ - pwrctrlpriv->rf_pwrstate = rf_on; - - /* enable Tx report. */ - rtw_write8(Adapter, REG_FWHW_TXQ_CTRL + 1, 0x0F); - - /* Suggested by SD1 pisa. Added by tynli. 2011.10.21. */ - rtw_write8(Adapter, REG_EARLY_MODE_CONTROL + 3, 0x01);/* Pretx_en, for WEP/TKIP SEC */ - - /* tynli_test_tx_report. */ - rtw_write16(Adapter, REG_TX_RPT_TIME, 0x3DF0); - - /* enable tx DMA to drop the redundate data of packet */ - res = rtw_read16(Adapter, REG_TXDMA_OFFSET_CHK, &value16); - if (res) - return _FAIL; - - rtw_write16(Adapter, REG_TXDMA_OFFSET_CHK, (value16 | DROP_DATA_EN)); - - /* 2010/08/26 MH Merge from 8192CE. */ - if (pwrctrlpriv->rf_pwrstate == rf_on) { - if (haldata->odmpriv.RFCalibrateInfo.bIQKInitialized) { - PHY_IQCalibrate_8188E(Adapter, true); - } else { - PHY_IQCalibrate_8188E(Adapter, false); - haldata->odmpriv.RFCalibrateInfo.bIQKInitialized = true; - } - - ODM_TXPowerTrackingCheck(&haldata->odmpriv); - - PHY_LCCalibrate_8188E(Adapter); - } - -/* _InitPABias(Adapter); */ - rtw_write8(Adapter, REG_USB_HRPWM, 0); - - /* ack for xmit mgmt frames. */ - res = rtw_read32(Adapter, REG_FWHW_TXQ_CTRL, ®); - if (res) - return _FAIL; - - rtw_write32(Adapter, REG_FWHW_TXQ_CTRL, reg | BIT(12)); - -exit: - return status; -} - -static void CardDisableRTL8188EU(struct adapter *Adapter) -{ - u8 val8; - struct hal_data_8188e *haldata = &Adapter->haldata; - int res; - - /* Stop Tx Report Timer. 0x4EC[Bit1]=b'0 */ - res = rtw_read8(Adapter, REG_TX_RPT_CTRL, &val8); - if (res) - return; - - rtw_write8(Adapter, REG_TX_RPT_CTRL, val8 & (~BIT(1))); - - /* stop rx */ - rtw_write8(Adapter, REG_CR, 0x0); - - /* Run LPS WL RFOFF flow */ - HalPwrSeqCmdParsing(Adapter, LPS_ENTER_FLOW); - - /* 2. 0x1F[7:0] = 0 turn off RF */ - - res = rtw_read8(Adapter, REG_MCUFWDL, &val8); - if (res) - return; - - if ((val8 & RAM_DL_SEL) && Adapter->bFWReady) { /* 8051 RAM code */ - /* Reset MCU 0x2[10]=0. */ - res = rtw_read8(Adapter, REG_SYS_FUNC_EN + 1, &val8); - if (res) - return; - - val8 &= ~BIT(2); /* 0x2[10], FEN_CPUEN */ - rtw_write8(Adapter, REG_SYS_FUNC_EN + 1, val8); - } - - /* reset MCU ready status */ - rtw_write8(Adapter, REG_MCUFWDL, 0); - - /* YJ,add,111212 */ - /* Disable 32k */ - res = rtw_read8(Adapter, REG_32K_CTRL, &val8); - if (res) - return; - - rtw_write8(Adapter, REG_32K_CTRL, val8 & (~BIT(0))); - - /* Card disable power action flow */ - HalPwrSeqCmdParsing(Adapter, DISABLE_FLOW); - - /* Reset MCU IO Wrapper */ - res = rtw_read8(Adapter, REG_RSV_CTRL + 1, &val8); - if (res) - return; - - rtw_write8(Adapter, REG_RSV_CTRL + 1, (val8 & (~BIT(3)))); - - res = rtw_read8(Adapter, REG_RSV_CTRL + 1, &val8); - if (res) - return; - - rtw_write8(Adapter, REG_RSV_CTRL + 1, val8 | BIT(3)); - - /* YJ,test add, 111207. For Power Consumption. */ - res = rtw_read8(Adapter, GPIO_IN, &val8); - if (res) - return; - - rtw_write8(Adapter, GPIO_OUT, val8); - rtw_write8(Adapter, GPIO_IO_SEL, 0xFF);/* Reg0x46 */ - - res = rtw_read8(Adapter, REG_GPIO_IO_SEL, &val8); - if (res) - return; - - rtw_write8(Adapter, REG_GPIO_IO_SEL, (val8 << 4)); - res = rtw_read8(Adapter, REG_GPIO_IO_SEL + 1, &val8); - if (res) - return; - - rtw_write8(Adapter, REG_GPIO_IO_SEL + 1, val8 | 0x0F);/* Reg0x43 */ - rtw_write32(Adapter, REG_BB_PAD_CTRL, 0x00080808);/* set LNA ,TRSW,EX_PA Pin to output mode */ - haldata->bMacPwrCtrlOn = false; - Adapter->bFWReady = false; -} - -u32 rtl8188eu_hal_deinit(struct adapter *Adapter) -{ - rtw_write32(Adapter, REG_HIMR_88E, IMR_DISABLED_88E); - rtw_write32(Adapter, REG_HIMRE_88E, IMR_DISABLED_88E); - - if (!Adapter->pwrctrlpriv.bkeepfwalive) { - if (Adapter->hw_init_completed) { - CardDisableRTL8188EU(Adapter); - } - } - return _SUCCESS; - } - -int rtl8188eu_inirp_init(struct adapter *Adapter) -{ - u8 i; - struct recv_buf *precvbuf; - struct recv_priv *precvpriv = &Adapter->recvpriv; - int ret; - - /* issue Rx irp to receive data */ - precvbuf = (struct recv_buf *)precvpriv->precv_buf; - for (i = 0; i < NR_RECVBUFF; i++) { - ret = rtw_read_port(Adapter, precvbuf); - if (ret) - return ret; - - precvbuf++; - precvpriv->free_recv_buf_queue_cnt--; - } - - return 0; -} - -/* */ -/* */ -/* EEPROM/EFUSE Content Parsing */ -/* */ -/* */ - -static void Hal_EfuseParseMACAddr_8188EU(struct adapter *adapt, u8 *hwinfo, bool AutoLoadFail) -{ - struct eeprom_priv *eeprom = &adapt->eeprompriv; - - if (AutoLoadFail) { - eth_random_addr(eeprom->mac_addr); - } else { - /* Read Permanent MAC address */ - memcpy(eeprom->mac_addr, &hwinfo[EEPROM_MAC_ADDR_88EU], ETH_ALEN); - } -} - -int ReadAdapterInfo8188EU(struct adapter *Adapter) -{ - struct eeprom_priv *eeprom = &Adapter->eeprompriv; - struct led_priv *ledpriv = &Adapter->ledpriv; - u8 *efuse_buf; - u8 eeValue; - int res; - - /* check system boot selection */ - res = rtw_read8(Adapter, REG_9346CR, &eeValue); - if (res) - return res; - - eeprom->bautoload_fail_flag = !(eeValue & EEPROM_EN); - - efuse_buf = kmalloc(EFUSE_MAP_LEN_88E, GFP_KERNEL); - if (!efuse_buf) - return -ENOMEM; - memset(efuse_buf, 0xFF, EFUSE_MAP_LEN_88E); - - if (!(eeValue & BOOT_FROM_EEPROM) && !eeprom->bautoload_fail_flag) { - rtl8188e_EfusePowerSwitch(Adapter, true); - rtl8188e_ReadEFuse(Adapter, EFUSE_MAP_LEN_88E, efuse_buf); - rtl8188e_EfusePowerSwitch(Adapter, false); - } - - /* parse the eeprom/efuse content */ - Hal_EfuseParseIDCode88E(Adapter, efuse_buf); - Hal_EfuseParseMACAddr_8188EU(Adapter, efuse_buf, eeprom->bautoload_fail_flag); - - Hal_ReadPowerSavingMode88E(Adapter, efuse_buf, eeprom->bautoload_fail_flag); - Hal_ReadTxPowerInfo88E(Adapter, efuse_buf, eeprom->bautoload_fail_flag); - rtl8188e_EfuseParseChnlPlan(Adapter, efuse_buf, eeprom->bautoload_fail_flag); - Hal_EfuseParseXtal_8188E(Adapter, efuse_buf, eeprom->bautoload_fail_flag); - Hal_ReadAntennaDiversity88E(Adapter, efuse_buf, eeprom->bautoload_fail_flag); - Hal_ReadThermalMeter_88E(Adapter, efuse_buf, eeprom->bautoload_fail_flag); - - ledpriv->bRegUseLed = true; - kfree(efuse_buf); - return 0; -} - -void UpdateHalRAMask8188EUsb(struct adapter *adapt, u32 mac_id, u8 rssi_level) -{ - u8 init_rate = 0; - u8 networkType, raid; - u32 mask, rate_bitmap; - u8 shortGIrate = false; - int supportRateNum = 0; - struct sta_info *psta; - struct hal_data_8188e *haldata = &adapt->haldata; - struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *cur_network = &pmlmeinfo->network; - - if (mac_id >= NUM_STA) /* CAM_SIZE */ - return; - psta = pmlmeinfo->FW_sta_info[mac_id].psta; - if (!psta) - return; - switch (mac_id) { - case 0:/* for infra mode */ - supportRateNum = rtw_get_rateset_len(cur_network->SupportedRates); - networkType = judge_network_type(adapt, cur_network->SupportedRates, supportRateNum) & 0xf; - raid = networktype_to_raid(networkType); - mask = update_supported_rate(cur_network->SupportedRates, supportRateNum); - mask |= (pmlmeinfo->HT_enable) ? update_MSC_rate(&pmlmeinfo->HT_caps) : 0; - if (support_short_GI(adapt, &pmlmeinfo->HT_caps)) - shortGIrate = true; - break; - case 1:/* for broadcast/multicast */ - supportRateNum = rtw_get_rateset_len(pmlmeinfo->FW_sta_info[mac_id].SupportedRates); - if (pmlmeext->cur_wireless_mode & WIRELESS_11B) - networkType = WIRELESS_11B; - else - networkType = WIRELESS_11G; - raid = networktype_to_raid(networkType); - mask = update_basic_rate(cur_network->SupportedRates, supportRateNum); - break; - default: /* for each sta in IBSS */ - supportRateNum = rtw_get_rateset_len(pmlmeinfo->FW_sta_info[mac_id].SupportedRates); - networkType = judge_network_type(adapt, pmlmeinfo->FW_sta_info[mac_id].SupportedRates, supportRateNum) & 0xf; - raid = networktype_to_raid(networkType); - mask = update_supported_rate(cur_network->SupportedRates, supportRateNum); - - /* todo: support HT in IBSS */ - break; - } - - rate_bitmap = 0x0fffffff; - rate_bitmap = ODM_Get_Rate_Bitmap(&haldata->odmpriv, mac_id, mask, rssi_level); - - mask &= rate_bitmap; - - init_rate = get_highest_rate_idx(mask) & 0x3f; - - if (haldata->fw_ractrl) { - mask |= ((raid << 28) & 0xf0000000); - psta->ra_mask = mask; - mask |= ((raid << 28) & 0xf0000000); - - /* to do ,for 8188E-SMIC */ - rtl8188e_set_raid_cmd(adapt, mask); - } else { - ODM_RA_UpdateRateInfo_8188E(&haldata->odmpriv, - mac_id, - raid, - mask, - shortGIrate - ); - } - /* set ra_id */ - psta->raid = raid; - psta->init_rate = init_rate; -} - -void SetBeaconRelatedRegisters8188EUsb(struct adapter *adapt) -{ - u32 value32; - struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - u32 bcn_ctrl_reg = REG_BCN_CTRL; - int res; - u8 reg; - /* reset TSF, enable update TSF, correcting TSF On Beacon */ - - /* BCN interval */ - rtw_write16(adapt, REG_BCN_INTERVAL, pmlmeinfo->bcn_interval); - rtw_write8(adapt, REG_ATIMWND, 0x02);/* 2ms */ - - _InitBeaconParameters(adapt); - - rtw_write8(adapt, REG_SLOT, 0x09); - - res = rtw_read32(adapt, REG_TCR, &value32); - if (res) - return; - - value32 &= ~TSFRST; - rtw_write32(adapt, REG_TCR, value32); - - value32 |= TSFRST; - rtw_write32(adapt, REG_TCR, value32); - - /* NOTE: Fix test chip's bug (about contention windows's randomness) */ - rtw_write8(adapt, REG_RXTSF_OFFSET_CCK, 0x50); - rtw_write8(adapt, REG_RXTSF_OFFSET_OFDM, 0x50); - - _BeaconFunctionEnable(adapt); - - rtw_resume_tx_beacon(adapt); - - res = rtw_read8(adapt, bcn_ctrl_reg, ®); - if (res) - return; - - rtw_write8(adapt, bcn_ctrl_reg, reg | BIT(1)); -} - -void rtl8188eu_init_default_value(struct adapter *adapt) -{ - struct hal_data_8188e *haldata = &adapt->haldata; - struct pwrctrl_priv *pwrctrlpriv; - u8 i; - - pwrctrlpriv = &adapt->pwrctrlpriv; - - /* init default value */ - haldata->fw_ractrl = false; - if (!pwrctrlpriv->bkeepfwalive) - haldata->LastHMEBoxNum = 0; - - /* init dm default value */ - haldata->odmpriv.RFCalibrateInfo.bIQKInitialized = false; - haldata->odmpriv.RFCalibrateInfo.TM_Trigger = 0;/* for IQK */ - haldata->pwrGroupCnt = 0; - haldata->odmpriv.RFCalibrateInfo.ThermalValue_HP_index = 0; - for (i = 0; i < HP_THERMAL_NUM; i++) - haldata->odmpriv.RFCalibrateInfo.ThermalValue_HP[i] = 0; -} diff --git a/drivers/staging/r8188eu/hal/usb_ops_linux.c b/drivers/staging/r8188eu/hal/usb_ops_linux.c deleted file mode 100644 index 9611b19ab55b..000000000000 --- a/drivers/staging/r8188eu/hal/usb_ops_linux.c +++ /dev/null @@ -1,476 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#include "../include/osdep_service.h" -#include "../include/drv_types.h" -#include "../include/osdep_intf.h" -#include "../include/usb_ops.h" -#include "../include/rtl8188e_hal.h" - -#define VENDOR_CMD_MAX_DATA_LEN 254 - -#define RTW_USB_CONTROL_MSG_TIMEOUT 500/* ms */ - -static int usb_read(struct adapter *adapt, u16 value, void *data, u8 size) -{ - struct dvobj_priv *dvobjpriv = adapter_to_dvobj(adapt); - struct usb_device *udev = dvobjpriv->pusbdev; - int status; - u8 io_buf[4]; - - if (adapt->bSurpriseRemoved) - return -EPERM; - - status = usb_control_msg_recv(udev, 0, REALTEK_USB_VENQT_CMD_REQ, - REALTEK_USB_VENQT_READ, value, - REALTEK_USB_VENQT_CMD_IDX, io_buf, - size, RTW_USB_CONTROL_MSG_TIMEOUT, - GFP_KERNEL); - - if (status == -ESHUTDOWN || - status == -ENODEV || - status == -ENOENT) { - /* - * device or controller has been disabled due to - * some problem that could not be worked around, - * device or bus doesn’t exist, endpoint does not - * exist or is not enabled. - */ - adapt->bSurpriseRemoved = true; - return status; - } - - if (status < 0) { - if (rtw_inc_and_chk_continual_urb_error(dvobjpriv)) - adapt->bSurpriseRemoved = true; - - return status; - } - - rtw_reset_continual_urb_error(dvobjpriv); - memcpy(data, io_buf, size); - - return status; -} - -static int usb_write(struct adapter *adapt, u16 value, void *data, u8 size) -{ - struct dvobj_priv *dvobjpriv = adapter_to_dvobj(adapt); - struct usb_device *udev = dvobjpriv->pusbdev; - int status; - u8 io_buf[VENDOR_CMD_MAX_DATA_LEN]; - - if (adapt->bSurpriseRemoved) - return -EPERM; - - memcpy(io_buf, data, size); - status = usb_control_msg_send(udev, 0, REALTEK_USB_VENQT_CMD_REQ, - REALTEK_USB_VENQT_WRITE, value, - REALTEK_USB_VENQT_CMD_IDX, io_buf, - size, RTW_USB_CONTROL_MSG_TIMEOUT, - GFP_KERNEL); - - if (status == -ESHUTDOWN || - status == -ENODEV || - status == -ENOENT) { - /* - * device or controller has been disabled due to - * some problem that could not be worked around, - * device or bus doesn’t exist, endpoint does not - * exist or is not enabled. - */ - adapt->bSurpriseRemoved = true; - return status; - } - - if (status < 0) { - if (rtw_inc_and_chk_continual_urb_error(dvobjpriv)) - adapt->bSurpriseRemoved = true; - - return status; - } - - rtw_reset_continual_urb_error(dvobjpriv); - - return status; -} - -int __must_check rtw_read8(struct adapter *adapter, u32 addr, u8 *data) -{ - u16 value = addr & 0xffff; - - return usb_read(adapter, value, data, 1); -} - -int __must_check rtw_read16(struct adapter *adapter, u32 addr, u16 *data) -{ - u16 value = addr & 0xffff; - __le16 le_data; - int res; - - res = usb_read(adapter, value, &le_data, 2); - if (res) - return res; - - *data = le16_to_cpu(le_data); - - return 0; -} - -int __must_check rtw_read32(struct adapter *adapter, u32 addr, u32 *data) -{ - u16 value = addr & 0xffff; - __le32 le_data; - int res; - - res = usb_read(adapter, value, &le_data, 4); - if (res) - return res; - - *data = le32_to_cpu(le_data); - - return 0; -} - -int rtw_write8(struct adapter *adapter, u32 addr, u8 val) -{ - u16 value = addr & 0xffff; - int ret; - - ret = usb_write(adapter, value, &val, 1); - - return RTW_STATUS_CODE(ret); -} - -int rtw_write16(struct adapter *adapter, u32 addr, u16 val) -{ - u16 value = addr & 0xffff; - __le16 data = cpu_to_le16(val); - int ret; - - ret = usb_write(adapter, value, &data, 2); - - return RTW_STATUS_CODE(ret); -} - -int rtw_write32(struct adapter *adapter, u32 addr, u32 val) -{ - u16 value = addr & 0xffff; - __le32 data = cpu_to_le32(val); - int ret; - - ret = usb_write(adapter, value, &data, 4); - - return RTW_STATUS_CODE(ret); -} - -int rtw_writeN(struct adapter *adapter, u32 addr, u32 length, u8 *data) -{ - u16 value = addr & 0xffff; - - if (length > VENDOR_CMD_MAX_DATA_LEN) - return -EINVAL; - - return usb_write(adapter, value, data, length); -} - -static void handle_txrpt_ccx_88e(struct adapter *adapter, u8 *buf) -{ - struct txrpt_ccx_88e *txrpt_ccx = (struct txrpt_ccx_88e *)buf; - - if (txrpt_ccx->int_ccx) { - if (txrpt_ccx->pkt_ok) - rtw_ack_tx_done(&adapter->xmitpriv, - RTW_SCTX_DONE_SUCCESS); - else - rtw_ack_tx_done(&adapter->xmitpriv, - RTW_SCTX_DONE_CCX_PKT_FAIL); - } -} - -static int recvbuf2recvframe(struct adapter *adapt, struct sk_buff *pskb) -{ - u8 *pbuf; - u8 shift_sz = 0; - u16 pkt_cnt; - u32 pkt_offset, skb_len, alloc_sz; - s32 transfer_len; - struct recv_stat *prxstat; - struct phy_stat *pphy_status = NULL; - struct sk_buff *pkt_copy = NULL; - struct recv_frame *precvframe = NULL; - struct rx_pkt_attrib *pattrib = NULL; - struct hal_data_8188e *haldata = &adapt->haldata; - struct recv_priv *precvpriv = &adapt->recvpriv; - struct __queue *pfree_recv_queue = &precvpriv->free_recv_queue; - - transfer_len = (s32)pskb->len; - pbuf = pskb->data; - - prxstat = (struct recv_stat *)pbuf; - pkt_cnt = (le32_to_cpu(prxstat->rxdw2) >> 16) & 0xff; - - do { - prxstat = (struct recv_stat *)pbuf; - - precvframe = rtw_alloc_recvframe(pfree_recv_queue); - if (!precvframe) - goto _exit_recvbuf2recvframe; - - INIT_LIST_HEAD(&precvframe->list); - precvframe->precvbuf = NULL; /* can't access the precvbuf for new arch. */ - precvframe->len = 0; - - update_recvframe_attrib_88e(precvframe, prxstat); - - pattrib = &precvframe->attrib; - - if ((pattrib->crc_err) || (pattrib->icv_err)) { - rtw_free_recvframe(precvframe, pfree_recv_queue); - goto _exit_recvbuf2recvframe; - } - - if ((pattrib->physt) && (pattrib->pkt_rpt_type == NORMAL_RX)) - pphy_status = (struct phy_stat *)(pbuf + RXDESC_OFFSET); - - pkt_offset = RXDESC_SIZE + pattrib->drvinfo_sz + pattrib->shift_sz + pattrib->pkt_len; - - if ((pattrib->pkt_len <= 0) || (pkt_offset > transfer_len)) { - rtw_free_recvframe(precvframe, pfree_recv_queue); - goto _exit_recvbuf2recvframe; - } - - /* Modified by Albert 20101213 */ - /* For 8 bytes IP header alignment. */ - if (pattrib->qos) /* Qos data, wireless lan header length is 26 */ - shift_sz = 6; - else - shift_sz = 0; - - skb_len = pattrib->pkt_len; - - /* for first fragment packet, driver need allocate 1536+drvinfo_sz+RXDESC_SIZE to defrag packet. */ - /* modify alloc_sz for recvive crc error packet by thomas 2011-06-02 */ - if ((pattrib->mfrag == 1) && (pattrib->frag_num == 0)) { - if (skb_len <= 1650) - alloc_sz = 1664; - else - alloc_sz = skb_len + 14; - } else { - alloc_sz = skb_len; - /* 6 is for IP header 8 bytes alignment in QoS packet case. */ - /* 8 is for skb->data 4 bytes alignment. */ - alloc_sz += 14; - } - - pkt_copy = netdev_alloc_skb(adapt->pnetdev, alloc_sz); - if (pkt_copy) { - precvframe->pkt = pkt_copy; - precvframe->rx_head = pkt_copy->data; - precvframe->rx_end = pkt_copy->data + alloc_sz; - skb_reserve(pkt_copy, 8 - ((size_t)(pkt_copy->data) & 7));/* force pkt_copy->data at 8-byte alignment address */ - skb_reserve(pkt_copy, shift_sz);/* force ip_hdr at 8-byte alignment address according to shift_sz. */ - memcpy(pkt_copy->data, (pbuf + pattrib->drvinfo_sz + RXDESC_SIZE), skb_len); - precvframe->rx_tail = pkt_copy->data; - precvframe->rx_data = pkt_copy->data; - } else { - if ((pattrib->mfrag == 1) && (pattrib->frag_num == 0)) { - rtw_free_recvframe(precvframe, pfree_recv_queue); - goto _exit_recvbuf2recvframe; - } - precvframe->pkt = skb_clone(pskb, GFP_ATOMIC); - if (precvframe->pkt) { - precvframe->rx_tail = pbuf + pattrib->drvinfo_sz + RXDESC_SIZE; - precvframe->rx_head = precvframe->rx_tail; - precvframe->rx_data = precvframe->rx_tail; - precvframe->rx_end = pbuf + pattrib->drvinfo_sz + RXDESC_SIZE + alloc_sz; - } else { - rtw_free_recvframe(precvframe, pfree_recv_queue); - goto _exit_recvbuf2recvframe; - } - } - - recvframe_put(precvframe, skb_len); - - pkt_offset = (u16)round_up(pkt_offset, 128); - - if (pattrib->pkt_rpt_type == NORMAL_RX) { /* Normal rx packet */ - if (pattrib->physt) - update_recvframe_phyinfo_88e(precvframe, (struct phy_stat *)pphy_status); - rtw_recv_entry(precvframe); - } else { - /* enqueue recvframe to txrtp queue */ - if (pattrib->pkt_rpt_type == TX_REPORT1) { - /* CCX-TXRPT ack for xmit mgmt frames. */ - handle_txrpt_ccx_88e(adapt, precvframe->rx_data); - } else if (pattrib->pkt_rpt_type == TX_REPORT2) { - ODM_RA_TxRPT2Handle_8188E( - &haldata->odmpriv, - precvframe->rx_data, - pattrib->pkt_len, - pattrib->MacIDValidEntry[0], - pattrib->MacIDValidEntry[1] - ); - } - rtw_free_recvframe(precvframe, pfree_recv_queue); - } - pkt_cnt--; - transfer_len -= pkt_offset; - pbuf += pkt_offset; - precvframe = NULL; - pkt_copy = NULL; - - if (transfer_len > 0 && pkt_cnt == 0) - pkt_cnt = (le32_to_cpu(prxstat->rxdw2) >> 16) & 0xff; - - } while ((transfer_len > 0) && (pkt_cnt > 0)); - -_exit_recvbuf2recvframe: - - return _SUCCESS; -} - -void rtl8188eu_recv_tasklet(unsigned long priv) -{ - struct sk_buff *pskb; - struct adapter *adapt = (struct adapter *)priv; - struct recv_priv *precvpriv = &adapt->recvpriv; - - while (NULL != (pskb = skb_dequeue(&precvpriv->rx_skb_queue))) { - if ((adapt->bDriverStopped) || (adapt->bSurpriseRemoved)) { - dev_kfree_skb_any(pskb); - break; - } - recvbuf2recvframe(adapt, pskb); - skb_reset_tail_pointer(pskb); - pskb->len = 0; - skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb); - } -} - -static void usb_read_port_complete(struct urb *purb) -{ - struct recv_buf *precvbuf = (struct recv_buf *)purb->context; - struct adapter *adapt = (struct adapter *)precvbuf->adapter; - struct recv_priv *precvpriv = &adapt->recvpriv; - - precvpriv->rx_pending_cnt--; - - if (adapt->bSurpriseRemoved || adapt->bDriverStopped || adapt->bReadPortCancel) { - precvbuf->reuse = true; - return; - } - - if (purb->status == 0) { /* SUCCESS */ - if ((purb->actual_length > MAX_RECVBUF_SZ) || (purb->actual_length < RXDESC_SIZE)) { - precvbuf->reuse = true; - rtw_read_port(adapt, precvbuf); - } else { - rtw_reset_continual_urb_error(adapter_to_dvobj(adapt)); - - skb_put(precvbuf->pskb, purb->actual_length); - skb_queue_tail(&precvpriv->rx_skb_queue, precvbuf->pskb); - - if (skb_queue_len(&precvpriv->rx_skb_queue) <= 1) - tasklet_schedule(&precvpriv->recv_tasklet); - - precvbuf->pskb = NULL; - precvbuf->reuse = false; - rtw_read_port(adapt, precvbuf); - } - } else { - skb_put(precvbuf->pskb, purb->actual_length); - precvbuf->pskb = NULL; - - if (rtw_inc_and_chk_continual_urb_error(adapter_to_dvobj(adapt))) - adapt->bSurpriseRemoved = true; - - switch (purb->status) { - case -EINVAL: - case -EPIPE: - case -ENODEV: - case -ESHUTDOWN: - case -ENOENT: - adapt->bDriverStopped = true; - break; - case -EPROTO: - case -EOVERFLOW: - precvbuf->reuse = true; - rtw_read_port(adapt, precvbuf); - break; - case -EINPROGRESS: - break; - default: - break; - } - } -} - -int rtw_read_port(struct adapter *adapter, struct recv_buf *precvbuf) -{ - struct urb *purb = NULL; - struct dvobj_priv *pdvobj = adapter_to_dvobj(adapter); - struct recv_priv *precvpriv = &adapter->recvpriv; - struct usb_device *pusbd = pdvobj->pusbdev; - int err; - unsigned int pipe; - size_t tmpaddr = 0; - size_t alignment = 0; - - if (adapter->bDriverStopped || adapter->bSurpriseRemoved) - return -EPERM; - - if (!precvbuf) - return -ENOMEM; - - if (!precvbuf->reuse || !precvbuf->pskb) { - precvbuf->pskb = skb_dequeue(&precvpriv->free_recv_skb_queue); - if (precvbuf->pskb) - precvbuf->reuse = true; - } - - /* re-assign for linux based on skb */ - if (!precvbuf->reuse || !precvbuf->pskb) { - precvbuf->pskb = netdev_alloc_skb(adapter->pnetdev, MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ); - if (!precvbuf->pskb) - return -ENOMEM; - - tmpaddr = (size_t)precvbuf->pskb->data; - alignment = tmpaddr & (RECVBUFF_ALIGN_SZ - 1); - skb_reserve(precvbuf->pskb, (RECVBUFF_ALIGN_SZ - alignment)); - } else { /* reuse skb */ - precvbuf->reuse = false; - } - - precvpriv->rx_pending_cnt++; - - purb = precvbuf->purb; - - /* translate DMA FIFO addr to pipehandle */ - pipe = usb_rcvbulkpipe(pusbd, pdvobj->RtInPipe); - - usb_fill_bulk_urb(purb, pusbd, pipe, - precvbuf->pskb->data, - MAX_RECVBUF_SZ, - usb_read_port_complete, - precvbuf);/* context is precvbuf */ - - err = usb_submit_urb(purb, GFP_ATOMIC); - if ((err) && (err != (-EPERM))) - return err; - - return 0; -} - -void rtl8188eu_xmit_tasklet(unsigned long priv) -{ - struct adapter *adapt = (struct adapter *)priv; - - if (check_fwstate(&adapt->mlmepriv, _FW_UNDER_SURVEY)) - return; - - do { - if (adapt->bDriverStopped || adapt->bSurpriseRemoved || adapt->bWritePortCancel) - break; - } while (rtl8188eu_xmitframe_complete(adapt)); -} diff --git a/drivers/staging/r8188eu/include/Hal8188EPhyCfg.h b/drivers/staging/r8188eu/include/Hal8188EPhyCfg.h deleted file mode 100644 index 4a0b782c33be..000000000000 --- a/drivers/staging/r8188eu/include/Hal8188EPhyCfg.h +++ /dev/null @@ -1,97 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#ifndef __INC_HAL8188EPHYCFG_H__ -#define __INC_HAL8188EPHYCFG_H__ - -#define MAX_AGGR_NUM 0x07 - -enum rf_radio_path { - RF_PATH_A = 0, /* Radio Path A */ - RF_PATH_B = 1, /* Radio Path B */ -}; - -#define MAX_PG_GROUP 13 - -#define RF_PATH_MAX 3 -#define MAX_TX_COUNT 4 /* path numbers */ - -#define CHANNEL_MAX_NUMBER 14 /* 14 is the max chnl number */ -#define MAX_CHNL_GROUP_24G 6 /* ch1~2, ch3~5, ch6~8, - *ch9~11, ch12~13, CH 14 - * total three groups */ - -struct bb_reg_def { - u32 rfintfs; /* set software control: */ - /* 0x870~0x877[8 bytes] */ - u32 rfintfi; /* readback data: */ - /* 0x8e0~0x8e7[8 bytes] */ - u32 rfintfo; /* output data: */ - /* 0x860~0x86f [16 bytes] */ - u32 rfintfe; /* output enable: */ - /* 0x860~0x86f [16 bytes] */ - u32 rf3wireOffset; /* LSSI data: */ - /* 0x840~0x84f [16 bytes] */ - u32 rfLSSI_Select; /* BB Band Select: */ - /* 0x878~0x87f [8 bytes] */ - u32 rfTxGainStage; /* Tx gain stage: */ - /* 0x80c~0x80f [4 bytes] */ - u32 rfHSSIPara1; /* wire parameter control1 : */ - /* 0x820~0x823,0x828~0x82b, - * 0x830~0x833, 0x838~0x83b [16 bytes] */ - u32 rfHSSIPara2; /* wire parameter control2 : */ - /* 0x824~0x827,0x82c~0x82f, 0x834~0x837, - * 0x83c~0x83f [16 bytes] */ - u32 rfSwitchControl; /* Tx Rx antenna control : */ - /* 0x858~0x85f [16 bytes] */ - u32 rfAGCControl1; /* AGC parameter control1 : */ - /* 0xc50~0xc53,0xc58~0xc5b, 0xc60~0xc63, - * 0xc68~0xc6b [16 bytes] */ - u32 rfAGCControl2; /* AGC parameter control2 : */ - /* 0xc54~0xc57,0xc5c~0xc5f, 0xc64~0xc67, - * 0xc6c~0xc6f [16 bytes] */ - u32 rfRxIQImbalance; /* OFDM Rx IQ imbalance matrix : */ - /* 0xc14~0xc17,0xc1c~0xc1f, 0xc24~0xc27, - * 0xc2c~0xc2f [16 bytes] */ - u32 rfRxAFE; /* Rx IQ DC ofset and Rx digital filter, - * Rx DC notch filter : */ - /* 0xc10~0xc13,0xc18~0xc1b, 0xc20~0xc23, - * 0xc28~0xc2b [16 bytes] */ - u32 rfTxIQImbalance; /* OFDM Tx IQ imbalance matrix */ - /* 0xc80~0xc83,0xc88~0xc8b, 0xc90~0xc93, - * 0xc98~0xc9b [16 bytes] */ - u32 rfTxAFE; /* Tx IQ DC Offset and Tx DFIR type */ - /* 0xc84~0xc87,0xc8c~0xc8f, 0xc94~0xc97, - * 0xc9c~0xc9f [16 bytes] */ - u32 rfLSSIReadBack; /* LSSI RF readback data SI mode */ - /* 0x8a0~0x8af [16 bytes] */ - u32 rfLSSIReadBackPi; /* LSSI RF readback data PI mode 0x8b8-8bc for - * Path A and B */ -}; - -/* BB and RF register read/write */ -u32 rtl8188e_PHY_QueryBBReg(struct adapter *adapter, u32 regaddr, u32 mask); -void rtl8188e_PHY_SetBBReg(struct adapter *Adapter, u32 RegAddr, - u32 mask, u32 data); -u32 rtl8188e_PHY_QueryRFReg(struct adapter *adapter, u32 regaddr, u32 mask); -void rtl8188e_PHY_SetRFReg(struct adapter *adapter, u32 regaddr, u32 mask, u32 data); - -/* Initialization related function */ -/* MAC/BB/RF HAL config */ -int PHY_MACConfig8188E(struct adapter *adapter); -int PHY_BBConfig8188E(struct adapter *adapter); - -/* BB TX Power R/W */ -void PHY_SetTxPowerLevel8188E(struct adapter *adapter, u8 channel); - -/* Switch bandwidth for 8192S */ -void PHY_SetBWMode8188E(struct adapter *adapter, - enum ht_channel_width chnlwidth, unsigned char offset); - -/* channel switch related funciton */ -void PHY_SwChnl8188E(struct adapter *adapter, u8 channel); - -void storePwrIndexDiffRateOffset(struct adapter *adapter, u32 regaddr, - u32 mask, u32 data); - -#endif diff --git a/drivers/staging/r8188eu/include/Hal8188EPhyReg.h b/drivers/staging/r8188eu/include/Hal8188EPhyReg.h deleted file mode 100644 index da2329be4474..000000000000 --- a/drivers/staging/r8188eu/include/Hal8188EPhyReg.h +++ /dev/null @@ -1,1072 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#ifndef __INC_HAL8188EPHYREG_H__ -#define __INC_HAL8188EPHYREG_H__ -/*--------------------------Define Parameters-------------------------------*/ -/* */ -/* BB-PHY register PMAC 0x100 PHY 0x800 - 0xEFF */ -/* 1. PMAC duplicate register due to connection: RF_Mode, TRxRN, NumOf L-STF */ -/* 2. 0x800/0x900/0xA00/0xC00/0xD00/0xE00 */ -/* 3. RF register 0x00-2E */ -/* 4. Bit Mask for BB/RF register */ -/* 5. Other definition for BB/RF R/W */ -/* */ - -/* */ -/* 1. PMAC duplicate register due to connection: RF_Mode, TRxRN, NumOf L-STF */ -/* 1. Page1(0x100) */ -/* */ -#define rPMAC_Reset 0x100 -#define rPMAC_TxStart 0x104 -#define rPMAC_TxLegacySIG 0x108 -#define rPMAC_TxHTSIG1 0x10c -#define rPMAC_TxHTSIG2 0x110 -#define rPMAC_PHYDebug 0x114 -#define rPMAC_TxPacketNum 0x118 -#define rPMAC_TxIdle 0x11c -#define rPMAC_TxMACHeader0 0x120 -#define rPMAC_TxMACHeader1 0x124 -#define rPMAC_TxMACHeader2 0x128 -#define rPMAC_TxMACHeader3 0x12c -#define rPMAC_TxMACHeader4 0x130 -#define rPMAC_TxMACHeader5 0x134 -#define rPMAC_TxDataType 0x138 -#define rPMAC_TxRandomSeed 0x13c -#define rPMAC_CCKPLCPPreamble 0x140 -#define rPMAC_CCKPLCPHeader 0x144 -#define rPMAC_CCKCRC16 0x148 -#define rPMAC_OFDMRxCRC32OK 0x170 -#define rPMAC_OFDMRxCRC32Er 0x174 -#define rPMAC_OFDMRxParityEr 0x178 -#define rPMAC_OFDMRxCRC8Er 0x17c -#define rPMAC_CCKCRxRC16Er 0x180 -#define rPMAC_CCKCRxRC32Er 0x184 -#define rPMAC_CCKCRxRC32OK 0x188 -#define rPMAC_TxStatus 0x18c - -/* 2. Page2(0x200) */ -/* The following two definition are only used for USB interface. */ -#define RF_BB_CMD_ADDR 0x02c0 /* RF/BB r/w cmd address. */ -#define RF_BB_CMD_DATA 0x02c4 /* RF/BB r/w cmd data. */ - -/* 3. Page8(0x800) */ -#define rFPGA0_RFMOD 0x800 /* RF mode & CCK TxSC RF BW Setting */ - -#define rFPGA0_TxInfo 0x804 /* Status report?? */ -#define rFPGA0_PSDFunction 0x808 - -#define rFPGA0_TxGainStage 0x80c /* Set TX PWR init gain? */ - -#define rFPGA0_RFTiming1 0x810 /* Useless now */ -#define rFPGA0_RFTiming2 0x814 - -#define rFPGA0_XA_HSSIParameter1 0x820 /* RF 3 wire register */ -#define rFPGA0_XA_HSSIParameter2 0x824 -#define rFPGA0_XB_HSSIParameter1 0x828 -#define rFPGA0_XB_HSSIParameter2 0x82c - -#define rFPGA0_XA_LSSIParameter 0x840 -#define rFPGA0_XB_LSSIParameter 0x844 - -#define rFPGA0_RFWakeUpParameter 0x850 /* Useless now */ -#define rFPGA0_RFSleepUpParameter 0x854 - -#define rFPGA0_XAB_SwitchControl 0x858 /* RF Channel switch */ -#define rFPGA0_XCD_SwitchControl 0x85c - -#define rFPGA0_XA_RFInterfaceOE 0x860 /* RF Channel switch */ -#define rFPGA0_XB_RFInterfaceOE 0x864 - -#define rFPGA0_XAB_RFInterfaceSW 0x870 /* RF Iface Software Control */ -#define rFPGA0_XCD_RFInterfaceSW 0x874 - -#define rFPGA0_XAB_RFParameter 0x878 /* RF Parameter */ -#define rFPGA0_XCD_RFParameter 0x87c - -/* Crystal cap setting RF-R/W protection for parameter4?? */ -#define rFPGA0_AnalogParameter1 0x880 -#define rFPGA0_AnalogParameter2 0x884 -#define rFPGA0_AnalogParameter3 0x888 -/* enable ad/da clock1 for dual-phy */ -#define rFPGA0_AdDaClockEn 0x888 -#define rFPGA0_AnalogParameter4 0x88c - -#define rFPGA0_XA_LSSIReadBack 0x8a0 /* Transceiver LSSI Readback */ -#define rFPGA0_XB_LSSIReadBack 0x8a4 -#define rFPGA0_XC_LSSIReadBack 0x8a8 -#define rFPGA0_XD_LSSIReadBack 0x8ac - -#define rFPGA0_PSDReport 0x8b4 /* Useless now */ -/* Transceiver A HSPI Readback */ -#define TransceiverA_HSPI_Readback 0x8b8 -/* Transceiver B HSPI Readback */ -#define TransceiverB_HSPI_Readback 0x8bc -/* Useless now RF Interface Readback Value */ -#define rFPGA0_XAB_RFInterfaceRB 0x8e0 -#define rFPGA0_XCD_RFInterfaceRB 0x8e4 /* Useless now */ - -/* 4. Page9(0x900) */ -/* RF mode & OFDM TxSC RF BW Setting?? */ -#define rFPGA1_RFMOD 0x900 - -#define rFPGA1_TxBlock 0x904 /* Useless now */ -#define rFPGA1_DebugSelect 0x908 /* Useless now */ -#define rFPGA1_TxInfo 0x90c /* Useless now Status report */ - -/* 5. PageA(0xA00) */ -/* Set Control channel to upper or lower - required only for 40MHz */ -#define rCCK0_System 0xa00 - -/* Disable init gain now Select RX path by RSSI */ -#define rCCK0_AFESetting 0xa04 -/* Disable init gain now Init gain */ -#define rCCK0_CCA 0xa08 - -/* AGC default value, saturation level Antenna Diversity, RX AGC, LNA Threshold, - * RX LNA Threshold useless now. Not the same as 90 series */ -#define rCCK0_RxAGC1 0xa0c -#define rCCK0_RxAGC2 0xa10 /* AGC & DAGC */ - -#define rCCK0_RxHP 0xa14 - -/* Timing recovery & Channel estimation threshold */ -#define rCCK0_DSPParameter1 0xa18 -#define rCCK0_DSPParameter2 0xa1c /* SQ threshold */ - -#define rCCK0_TxFilter1 0xa20 -#define rCCK0_TxFilter2 0xa24 -#define rCCK0_DebugPort 0xa28 /* debug port and Tx filter3 */ -#define rCCK0_FalseAlarmReport 0xa2c /* 0xa2d useless now */ -#define rCCK0_TRSSIReport 0xa50 -#define rCCK0_RxReport 0xa54 /* 0xa57 */ -#define rCCK0_FACounterLower 0xa5c /* 0xa5b */ -#define rCCK0_FACounterUpper 0xa58 /* 0xa5c */ - -/* */ -/* PageB(0xB00) */ -/* */ -#define rPdp_AntA 0xb00 -#define rPdp_AntA_4 0xb04 -#define rConfig_Pmpd_AntA 0xb28 -#define rConfig_AntA 0xb68 -#define rConfig_AntB 0xb6c -#define rPdp_AntB 0xb70 -#define rPdp_AntB_4 0xb74 -#define rConfig_Pmpd_AntB 0xb98 -#define rAPK 0xbd8 - -/* */ -/* 6. PageC(0xC00) */ -/* */ -#define rOFDM0_LSTF 0xc00 - -#define rOFDM0_TRxPathEnable 0xc04 -#define rOFDM0_TRMuxPar 0xc08 -#define rOFDM0_TRSWIsolation 0xc0c - -/* RxIQ DC offset, Rx digital filter, DC notch filter */ -#define rOFDM0_XARxAFE 0xc10 -#define rOFDM0_XARxIQImbalance 0xc14 /* RxIQ imbalance matrix */ -#define rOFDM0_XBRxAFE 0xc18 -#define rOFDM0_XBRxIQImbalance 0xc1c -#define rOFDM0_XCRxAFE 0xc20 -#define rOFDM0_XCRxIQImbalance 0xc24 -#define rOFDM0_XDRxAFE 0xc28 -#define rOFDM0_XDRxIQImbalance 0xc2c - -#define rOFDM0_RxDetector1 0xc30 /*PD,BW & SBD DM tune init gain*/ -#define rOFDM0_RxDetector2 0xc34 /* SBD & Fame Sync. */ -#define rOFDM0_RxDetector3 0xc38 /* Frame Sync. */ -#define rOFDM0_RxDetector4 0xc3c /* PD, SBD, Frame Sync & Short-GI */ - -#define rOFDM0_RxDSP 0xc40 /* Rx Sync Path */ -#define rOFDM0_CFOandDAGC 0xc44 /* CFO & DAGC */ -#define rOFDM0_CCADropThreshold 0xc48 /* CCA Drop threshold */ -#define rOFDM0_ECCAThreshold 0xc4c /* energy CCA */ - -#define rOFDM0_XAAGCCore1 0xc50 /* DIG */ -#define rOFDM0_XAAGCCore2 0xc54 -#define rOFDM0_XBAGCCore1 0xc58 -#define rOFDM0_XBAGCCore2 0xc5c -#define rOFDM0_XCAGCCore1 0xc60 -#define rOFDM0_XCAGCCore2 0xc64 -#define rOFDM0_XDAGCCore1 0xc68 -#define rOFDM0_XDAGCCore2 0xc6c - -#define rOFDM0_AGCParameter1 0xc70 -#define rOFDM0_AGCParameter2 0xc74 -#define rOFDM0_AGCRSSITable 0xc78 -#define rOFDM0_HTSTFAGC 0xc7c - -#define rOFDM0_XATxIQImbalance 0xc80 /* TX PWR TRACK and DIG */ -#define rOFDM0_XATxAFE 0xc84 -#define rOFDM0_XBTxIQImbalance 0xc88 -#define rOFDM0_XBTxAFE 0xc8c -#define rOFDM0_XCTxIQImbalance 0xc90 -#define rOFDM0_XCTxAFE 0xc94 -#define rOFDM0_XDTxIQImbalance 0xc98 -#define rOFDM0_XDTxAFE 0xc9c - -#define rOFDM0_RxIQExtAnta 0xca0 -#define rOFDM0_TxCoeff1 0xca4 -#define rOFDM0_TxCoeff2 0xca8 -#define rOFDM0_TxCoeff3 0xcac -#define rOFDM0_TxCoeff4 0xcb0 -#define rOFDM0_TxCoeff5 0xcb4 -#define rOFDM0_TxCoeff6 0xcb8 -#define rOFDM0_RxHPParameter 0xce0 -#define rOFDM0_TxPseudoNoiseWgt 0xce4 -#define rOFDM0_FrameSync 0xcf0 -#define rOFDM0_DFSReport 0xcf4 - -/* */ -/* 7. PageD(0xD00) */ -/* */ -#define rOFDM1_LSTF 0xd00 -#define rOFDM1_TRxPathEnable 0xd04 - -#define rOFDM1_CFO 0xd08 /* No setting now */ -#define rOFDM1_CSI1 0xd10 -#define rOFDM1_SBD 0xd14 -#define rOFDM1_CSI2 0xd18 -#define rOFDM1_CFOTracking 0xd2c -#define rOFDM1_TRxMesaure1 0xd34 -#define rOFDM1_IntfDet 0xd3c -#define rOFDM1_PseudoNoiseStateAB 0xd50 -#define rOFDM1_PseudoNoiseStateCD 0xd54 -#define rOFDM1_RxPseudoNoiseWgt 0xd58 - -#define rOFDM_PHYCounter1 0xda0 /* cca, parity fail */ -#define rOFDM_PHYCounter2 0xda4 /* rate illegal, crc8 fail */ -#define rOFDM_PHYCounter3 0xda8 /* MCS not support */ - -#define rOFDM_ShortCFOAB 0xdac /* No setting now */ -#define rOFDM_ShortCFOCD 0xdb0 -#define rOFDM_LongCFOAB 0xdb4 -#define rOFDM_LongCFOCD 0xdb8 -#define rOFDM_TailCFOAB 0xdbc -#define rOFDM_TailCFOCD 0xdc0 -#define rOFDM_PWMeasure1 0xdc4 -#define rOFDM_PWMeasure2 0xdc8 -#define rOFDM_BWReport 0xdcc -#define rOFDM_AGCReport 0xdd0 -#define rOFDM_RxSNR 0xdd4 -#define rOFDM_RxEVMCSI 0xdd8 -#define rOFDM_SIGReport 0xddc - -/* */ -/* 8. PageE(0xE00) */ -/* */ -#define rTxAGC_A_Rate18_06 0xe00 -#define rTxAGC_A_Rate54_24 0xe04 -#define rTxAGC_A_CCK1_Mcs32 0xe08 -#define rTxAGC_A_Mcs03_Mcs00 0xe10 -#define rTxAGC_A_Mcs07_Mcs04 0xe14 -#define rTxAGC_A_Mcs11_Mcs08 0xe18 -#define rTxAGC_A_Mcs15_Mcs12 0xe1c - -#define rTxAGC_B_Rate18_06 0x830 -#define rTxAGC_B_Rate54_24 0x834 -#define rTxAGC_B_CCK1_55_Mcs32 0x838 -#define rTxAGC_B_Mcs03_Mcs00 0x83c -#define rTxAGC_B_Mcs07_Mcs04 0x848 -#define rTxAGC_B_Mcs11_Mcs08 0x84c -#define rTxAGC_B_Mcs15_Mcs12 0x868 -#define rTxAGC_B_CCK11_A_CCK2_11 0x86c - -#define rFPGA0_IQK 0xe28 -#define rTx_IQK_Tone_A 0xe30 -#define rRx_IQK_Tone_A 0xe34 -#define rTx_IQK_PI_A 0xe38 -#define rRx_IQK_PI_A 0xe3c - -#define rTx_IQK 0xe40 -#define rRx_IQK 0xe44 -#define rIQK_AGC_Pts 0xe48 -#define rIQK_AGC_Rsp 0xe4c -#define rTx_IQK_Tone_B 0xe50 -#define rRx_IQK_Tone_B 0xe54 -#define rTx_IQK_PI_B 0xe58 -#define rRx_IQK_PI_B 0xe5c -#define rIQK_AGC_Cont 0xe60 - -#define rBlue_Tooth 0xe6c -#define rRx_Wait_CCA 0xe70 -#define rTx_CCK_RFON 0xe74 -#define rTx_CCK_BBON 0xe78 -#define rTx_OFDM_RFON 0xe7c -#define rTx_OFDM_BBON 0xe80 -#define rTx_To_Rx 0xe84 -#define rTx_To_Tx 0xe88 -#define rRx_CCK 0xe8c - -#define rTx_Power_Before_IQK_A 0xe94 -#define rTx_Power_After_IQK_A 0xe9c - -#define rRx_Power_Before_IQK_A 0xea0 -#define rRx_Power_Before_IQK_A_2 0xea4 -#define rRx_Power_After_IQK_A 0xea8 -#define rRx_Power_After_IQK_A_2 0xeac - -#define rTx_Power_Before_IQK_B 0xeb4 -#define rTx_Power_After_IQK_B 0xebc - -#define rRx_Power_Before_IQK_B 0xec0 -#define rRx_Power_Before_IQK_B_2 0xec4 -#define rRx_Power_After_IQK_B 0xec8 -#define rRx_Power_After_IQK_B_2 0xecc - -#define rRx_OFDM 0xed0 -#define rRx_Wait_RIFS 0xed4 -#define rRx_TO_Rx 0xed8 -#define rStandby 0xedc -#define rSleep 0xee0 -#define rPMPD_ANAEN 0xeec - -/* */ -/* 7. RF Register 0x00-0x2E (RF 8256) */ -/* RF-0222D 0x00-3F */ -/* */ -/* Zebra1 */ -#define rZebra1_HSSIEnable 0x0 /* Useless now */ -#define rZebra1_TRxEnable1 0x1 -#define rZebra1_TRxEnable2 0x2 -#define rZebra1_AGC 0x4 -#define rZebra1_ChargePump 0x5 -#define rZebra1_Channel 0x7 /* RF channel switch */ - -/* endif */ -#define rZebra1_TxGain 0x8 /* Useless now */ -#define rZebra1_TxLPF 0x9 -#define rZebra1_RxLPF 0xb -#define rZebra1_RxHPFCorner 0xc - -/* Zebra4 */ -#define rGlobalCtrl 0 /* Useless now */ -#define rRTL8256_TxLPF 19 -#define rRTL8256_RxLPF 11 - -/* RTL8258 */ -#define rRTL8258_TxLPF 0x11 /* Useless now */ -#define rRTL8258_RxLPF 0x13 -#define rRTL8258_RSSILPF 0xa - -/* */ -/* RL6052 Register definition */ -/* */ -#define RF_AC 0x00 /* */ - -#define RF_IQADJ_G1 0x01 /* */ -#define RF_IQADJ_G2 0x02 /* */ - -#define RF_POW_TRSW 0x05 /* */ - -#define RF_GAIN_RX 0x06 /* */ -#define RF_GAIN_TX 0x07 /* */ - -#define RF_TXM_IDAC 0x08 /* */ -#define RF_IPA_G 0x09 /* */ -#define RF_TXBIAS_G 0x0A -#define RF_TXPA_AG 0x0B -#define RF_IPA_A 0x0C /* */ -#define RF_TXBIAS_A 0x0D -#define RF_BS_PA_APSET_G9_G11 0x0E -#define RF_BS_IQGEN 0x0F /* */ - -#define RF_MODE1 0x10 /* */ -#define RF_MODE2 0x11 /* */ - -#define RF_RX_AGC_HP 0x12 /* */ -#define RF_TX_AGC 0x13 /* */ -#define RF_BIAS 0x14 /* */ -#define RF_IPA 0x15 /* */ -#define RF_TXBIAS 0x16 -#define RF_POW_ABILITY 0x17 /* */ -#define RF_CHNLBW 0x18 /* RF channel and BW switch */ -#define RF_TOP 0x19 /* */ - -#define RF_RX_G1 0x1A /* */ -#define RF_RX_G2 0x1B /* */ - -#define RF_RX_BB2 0x1C /* */ -#define RF_RX_BB1 0x1D /* */ - -#define RF_RCK1 0x1E /* */ -#define RF_RCK2 0x1F /* */ - -#define RF_TX_G1 0x20 /* */ -#define RF_TX_G2 0x21 /* */ -#define RF_TX_G3 0x22 /* */ - -#define RF_TX_BB1 0x23 /* */ - -#define RF_T_METER_92D 0x42 /* */ -#define RF_T_METER_88E 0x42 /* */ -#define RF_T_METER 0x24 /* */ - -#define RF_SYN_G1 0x25 /* RF TX Power control */ -#define RF_SYN_G2 0x26 /* RF TX Power control */ -#define RF_SYN_G3 0x27 /* RF TX Power control */ -#define RF_SYN_G4 0x28 /* RF TX Power control */ -#define RF_SYN_G5 0x29 /* RF TX Power control */ -#define RF_SYN_G6 0x2A /* RF TX Power control */ -#define RF_SYN_G7 0x2B /* RF TX Power control */ -#define RF_SYN_G8 0x2C /* RF TX Power control */ - -#define RF_RCK_OS 0x30 /* RF TX PA control */ -#define RF_TXPA_G1 0x31 /* RF TX PA control */ -#define RF_TXPA_G2 0x32 /* RF TX PA control */ -#define RF_TXPA_G3 0x33 /* RF TX PA control */ -#define RF_TX_BIAS_A 0x35 -#define RF_TX_BIAS_D 0x36 -#define RF_LOBF_9 0x38 -#define RF_RXRF_A3 0x3C /* */ -#define RF_TRSW 0x3F - -#define RF_TXRF_A2 0x41 -#define RF_TXPA_G4 0x46 -#define RF_TXPA_A4 0x4B -#define RF_0x52 0x52 -#define RF_WE_LUT 0xEF - -/* */ -/* Bit Mask */ -/* */ -/* 1. Page1(0x100) */ -#define bBBResetB 0x100 /* Useless now? */ -#define bGlobalResetB 0x200 -#define bOFDMTxStart 0x4 -#define bCCKTxStart 0x8 -#define bCRC32Debug 0x100 -#define bPMACLoopback 0x10 -#define bTxLSIG 0xffffff -#define bOFDMTxRate 0xf -#define bOFDMTxReserved 0x10 -#define bOFDMTxLength 0x1ffe0 -#define bOFDMTxParity 0x20000 -#define bTxHTSIG1 0xffffff -#define bTxHTMCSRate 0x7f -#define bTxHTBW 0x80 -#define bTxHTLength 0xffff00 -#define bTxHTSIG2 0xffffff -#define bTxHTSmoothing 0x1 -#define bTxHTSounding 0x2 -#define bTxHTReserved 0x4 -#define bTxHTAggreation 0x8 -#define bTxHTSTBC 0x30 -#define bTxHTAdvanceCoding 0x40 -#define bTxHTShortGI 0x80 -#define bTxHTNumberHT_LTF 0x300 -#define bTxHTCRC8 0x3fc00 -#define bCounterReset 0x10000 -#define bNumOfOFDMTx 0xffff -#define bNumOfCCKTx 0xffff0000 -#define bTxIdleInterval 0xffff -#define bOFDMService 0xffff0000 -#define bTxMACHeader 0xffffffff -#define bTxDataInit 0xff -#define bTxHTMode 0x100 -#define bTxDataType 0x30000 -#define bTxRandomSeed 0xffffffff -#define bCCKTxPreamble 0x1 -#define bCCKTxSFD 0xffff0000 -#define bCCKTxSIG 0xff -#define bCCKTxService 0xff00 -#define bCCKLengthExt 0x8000 -#define bCCKTxLength 0xffff0000 -#define bCCKTxCRC16 0xffff -#define bCCKTxStatus 0x1 -#define bOFDMTxStatus 0x2 - -#define IS_BB_REG_OFFSET_92S(_Offset) \ - ((_Offset >= 0x800) && (_Offset <= 0xfff)) - -/* 2. Page8(0x800) */ -#define bRFMOD 0x1 /* Reg 0x800 rFPGA0_RFMOD */ -#define bJapanMode 0x2 -#define bCCKTxSC 0x30 -#define bCCKEn 0x1000000 -#define bOFDMEn 0x2000000 - -#define bOFDMRxADCPhase 0x10000 /* Useless now */ -#define bOFDMTxDACPhase 0x40000 -#define bXATxAGC 0x3f - -#define bAntennaSelect 0x0300 - -#define bXBTxAGC 0xf00 /* Reg 80c rFPGA0_TxGainStage */ -#define bXCTxAGC 0xf000 -#define bXDTxAGC 0xf0000 - -#define bPAStart 0xf0000000 /* Useless now */ -#define bTRStart 0x00f00000 -#define bRFStart 0x0000f000 -#define bBBStart 0x000000f0 -#define bBBCCKStart 0x0000000f -#define bPAEnd 0xf /* Reg0x814 */ -#define bTREnd 0x0f000000 -#define bRFEnd 0x000f0000 -#define bCCAMask 0x000000f0 /* T2R */ -#define bR2RCCAMask 0x00000f00 -#define bHSSI_R2TDelay 0xf8000000 -#define bHSSI_T2RDelay 0xf80000 -#define bContTxHSSI 0x400 /* change gain at continue Tx */ -#define bIGFromCCK 0x200 -#define bAGCAddress 0x3f -#define bRxHPTx 0x7000 -#define bRxHPT2R 0x38000 -#define bRxHPCCKIni 0xc0000 -#define bAGCTxCode 0xc00000 -#define bAGCRxCode 0x300000 - -/* Reg 0x820~84f rFPGA0_XA_HSSIParameter1 */ -#define b3WireDataLength 0x800 -#define b3WireAddressLength 0x400 - -#define b3WireRFPowerDown 0x1 /* Useless now */ -#define b5GPAPEPolarity 0x40000000 -#define b2GPAPEPolarity 0x80000000 -#define bRFSW_TxDefaultAnt 0x3 -#define bRFSW_TxOptionAnt 0x30 -#define bRFSW_RxDefaultAnt 0x300 -#define bRFSW_RxOptionAnt 0x3000 -#define bRFSI_3WireData 0x1 -#define bRFSI_3WireClock 0x2 -#define bRFSI_3WireLoad 0x4 -#define bRFSI_3WireRW 0x8 -#define bRFSI_3Wire 0xf - -#define bRFSI_RFENV 0x10 /* Reg 0x870 rFPGA0_XAB_RFInterfaceSW */ - -#define bRFSI_TRSW 0x20 /* Useless now */ -#define bRFSI_TRSWB 0x40 -#define bRFSI_ANTSW 0x100 -#define bRFSI_ANTSWB 0x200 -#define bRFSI_PAPE 0x400 -#define bRFSI_PAPE5G 0x800 -#define bBandSelect 0x1 -#define bHTSIG2_GI 0x80 -#define bHTSIG2_Smoothing 0x01 -#define bHTSIG2_Sounding 0x02 -#define bHTSIG2_Aggreaton 0x08 -#define bHTSIG2_STBC 0x30 -#define bHTSIG2_AdvCoding 0x40 -#define bHTSIG2_NumOfHTLTF 0x300 -#define bHTSIG2_CRC8 0x3fc -#define bHTSIG1_MCS 0x7f -#define bHTSIG1_BandWidth 0x80 -#define bHTSIG1_HTLength 0xffff -#define bLSIG_Rate 0xf -#define bLSIG_Reserved 0x10 -#define bLSIG_Length 0x1fffe -#define bLSIG_Parity 0x20 -#define bCCKRxPhase 0x4 - -#define bLSSIReadAddress 0x7f800000 /* T65 RF */ - -#define bLSSIReadEdge 0x80000000 /* LSSI "Read" edge signal */ - -#define bLSSIReadBackData 0xfffff /* T65 RF */ - -#define bLSSIReadOKFlag 0x1000 /* Useless now */ -#define bCCKSampleRate 0x8 /* 0: 44MHz, 1:88MHz */ -#define bRegulator0Standby 0x1 -#define bRegulatorPLLStandby 0x2 -#define bRegulator1Standby 0x4 -#define bPLLPowerUp 0x8 -#define bDPLLPowerUp 0x10 -#define bDA10PowerUp 0x20 -#define bAD7PowerUp 0x200 -#define bDA6PowerUp 0x2000 -#define bXtalPowerUp 0x4000 -#define b40MDClkPowerUP 0x8000 -#define bDA6DebugMode 0x20000 -#define bDA6Swing 0x380000 - -/* Reg 0x880 rFPGA0_AnalogParameter1 20/40 CCK support switch 40/80 BB MHZ */ -#define bADClkPhase 0x4000000 - -#define b80MClkDelay 0x18000000 /* Useless */ -#define bAFEWatchDogEnable 0x20000000 - -/* Reg 0x884 rFPGA0_AnalogParameter2 Crystal cap */ -#define bXtalCap01 0xc0000000 -#define bXtalCap23 0x3 -#define bXtalCap92x 0x0f000000 -#define bXtalCap 0x0f000000 - -#define bIntDifClkEnable 0x400 /* Useless */ -#define bExtSigClkEnable 0x800 -#define bBandgapMbiasPowerUp 0x10000 -#define bAD11SHGain 0xc0000 -#define bAD11InputRange 0x700000 -#define bAD11OPCurrent 0x3800000 -#define bIPathLoopback 0x4000000 -#define bQPathLoopback 0x8000000 -#define bAFELoopback 0x10000000 -#define bDA10Swing 0x7e0 -#define bDA10Reverse 0x800 -#define bDAClkSource 0x1000 -#define bAD7InputRange 0x6000 -#define bAD7Gain 0x38000 -#define bAD7OutputCMMode 0x40000 -#define bAD7InputCMMode 0x380000 -#define bAD7Current 0xc00000 -#define bRegulatorAdjust 0x7000000 -#define bAD11PowerUpAtTx 0x1 -#define bDA10PSAtTx 0x10 -#define bAD11PowerUpAtRx 0x100 -#define bDA10PSAtRx 0x1000 -#define bCCKRxAGCFormat 0x200 -#define bPSDFFTSamplepPoint 0xc000 -#define bPSDAverageNum 0x3000 -#define bIQPathControl 0xc00 -#define bPSDFreq 0x3ff -#define bPSDAntennaPath 0x30 -#define bPSDIQSwitch 0x40 -#define bPSDRxTrigger 0x400000 -#define bPSDTxTrigger 0x80000000 -#define bPSDSineToneScale 0x7f000000 -#define bPSDReport 0xffff - -/* 3. Page9(0x900) */ -#define bOFDMTxSC 0x30000000 /* Useless */ -#define bCCKTxOn 0x1 -#define bOFDMTxOn 0x2 -#define bDebugPage 0xfff /* reset debug page and HWord, LWord */ -#define bDebugItem 0xff /* reset debug page and LWord */ -#define bAntL 0x10 -#define bAntNonHT 0x100 -#define bAntHT1 0x1000 -#define bAntHT2 0x10000 -#define bAntHT1S1 0x100000 -#define bAntNonHTS1 0x1000000 - -/* 4. PageA(0xA00) */ -#define bCCKBBMode 0x3 /* Useless */ -#define bCCKTxPowerSaving 0x80 -#define bCCKRxPowerSaving 0x40 - -#define bCCKSideBand 0x10 /* Reg 0xa00 rCCK0_System 20/40 */ - -#define bCCKScramble 0x8 /* Useless */ -#define bCCKAntDiversity 0x8000 -#define bCCKCarrierRecovery 0x4000 -#define bCCKTxRate 0x3000 -#define bCCKDCCancel 0x0800 -#define bCCKISICancel 0x0400 -#define bCCKMatchFilter 0x0200 -#define bCCKEqualizer 0x0100 -#define bCCKPreambleDetect 0x800000 -#define bCCKFastFalseCCA 0x400000 -#define bCCKChEstStart 0x300000 -#define bCCKCCACount 0x080000 -#define bCCKcs_lim 0x070000 -#define bCCKBistMode 0x80000000 -#define bCCKCCAMask 0x40000000 -#define bCCKTxDACPhase 0x4 -#define bCCKRxADCPhase 0x20000000 /* r_rx_clk */ -#define bCCKr_cp_mode0 0x0100 -#define bCCKTxDCOffset 0xf0 -#define bCCKRxDCOffset 0xf -#define bCCKCCAMode 0xc000 -#define bCCKFalseCS_lim 0x3f00 -#define bCCKCS_ratio 0xc00000 -#define bCCKCorgBit_sel 0x300000 -#define bCCKPD_lim 0x0f0000 -#define bCCKNewCCA 0x80000000 -#define bCCKRxHPofIG 0x8000 -#define bCCKRxIG 0x7f00 -#define bCCKLNAPolarity 0x800000 -#define bCCKRx1stGain 0x7f0000 -#define bCCKRFExtend 0x20000000 /* CCK Rx Iinital gain polarity */ -#define bCCKRxAGCSatLevel 0x1f000000 -#define bCCKRxAGCSatCount 0xe0 -#define bCCKRxRFSettle 0x1f /* AGCsamp_dly */ -#define bCCKFixedRxAGC 0x8000 -#define bCCKAntennaPolarity 0x2000 -#define bCCKTxFilterType 0x0c00 -#define bCCKRxAGCReportType 0x0300 -#define bCCKRxDAGCEn 0x80000000 -#define bCCKRxDAGCPeriod 0x20000000 -#define bCCKRxDAGCSatLevel 0x1f000000 -#define bCCKTimingRecovery 0x800000 -#define bCCKTxC0 0x3f0000 -#define bCCKTxC1 0x3f000000 -#define bCCKTxC2 0x3f -#define bCCKTxC3 0x3f00 -#define bCCKTxC4 0x3f0000 -#define bCCKTxC5 0x3f000000 -#define bCCKTxC6 0x3f -#define bCCKTxC7 0x3f00 -#define bCCKDebugPort 0xff0000 -#define bCCKDACDebug 0x0f000000 -#define bCCKFalseAlarmEnable 0x8000 -#define bCCKFalseAlarmRead 0x4000 -#define bCCKTRSSI 0x7f -#define bCCKRxAGCReport 0xfe -#define bCCKRxReport_AntSel 0x80000000 -#define bCCKRxReport_MFOff 0x40000000 -#define bCCKRxRxReport_SQLoss 0x20000000 -#define bCCKRxReport_Pktloss 0x10000000 -#define bCCKRxReport_Lockedbit 0x08000000 -#define bCCKRxReport_RateError 0x04000000 -#define bCCKRxReport_RxRate 0x03000000 -#define bCCKRxFACounterLower 0xff -#define bCCKRxFACounterUpper 0xff000000 -#define bCCKRxHPAGCStart 0xe000 -#define bCCKRxHPAGCFinal 0x1c00 -#define bCCKRxFalseAlarmEnable 0x8000 -#define bCCKFACounterFreeze 0x4000 -#define bCCKTxPathSel 0x10000000 -#define bCCKDefaultRxPath 0xc000000 -#define bCCKOptionRxPath 0x3000000 - -/* 5. PageC(0xC00) */ -#define bNumOfSTF 0x3 /* Useless */ -#define bShift_L 0xc0 -#define bGI_TH 0xc -#define bRxPathA 0x1 -#define bRxPathB 0x2 -#define bRxPathC 0x4 -#define bRxPathD 0x8 -#define bTxPathA 0x1 -#define bTxPathB 0x2 -#define bTxPathC 0x4 -#define bTxPathD 0x8 -#define bTRSSIFreq 0x200 -#define bADCBackoff 0x3000 -#define bDFIRBackoff 0xc000 -#define bTRSSILatchPhase 0x10000 -#define bRxIDCOffset 0xff -#define bRxQDCOffset 0xff00 -#define bRxDFIRMode 0x1800000 -#define bRxDCNFType 0xe000000 -#define bRXIQImb_A 0x3ff -#define bRXIQImb_B 0xfc00 -#define bRXIQImb_C 0x3f0000 -#define bRXIQImb_D 0xffc00000 -#define bDC_dc_Notch 0x60000 -#define bRxNBINotch 0x1f000000 -#define bPD_TH 0xf -#define bPD_TH_Opt2 0xc000 -#define bPWED_TH 0x700 -#define bIfMF_Win_L 0x800 -#define bPD_Option 0x1000 -#define bMF_Win_L 0xe000 -#define bBW_Search_L 0x30000 -#define bwin_enh_L 0xc0000 -#define bBW_TH 0x700000 -#define bED_TH2 0x3800000 -#define bBW_option 0x4000000 -#define bRatio_TH 0x18000000 -#define bWindow_L 0xe0000000 -#define bSBD_Option 0x1 -#define bFrame_TH 0x1c -#define bFS_Option 0x60 -#define bDC_Slope_check 0x80 -#define bFGuard_Counter_DC_L 0xe00 -#define bFrame_Weight_Short 0x7000 -#define bSub_Tune 0xe00000 -#define bFrame_DC_Length 0xe000000 -#define bSBD_start_offset 0x30000000 -#define bFrame_TH_2 0x7 -#define bFrame_GI2_TH 0x38 -#define bGI2_Sync_en 0x40 -#define bSarch_Short_Early 0x300 -#define bSarch_Short_Late 0xc00 -#define bSarch_GI2_Late 0x70000 -#define bCFOAntSum 0x1 -#define bCFOAcc 0x2 -#define bCFOStartOffset 0xc -#define bCFOLookBack 0x70 -#define bCFOSumWeight 0x80 -#define bDAGCEnable 0x10000 -#define bTXIQImb_A 0x3ff -#define bTXIQImb_B 0xfc00 -#define bTXIQImb_C 0x3f0000 -#define bTXIQImb_D 0xffc00000 -#define bTxIDCOffset 0xff -#define bTxQDCOffset 0xff00 -#define bTxDFIRMode 0x10000 -#define bTxPesudoNoiseOn 0x4000000 -#define bTxPesudoNoise_A 0xff -#define bTxPesudoNoise_B 0xff00 -#define bTxPesudoNoise_C 0xff0000 -#define bTxPesudoNoise_D 0xff000000 -#define bCCADropOption 0x20000 -#define bCCADropThres 0xfff00000 -#define bEDCCA_H 0xf -#define bEDCCA_L 0xf0 -#define bLambda_ED 0x300 -#define bRxInitialGain 0x7f -#define bRxAntDivEn 0x80 -#define bRxAGCAddressForLNA 0x7f00 -#define bRxHighPowerFlow 0x8000 -#define bRxAGCFreezeThres 0xc0000 -#define bRxFreezeStep_AGC1 0x300000 -#define bRxFreezeStep_AGC2 0xc00000 -#define bRxFreezeStep_AGC3 0x3000000 -#define bRxFreezeStep_AGC0 0xc000000 -#define bRxRssi_Cmp_En 0x10000000 -#define bRxQuickAGCEn 0x20000000 -#define bRxAGCFreezeThresMode 0x40000000 -#define bRxOverFlowCheckType 0x80000000 -#define bRxAGCShift 0x7f -#define bTRSW_Tri_Only 0x80 -#define bPowerThres 0x300 -#define bRxAGCEn 0x1 -#define bRxAGCTogetherEn 0x2 -#define bRxAGCMin 0x4 -#define bRxHP_Ini 0x7 -#define bRxHP_TRLNA 0x70 -#define bRxHP_RSSI 0x700 -#define bRxHP_BBP1 0x7000 -#define bRxHP_BBP2 0x70000 -#define bRxHP_BBP3 0x700000 -#define bRSSI_H 0x7f0000 /* threshold for high power */ -#define bRSSI_Gen 0x7f000000 /* threshold for ant diversity */ -#define bRxSettle_TRSW 0x7 -#define bRxSettle_LNA 0x38 -#define bRxSettle_RSSI 0x1c0 -#define bRxSettle_BBP 0xe00 -#define bRxSettle_RxHP 0x7000 -#define bRxSettle_AntSW_RSSI 0x38000 -#define bRxSettle_AntSW 0xc0000 -#define bRxProcessTime_DAGC 0x300000 -#define bRxSettle_HSSI 0x400000 -#define bRxProcessTime_BBPPW 0x800000 -#define bRxAntennaPowerShift 0x3000000 -#define bRSSITableSelect 0xc000000 -#define bRxHP_Final 0x7000000 -#define bRxHTSettle_BBP 0x7 -#define bRxHTSettle_HSSI 0x8 -#define bRxHTSettle_RxHP 0x70 -#define bRxHTSettle_BBPPW 0x80 -#define bRxHTSettle_Idle 0x300 -#define bRxHTSettle_Reserved 0x1c00 -#define bRxHTRxHPEn 0x8000 -#define bRxHTAGCFreezeThres 0x30000 -#define bRxHTAGCTogetherEn 0x40000 -#define bRxHTAGCMin 0x80000 -#define bRxHTAGCEn 0x100000 -#define bRxHTDAGCEn 0x200000 -#define bRxHTRxHP_BBP 0x1c00000 -#define bRxHTRxHP_Final 0xe0000000 -#define bRxPWRatioTH 0x3 -#define bRxPWRatioEn 0x4 -#define bRxMFHold 0x3800 -#define bRxPD_Delay_TH1 0x38 -#define bRxPD_Delay_TH2 0x1c0 -#define bRxPD_DC_COUNT_MAX 0x600 -#define bRxPD_Delay_TH 0x8000 -#define bRxProcess_Delay 0xf0000 -#define bRxSearchrange_GI2_Early 0x700000 -#define bRxFrame_Guard_Counter_L 0x3800000 -#define bRxSGI_Guard_L 0xc000000 -#define bRxSGI_Search_L 0x30000000 -#define bRxSGI_TH 0xc0000000 -#define bDFSCnt0 0xff -#define bDFSCnt1 0xff00 -#define bDFSFlag 0xf0000 -#define bMFWeightSum 0x300000 -#define bMinIdxTH 0x7f000000 -#define bDAFormat 0x40000 -#define bTxChEmuEnable 0x01000000 -#define bTRSWIsolation_A 0x7f -#define bTRSWIsolation_B 0x7f00 -#define bTRSWIsolation_C 0x7f0000 -#define bTRSWIsolation_D 0x7f000000 -#define bExtLNAGain 0x7c00 - -/* 6. PageE(0xE00) */ -#define bSTBCEn 0x4 /* Useless */ -#define bAntennaMapping 0x10 -#define bNss 0x20 -#define bCFOAntSumD 0x200 -#define bPHYCounterReset 0x8000000 -#define bCFOReportGet 0x4000000 -#define bOFDMContinueTx 0x10000000 -#define bOFDMSingleCarrier 0x20000000 -#define bOFDMSingleTone 0x40000000 -#define bHTDetect 0x100 -#define bCFOEn 0x10000 -#define bCFOValue 0xfff00000 -#define bSigTone_Re 0x3f -#define bSigTone_Im 0x7f00 -#define bCounter_CCA 0xffff -#define bCounter_ParityFail 0xffff0000 -#define bCounter_RateIllegal 0xffff -#define bCounter_CRC8Fail 0xffff0000 -#define bCounter_MCSNoSupport 0xffff -#define bCounter_FastSync 0xffff -#define bShortCFO 0xfff -#define bShortCFOTLength 12 /* total */ -#define bShortCFOFLength 11 /* fraction */ -#define bLongCFO 0x7ff -#define bLongCFOTLength 11 -#define bLongCFOFLength 11 -#define bTailCFO 0x1fff -#define bTailCFOTLength 13 -#define bTailCFOFLength 12 -#define bmax_en_pwdB 0xffff -#define bCC_power_dB 0xffff0000 -#define bnoise_pwdB 0xffff -#define bPowerMeasTLength 10 -#define bPowerMeasFLength 3 -#define bRx_HT_BW 0x1 -#define bRxSC 0x6 -#define bRx_HT 0x8 -#define bNB_intf_det_on 0x1 -#define bIntf_win_len_cfg 0x30 -#define bNB_Intf_TH_cfg 0x1c0 -#define bRFGain 0x3f -#define bTableSel 0x40 -#define bTRSW 0x80 -#define bRxSNR_A 0xff -#define bRxSNR_B 0xff00 -#define bRxSNR_C 0xff0000 -#define bRxSNR_D 0xff000000 -#define bSNREVMTLength 8 -#define bSNREVMFLength 1 -#define bCSI1st 0xff -#define bCSI2nd 0xff00 -#define bRxEVM1st 0xff0000 -#define bRxEVM2nd 0xff000000 -#define bSIGEVM 0xff -#define bPWDB 0xff00 -#define bSGIEN 0x10000 - -#define bSFactorQAM1 0xf /* Useless */ -#define bSFactorQAM2 0xf0 -#define bSFactorQAM3 0xf00 -#define bSFactorQAM4 0xf000 -#define bSFactorQAM5 0xf0000 -#define bSFactorQAM6 0xf0000 -#define bSFactorQAM7 0xf00000 -#define bSFactorQAM8 0xf000000 -#define bSFactorQAM9 0xf0000000 -#define bCSIScheme 0x100000 - -#define bNoiseLvlTopSet 0x3 /* Useless */ -#define bChSmooth 0x4 -#define bChSmoothCfg1 0x38 -#define bChSmoothCfg2 0x1c0 -#define bChSmoothCfg3 0xe00 -#define bChSmoothCfg4 0x7000 -#define bMRCMode 0x800000 -#define bTHEVMCfg 0x7000000 - -#define bLoopFitType 0x1 /* Useless */ -#define bUpdCFO 0x40 -#define bUpdCFOOffData 0x80 -#define bAdvUpdCFO 0x100 -#define bAdvTimeCtrl 0x800 -#define bUpdClko 0x1000 -#define bFC 0x6000 -#define bTrackingMode 0x8000 -#define bPhCmpEnable 0x10000 -#define bUpdClkoLTF 0x20000 -#define bComChCFO 0x40000 -#define bCSIEstiMode 0x80000 -#define bAdvUpdEqz 0x100000 -#define bUChCfg 0x7000000 -#define bUpdEqz 0x8000000 - -/* Rx Pseduo noise */ -#define bRxPesudoNoiseOn 0x20000000 /* Useless */ -#define bRxPesudoNoise_A 0xff -#define bRxPesudoNoise_B 0xff00 -#define bRxPesudoNoise_C 0xff0000 -#define bRxPesudoNoise_D 0xff000000 -#define bPesudoNoiseState_A 0xffff -#define bPesudoNoiseState_B 0xffff0000 -#define bPesudoNoiseState_C 0xffff -#define bPesudoNoiseState_D 0xffff0000 - -/* 7. RF Register */ -/* Zebra1 */ -#define bZebra1_HSSIEnable 0x8 /* Useless */ -#define bZebra1_TRxControl 0xc00 -#define bZebra1_TRxGainSetting 0x07f -#define bZebra1_RxCorner 0xc00 -#define bZebra1_TxChargePump 0x38 -#define bZebra1_RxChargePump 0x7 -#define bZebra1_ChannelNum 0xf80 -#define bZebra1_TxLPFBW 0x400 -#define bZebra1_RxLPFBW 0x600 - -/* Zebra4 */ -#define bRTL8256RegModeCtrl1 0x100 /* Useless */ -#define bRTL8256RegModeCtrl0 0x40 -#define bRTL8256_TxLPFBW 0x18 -#define bRTL8256_RxLPFBW 0x600 - -/* RTL8258 */ -#define bRTL8258_TxLPFBW 0xc /* Useless */ -#define bRTL8258_RxLPFBW 0xc00 -#define bRTL8258_RSSILPFBW 0xc0 - -/* */ -/* Other Definition */ -/* */ - -/* byte endable for sb_write */ -#define bByte0 0x1 /* Useless */ -#define bByte1 0x2 -#define bByte2 0x4 -#define bByte3 0x8 -#define bWord0 0x3 -#define bWord1 0xc -#define bDWord 0xf - -/* for PutRegsetting & GetRegSetting BitMask */ -#define bMaskByte0 0xff /* Reg 0xc50 rOFDM0_XAAGCCore~0xC6f */ -#define bMaskByte1 0xff00 -#define bMaskByte2 0xff0000 -#define bMaskByte3 0xff000000 -#define bMaskHWord 0xffff0000 -#define bMaskLWord 0x0000ffff -#define bMaskDWord 0xffffffff -#define bMask12Bits 0xfff -#define bMaskH4Bits 0xf0000000 -#define bMaskOFDM_D 0xffc00000 -#define bMaskCCK 0x3f3f3f3f - -/* for PutRFRegsetting & GetRFRegSetting BitMask */ -#define bRFRegOffsetMask 0xfffff - -#define bEnable 0x1 /* Useless */ -#define bDisable 0x0 - -#define LeftAntenna 0x0 /* Useless */ -#define RightAntenna 0x1 - -#define tCheckTxStatus 500 /* 500ms Useless */ -#define tUpdateRxCounter 100 /* 100ms */ - -#define rateCCK 0 /* Useless */ -#define rateOFDM 1 -#define rateHT 2 - -/* define Register-End */ -#define bPMAC_End 0x1ff /* Useless */ -#define bFPGAPHY0_End 0x8ff -#define bFPGAPHY1_End 0x9ff -#define bCCKPHY0_End 0xaff -#define bOFDMPHY0_End 0xcff -#define bOFDMPHY1_End 0xdff - -#define bPMACControl 0x0 /* Useless */ -#define bWMACControl 0x1 -#define bWNICControl 0x2 - -#define PathA 0x0 /* Useless */ -#define PathB 0x1 -#define PathC 0x2 -#define PathD 0x3 - -/*--------------------------Define Parameters-------------------------------*/ - -#endif diff --git a/drivers/staging/r8188eu/include/Hal8188ERateAdaptive.h b/drivers/staging/r8188eu/include/Hal8188ERateAdaptive.h deleted file mode 100644 index c571ad9478ea..000000000000 --- a/drivers/staging/r8188eu/include/Hal8188ERateAdaptive.h +++ /dev/null @@ -1,49 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright (c) 2011 Realtek Semiconductor Corp. */ - -#ifndef __INC_RA_H -#define __INC_RA_H -/* Module Name: RateAdaptive.h - * Abstract: Prototype of RA and related data structure. - */ - -#include - -/* Rate adaptive define */ -#define PERENTRY 23 -#define RETRYSIZE 5 -#define RATESIZE 28 -#define TX_RPT2_ITEM_SIZE 8 - -/* TX report 2 format in Rx desc */ -#define GET_TX_RPT2_DESC_PKT_LEN_88E(__rxstatusdesc) \ - le32_get_bits(*(__le32 *)__rxstatusdesc, GENMASK(8, 0)) -#define GET_TX_RPT2_DESC_MACID_VALID_1_88E(__rxstatusdesc) \ - le32_to_cpu((*(__le32 *)(__rxstatusdesc + 16)) -#define GET_TX_RPT2_DESC_MACID_VALID_2_88E(__rxstatusdesc) \ - le32_to_cpu((*(__le32 *)(__rxstatusdesc + 20)) -/* End rate adaptive define */ - -int ODM_RAInfo_Init_all(struct odm_dm_struct *dm_odm); - -int ODM_RAInfo_Init(struct odm_dm_struct *dm_odm, u8 MacID); - -u8 ODM_RA_GetShortGI_8188E(struct odm_dm_struct *dm_odm, u8 MacID); - -u8 ODM_RA_GetDecisionRate_8188E(struct odm_dm_struct *dm_odm, u8 MacID); - -u8 ODM_RA_GetHwPwrStatus_8188E(struct odm_dm_struct *dm_odm, u8 MacID); -void ODM_RA_UpdateRateInfo_8188E(struct odm_dm_struct *dm_odm, u8 MacID, - u8 RateID, u32 RateMask, - u8 SGIEnable); - -void ODM_RA_SetRSSI_8188E(struct odm_dm_struct *dm_odm, u8 macid, - u8 rssi); - -void ODM_RA_TxRPT2Handle_8188E(struct odm_dm_struct *dm_odm, - u8 *txrpt_buf, u16 txrpt_len, - u32 validentry0, u32 validentry1); - -void ODM_RA_Set_TxRPT_Time(struct odm_dm_struct *dm_odm, u16 minRptTime); - -#endif diff --git a/drivers/staging/r8188eu/include/HalHWImg8188E_BB.h b/drivers/staging/r8188eu/include/HalHWImg8188E_BB.h deleted file mode 100644 index 0a290bc31c4d..000000000000 --- a/drivers/staging/r8188eu/include/HalHWImg8188E_BB.h +++ /dev/null @@ -1,27 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#ifndef __INC_BB_8188E_HW_IMG_H -#define __INC_BB_8188E_HW_IMG_H - -/* static bool CheckCondition(const u32 Condition, const u32 Hex); */ - -/****************************************************************************** -* AGC_TAB_1T.TXT -******************************************************************************/ - -int ODM_ReadAndConfig_AGC_TAB_1T_8188E(struct odm_dm_struct *odm); - -/****************************************************************************** -* PHY_REG_1T.TXT -******************************************************************************/ - -int ODM_ReadAndConfig_PHY_REG_1T_8188E(struct odm_dm_struct *odm); - -/****************************************************************************** -* PHY_REG_PG.TXT -******************************************************************************/ - -void ODM_ReadAndConfig_PHY_REG_PG_8188E(struct odm_dm_struct *dm_odm); - -#endif diff --git a/drivers/staging/r8188eu/include/HalHWImg8188E_MAC.h b/drivers/staging/r8188eu/include/HalHWImg8188E_MAC.h deleted file mode 100644 index b3d67c1a8050..000000000000 --- a/drivers/staging/r8188eu/include/HalHWImg8188E_MAC.h +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#ifndef __INC_MAC_8188E_HW_IMG_H -#define __INC_MAC_8188E_HW_IMG_H - -/****************************************************************************** -* MAC_REG.TXT -******************************************************************************/ -int ODM_ReadAndConfig_MAC_REG_8188E(struct odm_dm_struct *pDM_Odm); - -#endif /* end of HWIMG_SUPPORT */ diff --git a/drivers/staging/r8188eu/include/HalHWImg8188E_RF.h b/drivers/staging/r8188eu/include/HalHWImg8188E_RF.h deleted file mode 100644 index 880feadb4340..000000000000 --- a/drivers/staging/r8188eu/include/HalHWImg8188E_RF.h +++ /dev/null @@ -1,13 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#ifndef __INC_RF_8188E_HW_IMG_H -#define __INC_RF_8188E_HW_IMG_H - -/****************************************************************************** - * RadioA_1T.TXT - ******************************************************************************/ - -int ODM_ReadAndConfig_RadioA_1T_8188E(struct odm_dm_struct *odm); - -#endif /* end of HWIMG_SUPPORT */ diff --git a/drivers/staging/r8188eu/include/HalPhyRf_8188e.h b/drivers/staging/r8188eu/include/HalPhyRf_8188e.h deleted file mode 100644 index b75a5d869c56..000000000000 --- a/drivers/staging/r8188eu/include/HalPhyRf_8188e.h +++ /dev/null @@ -1,36 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#ifndef __HAL_PHY_RF_8188E_H__ -#define __HAL_PHY_RF_8188E_H__ - -/*--------------------------Define Parameters-------------------------------*/ -#define IQK_DELAY_TIME_88E 10 /* ms */ -#define index_mapping_NUM_88E 15 -#define AVG_THERMAL_NUM_88E 4 - -void ODM_TxPwrTrackAdjust88E(struct odm_dm_struct *pDM_Odm, - u8 Type, /* 0 = OFDM, 1 = CCK */ - u8 *pDirection,/* 1 = +(incr) 2 = -(decr) */ - u32 *pOutWriteVal); /* Tx tracking CCK/OFDM BB - * swing index adjust */ - -void odm_TXPowerTrackingCallback_ThermalMeter_8188E(struct adapter *Adapter); - -/* 1 7. IQK */ - -void PHY_IQCalibrate_8188E(struct adapter *Adapter, bool ReCovery); - -/* LC calibrate */ -void PHY_LCCalibrate_8188E(struct adapter *pAdapter); - -/* AP calibrate */ -void PHY_DigitalPredistortion_8188E(struct adapter *pAdapter); - -void _PHY_SaveADDARegisters(struct adapter *pAdapter, u32 *ADDAReg, - u32 *ADDABackup, u32 RegisterNum); - -void _PHY_MACSettingCalibration(struct adapter *pAdapter, u32 *MACReg, - u32 *MACBackup); - -#endif /* #ifndef __HAL_PHY_RF_8188E_H__ */ diff --git a/drivers/staging/r8188eu/include/HalPwrSeqCmd.h b/drivers/staging/r8188eu/include/HalPwrSeqCmd.h deleted file mode 100644 index 0886300d26bf..000000000000 --- a/drivers/staging/r8188eu/include/HalPwrSeqCmd.h +++ /dev/null @@ -1,18 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#ifndef __HALPWRSEQCMD_H__ -#define __HALPWRSEQCMD_H__ - -#include "drv_types.h" - -enum r8188eu_pwr_seq { - PWR_ON_FLOW, - DISABLE_FLOW, - LPS_ENTER_FLOW, -}; - -/* Prototype of protected function. */ -u8 HalPwrSeqCmdParsing(struct adapter *padapter, enum r8188eu_pwr_seq seq); - -#endif diff --git a/drivers/staging/r8188eu/include/HalVerDef.h b/drivers/staging/r8188eu/include/HalVerDef.h deleted file mode 100644 index 7a530c7d57eb..000000000000 --- a/drivers/staging/r8188eu/include/HalVerDef.h +++ /dev/null @@ -1,42 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ -#ifndef __HAL_VERSION_DEF_H__ -#define __HAL_VERSION_DEF_H__ - -enum HAL_CHIP_TYPE { - TEST_CHIP = 0, - NORMAL_CHIP = 1, -}; - -enum HAL_CUT_VERSION { - A_CUT_VERSION = 0, - B_CUT_VERSION = 1, - C_CUT_VERSION = 2, - D_CUT_VERSION = 3, - E_CUT_VERSION = 4, -}; - -enum HAL_VENDOR { - CHIP_VENDOR_TSMC = 0, - CHIP_VENDOR_UMC = 1, -}; - -struct HAL_VERSION { - enum HAL_CHIP_TYPE ChipType; - enum HAL_CUT_VERSION CUTVersion; - enum HAL_VENDOR VendorType; -}; - -/* Get element */ -#define GET_CVID_CHIP_TYPE(version) (((version).ChipType)) -#define GET_CVID_MANUFACTUER(version) (((version).VendorType)) - -/* HAL_CHIP_TYPE_E */ -#define IS_NORMAL_CHIP(version) \ - (GET_CVID_CHIP_TYPE(version) == NORMAL_CHIP) - -/* HAL_VENDOR_E */ -#define IS_CHIP_VENDOR_TSMC(version) \ - (GET_CVID_MANUFACTUER(version) == CHIP_VENDOR_TSMC) - -#endif diff --git a/drivers/staging/r8188eu/include/drv_types.h b/drivers/staging/r8188eu/include/drv_types.h deleted file mode 100644 index 159990facb8a..000000000000 --- a/drivers/staging/r8188eu/include/drv_types.h +++ /dev/null @@ -1,224 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2007 - 2012 Realtek Corporation. */ - -/*----------------------------------------------------------------------------- - - For type defines and data structure defines - -------------------------------------------------------------------------------*/ - -#ifndef __DRV_TYPES_H__ -#define __DRV_TYPES_H__ - -#include "osdep_service.h" -#include "wlan_bssdef.h" -#include "rtw_ht.h" -#include "rtw_cmd.h" -#include "rtw_xmit.h" -#include "rtw_recv.h" -#include "hal_intf.h" -#include "hal_com.h" -#include "rtw_security.h" -#include "rtw_pwrctrl.h" -#include "rtw_io.h" -#include "rtw_eeprom.h" -#include "sta_info.h" -#include "rtw_mlme.h" -#include "rtw_rf.h" -#include "rtw_event.h" -#include "rtw_led.h" -#include "rtw_mlme_ext.h" -#include "rtw_p2p.h" -#include "rtw_ap.h" -#include "rtw_br_ext.h" -#include "rtl8188e_hal.h" -#include "rtw_fw.h" - -#define FW_RTL8188EU "rtlwifi/rtl8188eufw.bin" - -struct registry_priv { - u8 rfintfs; - u8 lbkmode; - u8 hci; - struct ndis_802_11_ssid ssid; - u8 network_mode; /* infra, ad-hoc, auto */ - u8 channel;/* ad-hoc support requirement */ - u8 wireless_mode;/* A, B, G, auto */ - u8 scan_mode;/* active, passive */ - u8 radio_enable; - u8 preamble;/* long, short, auto */ - u8 vrtl_carrier_sense;/* Enable, Disable, Auto */ - u8 vcs_type;/* RTS/CTS, CTS-to-self */ - u16 rts_thresh; - u16 frag_thresh; - u8 adhoc_tx_pwr; - u8 soft_ap; - u8 power_mgnt; - u8 ips_mode; - u8 smart_ps; - u8 long_retry_lmt; - u8 short_retry_lmt; - u16 busy_thresh; - u8 ack_policy; - u8 software_encrypt; - u8 software_decrypt; - u8 acm_method; - /* UAPSD */ - u8 wmm_enable; - u8 uapsd_enable; - u8 uapsd_max_sp; - u8 uapsd_acbk_en; - u8 uapsd_acbe_en; - u8 uapsd_acvi_en; - u8 uapsd_acvo_en; - - u8 led_enable; - - struct wlan_bssid_ex dev_network; - - u8 ht_enable; - u8 cbw40_enable; - u8 ampdu_enable;/* for tx */ - u8 rx_stbc; - u8 ampdu_amsdu;/* A-MPDU Supports A-MSDU is permitted */ - u8 lowrate_two_xmit; - - u8 low_power; - - u8 wifi_spec;/* !turbo_mode */ - - u8 channel_plan; - bool bAcceptAddbaReq; - - u8 antdiv_cfg; - u8 antdiv_type; - - u8 usbss_enable;/* 0:disable,1:enable */ - u8 hwpdn_mode;/* 0:disable,1:enable,2:decide by EFUSE config */ - u8 hwpwrp_detect;/* 0:disable,1:enable */ - - u8 hw_wps_pbc;/* 0:disable,1:enable */ - - u8 max_roaming_times; /* the max number driver will try */ - - u8 fw_iol; /* enable iol without other concern */ - - u8 enable80211d; - - u8 ifname[16]; - u8 if2name[16]; - - u8 notch_filter; -}; - -#define MAX_CONTINUAL_URB_ERR 4 - -struct dvobj_priv { - struct adapter *if1; - - /* For 92D, DMDP have 2 interface. */ - u8 InterfaceNumber; - u8 NumInterfaces; - - /* In /Out Pipe information */ - int RtInPipe; - int RtOutPipe[3]; - u8 Queue2Pipe[HW_QUEUE_ENTRY];/* for out pipe mapping */ - - struct rt_firmware firmware; - -/*-------- below is for USB INTERFACE --------*/ - - u8 RtNumOutPipes; - - struct usb_interface *pusbintf; - struct usb_device *pusbdev; - - atomic_t continual_urb_error; -}; - -static inline struct device *dvobj_to_dev(struct dvobj_priv *dvobj) -{ - /* todo: get interface type from dvobj and the return - * the dev accordingly */ - return &dvobj->pusbintf->dev; -}; - -struct adapter { - int pid[3];/* process id from UI, 0:wps, 1:hostapd, 2:dhcpcd */ - - struct dvobj_priv *dvobj; - struct mlme_priv mlmepriv; - struct mlme_ext_priv mlmeextpriv; - struct cmd_priv cmdpriv; - struct evt_priv evtpriv; - struct xmit_priv xmitpriv; - struct recv_priv recvpriv; - struct sta_priv stapriv; - struct security_priv securitypriv; - struct registry_priv registrypriv; - struct pwrctrl_priv pwrctrlpriv; - struct eeprom_priv eeprompriv; - struct led_priv ledpriv; - struct wifidirect_info wdinfo; - - struct hal_data_8188e haldata; - - s32 bDriverStopped; - s32 bSurpriseRemoved; - - u8 hw_init_completed; - s8 signal_strength; - - void *cmdThread; - struct net_device *pnetdev; - - /* used by rtw_rereg_nd_name related function */ - struct rereg_nd_name_data { - struct net_device *old_pnetdev; - char old_ifname[IFNAMSIZ]; - u8 old_ips_mode; - u8 old_bRegUseLed; - } rereg_nd_name_priv; - - int bup; - struct net_device_stats stats; - struct iw_statistics iwstats; - - int net_closed; - u8 bFWReady; - u8 bReadPortCancel; - u8 bWritePortCancel; - u8 bRxRSSIDisplay; - /* The driver will show up the desired channel number - * when this flag is 1. */ - u8 bNotifyChannelChange; - /* The driver will show the current P2P status when the - * upper application reads it. */ - u8 bShowGetP2PState; - struct adapter *pbuddy_adapter; - - struct mutex *hw_init_mutex; - - spinlock_t br_ext_lock; - struct nat25_network_db_entry *nethash[NAT25_HASH_SIZE]; - int pppoe_connection_in_progress; - unsigned char pppoe_addr[ETH_ALEN]; - unsigned char scdb_mac[ETH_ALEN]; - unsigned char scdb_ip[4]; - struct nat25_network_db_entry *scdb_entry; - unsigned char br_mac[ETH_ALEN]; - unsigned char br_ip[4]; - struct br_ext_info ethBrExtInfo; -}; - -#define adapter_to_dvobj(adapter) (adapter->dvobj) - -void rtw_handle_dualmac(struct adapter *adapter, bool init); - -static inline u8 *myid(struct eeprom_priv *peepriv) -{ - return peepriv->mac_addr; -} - -#endif /* __DRV_TYPES_H__ */ diff --git a/drivers/staging/r8188eu/include/hal_com.h b/drivers/staging/r8188eu/include/hal_com.h deleted file mode 100644 index cd3f845e146a..000000000000 --- a/drivers/staging/r8188eu/include/hal_com.h +++ /dev/null @@ -1,146 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#ifndef __HAL_COMMON_H__ -#define __HAL_COMMON_H__ - -/* */ -/* Rate Definition */ -/* */ -/* CCK */ -#define RATR_1M 0x00000001 -#define RATR_2M 0x00000002 -#define RATR_55M 0x00000004 -#define RATR_11M 0x00000008 -/* OFDM */ -#define RATR_6M 0x00000010 -#define RATR_9M 0x00000020 -#define RATR_12M 0x00000040 -#define RATR_18M 0x00000080 -#define RATR_24M 0x00000100 -#define RATR_36M 0x00000200 -#define RATR_48M 0x00000400 -#define RATR_54M 0x00000800 -/* MCS 1 Spatial Stream */ -#define RATR_MCS0 0x00001000 -#define RATR_MCS1 0x00002000 -#define RATR_MCS2 0x00004000 -#define RATR_MCS3 0x00008000 -#define RATR_MCS4 0x00010000 -#define RATR_MCS5 0x00020000 -#define RATR_MCS6 0x00040000 -#define RATR_MCS7 0x00080000 -/* MCS 2 Spatial Stream */ -#define RATR_MCS8 0x00100000 -#define RATR_MCS9 0x00200000 -#define RATR_MCS10 0x00400000 -#define RATR_MCS11 0x00800000 -#define RATR_MCS12 0x01000000 -#define RATR_MCS13 0x02000000 -#define RATR_MCS14 0x04000000 -#define RATR_MCS15 0x08000000 - -/* CCK */ -#define RATE_1M BIT(0) -#define RATE_2M BIT(1) -#define RATE_5_5M BIT(2) -#define RATE_11M BIT(3) -/* OFDM */ -#define RATE_6M BIT(4) -#define RATE_9M BIT(5) -#define RATE_12M BIT(6) -#define RATE_18M BIT(7) -#define RATE_24M BIT(8) -#define RATE_36M BIT(9) -#define RATE_48M BIT(10) -#define RATE_54M BIT(11) -/* MCS 1 Spatial Stream */ -#define RATE_MCS0 BIT(12) -#define RATE_MCS1 BIT(13) -#define RATE_MCS2 BIT(14) -#define RATE_MCS3 BIT(15) -#define RATE_MCS4 BIT(16) -#define RATE_MCS5 BIT(17) -#define RATE_MCS6 BIT(18) -#define RATE_MCS7 BIT(19) -/* MCS 2 Spatial Stream */ -#define RATE_MCS8 BIT(20) -#define RATE_MCS9 BIT(21) -#define RATE_MCS10 BIT(22) -#define RATE_MCS11 BIT(23) -#define RATE_MCS12 BIT(24) -#define RATE_MCS13 BIT(25) -#define RATE_MCS14 BIT(26) -#define RATE_MCS15 BIT(27) - -/* ALL CCK Rate */ -#define RATE_ALL_CCK (RATR_1M | RATR_2M | RATR_55M | RATR_11M) -#define RATE_ALL_OFDM_AG (RATR_6M | RATR_9M | RATR_12M | RATR_18M | \ - RATR_24M | RATR_36M | RATR_48M | RATR_54M) -#define RATE_ALL_OFDM_1SS (RATR_MCS0 | RATR_MCS1 | RATR_MCS2 | \ - RATR_MCS3 | RATR_MCS4 | RATR_MCS5|RATR_MCS6 | \ - RATR_MCS7) -#define RATE_ALL_OFDM_2SS (RATR_MCS8 | RATR_MCS9 | RATR_MCS10 | \ - RATR_MCS11 | RATR_MCS12 | RATR_MCS13 | \ - RATR_MCS14 | RATR_MCS15) - -/*------------------------------ Tx Desc definition Macro --------------------*/ -/* pragma mark -- Tx Desc related definition. -- */ -/* Rate */ -/* CCK Rates, TxHT = 0 */ -#define DESC_RATE1M 0x00 -#define DESC_RATE2M 0x01 -#define DESC_RATE5_5M 0x02 -#define DESC_RATE11M 0x03 - -/* OFDM Rates, TxHT = 0 */ -#define DESC_RATE6M 0x04 -#define DESC_RATE9M 0x05 -#define DESC_RATE12M 0x06 -#define DESC_RATE18M 0x07 -#define DESC_RATE24M 0x08 -#define DESC_RATE36M 0x09 -#define DESC_RATE48M 0x0a -#define DESC_RATE54M 0x0b - -/* MCS Rates, TxHT = 1 */ -#define DESC_RATEMCS0 0x0c -#define DESC_RATEMCS1 0x0d -#define DESC_RATEMCS2 0x0e -#define DESC_RATEMCS3 0x0f -#define DESC_RATEMCS4 0x10 -#define DESC_RATEMCS5 0x11 -#define DESC_RATEMCS6 0x12 -#define DESC_RATEMCS7 0x13 -#define DESC_RATEMCS8 0x14 -#define DESC_RATEMCS9 0x15 -#define DESC_RATEMCS10 0x16 -#define DESC_RATEMCS11 0x17 -#define DESC_RATEMCS12 0x18 -#define DESC_RATEMCS13 0x19 -#define DESC_RATEMCS14 0x1a -#define DESC_RATEMCS15 0x1b -#define DESC_RATEMCS15_SG 0x1c -#define DESC_RATEMCS32 0x20 - -/* 1 Byte long (in unit of TU) */ -#define REG_P2P_CTWIN 0x0572 -#define REG_NOA_DESC_SEL 0x05CF -#define REG_NOA_DESC_DURATION 0x05E0 -#define REG_NOA_DESC_INTERVAL 0x05E4 -#define REG_NOA_DESC_START 0x05E8 -#define REG_NOA_DESC_COUNT 0x05EC - -/* return the final channel plan decision */ -u8 hal_com_get_channel_plan(struct adapter *padapter, - u8 hw_channel_plan, - u8 sw_channel_plan, - u8 def_channel_plan, - bool AutoLoadFail -); - -u8 MRateToHwRate(u8 rate); - -void HalSetBrateCfg(struct adapter *Adapter, u8 *mBratesOS, u16 *pBrateCfg); - -#endif /* __HAL_COMMON_H__ */ diff --git a/drivers/staging/r8188eu/include/hal_intf.h b/drivers/staging/r8188eu/include/hal_intf.h deleted file mode 100644 index 296aa5b8268d..000000000000 --- a/drivers/staging/r8188eu/include/hal_intf.h +++ /dev/null @@ -1,44 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2007 - 2012 Realtek Corporation. */ - -#ifndef __HAL_INTF_H__ -#define __HAL_INTF_H__ - -#include "osdep_service.h" -#include "drv_types.h" -#include "Hal8188EPhyCfg.h" - -typedef s32 (*c2h_id_filter)(u8 id); - -int rtl8188eu_interface_configure(struct adapter *adapt); -int ReadAdapterInfo8188EU(struct adapter *Adapter); -void rtl8188eu_init_default_value(struct adapter *adapt); -void rtl8188e_SetHalODMVar(struct adapter *Adapter, void *pValue1, bool bSet); -u32 rtl8188eu_InitPowerOn(struct adapter *adapt); -void rtl8188e_EfusePowerSwitch(struct adapter *pAdapter, u8 PwrState); -void rtl8188e_ReadEFuse(struct adapter *Adapter, u16 _size_byte, u8 *pbuf); - -void hal_notch_filter_8188e(struct adapter *adapter, bool enable); - -void SetBeaconRelatedRegisters8188EUsb(struct adapter *adapt); -void UpdateHalRAMask8188EUsb(struct adapter *adapt, u32 mac_id, u8 rssi_level); - -int rtl8188e_IOL_exec_cmds_sync(struct adapter *adapter, - struct xmit_frame *xmit_frame, u32 max_wating_ms, u32 bndy_cnt); - -int rtl8188eu_inirp_init(struct adapter *Adapter); - -uint rtw_hal_init(struct adapter *padapter); -uint rtw_hal_deinit(struct adapter *padapter); -void rtw_hal_stop(struct adapter *padapter); - -u32 rtl8188eu_hal_init(struct adapter *Adapter); -u32 rtl8188eu_hal_deinit(struct adapter *Adapter); - -void rtw_hal_update_ra_mask(struct adapter *padapter, u32 mac_id, u8 level); -void rtw_hal_clone_data(struct adapter *dst_adapt, - struct adapter *src_adapt); - -u8 rtw_do_join(struct adapter *padapter); - -#endif /* __HAL_INTF_H__ */ diff --git a/drivers/staging/r8188eu/include/ieee80211.h b/drivers/staging/r8188eu/include/ieee80211.h deleted file mode 100644 index e7a4f8af497a..000000000000 --- a/drivers/staging/r8188eu/include/ieee80211.h +++ /dev/null @@ -1,817 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#ifndef __IEEE80211_H -#define __IEEE80211_H - -#include "osdep_service.h" -#include "drv_types.h" -#include "wifi.h" -#include - -#define MGMT_QUEUE_NUM 5 - -#define ETH_TYPE_LEN 2 -#define PAYLOAD_TYPE_LEN 1 - -#define RTL_IOCTL_HOSTAPD (SIOCIWFIRSTPRIV + 28) - -/* STA flags */ -#define WLAN_STA_AUTH BIT(0) -#define WLAN_STA_ASSOC BIT(1) -#define WLAN_STA_PS BIT(2) -#define WLAN_STA_TIM BIT(3) -#define WLAN_STA_PERM BIT(4) -#define WLAN_STA_AUTHORIZED BIT(5) -#define WLAN_STA_PENDING_POLL BIT(6) /* pending activity poll not ACKed */ -#define WLAN_STA_SHORT_PREAMBLE BIT(7) -#define WLAN_STA_PREAUTH BIT(8) -#define WLAN_STA_WME BIT(9) -#define WLAN_STA_MFP BIT(10) -#define WLAN_STA_HT BIT(11) -#define WLAN_STA_WPS BIT(12) -#define WLAN_STA_MAYBE_WPS BIT(13) -#define WLAN_STA_NONERP BIT(31) - -#define IEEE_CMD_SET_WPA_PARAM 1 -#define IEEE_CMD_SET_WPA_IE 2 -#define IEEE_CMD_SET_ENCRYPTION 3 -#define IEEE_CMD_MLME 4 - -#define IEEE_PARAM_WPA_ENABLED 1 -#define IEEE_PARAM_TKIP_COUNTERMEASURES 2 -#define IEEE_PARAM_DROP_UNENCRYPTED 3 -#define IEEE_PARAM_PRIVACY_INVOKED 4 -#define IEEE_PARAM_AUTH_ALGS 5 -#define IEEE_PARAM_IEEE_802_1X 6 -#define IEEE_PARAM_WPAX_SELECT 7 - -#define AUTH_ALG_OPEN_SYSTEM 0x1 -#define AUTH_ALG_SHARED_KEY 0x2 -#define AUTH_ALG_LEAP 0x00000004 - -#define IEEE_MLME_STA_DEAUTH 1 -#define IEEE_MLME_STA_DISASSOC 2 - -#define IEEE_CRYPT_ERR_UNKNOWN_ALG 2 -#define IEEE_CRYPT_ERR_UNKNOWN_ADDR 3 -#define IEEE_CRYPT_ERR_CRYPT_INIT_FAILED 4 -#define IEEE_CRYPT_ERR_KEY_SET_FAILED 5 -#define IEEE_CRYPT_ERR_TX_KEY_SET_FAILED 6 -#define IEEE_CRYPT_ERR_CARD_CONF_FAILED 7 - -#define IEEE_CRYPT_ALG_NAME_LEN 16 - -#define WPA_CIPHER_NONE BIT(0) -#define WPA_CIPHER_WEP40 BIT(1) -#define WPA_CIPHER_WEP104 BIT(2) -#define WPA_CIPHER_TKIP BIT(3) -#define WPA_CIPHER_CCMP BIT(4) - - -#define WPA_SELECTOR_LEN 4 -extern u8 RTW_WPA_OUI_TYPE[]; -extern u16 RTW_WPA_VERSION; -extern u8 WPA_AUTH_KEY_MGMT_NONE[]; -extern u8 WPA_AUTH_KEY_MGMT_UNSPEC_802_1X[]; -extern u8 WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X[]; -extern u8 WPA_CIPHER_SUITE_NONE[]; -extern u8 WPA_CIPHER_SUITE_WEP40[]; -extern u8 WPA_CIPHER_SUITE_TKIP[]; -extern u8 WPA_CIPHER_SUITE_WRAP[]; -extern u8 WPA_CIPHER_SUITE_CCMP[]; -extern u8 WPA_CIPHER_SUITE_WEP104[]; - -#define RSN_HEADER_LEN 4 -#define RSN_SELECTOR_LEN 4 - -extern u16 RSN_VERSION_BSD; -extern u8 RSN_AUTH_KEY_MGMT_UNSPEC_802_1X[]; -extern u8 RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X[]; -extern u8 RSN_CIPHER_SUITE_NONE[]; -extern u8 RSN_CIPHER_SUITE_WEP40[]; -extern u8 RSN_CIPHER_SUITE_TKIP[]; -extern u8 RSN_CIPHER_SUITE_WRAP[]; -extern u8 RSN_CIPHER_SUITE_CCMP[]; -extern u8 RSN_CIPHER_SUITE_WEP104[]; - -enum ratr_table_mode { - RATR_INX_WIRELESS_NGB = 0, /* BGN 40 Mhz 2SS 1SS */ - RATR_INX_WIRELESS_NG = 1, /* GN or N */ - RATR_INX_WIRELESS_NB = 2, /* BGN 20 Mhz 2SS 1SS or BN */ - RATR_INX_WIRELESS_N = 3, - RATR_INX_WIRELESS_GB = 4, - RATR_INX_WIRELESS_G = 5, - RATR_INX_WIRELESS_B = 6, - RATR_INX_WIRELESS_MC = 7, - RATR_INX_WIRELESS_AC_N = 8, -}; - -enum NETWORK_TYPE { - WIRELESS_INVALID = 0, - /* Sub-Element */ - WIRELESS_11B = BIT(0), /* tx:cck only, rx:cck only, hw: cck */ - WIRELESS_11G = BIT(1), /* tx:ofdm only, rx:ofdm & cck, hw:cck & ofdm*/ - WIRELESS_11_24N = BIT(3), /* tx:MCS only, rx:MCS & cck, hw:MCS & cck */ - - /* Combination */ - /* tx: cck & ofdm, rx: cck & ofdm & MCS, hw: cck & ofdm */ - WIRELESS_11BG = (WIRELESS_11B | WIRELESS_11G), - /* tx: ofdm & MCS, rx: ofdm & cck & MCS, hw: cck & ofdm */ - WIRELESS_11G_24N = (WIRELESS_11G | WIRELESS_11_24N), - /* tx: ofdm & cck & MCS, rx: ofdm & cck & MCS, hw: ofdm & cck */ - WIRELESS_11BG_24N = (WIRELESS_11B | WIRELESS_11G | WIRELESS_11_24N), -}; - -struct ieee_param { - u32 cmd; - u8 sta_addr[ETH_ALEN]; - union { - struct { - u8 name; - u32 value; - } wpa_param; - struct { - u32 len; - u8 reserved[32]; - u8 data[]; - } wpa_ie; - struct { - int command; - int reason_code; - } mlme; - struct { - u8 alg[IEEE_CRYPT_ALG_NAME_LEN]; - u8 set_tx; - u32 err; - u8 idx; - u8 seq[8]; /* sequence counter (set: RX, get: TX) */ - u16 key_len; - u8 key[]; - } crypt; - struct { - u16 aid; - u16 capability; - int flags; - u8 tx_supp_rates[16]; - struct ieee80211_ht_cap ht_cap; - } add_sta; - struct { - u8 reserved[2];/* for set max_num_sta */ - u8 buf[]; - } bcn_ie; - } u; -}; - -#define IEEE80211_DATA_LEN 2304 -/* Maximum size for the MA-UNITDATA primitive, 802.11 standard section - 6.2.1.1.2. - - The figure in section 7.1.2 suggests a body size of up to 2312 - bytes is allowed, which is a bit confusing, I suspect this - represents the 2304 bytes of real data, plus a possible 8 bytes of - WEP IV and ICV. (this interpretation suggested by Ramiro Barreiro) */ - -#define IEEE80211_HLEN 30 -#define IEEE80211_FRAME_LEN (IEEE80211_DATA_LEN + IEEE80211_HLEN) - -/* this is stolen from ipw2200 driver */ -#define IEEE_IBSS_MAC_HASH_SIZE 31 - -#define IEEE80211_3ADDR_LEN 24 -#define IEEE80211_4ADDR_LEN 30 -#define IEEE80211_FCS_LEN 4 - -#define MIN_FRAG_THRESHOLD 256U -#define MAX_FRAG_THRESHOLD 2346U - -/* Frame control field constants */ -#define RTW_IEEE80211_FCTL_VERS 0x0003 -#define RTW_IEEE80211_FCTL_FTYPE 0x000c -#define RTW_IEEE80211_FCTL_STYPE 0x00f0 -#define RTW_IEEE80211_FCTL_TODS 0x0100 -#define RTW_IEEE80211_FCTL_FROMDS 0x0200 -#define RTW_IEEE80211_FCTL_MOREFRAGS 0x0400 -#define RTW_IEEE80211_FCTL_RETRY 0x0800 -#define RTW_IEEE80211_FCTL_PM 0x1000 -#define RTW_IEEE80211_FCTL_MOREDATA 0x2000 -#define RTW_IEEE80211_FCTL_PROTECTED 0x4000 -#define RTW_IEEE80211_FCTL_ORDER 0x8000 -#define RTW_IEEE80211_FCTL_CTL_EXT 0x0f00 - -#define RTW_IEEE80211_FTYPE_MGMT 0x0000 -#define RTW_IEEE80211_FTYPE_CTL 0x0004 -#define RTW_IEEE80211_FTYPE_DATA 0x0008 -#define RTW_IEEE80211_FTYPE_EXT 0x000c - -/* management */ -#define RTW_IEEE80211_STYPE_ASSOC_REQ 0x0000 -#define RTW_IEEE80211_STYPE_ASSOC_RESP 0x0010 -#define RTW_IEEE80211_STYPE_REASSOC_REQ 0x0020 -#define RTW_IEEE80211_STYPE_REASSOC_RESP 0x0030 -#define RTW_IEEE80211_STYPE_PROBE_REQ 0x0040 -#define RTW_IEEE80211_STYPE_PROBE_RESP 0x0050 -#define RTW_IEEE80211_STYPE_BEACON 0x0080 -#define RTW_IEEE80211_STYPE_ATIM 0x0090 -#define RTW_IEEE80211_STYPE_DISASSOC 0x00A0 -#define RTW_IEEE80211_STYPE_AUTH 0x00B0 -#define RTW_IEEE80211_STYPE_DEAUTH 0x00C0 -#define RTW_IEEE80211_STYPE_ACTION 0x00D0 - -/* control */ -#define RTW_IEEE80211_STYPE_CTL_EXT 0x0060 -#define RTW_IEEE80211_STYPE_BACK_REQ 0x0080 -#define RTW_IEEE80211_STYPE_BACK 0x0090 -#define RTW_IEEE80211_STYPE_PSPOLL 0x00A0 -#define RTW_IEEE80211_STYPE_RTS 0x00B0 -#define RTW_IEEE80211_STYPE_CTS 0x00C0 -#define RTW_IEEE80211_STYPE_ACK 0x00D0 -#define RTW_IEEE80211_STYPE_CFEND 0x00E0 -#define RTW_IEEE80211_STYPE_CFENDACK 0x00F0 - -/* data */ -#define RTW_IEEE80211_STYPE_DATA 0x0000 -#define RTW_IEEE80211_STYPE_DATA_CFACK 0x0010 -#define RTW_IEEE80211_STYPE_DATA_CFPOLL 0x0020 -#define RTW_IEEE80211_STYPE_DATA_CFACKPOLL 0x0030 -#define RTW_IEEE80211_STYPE_NULLFUNC 0x0040 -#define RTW_IEEE80211_STYPE_CFACK 0x0050 -#define RTW_IEEE80211_STYPE_CFPOLL 0x0060 -#define RTW_IEEE80211_STYPE_CFACKPOLL 0x0070 -#define RTW_IEEE80211_STYPE_QOS_DATA 0x0080 -#define RTW_IEEE80211_STYPE_QOS_DATA_CFACK 0x0090 -#define RTW_IEEE80211_STYPE_QOS_DATA_CFPOLL 0x00A0 -#define RTW_IEEE80211_STYPE_QOS_DATA_CFACKPOLL 0x00B0 -#define RTW_IEEE80211_STYPE_QOS_NULLFUNC 0x00C0 -#define RTW_IEEE80211_STYPE_QOS_CFACK 0x00D0 -#define RTW_IEEE80211_STYPE_QOS_CFPOLL 0x00E0 -#define RTW_IEEE80211_STYPE_QOS_CFACKPOLL 0x00F0 - -/* sequence control field */ -#define RTW_IEEE80211_SCTL_FRAG 0x000F -#define RTW_IEEE80211_SCTL_SEQ 0xFFF0 - -#define RTW_ERP_INFO_NON_ERP_PRESENT BIT(0) -#define RTW_ERP_INFO_USE_PROTECTION BIT(1) -#define RTW_ERP_INFO_BARKER_PREAMBLE_MODE BIT(2) - -/* QoS, QOS */ -#define NORMAL_ACK 0 -#define NO_ACK 1 -#define NON_EXPLICIT_ACK 2 -#define BLOCK_ACK 3 - -#ifndef ETH_P_PAE -#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ -#endif /* ETH_P_PAE */ - -#define ETH_P_PREAUTH 0x88C7 /* IEEE 802.11i pre-authentication */ - -#define ETH_P_ECONET 0x0018 - -#ifndef ETH_P_80211_RAW -#define ETH_P_80211_RAW (ETH_P_ECONET + 1) -#endif - -/* IEEE 802.11 defines */ - -#define P80211_OUI_LEN 3 - -struct ieee80211_snap_hdr { - u8 dsap; /* always 0xAA */ - u8 ssap; /* always 0xAA */ - u8 ctrl; /* always 0x03 */ - u8 oui[P80211_OUI_LEN]; /* organizational universal id */ -} __packed; - -#define SNAP_SIZE sizeof(struct ieee80211_snap_hdr) - -#define WLAN_FC_GET_TYPE(fc) ((fc) & RTW_IEEE80211_FCTL_FTYPE) -#define WLAN_FC_GET_STYPE(fc) ((fc) & RTW_IEEE80211_FCTL_STYPE) - -#define WLAN_QC_GET_TID(qc) ((qc) & 0x0f) - -#define WLAN_GET_SEQ_FRAG(seq) ((seq) & RTW_IEEE80211_SCTL_FRAG) -#define WLAN_GET_SEQ_SEQ(seq) ((seq) & RTW_IEEE80211_SCTL_SEQ) - -/* Authentication algorithms */ -#define WLAN_AUTH_OPEN 0 -#define WLAN_AUTH_SHARED_KEY 1 - -#define WLAN_AUTH_CHALLENGE_LEN 128 - -#define WLAN_CAPABILITY_BSS (1<<0) -#define WLAN_CAPABILITY_IBSS (1<<1) -#define WLAN_CAPABILITY_CF_POLLABLE (1<<2) -#define WLAN_CAPABILITY_CF_POLL_REQUEST (1<<3) -#define WLAN_CAPABILITY_PRIVACY (1<<4) -#define WLAN_CAPABILITY_SHORT_PREAMBLE (1<<5) -#define WLAN_CAPABILITY_PBCC (1<<6) -#define WLAN_CAPABILITY_CHANNEL_AGILITY (1<<7) -#define WLAN_CAPABILITY_SHORT_SLOT (1<<10) - -/* Status codes */ -#define WLAN_STATUS_SUCCESS 0 -#define WLAN_STATUS_UNSPECIFIED_FAILURE 1 -#define WLAN_STATUS_CAPS_UNSUPPORTED 10 -#define WLAN_STATUS_REASSOC_NO_ASSOC 11 -#define WLAN_STATUS_ASSOC_DENIED_UNSPEC 12 -#define WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG 13 -#define WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION 14 -#define WLAN_STATUS_CHALLENGE_FAIL 15 -#define WLAN_STATUS_AUTH_TIMEOUT 16 -#define WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA 17 -#define WLAN_STATUS_ASSOC_DENIED_RATES 18 -/* 802.11b */ -#define WLAN_STATUS_ASSOC_DENIED_NOSHORT 19 -#define WLAN_STATUS_ASSOC_DENIED_NOPBCC 20 -#define WLAN_STATUS_ASSOC_DENIED_NOAGILITY 21 - -/* Reason codes */ -#define WLAN_REASON_UNSPECIFIED 1 -#define WLAN_REASON_PREV_AUTH_NOT_VALID 2 -#define WLAN_REASON_DEAUTH_LEAVING 3 -#define WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY 4 -#define WLAN_REASON_DISASSOC_AP_BUSY 5 -#define WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA 6 -#define WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA 7 -#define WLAN_REASON_DISASSOC_STA_HAS_LEFT 8 -#define WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH 9 -#define WLAN_REASON_JOIN_WRONG_CHANNEL 65534 -#define WLAN_REASON_EXPIRATION_CHK 65535 - -/* Information Element IDs */ -#define WLAN_EID_SSID 0 -#define WLAN_EID_SUPP_RATES 1 -#define WLAN_EID_FH_PARAMS 2 -#define WLAN_EID_DS_PARAMS 3 -#define WLAN_EID_CF_PARAMS 4 -#define WLAN_EID_TIM 5 -#define WLAN_EID_IBSS_PARAMS 6 -#define WLAN_EID_CHALLENGE 16 -/* EIDs defined by IEEE 802.11h - START */ -#define WLAN_EID_PWR_CONSTRAINT 32 -#define WLAN_EID_PWR_CAPABILITY 33 -#define WLAN_EID_TPC_REQUEST 34 -#define WLAN_EID_TPC_REPORT 35 -#define WLAN_EID_SUPPORTED_CHANNELS 36 -#define WLAN_EID_CHANNEL_SWITCH 37 -#define WLAN_EID_MEASURE_REQUEST 38 -#define WLAN_EID_MEASURE_REPORT 39 -#define WLAN_EID_QUITE 40 -#define WLAN_EID_IBSS_DFS 41 -/* EIDs defined by IEEE 802.11h - END */ -#define WLAN_EID_ERP_INFO 42 -#define WLAN_EID_HT_CAP 45 -#define WLAN_EID_RSN 48 -#define WLAN_EID_EXT_SUPP_RATES 50 -#define WLAN_EID_MOBILITY_DOMAIN 54 -#define WLAN_EID_FAST_BSS_TRANSITION 55 -#define WLAN_EID_TIMEOUT_INTERVAL 56 -#define WLAN_EID_RIC_DATA 57 -#define WLAN_EID_HT_OPERATION 61 -#define WLAN_EID_SECONDARY_CHANNEL_OFFSET 62 -#define WLAN_EID_20_40_BSS_COEXISTENCE 72 -#define WLAN_EID_20_40_BSS_INTOLERANT 73 -#define WLAN_EID_OVERLAPPING_BSS_SCAN_PARAMS 74 -#define WLAN_EID_MMIE 76 -#define WLAN_EID_VENDOR_SPECIFIC 221 -#define WLAN_EID_GENERIC (WLAN_EID_VENDOR_SPECIFIC) - -#define IEEE80211_MGMT_HDR_LEN 24 -#define IEEE80211_DATA_HDR3_LEN 24 -#define IEEE80211_DATA_HDR4_LEN 30 - -#define IEEE80211_STATMASK_SIGNAL (1<<0) -#define IEEE80211_STATMASK_RSSI (1<<1) -#define IEEE80211_STATMASK_NOISE (1<<2) -#define IEEE80211_STATMASK_RATE (1<<3) -#define IEEE80211_STATMASK_WEMASK 0x7 - -#define IEEE80211_CCK_MODULATION (1<<0) -#define IEEE80211_OFDM_MODULATION (1<<1) - -#define IEEE80211_24GHZ_BAND (1<<0) -#define IEEE80211_52GHZ_BAND (1<<1) - -#define IEEE80211_CCK_RATE_LEN 4 -#define IEEE80211_NUM_OFDM_RATESLEN 8 - -#define IEEE80211_CCK_RATE_1MB 0x02 -#define IEEE80211_CCK_RATE_2MB 0x04 -#define IEEE80211_CCK_RATE_5MB 0x0B -#define IEEE80211_CCK_RATE_11MB 0x16 -#define IEEE80211_OFDM_RATE_LEN 8 -#define IEEE80211_OFDM_RATE_6MB 0x0C -#define IEEE80211_OFDM_RATE_9MB 0x12 -#define IEEE80211_OFDM_RATE_12MB 0x18 -#define IEEE80211_OFDM_RATE_18MB 0x24 -#define IEEE80211_OFDM_RATE_24MB 0x30 -#define IEEE80211_OFDM_RATE_36MB 0x48 -#define IEEE80211_OFDM_RATE_48MB 0x60 -#define IEEE80211_OFDM_RATE_54MB 0x6C -#define IEEE80211_BASIC_RATE_MASK 0x80 - -#define IEEE80211_CCK_RATE_1MB_MASK (1<<0) -#define IEEE80211_CCK_RATE_2MB_MASK (1<<1) -#define IEEE80211_CCK_RATE_5MB_MASK (1<<2) -#define IEEE80211_CCK_RATE_11MB_MASK (1<<3) -#define IEEE80211_OFDM_RATE_6MB_MASK (1<<4) -#define IEEE80211_OFDM_RATE_9MB_MASK (1<<5) -#define IEEE80211_OFDM_RATE_12MB_MASK (1<<6) -#define IEEE80211_OFDM_RATE_18MB_MASK (1<<7) -#define IEEE80211_OFDM_RATE_24MB_MASK (1<<8) -#define IEEE80211_OFDM_RATE_36MB_MASK (1<<9) -#define IEEE80211_OFDM_RATE_48MB_MASK (1<<10) -#define IEEE80211_OFDM_RATE_54MB_MASK (1<<11) - -#define IEEE80211_CCK_RATES_MASK 0x0000000F -#define IEEE80211_CCK_BASIC_RATES_MASK (IEEE80211_CCK_RATE_1MB_MASK | \ - IEEE80211_CCK_RATE_2MB_MASK) -#define IEEE80211_CCK_DEFAULT_RATES_MASK \ - (IEEE80211_CCK_BASIC_RATES_MASK | \ - IEEE80211_CCK_RATE_5MB_MASK | \ - IEEE80211_CCK_RATE_11MB_MASK) - -#define IEEE80211_OFDM_RATES_MASK 0x00000FF0 -#define IEEE80211_OFDM_BASIC_RATES_MASK (IEEE80211_OFDM_RATE_6MB_MASK | \ - IEEE80211_OFDM_RATE_12MB_MASK | \ - IEEE80211_OFDM_RATE_24MB_MASK) -#define IEEE80211_OFDM_DEFAULT_RATES_MASK \ - (IEEE80211_OFDM_BASIC_RATES_MASK | \ - IEEE80211_OFDM_RATE_9MB_MASK | \ - IEEE80211_OFDM_RATE_18MB_MASK | \ - IEEE80211_OFDM_RATE_36MB_MASK | \ - IEEE80211_OFDM_RATE_48MB_MASK | \ - IEEE80211_OFDM_RATE_54MB_MASK) -#define IEEE80211_DEFAULT_RATES_MASK \ - (IEEE80211_OFDM_DEFAULT_RATES_MASK | \ - IEEE80211_CCK_DEFAULT_RATES_MASK) - -#define IEEE80211_NUM_OFDM_RATES 8 -#define IEEE80211_NUM_CCK_RATES 4 -#define IEEE80211_OFDM_SHIFT_MASK_A 4 - -/* IEEE 802.11 requires that STA supports concurrent reception of at least - * three fragmented frames. This define can be increased to support more - * concurrent frames, but it should be noted that each entry can consume about - * 2 kB of RAM and increasing cache size will slow down frame reassembly. */ -#define IEEE80211_FRAG_CACHE_LEN 4 - -#define SEC_KEY_1 (1<<0) -#define SEC_KEY_2 (1<<1) -#define SEC_KEY_3 (1<<2) -#define SEC_KEY_4 (1<<3) -#define SEC_ACTIVE_KEY (1<<4) -#define SEC_AUTH_MODE (1<<5) -#define SEC_UNICAST_GROUP (1<<6) -#define SEC_LEVEL (1<<7) -#define SEC_ENABLED (1<<8) - -#define SEC_LEVEL_0 0 /* None */ -#define SEC_LEVEL_1 1 /* WEP 40 and 104 bit */ -#define SEC_LEVEL_2 2 /* Level 1 + TKIP */ -#define SEC_LEVEL_2_CKIP 3 /* Level 1 + CKIP */ -#define SEC_LEVEL_3 4 /* Level 2 + CCMP */ - -#define WEP_KEYS 4 -#define WEP_KEY_LEN 13 - -/* - - 802.11 data frame from AP - - ,-------------------------------------------------------------------. -Bytes | 2 | 2 | 6 | 6 | 6 | 2 | 0..2312 | 4 | - |------|------|---------|---------|---------|------|---------|------| -Desc. | ctrl | dura | DA/RA | TA | SA | Sequ | frame | fcs | - | | tion | (BSSID) | | | ence | data | | - `-------------------------------------------------------------------' - -Total: 28-2340 bytes - -*/ - -#define BEACON_PROBE_SSID_ID_POSITION 12 - -/* Management Frame Information Element Types */ -#define MFIE_TYPE_SSID 0 -#define MFIE_TYPE_RATES 1 -#define MFIE_TYPE_FH_SET 2 -#define MFIE_TYPE_DS_SET 3 -#define MFIE_TYPE_CF_SET 4 -#define MFIE_TYPE_TIM 5 -#define MFIE_TYPE_IBSS_SET 6 -#define MFIE_TYPE_CHALLENGE 16 -#define MFIE_TYPE_ERP 42 -#define MFIE_TYPE_RSN 48 -#define MFIE_TYPE_RATES_EX 50 -#define MFIE_TYPE_GENERIC 221 - -/* - * These are the data types that can make up management packets - * - u16 auth_algorithm; - u16 auth_sequence; - u16 beacon_interval; - u16 capability; - u8 current_ap[ETH_ALEN]; - u16 listen_interval; - struct { - u16 association_id:14, reserved:2; - } __packed; - u32 time_stamp[2]; - u16 reason; - u16 status; -*/ - -#define IEEE80211_DEFAULT_TX_ESSID "Penguin" -#define IEEE80211_DEFAULT_BASIC_RATE 10 - -/* SWEEP TABLE ENTRIES NUMBER*/ -#define MAX_SWEEP_TAB_ENTRIES 42 -#define MAX_SWEEP_TAB_ENTRIES_PER_PACKET 7 -/* MAX_RATES_LENGTH needs to be 12. The spec says 8, and many APs - * only use 8, and then use extended rates for the remaining supported - * rates. Other APs, however, stick all of their supported rates on the - * main rates information element... */ -#define MAX_RATES_LENGTH ((u8)12) -#define MAX_RATES_EX_LENGTH ((u8)16) -#define MAX_NETWORK_COUNT 128 -#define MAX_CHANNEL_NUMBER 161 -#define IEEE80211_SOFTMAC_SCAN_TIME 400 -/* HZ / 2) */ -#define IEEE80211_SOFTMAC_ASSOC_RETRY_TIME (HZ * 2) - -#define CRC_LENGTH 4U - -#define MAX_WPA_IE_LEN (256) -#define MAX_WPS_IE_LEN (512) -#define MAX_P2P_IE_LEN (256) -#define MAX_WFD_IE_LEN (128) - -#define NETWORK_EMPTY_ESSID (1<<0) -#define NETWORK_HAS_OFDM (1<<1) -#define NETWORK_HAS_CCK (1<<2) - -#define IEEE80211_DTIM_MBCAST 4 -#define IEEE80211_DTIM_UCAST 2 -#define IEEE80211_DTIM_VALID 1 -#define IEEE80211_DTIM_INVALID 0 - -#define IEEE80211_PS_DISABLED 0 -#define IEEE80211_PS_UNICAST IEEE80211_DTIM_UCAST -#define IEEE80211_PS_MBCAST IEEE80211_DTIM_MBCAST -#define IW_ESSID_MAX_SIZE 32 -/* -join_res: --1: authentication fail --2: association fail -> 0: TID -*/ - -#define DEFAULT_MAX_SCAN_AGE (15 * HZ) -#define DEFAULT_FTS 2346 - -static inline int is_multicast_mac_addr(const u8 *addr) -{ - return ((addr[0] != 0xff) && (0x01 & addr[0])); -} - -static inline int is_broadcast_mac_addr(const u8 *addr) -{ - return (addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) && - (addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff); -} - -#define CFG_IEEE80211_RESERVE_FCS (1<<0) -#define CFG_IEEE80211_COMPUTE_FCS (1<<1) - -#define MAXTID 16 - -/* Action category code */ -enum rtw_ieee80211_category { - RTW_WLAN_CATEGORY_P2P = 0x7f,/* P2P action frames */ -}; - -/* SPECTRUM_MGMT action code */ -enum rtw_ieee80211_spectrum_mgmt_actioncode { - RTW_WLAN_ACTION_SPCT_MSR_REQ = 0, - RTW_WLAN_ACTION_SPCT_MSR_RPRT = 1, - RTW_WLAN_ACTION_SPCT_TPC_REQ = 2, - RTW_WLAN_ACTION_SPCT_TPC_RPRT = 3, - RTW_WLAN_ACTION_SPCT_CHL_SWITCH = 4, - RTW_WLAN_ACTION_SPCT_EXT_CHL_SWITCH = 5, -}; - -enum _PUBLIC_ACTION { - ACT_PUBLIC_BSSCOEXIST = 0, /* 20/40 BSS Coexistence */ - ACT_PUBLIC_DSE_ENABLE = 1, - ACT_PUBLIC_DSE_DEENABLE = 2, - ACT_PUBLIC_DSE_REG_LOCATION = 3, - ACT_PUBLIC_EXT_CHL_SWITCH = 4, - ACT_PUBLIC_DSE_MSR_REQ = 5, - ACT_PUBLIC_DSE_MSR_RPRT = 6, - ACT_PUBLIC_MP = 7, /* Measurement Pilot */ - ACT_PUBLIC_DSE_PWR_CONSTRAINT = 8, - ACT_PUBLIC_VENDOR = 9, /* for WIFI_DIRECT */ - ACT_PUBLIC_GAS_INITIAL_REQ = 10, - ACT_PUBLIC_GAS_INITIAL_RSP = 11, - ACT_PUBLIC_GAS_COMEBACK_REQ = 12, - ACT_PUBLIC_GAS_COMEBACK_RSP = 13, - ACT_PUBLIC_TDLS_DISCOVERY_RSP = 14, - ACT_PUBLIC_LOCATION_TRACK = 15, - ACT_PUBLIC_MAX -}; - -#define OUI_MICROSOFT 0x0050f2 /* Microsoft (also used in Wi-Fi specs) - * 00:50:F2 */ -#define WME_OUI_TYPE 2 -#define WME_OUI_SUBTYPE_INFORMATION_ELEMENT 0 -#define WME_OUI_SUBTYPE_PARAMETER_ELEMENT 1 -#define WME_OUI_SUBTYPE_TSPEC_ELEMENT 2 -#define WME_VERSION 1 - -#define WME_ACTION_CODE_SETUP_REQUEST 0 -#define WME_ACTION_CODE_SETUP_RESPONSE 1 -#define WME_ACTION_CODE_TEARDOWN 2 - -#define WME_SETUP_RESPONSE_STATUS_ADMISSION_ACCEPTED 0 -#define WME_SETUP_RESPONSE_STATUS_INVALID_PARAMETERS 1 -#define WME_SETUP_RESPONSE_STATUS_REFUSED 3 - -#define WME_TSPEC_DIRECTION_UPLINK 0 -#define WME_TSPEC_DIRECTION_DOWNLINK 1 -#define WME_TSPEC_DIRECTION_BI_DIRECTIONAL 3 - -#define OUI_BROADCOM 0x00904c /* Broadcom (Epigram) */ - -#define VENDOR_HT_CAPAB_OUI_TYPE 0x33 /* 00-90-4c:0x33 */ - -/** - * enum rtw_ieee80211_channel_flags - channel flags - * - * Channel flags set by the regulatory control code. - * - * @RTW_IEEE80211_CHAN_DISABLED: This channel is disabled. - * @RTW_IEEE80211_CHAN_PASSIVE_SCAN: Only passive scanning is permitted - * on this channel. - * @RTW_IEEE80211_CHAN_NO_IBSS: IBSS is not allowed on this channel. - * @RTW_IEEE80211_CHAN_RADAR: Radar detection is required on this channel. - * @RTW_IEEE80211_CHAN_NO_HT40PLUS: extension channel above this channel - * is not permitted. - * @RTW_IEEE80211_CHAN_NO_HT40MINUS: extension channel below this channel - * is not permitted. - */ -enum rtw_ieee80211_channel_flags { - RTW_IEEE80211_CHAN_DISABLED = 1<<0, - RTW_IEEE80211_CHAN_PASSIVE_SCAN = 1<<1, - RTW_IEEE80211_CHAN_NO_IBSS = 1<<2, - RTW_IEEE80211_CHAN_RADAR = 1<<3, - RTW_IEEE80211_CHAN_NO_HT40PLUS = 1<<4, - RTW_IEEE80211_CHAN_NO_HT40MINUS = 1<<5, -}; - -#define RTW_IEEE80211_CHAN_NO_HT40 \ - (RTW_IEEE80211_CHAN_NO_HT40PLUS | RTW_IEEE80211_CHAN_NO_HT40MINUS) - -/* Represent channel details, subset of ieee80211_channel */ -struct rtw_ieee80211_channel { - u16 hw_value; - u32 flags; -}; - -#define CHAN_FMT \ - "hw_value:%u, " \ - "flags:0x%08x" \ - -#define CHAN_ARG(channel) \ - (channel)->hw_value \ - , (channel)->flags \ - -/* Parsed Information Elements */ -struct rtw_ieee802_11_elems { - u8 *ssid; - u8 ssid_len; - u8 *supp_rates; - u8 supp_rates_len; - u8 *fh_params; - u8 fh_params_len; - u8 *ds_params; - u8 ds_params_len; - u8 *cf_params; - u8 cf_params_len; - u8 *tim; - u8 tim_len; - u8 *ibss_params; - u8 ibss_params_len; - u8 *challenge; - u8 challenge_len; - u8 *erp_info; - u8 erp_info_len; - u8 *ext_supp_rates; - u8 ext_supp_rates_len; - u8 *wpa_ie; - u8 wpa_ie_len; - u8 *rsn_ie; - u8 rsn_ie_len; - u8 *wme; - u8 wme_len; - u8 *wme_tspec; - u8 wme_tspec_len; - u8 *wps_ie; - u8 wps_ie_len; - u8 *power_cap; - u8 power_cap_len; - u8 *supp_channels; - u8 supp_channels_len; - u8 *mdie; - u8 mdie_len; - u8 *ftie; - u8 ftie_len; - u8 *timeout_int; - u8 timeout_int_len; - u8 *ht_capabilities; - u8 ht_capabilities_len; - u8 *ht_operation; - u8 ht_operation_len; - u8 *vendor_ht_cap; - u8 vendor_ht_cap_len; -}; - -enum parse_res { - ParseOK = 0, - ParseUnknown = 1, - ParseFailed = -1 -}; - -enum parse_res rtw_ieee802_11_parse_elems(u8 *start, uint len, - struct rtw_ieee802_11_elems *elems, - int show_errors); - -u8 *rtw_set_fixed_ie(unsigned char *pbuf, unsigned int len, - unsigned char *source, unsigned int *frlen); -u8 *rtw_set_ie(u8 *pbuf, int index, uint len, u8 *source, uint *frlen); -u8 *rtw_get_ie(u8 *pbuf, int index, int *len, int limit); - -void rtw_set_supported_rate(u8 *SupportedRates, uint mode); - -unsigned char *rtw_get_wpa_ie(unsigned char *pie, int *wpa_ie_len, int limit); -unsigned char *rtw_get_wpa2_ie(unsigned char *pie, int *rsn_ie_len, int limit); -int rtw_get_wpa_cipher_suite(u8 *s); -int rtw_get_wpa2_cipher_suite(u8 *s); -int rtw_get_wapi_ie(u8 *in_ie, uint in_len, u8 *wapi_ie, u16 *wapi_len); -int rtw_parse_wpa_ie(u8 *wpa_ie, int wpa_ie_len, int *group_cipher, - int *pairwise_cipher, int *is_8021x); -int rtw_parse_wpa2_ie(u8 *wpa_ie, int wpa_ie_len, int *group_cipher, - int *pairwise_cipher, int *is_8021x); - -int rtw_get_sec_ie(u8 *in_ie, uint in_len, u8 *rsn_ie, u16 *rsn_len, - u8 *wpa_ie, u16 *wpa_len); - -u8 rtw_is_wps_ie(u8 *ie_ptr, uint *wps_ielen); -u8 *rtw_get_wps_ie(u8 *in_ie, uint in_len, u8 *wps_ie, uint *wps_ielen); -u8 *rtw_get_wps_attr(u8 *wps_ie, uint wps_ielen, u16 target_attr_id, - u8 *buf_attr, u32 *len_attr); -u8 *rtw_get_wps_attr_content(u8 *wps_ie, uint wps_ielen, u16 target_attr_id, - u8 *buf_content, uint *len_content); - -/** - * for_each_ie - iterate over continuous IEs - * @ie: - * @buf: - * @buf_len: - */ -#define for_each_ie(ie, buf, buf_len) \ - for (ie = (void *)buf; (((u8 *)ie) - ((u8 *)buf) + 1) < buf_len; \ - ie = (void *)(((u8 *)ie) + *(((u8 *)ie)+1) + 2)) - -u8 *rtw_get_p2p_ie(u8 *in_ie, int in_len, u8 *p2p_ie, uint *p2p_ielen); -u8 *rtw_get_p2p_attr(u8 *p2p_ie, uint p2p_ielen, u8 target_attr_id, - u8 *buf_attr, u32 *len_attr); -u8 *rtw_get_p2p_attr_content(u8 *p2p_ie, uint p2p_ielen, u8 target_attr_id, - u8 *buf_content, uint *len_content); -u32 rtw_set_p2p_attr_content(u8 *pbuf, u8 attr_id, u16 attr_len, - u8 *pdata_attr); -void rtw_wlan_bssid_ex_remove_p2p_attr(struct wlan_bssid_ex *bss_ex, - u8 attr_id); -uint rtw_get_rateset_len(u8 *rateset); - -struct registry_priv; -int rtw_generate_ie(struct registry_priv *pregistrypriv); - -int rtw_get_bit_value_from_ieee_value(u8 val); - -bool rtw_is_cckrates_included(u8 *rate); - -bool rtw_is_cckratesonly_included(u8 *rate); - -int rtw_check_network_type(unsigned char *rate, int ratelen, int channel); - -void rtw_get_bcn_info(struct wlan_network *pnetwork); - -void rtw_macaddr_cfg(u8 *mac_addr); - -u16 rtw_mcs_rate(u8 bw_40MHz, u8 short_GI_20, u8 short_GI_40, unsigned char *MCS_rate); - -#endif /* IEEE80211_H */ diff --git a/drivers/staging/r8188eu/include/odm.h b/drivers/staging/r8188eu/include/odm.h deleted file mode 100644 index 8cea166b7b73..000000000000 --- a/drivers/staging/r8188eu/include/odm.h +++ /dev/null @@ -1,416 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#ifndef __HALDMOUTSRC_H__ -#define __HALDMOUTSRC_H__ - -struct rtw_dig { - u8 PreIGValue; - u8 CurIGValue; - u8 BackupIGValue; - - u8 rx_gain_range_max; - u8 rx_gain_range_min; - - u8 CurCCK_CCAThres; - - u8 LargeFAHit; - u8 ForbiddenIGI; - u32 Recover_cnt; - - u8 DIG_Dynamic_MIN_0; - bool bMediaConnect_0; - - u32 AntDiv_RSSI_max; - u32 RSSI_max; -}; - -struct rtl_ps { - u8 pre_rf_state; - u8 cur_rf_state; - u8 initialize; - u32 reg_874; - u32 reg_c70; - u32 reg_85c; - u32 reg_a74; - -}; - -struct false_alarm_stats { - u32 Cnt_Parity_Fail; - u32 Cnt_Rate_Illegal; - u32 Cnt_Crc8_fail; - u32 Cnt_Mcs_fail; - u32 Cnt_Ofdm_fail; - u32 Cnt_Cck_fail; - u32 Cnt_all; - u32 Cnt_Fast_Fsync; - u32 Cnt_SB_Search_fail; - u32 Cnt_OFDM_CCA; - u32 Cnt_CCK_CCA; - u32 Cnt_CCA_all; - u32 Cnt_BW_USC; /* Gary */ - u32 Cnt_BW_LSC; /* Gary */ -}; - -#define ODM_ASSOCIATE_ENTRY_NUM 32 /* Max size of AsocEntry[]. */ - -struct sw_ant_switch { - u8 CurAntenna; - u8 SWAS_NoLink_State; /* Before link Antenna Switch check */ - u8 RxIdleAnt; -}; - -struct edca_turbo { - bool bCurrentTurboEDCA; - bool bIsCurRDLState; - u32 prv_traffic_idx; /* edca turbo */ -}; - -struct odm_rate_adapt { - u8 HighRSSIThresh; /* if RSSI > HighRSSIThresh => RATRState is DM_RATR_STA_HIGH */ - u8 LowRSSIThresh; /* if RSSI <= LowRSSIThresh => RATRState is DM_RATR_STA_LOW */ - u8 RATRState; /* Current RSSI level, DM_RATR_STA_HIGH/DM_RATR_STA_MIDDLE/DM_RATR_STA_LOW */ - u32 LastRATR; /* RATR Register Content */ -}; - -#define IQK_MAC_REG_NUM 4 -#define IQK_ADDA_REG_NUM 16 -#define IQK_BB_REG_NUM 9 -#define HP_THERMAL_NUM 8 - -#define AVG_THERMAL_NUM 8 - -struct odm_phy_dbg_info { - /* ODM Write,debug info */ - s8 RxSNRdB[MAX_PATH_NUM_92CS]; - u64 NumQryPhyStatus; - /* Others */ - s32 RxEVM[MAX_PATH_NUM_92CS]; -}; - -struct odm_per_pkt_info { - s8 Rate; - u8 StationID; - bool bPacketMatchBSSID; - bool bPacketToSelf; - bool bPacketBeacon; -}; - -/* 2011/10/20 MH Define Common info enum for all team. */ - -enum odm_common_info_def { - /* Fixed value: */ - - /* HOOK BEFORE REG INIT----------- */ - ODM_CMNINFO_MP_TEST_CHIP, - /* HOOK BEFORE REG INIT----------- */ - -/* CALL BY VALUE------------- */ - ODM_CMNINFO_RF_ANTENNA_TYPE, /* u8 */ -/* CALL BY VALUE-------------*/ -}; - -enum odm_ability_def { - /* BB ODM section BIT 0-15 */ - ODM_BB_RSSI_MONITOR = BIT(4), - ODM_BB_ANT_DIV = BIT(6), - ODM_BB_PWR_TRA = BIT(8), -}; - -#define ODM_ITRF_USB 0x2 -#define ODM_CE 0x04 - -/* ODM_CMNINFO_WM_MODE */ -enum odm_wireless_mode { - ODM_WM_UNKNOW = 0x0, - ODM_WM_B = BIT(0), - ODM_WM_G = BIT(1), - ODM_WM_N24G = BIT(3), - ODM_WM_AUTO = BIT(5), -}; - -struct odm_ra_info { - u8 RateID; - u32 RateMask; - u32 RAUseRate; - u8 RateSGI; - u8 RssiStaRA; - u8 PreRssiStaRA; - u8 SGIEnable; - u8 DecisionRate; - u8 PreRate; - u8 HighestRate; - u8 LowestRate; - u32 NscUp; - u32 NscDown; - u16 RTY[5]; - u32 TOTAL; - u16 DROP; - u8 Active; - u16 RptTime; - u8 RAWaitingCounter; - u8 RAPendingCounter; - u8 PTActive; /* on or off */ - u8 PTTryState; /* 0 trying state, 1 for decision state */ - u8 PTStage; /* 0~6 */ - u8 PTStopCount; /* Stop PT counter */ - u8 PTPreRate; /* if rate change do PT */ - u8 PTPreRssi; /* if RSSI change 5% do PT */ - u8 PTModeSS; /* decide whitch rate should do PT */ - u8 RAstage; /* StageRA, decide how many times RA will be done - * between PT */ - u8 PTSmoothFactor; -}; - -struct odm_rf_cal { - /* for tx power tracking */ - u32 RegA24; /* for TempCCK */ - s32 RegE94; - s32 RegE9C; - s32 RegEB4; - s32 RegEBC; - - u8 TxPowerTrackControl; /* for mp mode, turn off txpwrtracking - * as default */ - u8 TM_Trigger; - u8 InternalPA5G[2]; /* pathA / pathB */ - - u8 ThermalMeter[2]; /* ThermalMeter, index 0 for RFIC0, - * and 1 for RFIC1 */ - u8 ThermalValue; - u8 ThermalValue_LCK; - u8 ThermalValue_IQK; - u8 ThermalValue_DPK; - u8 ThermalValue_AVG[AVG_THERMAL_NUM]; - u8 ThermalValue_AVG_index; - u8 ThermalValue_RxGain; - u8 ThermalValue_Crystal; - u8 ThermalValue_DPKstore; - u8 ThermalValue_DPKtrack; - bool TxPowerTrackingInProgress; - bool bDPKenable; - - bool bReloadtxpowerindex; - u8 bRfPiEnable; - - u8 CCK_index; - u8 OFDM_index; - bool bDoneTxpower; - - u8 ThermalValue_HP[HP_THERMAL_NUM]; - u8 ThermalValue_HP_index; - - u8 Delta_IQK; - u8 Delta_LCK; - - /* for IQK */ - u32 RegC04; - u32 Reg874; - u32 RegC08; - u32 RegB68; - u32 RegB6C; - u32 Reg870; - u32 Reg860; - u32 Reg864; - - bool bIQKInitialized; - bool bAntennaDetected; - u32 ADDA_backup[IQK_ADDA_REG_NUM]; - u32 IQK_MAC_backup[IQK_MAC_REG_NUM]; - u32 IQK_BB_backup_recover[9]; - u32 IQK_BB_backup[IQK_BB_REG_NUM]; - - /* for APK */ - u32 APKoutput[2][2]; /* path A/B; output1_1a/output1_2a */ - u8 bAPKdone; - u8 bAPKThermalMeterIgnore; - u8 bDPdone; - u8 bDPPathAOK; - u8 bDPPathBOK; -}; - -/* ODM Dynamic common info value definition */ - -struct fast_ant_train { - u8 antsel_rx_keep_0; - u8 antsel_rx_keep_1; - u8 antsel_rx_keep_2; - u8 antsel_a[ODM_ASSOCIATE_ENTRY_NUM]; - u8 antsel_b[ODM_ASSOCIATE_ENTRY_NUM]; - u8 antsel_c[ODM_ASSOCIATE_ENTRY_NUM]; - u32 MainAnt_Sum[ODM_ASSOCIATE_ENTRY_NUM]; - u32 AuxAnt_Sum[ODM_ASSOCIATE_ENTRY_NUM]; - u32 MainAnt_Cnt[ODM_ASSOCIATE_ENTRY_NUM]; - u32 AuxAnt_Cnt[ODM_ASSOCIATE_ENTRY_NUM]; - u8 RxIdleAnt; - bool bBecomeLinked; -}; - -enum ant_div_type { - NO_ANTDIV = 0xFF, - CG_TRX_HW_ANTDIV = 0x01, - CGCS_RX_HW_ANTDIV = 0x02, - FIXED_HW_ANTDIV = 0x03, - CG_TRX_SMART_ANTDIV = 0x04, -}; - -/* Copy from SD4 defined structure. We use to support PHY DM integration. */ -struct odm_dm_struct { - struct adapter *Adapter; /* For CE/NIC team */ - -/* ODM HANDLE, DRIVER NEEDS NOT TO HOOK------ */ - bool bCckHighPower; - u8 RFPathRxEnable; /* ODM_CMNINFO_RFPATH_ENABLE */ - u8 ControlChannel; -/* ODM HANDLE, DRIVER NEEDS NOT TO HOOK------ */ - -/* 1 COMMON INFORMATION */ - /* Init Value */ -/* HOOK BEFORE REG INIT----------- */ - /* ODM Support Ability DIG/RATR/TX_PWR_TRACK/ �K�K = 1/2/3/�K */ - u32 SupportAbility; - - u32 BK_SupportAbility; - u8 AntDivType; -/* HOOK BEFORE REG INIT----------- */ - - /* Dynamic Value */ -/* POINTER REFERENCE----------- */ - /* Wireless mode B/G/A/N = BIT(0)/BIT(1)/BIT(2)/BIT(3) */ - u8 *pWirelessMode; /* ODM_WIRELESS_MODE_E */ - /* Secondary channel offset don't_care/below/above = 0/1/2 */ - u8 *pSecChOffset; - /* BW info 20M/40M/80M = 0/1/2 */ - enum ht_channel_width *pBandWidth; - /* Central channel location Ch1/Ch2/.... */ - u8 *pChannel; /* central channel number */ - - /* Common info for Status */ - bool *pbScanInProcess; - bool *pbPowerSaving; -/* POINTER REFERENCE----------- */ - /* */ -/* CALL BY VALUE------------- */ - bool bLinked; - u8 RSSI_Min; - bool bIsMPChip; - bool bOneEntryOnly; -/* CALL BY VALUE------------- */ - - /* 2 Define STA info. */ - /* _ODM_STA_INFO */ - /* For MP, we need to reduce one array pointer for default port.?? */ - struct sta_info *pODM_StaInfo[ODM_ASSOCIATE_ENTRY_NUM]; - - u16 CurrminRptTime; - struct odm_ra_info RAInfo[ODM_ASSOCIATE_ENTRY_NUM]; /* Use MacID as - * array index. STA MacID=0, - * VWiFi Client MacID={1, ODM_ASSOCIATE_ENTRY_NUM-1} */ - - /* Latest packet phy info (ODM write) */ - struct odm_phy_dbg_info PhyDbgInfo; - - /* ODM Structure */ - struct fast_ant_train DM_FatTable; - struct rtw_dig DM_DigTable; - struct rtl_ps DM_PSTable; - struct false_alarm_stats FalseAlmCnt; - struct sw_ant_switch DM_SWAT_Table; - - struct edca_turbo DM_EDCA_Table; - - /* PSD */ - bool bDMInitialGainEnable; - - struct odm_rate_adapt RateAdaptive; - - struct odm_rf_cal RFCalibrateInfo; - - /* TX power tracking */ - u8 BbSwingIdxOfdm; - u8 BbSwingIdxOfdmCurrent; - u8 BbSwingIdxOfdmBase; - bool BbSwingFlagOfdm; - u8 BbSwingIdxCck; - u8 BbSwingIdxCckCurrent; - u8 BbSwingIdxCckBase; - bool BbSwingFlagCck; -}; - -enum odm_bb_config_type { - CONFIG_BB_PHY_REG, - CONFIG_BB_AGC_TAB, - CONFIG_BB_AGC_TAB_2G, - CONFIG_BB_PHY_REG_PG, -}; - -#define DM_DIG_MAX_NIC 0x4e -#define DM_DIG_MIN_NIC 0x1e /* 0x22/0x1c */ - -#define DM_DIG_MAX_AP 0x32 - -/* vivi 92c&92d has different definition, 20110504 */ -/* this is for 92c */ -#define DM_DIG_FA_TH0 0x200/* 0x20 */ -#define DM_DIG_FA_TH1 0x300/* 0x100 */ -#define DM_DIG_FA_TH2 0x400/* 0x200 */ - -/* 3=========================================================== */ -/* 3 Rate Adaptive */ -/* 3=========================================================== */ -#define DM_RATR_STA_INIT 0 -#define DM_RATR_STA_HIGH 1 -#define DM_RATR_STA_MIDDLE 2 -#define DM_RATR_STA_LOW 3 - -/* 3=========================================================== */ -/* 3 BB Power Save */ -/* 3=========================================================== */ - -enum dm_rf { - RF_Save = 0, - RF_Normal = 1, - RF_MAX = 2, -}; - -/* 3=========================================================== */ -/* 3 Antenna Diversity */ -/* 3=========================================================== */ -enum dm_swas { - Antenna_A = 1, - Antenna_B = 2, - Antenna_MAX = 3, -}; - -/* Extern Global Variables. */ -#define OFDM_TABLE_SIZE_92D 43 -#define CCK_TABLE_SIZE 33 - -extern u32 OFDMSwingTable[OFDM_TABLE_SIZE_92D]; -extern u8 cck_swing_table[CCK_TABLE_SIZE][8]; - -/* check Sta pointer valid or not */ -#define IS_STA_VALID(pSta) (pSta) - -void ODM_Write_DIG(struct odm_dm_struct *pDM_Odm, u8 CurrentIGI); -void ODM_Write_CCK_CCA_Thres(struct odm_dm_struct *pDM_Odm, u8 CurCCK_CCAThres); - -void ODM_RF_Saving(struct odm_dm_struct *pDM_Odm, u8 bForceInNormal); - -void ODM_TXPowerTrackingCheck(struct odm_dm_struct *pDM_Odm); - -bool ODM_RAStateCheck(struct odm_dm_struct *pDM_Odm, s32 RSSI, - bool bForceUpdate, u8 *pRATRState); - -u32 ODM_Get_Rate_Bitmap(struct odm_dm_struct *pDM_Odm, u32 macid, - u32 ra_mask, u8 rssi_level); - -void ODM_DMInit(struct odm_dm_struct *pDM_Odm); - -void ODM_DMWatchdog(struct odm_dm_struct *pDM_Odm); - -void ODM_CmnInfoInit(struct odm_dm_struct *pDM_Odm, - enum odm_common_info_def CmnInfo, u32 Value); - -#endif diff --git a/drivers/staging/r8188eu/include/odm_HWConfig.h b/drivers/staging/r8188eu/include/odm_HWConfig.h deleted file mode 100644 index 3f7185780e87..000000000000 --- a/drivers/staging/r8188eu/include/odm_HWConfig.h +++ /dev/null @@ -1,69 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#ifndef __HALHWOUTSRC_H__ -#define __HALHWOUTSRC_H__ - -/* CCK Rates, TxHT = 0 */ -#define DESC92C_RATE1M 0x00 -#define DESC92C_RATE11M 0x03 - -/* MCS Rates, TxHT = 1 */ -#define DESC92C_RATEMCS8 0x14 -#define DESC92C_RATEMCS15 0x1b - -/* structure and define */ - -struct phy_rx_agc_info { - #ifdef __LITTLE_ENDIAN - u8 gain:7, trsw:1; - #else - u8 trsw:1, gain:7; - #endif -}; - -struct phy_status_rpt { - struct phy_rx_agc_info path_agc[3]; - u8 ch_corr[2]; - u8 cck_sig_qual_ofdm_pwdb_all; - u8 cck_agc_rpt_ofdm_cfosho_a; - u8 cck_rpt_b_ofdm_cfosho_b; - u8 rsvd_1;/* ch_corr_msb; */ - u8 noise_power_db_msb; - u8 path_cfotail[2]; - u8 pcts_mask[2]; - s8 stream_rxevm[2]; - u8 path_rxsnr[3]; - u8 noise_power_db_lsb; - u8 rsvd_2[3]; - u8 stream_csi[2]; - u8 stream_target_csi[2]; - s8 sig_evm; - u8 rsvd_3; - -#ifdef __LITTLE_ENDIAN - u8 antsel_rx_keep_2:1; /* ex_intf_flg:1; */ - u8 sgi_en:1; - u8 rxsc:2; - u8 idle_long:1; - u8 r_ant_train_en:1; - u8 ant_sel_b:1; - u8 ant_sel:1; -#else /* _BIG_ENDIAN_ */ - u8 ant_sel:1; - u8 ant_sel_b:1; - u8 r_ant_train_en:1; - u8 idle_long:1; - u8 rxsc:2; - u8 sgi_en:1; - u8 antsel_rx_keep_2:1; /* ex_intf_flg:1; */ -#endif -}; - -void ODM_PhyStatusQuery(struct odm_dm_struct *pDM_Odm, - struct phy_info *pPhyInfo, - u8 *pPhyStatus, - struct odm_per_pkt_info *pPktinfo, - struct adapter *adapt); - -#endif diff --git a/drivers/staging/r8188eu/include/odm_RTL8188E.h b/drivers/staging/r8188eu/include/odm_RTL8188E.h deleted file mode 100644 index 4f16af248591..000000000000 --- a/drivers/staging/r8188eu/include/odm_RTL8188E.h +++ /dev/null @@ -1,35 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#ifndef __ODM_RTL8188E_H__ -#define __ODM_RTL8188E_H__ - -#define MAIN_ANT 0 -#define AUX_ANT 1 -#define MAIN_ANT_CG_TRX 1 -#define AUX_ANT_CG_TRX 0 -#define MAIN_ANT_CGCS_RX 0 -#define AUX_ANT_CGCS_RX 1 - -#define SET_TX_DESC_ANTSEL_A_88E(__ptxdesc, __value) \ - le32p_replace_bits((__le32 *)(__ptxdesc + 8), __value, BIT(24)) -#define SET_TX_DESC_ANTSEL_B_88E(__ptxdesc, __value) \ - le32p_replace_bits((__le32 *)(__ptxdesc + 8), __value, BIT(25)) -#define SET_TX_DESC_ANTSEL_C_88E(__ptxdesc, __value) \ - le32p_replace_bits((__le32 *)(__ptxdesc + 28), __value, BIT(29)) - -void ODM_AntennaDiversityInit_88E(struct odm_dm_struct *pDM_Odm); - -void ODM_AntennaDiversity_88E(struct odm_dm_struct *pDM_Odm); - -void ODM_SetTxAntByTxInfo_88E(struct odm_dm_struct *pDM_Odm, u8 *pDesc, - u8 macId); - -void ODM_UpdateRxIdleAnt_88E(struct odm_dm_struct *pDM_Odm, u8 Ant); - -void ODM_AntselStatistics_88E(struct odm_dm_struct *pDM_Odm, u8 antsel_tr_mux, - u32 MacId, u8 RxPWDBAll); - -void odm_FastAntTraining(struct odm_dm_struct *pDM_Odm); - -#endif diff --git a/drivers/staging/r8188eu/include/odm_RegDefine11N.h b/drivers/staging/r8188eu/include/odm_RegDefine11N.h deleted file mode 100644 index 82a602b39cc7..000000000000 --- a/drivers/staging/r8188eu/include/odm_RegDefine11N.h +++ /dev/null @@ -1,47 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#ifndef __ODM_REGDEFINE11N_H__ -#define __ODM_REGDEFINE11N_H__ - -/* 2 BB REG LIST */ -/* PAGE 8 */ -#define ODM_REG_TX_ANT_CTRL_11N 0x80C -#define ODM_REG_RX_DEFUALT_A_11N 0x858 -#define ODM_REG_ANTSEL_CTRL_11N 0x860 -#define ODM_REG_RX_ANT_CTRL_11N 0x864 -#define ODM_REG_PIN_CTRL_11N 0x870 -#define ODM_REG_SC_CNT_11N 0x8C4 -/* PAGE 9 */ -#define ODM_REG_ANT_MAPPING1_11N 0x914 -/* PAGE A */ -#define ODM_REG_CCK_ANTDIV_PARA1_11N 0xA00 -#define ODM_REG_CCK_CCA_11N 0xA0A -#define ODM_REG_CCK_ANTDIV_PARA2_11N 0xA0C -#define ODM_REG_CCK_FA_RST_11N 0xA2C -#define ODM_REG_CCK_FA_MSB_11N 0xA58 -#define ODM_REG_CCK_FA_LSB_11N 0xA5C -#define ODM_REG_CCK_CCA_CNT_11N 0xA60 -#define ODM_REG_BB_PWR_SAV4_11N 0xA74 -/* PAGE B */ -#define ODM_REG_LNA_SWITCH_11N 0xB2C -/* PAGE C */ -#define ODM_REG_OFDM_FA_HOLDC_11N 0xC00 -#define ODM_REG_OFDM_FA_RSTC_11N 0xC0C -#define ODM_REG_IGI_A_11N 0xC50 -#define ODM_REG_ANTDIV_PARA1_11N 0xCA4 -#define ODM_REG_OFDM_FA_TYPE1_11N 0xCF0 -/* PAGE D */ -#define ODM_REG_OFDM_FA_RSTD_11N 0xD00 -#define ODM_REG_OFDM_FA_TYPE2_11N 0xDA0 -#define ODM_REG_OFDM_FA_TYPE3_11N 0xDA4 -#define ODM_REG_OFDM_FA_TYPE4_11N 0xDA8 - -/* 2 MAC REG LIST */ -#define ODM_REG_ANTSEL_PIN_11N 0x4C -#define ODM_REG_RESP_TX_11N 0x6D8 - -/* DIG Related */ -#define ODM_BIT_IGI_11N 0x0000007F - -#endif diff --git a/drivers/staging/r8188eu/include/osdep_intf.h b/drivers/staging/r8188eu/include/osdep_intf.h deleted file mode 100644 index 457fb3852a19..000000000000 --- a/drivers/staging/r8188eu/include/osdep_intf.h +++ /dev/null @@ -1,30 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#ifndef __OSDEP_INTF_H_ -#define __OSDEP_INTF_H_ - -#include "osdep_service.h" -#include "drv_types.h" - -int netdev_open(struct net_device *pnetdev); -int netdev_close(struct net_device *pnetdev); - -u8 rtw_init_drv_sw(struct adapter *padapter); -void rtw_free_drv_sw(struct adapter *padapter); -void rtw_reset_drv_sw(struct adapter *padapter); - -int rtw_start_drv_threads(struct adapter *padapter); -void rtw_stop_drv_threads (struct adapter *padapter); -void rtw_cancel_all_timer(struct adapter *padapter); - -int rtw_init_netdev_name(struct net_device *pnetdev, const char *ifname); -struct net_device *rtw_init_netdev(struct adapter *padapter); -u16 rtw_recv_select_queue(struct sk_buff *skb); - -void rtw_ips_dev_unload(struct adapter *padapter); - -int rtw_ips_pwr_up(struct adapter *padapter); -void rtw_ips_pwr_down(struct adapter *padapter); - -#endif /* _OSDEP_INTF_H_ */ diff --git a/drivers/staging/r8188eu/include/osdep_service.h b/drivers/staging/r8188eu/include/osdep_service.h deleted file mode 100644 index f8ed04f32cae..000000000000 --- a/drivers/staging/r8188eu/include/osdep_service.h +++ /dev/null @@ -1,153 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#ifndef __OSDEP_SERVICE_H_ -#define __OSDEP_SERVICE_H_ - -#include - -#define _FAIL 0 -#define _SUCCESS 1 -#define RTW_RX_HANDLED 2 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* Necessary because we use the proc fs */ -#include /* for struct tasklet_struct */ -#include -#include -#include - -#include -#include - -struct __queue { - struct list_head queue; - spinlock_t lock; -}; - -static inline struct list_head *get_list_head(struct __queue *queue) -{ - return (&(queue->queue)); -} - -static inline void _set_timer(struct timer_list *ptimer, u32 delay_time) -{ - mod_timer(ptimer, jiffies + msecs_to_jiffies(delay_time)); -} - -static inline int rtw_netif_queue_stopped(struct net_device *pnetdev) -{ - return netif_tx_queue_stopped(netdev_get_tx_queue(pnetdev, 0)) && - netif_tx_queue_stopped(netdev_get_tx_queue(pnetdev, 1)) && - netif_tx_queue_stopped(netdev_get_tx_queue(pnetdev, 2)) && - netif_tx_queue_stopped(netdev_get_tx_queue(pnetdev, 3)); -} - -int RTW_STATUS_CODE(int error_code); - -void *rtw_malloc2d(int h, int w, int size); - -#define rtw_init_queue(q) \ - do { \ - INIT_LIST_HEAD(&((q)->queue)); \ - spin_lock_init(&((q)->lock)); \ - } while (0) - -static inline unsigned char _cancel_timer_ex(struct timer_list *ptimer) -{ - return del_timer_sync(ptimer); -} - -static inline void flush_signals_thread(void) -{ - if (signal_pending (current)) - flush_signals(current); -} - -struct rtw_netdev_priv_indicator { - void *priv; - u32 sizeof_priv; -}; -struct net_device *rtw_alloc_etherdev_with_old_priv(int sizeof_priv, - void *old_priv); -struct net_device *rtw_alloc_etherdev(int sizeof_priv); - -#define rtw_netdev_priv(netdev) \ - (((struct rtw_netdev_priv_indicator *)netdev_priv(netdev))->priv) -void rtw_free_netdev(struct net_device *netdev); - -#define NDEV_FMT "%s" -#define NDEV_ARG(ndev) ndev->name -#define ADPT_FMT "%s" -#define ADPT_ARG(adapter) adapter->pnetdev->name -#define FUNC_NDEV_FMT "%s(%s)" -#define FUNC_NDEV_ARG(ndev) __func__, ndev->name -#define FUNC_ADPT_FMT "%s(%s)" -#define FUNC_ADPT_ARG(adapter) __func__, adapter->pnetdev->name - -#define rtw_signal_process(pid, sig) kill_pid(find_vpid((pid)), (sig), 1) - -/* Macros for handling unaligned memory accesses */ - -#define RTW_GET_BE16(a) ((u16) (((a)[0] << 8) | (a)[1])) -#define RTW_PUT_BE16(a, val) \ - do { \ - (a)[0] = ((u16) (val)) >> 8; \ - (a)[1] = ((u16) (val)) & 0xff; \ - } while (0) - -#define RTW_PUT_LE16(a, val) \ - do { \ - (a)[1] = ((u16) (val)) >> 8; \ - (a)[0] = ((u16) (val)) & 0xff; \ - } while (0) - -#define RTW_GET_BE24(a) ((((u32) (a)[0]) << 16) | (((u32) (a)[1]) << 8) | \ - ((u32) (a)[2])) - -#define RTW_PUT_BE32(a, val) \ - do { \ - (a)[0] = (u8) ((((u32) (val)) >> 24) & 0xff); \ - (a)[1] = (u8) ((((u32) (val)) >> 16) & 0xff); \ - (a)[2] = (u8) ((((u32) (val)) >> 8) & 0xff); \ - (a)[3] = (u8) (((u32) (val)) & 0xff); \ - } while (0) - -void rtw_buf_update(u8 **buf, u32 *buf_len, u8 *src, u32 src_len); - -struct rtw_cbuf { - u32 write; - u32 read; - u32 size; - void *bufs[]; -}; - -bool rtw_cbuf_empty(struct rtw_cbuf *cbuf); -void *rtw_cbuf_pop(struct rtw_cbuf *cbuf); -struct rtw_cbuf *rtw_cbuf_alloc(u32 size); -int wifirate2_ratetbl_inx(unsigned char rate); - -#endif diff --git a/drivers/staging/r8188eu/include/rtl8188e_cmd.h b/drivers/staging/r8188eu/include/rtl8188e_cmd.h deleted file mode 100644 index c785cf8ed683..000000000000 --- a/drivers/staging/r8188eu/include/rtl8188e_cmd.h +++ /dev/null @@ -1,90 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#ifndef __RTL8188E_CMD_H__ -#define __RTL8188E_CMD_H__ - -enum RTL8188E_H2C_CMD_ID { - /* Class Common */ - H2C_COM_RSVD_PAGE = 0x00, - H2C_COM_MEDIA_STATUS_RPT = 0x01, - H2C_COM_SCAN = 0x02, - H2C_COM_KEEP_ALIVE = 0x03, - H2C_COM_DISCNT_DECISION = 0x04, - H2C_COM_INIT_OFFLOAD = 0x06, - H2C_COM_REMOTE_WAKE_CTL = 0x07, - H2C_COM_AP_OFFLOAD = 0x08, - H2C_COM_BCN_RSVD_PAGE = 0x09, - H2C_COM_PROB_RSP_RSVD_PAGE = 0x0A, - - /* Class PS */ - H2C_PS_PWR_MODE = 0x20, - H2C_PS_TUNE_PARA = 0x21, - H2C_PS_TUNE_PARA_2 = 0x22, - H2C_PS_LPS_PARA = 0x23, - H2C_PS_P2P_OFFLOAD = 0x24, - - /* Class DM */ - H2C_DM_MACID_CFG = 0x40, - H2C_DM_TXBF = 0x41, -}; - -struct cmd_msg_parm { - u8 eid; /* element id */ - u8 sz; /* sz */ - u8 buf[6]; -}; - -struct setpwrmode_parm { - u8 Mode;/* 0:Active,1:LPS,2:WMMPS */ - u8 SmartPS_RLBM;/* LPS= 0:PS_Poll,1:PS_Poll,2:NullData,WMM= 0:PS_Poll,1:NullData */ - u8 AwakeInterval; /* unit: beacon interval */ - u8 bAllQueueUAPSD; - u8 PwrState;/* AllON(0x0c),RFON(0x04),RFOFF(0x00) */ -}; - -struct H2C_SS_RFOFF_PARAM { - u8 ROFOn; /* 1: on, 0:off */ - u16 gpio_period; /* unit: 1024 us */ -} __packed; - -struct joinbssrpt_parm { - u8 OpMode; /* RT_MEDIA_STATUS */ -}; - -struct rsvdpage_loc { - u8 LocProbeRsp; - u8 LocPsPoll; - u8 LocNullData; - u8 LocQosNull; - u8 LocBTQosNull; -}; - -struct P2P_PS_Offload_t { - u8 Offload_En:1; - u8 role:1; /* 1: Owner, 0: Client */ - u8 CTWindow_En:1; - u8 NoA0_En:1; - u8 NoA1_En:1; - u8 AllStaSleep:1; /* Only valid in Owner */ - u8 discovery:1; - u8 rsvd:1; -}; - -struct P2P_PS_CTWPeriod_t { - u8 CTWPeriod; /* TU */ -}; - -/* host message to firmware cmd */ -void rtl8188e_set_FwPwrMode_cmd(struct adapter *padapter, u8 Mode); -void rtl8188e_set_FwJoinBssReport_cmd(struct adapter *padapter, u8 mstatus); -u8 rtl8188e_set_raid_cmd(struct adapter *padapter, u32 mask); -void rtl8188e_Add_RateATid(struct adapter *padapter, u32 bitmap, u8 arg, - u8 rssi_level); - -void rtl8188e_set_p2p_ps_offload_cmd(struct adapter *adapt, u8 p2p_ps_state); - -void CheckFwRsvdPageContent(struct adapter *adapt); -void rtl8188e_set_FwMediaStatus_cmd(struct adapter *adapt, u16 mstatus_rpt); - -#endif/* __RTL8188E_CMD_H__ */ diff --git a/drivers/staging/r8188eu/include/rtl8188e_dm.h b/drivers/staging/r8188eu/include/rtl8188e_dm.h deleted file mode 100644 index d62cdfc2db20..000000000000 --- a/drivers/staging/r8188eu/include/rtl8188e_dm.h +++ /dev/null @@ -1,28 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#ifndef __RTL8188E_DM_H__ -#define __RTL8188E_DM_H__ - -enum{ - UP_LINK, - DOWN_LINK, -}; - -struct dm_priv { - u32 InitODMFlag; - - /* Lower Signal threshold for Rate Adaptive */ - int EntryMinUndecoratedSmoothedPWDB; - int MinUndecoratedPWDBForDM; -}; - -void rtl8188e_init_dm_priv(struct adapter *adapt); -void rtl8188e_InitHalDm(struct adapter *adapt); -void rtl8188e_HalDmWatchDog(struct adapter *adapt); - -void AntDivCompare8188E(struct adapter *adapt, struct wlan_bssid_ex *dst, - struct wlan_bssid_ex *src); -u8 AntDivBeforeLink8188E(struct adapter *adapt); - -#endif diff --git a/drivers/staging/r8188eu/include/rtl8188e_hal.h b/drivers/staging/r8188eu/include/rtl8188e_hal.h deleted file mode 100644 index feeb37c22897..000000000000 --- a/drivers/staging/r8188eu/include/rtl8188e_hal.h +++ /dev/null @@ -1,181 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#ifndef __RTL8188E_HAL_H__ -#define __RTL8188E_HAL_H__ - -/* include HAL Related header after HAL Related compiling flags */ -#include "rtl8188e_spec.h" -#include "Hal8188EPhyReg.h" -#include "Hal8188EPhyCfg.h" -#include "rtl8188e_rf.h" -#include "rtl8188e_dm.h" -#include "rtl8188e_recv.h" -#include "rtl8188e_xmit.h" -#include "rtl8188e_cmd.h" -#include "rtw_efuse.h" -#include "odm.h" -#include "odm_HWConfig.h" -#include "odm_RegDefine11N.h" -#include "HalPhyRf_8188e.h" -#include "Hal8188ERateAdaptive.h" -#include "HalHWImg8188E_MAC.h" -#include "HalHWImg8188E_RF.h" -#include "HalHWImg8188E_BB.h" -#include "odm_RTL8188E.h" - -#define DRVINFO_SZ 4 /* unit is 8bytes */ -#define PageNum_128(_Len) (u32)(((_Len)>>7) + ((_Len) & 0x7F ? 1 : 0)) - -#define DRIVER_EARLY_INT_TIME 0x05 -#define BCN_DMA_ATIME_INT_TIME 0x02 - -#define MAX_RX_DMA_BUFFER_SIZE_88E \ - 0x2400 /* 9k for 88E nornal chip , MaxRxBuff=10k-max(TxReportSize(64*8), - * WOLPattern(16*24)) */ - -#define TX_SELE_LQ BIT(1) /* Low Queue */ -#define TX_SELE_NQ BIT(2) /* Normal Queue */ - -/* Note: We will divide number of page equally for each queue other - * than public queue! */ -/* 22k = 22528 bytes = 176 pages (@page = 128 bytes) */ -/* must reserved about 7 pages for LPS => 176-7 = 169 (0xA9) */ -/* 2*BCN / 1*ps-poll / 1*null-data /1*prob_rsp /1*QOS null-data /1*BT QOS - * null-data */ - -#define TX_TOTAL_PAGE_NUMBER_88E 0xA9/* 169 (21632=> 21k) */ - -#define TX_PAGE_BOUNDARY_88E (TX_TOTAL_PAGE_NUMBER_88E + 1) - -#include "HalVerDef.h" -#include "hal_com.h" - -/* Channel Plan */ -enum ChannelPlan { - CHPL_FCC = 0, - CHPL_IC = 1, - CHPL_ETSI = 2, - CHPL_SPA = 3, - CHPL_FRANCE = 4, - CHPL_MKK = 5, - CHPL_MKK1 = 6, - CHPL_ISRAEL = 7, - CHPL_TELEC = 8, - CHPL_GLOBAL = 9, - CHPL_WORLD = 10, -}; - -struct txpowerinfo24g { - u8 IndexCCK_Base[RF_PATH_MAX][MAX_CHNL_GROUP_24G]; - u8 IndexBW40_Base[RF_PATH_MAX][MAX_CHNL_GROUP_24G]; - /* If only one tx, only BW20 and OFDM are used. */ - s8 CCK_Diff[RF_PATH_MAX][MAX_TX_COUNT]; - s8 OFDM_Diff[RF_PATH_MAX][MAX_TX_COUNT]; - s8 BW20_Diff[RF_PATH_MAX][MAX_TX_COUNT]; - s8 BW40_Diff[RF_PATH_MAX][MAX_TX_COUNT]; -}; - -#define EFUSE_REAL_CONTENT_LEN 512 -#define AVAILABLE_EFUSE_ADDR(addr) (addr < EFUSE_REAL_CONTENT_LEN) - -#define EFUSE_REAL_CONTENT_LEN_88E 256 -#define EFUSE_MAP_LEN_88E 512 -#define EFUSE_MAX_SECTION_88E 64 -/* To prevent out of boundary programming case, leave 1byte and program - * full section */ -/* 9bytes + 1byt + 5bytes and pre 1byte. */ -/* For worst case: */ -/* | 2byte|----8bytes----|1byte|--7bytes--| 92D */ -/* PG data exclude header, dummy 7 bytes from CP test and reserved 1byte. */ -#define EFUSE_OOB_PROTECT_BYTES_88E 18 - -#define EFUSE_PROTECT_BYTES_BANK 16 - -#define USB_RXAGG_PAGE_COUNT 48 -#define USB_RXAGG_PAGE_TIMEOUT 0x4 - -struct hal_data_8188e { - struct HAL_VERSION VersionID; - /* current WIFI_PHY values */ - enum ht_channel_width CurrentChannelBW; - u8 CurrentChannel; - u8 nCur40MhzPrimeSC;/* Control channel sub-carrier */ - - u8 EEPROMRegulatory; - u8 EEPROMThermalMeter; - - u8 Index24G_CCK_Base[CHANNEL_MAX_NUMBER]; - u8 Index24G_BW40_Base[CHANNEL_MAX_NUMBER]; - /* If only one tx, only BW20 and OFDM are used. */ - s8 OFDM_24G_Diff[MAX_TX_COUNT]; - s8 BW20_24G_Diff[MAX_TX_COUNT]; - - /* HT 20<->40 Pwr diff */ - u8 TxPwrHt20Diff[RF_PATH_MAX][CHANNEL_MAX_NUMBER]; - /* For HT<->legacy pwr diff */ - u8 TxPwrLegacyHtDiff[RF_PATH_MAX][CHANNEL_MAX_NUMBER]; - /* For power group */ - u8 PwrGroupHT20[RF_PATH_MAX][CHANNEL_MAX_NUMBER]; - u8 PwrGroupHT40[RF_PATH_MAX][CHANNEL_MAX_NUMBER]; - - /* Read/write are allow for following hardware information variables */ - u8 pwrGroupCnt; - u32 MCSTxPowerLevelOriginalOffset[MAX_PG_GROUP][16]; - - u8 CrystalCap; - - u32 AcParam_BE; /* Original parameter for BE, use for EDCA turbo. */ - - struct bb_reg_def PHYRegDef; - - u32 RfRegChnlVal; - - /* for host message to fw */ - u8 LastHMEBoxNum; - - u8 fw_ractrl; - u8 RegFwHwTxQCtrl; - u8 RegReg542; - u8 RegCR_1; - - struct dm_priv dmpriv; - struct odm_dm_struct odmpriv; - - u8 CurAntenna; - u8 AntDivCfg; - u8 TRxAntDivType; - - u8 out_ep_extra_queues; - - struct P2P_PS_Offload_t p2p_ps_offload; - - /* Auto FSM to Turn On, include clock, isolation, power control - * for MAC only */ - u8 bMacPwrCtrlOn; -}; - -s32 InitLLTTable(struct adapter *padapter, u8 txpktbuf_bndy); - -/* EFuse */ -void Hal_EfuseParseIDCode88E(struct adapter *padapter, u8 *hwinfo); -void Hal_ReadTxPowerInfo88E(struct adapter *padapter, u8 *hwinfo, - bool AutoLoadFail); - -void rtl8188e_EfuseParseChnlPlan(struct adapter *padapter, u8 *hwinfo, - bool AutoLoadFail); -void Hal_ReadAntennaDiversity88E(struct adapter *pAdapter, u8 *PROMContent, - bool AutoLoadFail); -void Hal_ReadThermalMeter_88E(struct adapter *padapter, u8 *PROMContent, - bool AutoloadFail); -void Hal_EfuseParseXtal_8188E(struct adapter *pAdapter, u8 *hwinfo, - bool AutoLoadFail); -void Hal_ReadPowerSavingMode88E(struct adapter *pAdapter, u8 *hwinfo, - bool AutoLoadFail); - -void rtl8188e_read_chip_version(struct adapter *padapter); - -s32 rtl8188e_iol_efuse_patch(struct adapter *padapter); -void rtw_cancel_all_timer(struct adapter *padapter); - -#endif /* __RTL8188E_HAL_H__ */ diff --git a/drivers/staging/r8188eu/include/rtl8188e_recv.h b/drivers/staging/r8188eu/include/rtl8188e_recv.h deleted file mode 100644 index dc4f358f646d..000000000000 --- a/drivers/staging/r8188eu/include/rtl8188e_recv.h +++ /dev/null @@ -1,40 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#ifndef __RTL8188E_RECV_H__ -#define __RTL8188E_RECV_H__ - -#define TX_RPT1_PKT_LEN 8 - -#define NR_PREALLOC_RECV_SKB (8) - -#define NR_RECVBUFF (4) - -#define MAX_RECVBUF_SZ (15360) /* 15k < 16k */ - -struct phy_stat { - unsigned int phydw0; - unsigned int phydw1; - unsigned int phydw2; - unsigned int phydw3; - unsigned int phydw4; - unsigned int phydw5; - unsigned int phydw6; - unsigned int phydw7; -}; - -/* Rx smooth factor */ -#define Rx_Smooth_Factor (20) - -enum rx_packet_type { - NORMAL_RX,/* Normal rx packet */ - TX_REPORT1,/* CCX */ - TX_REPORT2,/* TX RPT */ - HIS_REPORT,/* USB HISR RPT */ -}; - -void rtl8188eu_recv_tasklet(unsigned long priv); -void update_recvframe_phyinfo_88e(struct recv_frame *fra, struct phy_stat *phy); -void update_recvframe_attrib_88e(struct recv_frame *fra, struct recv_stat *stat); - -#endif diff --git a/drivers/staging/r8188eu/include/rtl8188e_rf.h b/drivers/staging/r8188eu/include/rtl8188e_rf.h deleted file mode 100644 index 63ac0acc68fd..000000000000 --- a/drivers/staging/r8188eu/include/rtl8188e_rf.h +++ /dev/null @@ -1,18 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#ifndef __RTL8188E_RF_H__ -#define __RTL8188E_RF_H__ - -#define RF6052_MAX_TX_PWR 0x3F -#define RF6052_MAX_REG 0x3F -#define RF6052_MAX_PATH 2 - -int phy_RF6052_Config_ParaFile(struct adapter *Adapter); -void rtl8188e_PHY_RF6052SetBandwidth(struct adapter *Adapter, - enum ht_channel_width Bandwidth); -void rtl8188e_PHY_RF6052SetCckTxPower(struct adapter *Adapter, u8 *level); -void rtl8188e_PHY_RF6052SetOFDMTxPower(struct adapter *Adapter, u8 *ofdm, - u8 *pwrbw20, u8 *pwrbw40, u8 channel); - -#endif/* __RTL8188E_RF_H__ */ diff --git a/drivers/staging/r8188eu/include/rtl8188e_spec.h b/drivers/staging/r8188eu/include/rtl8188e_spec.h deleted file mode 100644 index 25b31417cd58..000000000000 --- a/drivers/staging/r8188eu/include/rtl8188e_spec.h +++ /dev/null @@ -1,1142 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#ifndef __RTL8188E_SPEC_H__ -#define __RTL8188E_SPEC_H__ - -/* 8192C Register offset definition */ - -#define HAL_PS_TIMER_INT_DELAY 50 /* 50 microseconds */ -#define HAL_92C_NAV_UPPER_UNIT 128 /* micro-second */ - -/* 8188E PKT_BUFF_ACCESS_CTRL value */ -#define TXPKT_BUF_SELECT 0x69 -#define RXPKT_BUF_SELECT 0xA5 -#define DISABLE_TRXPKT_BUF_ACCESS 0x0 - -/* 0x0000h ~ 0x00FFh System Configuration */ -#define REG_SYS_ISO_CTRL 0x0000 -#define REG_SYS_FUNC_EN 0x0002 -#define REG_APS_FSMCO 0x0004 -#define REG_SYS_CLKR 0x0008 -#define REG_9346CR 0x000A -#define REG_EE_VPD 0x000C -#define REG_AFE_MISC 0x0010 -#define REG_SPS0_CTRL 0x0011 -#define REG_SPS_OCP_CFG 0x0018 -#define REG_RSV_CTRL 0x001C -#define REG_RF_CTRL 0x001F -#define REG_LDOA15_CTRL 0x0020 -#define REG_LDOV12D_CTRL 0x0021 -#define REG_LDOHCI12_CTRL 0x0022 -#define REG_LPLDO_CTRL 0x0023 -#define REG_AFE_XTAL_CTRL 0x0024 -#define REG_AFE_PLL_CTRL 0x0028 -#define REG_APE_PLL_CTRL_EXT 0x002c -#define REG_EFUSE_CTRL 0x0030 -#define REG_EFUSE_TEST 0x0034 -#define REG_GPIO_MUXCFG 0x0040 -#define REG_GPIO_IO_SEL 0x0042 -#define REG_MAC_PINMUX_CFG 0x0043 -#define REG_GPIO_PIN_CTRL 0x0044 -#define REG_GPIO_INTM 0x0048 -#define REG_LEDCFG0 0x004C -#define REG_LEDCFG1 0x004D -#define REG_LEDCFG2 0x004E -#define REG_LEDCFG3 0x004F -#define REG_FSIMR 0x0050 -#define REG_FSISR 0x0054 -#define REG_HSIMR 0x0058 -#define REG_HSISR 0x005c -#define REG_GPIO_PIN_CTRL_2 0x0060 /* RTL8723 WIFI/BT/GPS - * Multi-Function GPIO Pin Control. */ -#define REG_GPIO_IO_SEL_2 0x0062 /* RTL8723 WIFI/BT/GPS - * Multi-Function GPIO Select. */ -#define REG_BB_PAD_CTRL 0x0064 -#define REG_MULTI_FUNC_CTRL 0x0068 /* RTL8723 WIFI/BT/GPS - * Multi-Function control source. */ -#define REG_GPIO_OUTPUT 0x006c -#define REG_AFE_XTAL_CTRL_EXT 0x0078 /* RTL8188E */ -#define REG_XCK_OUT_CTRL 0x007c /* RTL8188E */ -#define REG_MCUFWDL 0x0080 -#define REG_WOL_EVENT 0x0081 /* RTL8188E */ -#define REG_MCUTSTCFG 0x0084 -#define REG_HMEBOX_E0 0x0088 -#define REG_HMEBOX_E1 0x008A -#define REG_HMEBOX_E2 0x008C -#define REG_HMEBOX_E3 0x008E -#define REG_HMEBOX_EXT_0 0x01F0 -#define REG_HMEBOX_EXT_1 0x01F4 -#define REG_HMEBOX_EXT_2 0x01F8 -#define REG_HMEBOX_EXT_3 0x01FC -#define REG_HIMR_88E 0x00B0 -#define REG_HISR_88E 0x00B4 -#define REG_HIMRE_88E 0x00B8 -#define REG_HISRE_88E 0x00BC -#define REG_EFUSE_ACCESS 0x00CF /* Efuse access protection - * for RTL8723 */ -#define REG_BIST_SCAN 0x00D0 -#define REG_BIST_RPT 0x00D4 -#define REG_BIST_ROM_RPT 0x00D8 -#define REG_USB_SIE_INTF 0x00E0 -#define REG_PCIE_MIO_INTF 0x00E4 -#define REG_PCIE_MIO_INTD 0x00E8 -#define REG_HPON_FSM 0x00EC -#define REG_SYS_CFG 0x00F0 -#define REG_GPIO_OUTSTS 0x00F4 /* For RTL8723 only. */ -#define REG_TYPE_ID 0x00FC - -#define REG_MAC_PHY_CTRL_NORMAL 0x00f8 - -/* 0x0100h ~ 0x01FFh MACTOP General Configuration */ -#define REG_CR 0x0100 -#define REG_PBP 0x0104 -#define REG_PKT_BUFF_ACCESS_CTRL 0x0106 -#define REG_TRXDMA_CTRL 0x010C -#define REG_TRXFF_BNDY 0x0114 -#define REG_TRXFF_STATUS 0x0118 -#define REG_RXFF_PTR 0x011C -/* define REG_HIMR 0x0120 */ -/* define REG_HISR 0x0124 */ -#define REG_HIMRE 0x0128 -#define REG_HISRE 0x012C -#define REG_CPWM 0x012F -#define REG_FWIMR 0x0130 -#define REG_FTIMR 0x0138 -#define REG_FWISR 0x0134 -#define REG_PKTBUF_DBG_CTRL 0x0140 -#define REG_PKTBUF_DBG_ADDR (REG_PKTBUF_DBG_CTRL) -#define REG_RXPKTBUF_DBG (REG_PKTBUF_DBG_CTRL+2) -#define REG_TXPKTBUF_DBG (REG_PKTBUF_DBG_CTRL+3) -#define REG_RXPKTBUF_CTRL (REG_PKTBUF_DBG_CTRL+2) -#define REG_PKTBUF_DBG_DATA_L 0x0144 -#define REG_PKTBUF_DBG_DATA_H 0x0148 - -#define REG_TC0_CTRL 0x0150 -#define REG_TC1_CTRL 0x0154 -#define REG_TC2_CTRL 0x0158 -#define REG_TC3_CTRL 0x015C -#define REG_TC4_CTRL 0x0160 -#define REG_TCUNIT_BASE 0x0164 -#define REG_MBIST_START 0x0174 -#define REG_MBIST_DONE 0x0178 -#define REG_MBIST_FAIL 0x017C -#define REG_32K_CTRL 0x0194 /* RTL8188E */ -#define REG_C2HEVT_MSG_NORMAL 0x01A0 -#define REG_C2HEVT_CLEAR 0x01AF -#define REG_MCUTST_1 0x01c0 -#define REG_FMETHR 0x01C8 -#define REG_HMETFR 0x01CC -#define REG_HMEBOX_0 0x01D0 -#define REG_HMEBOX_1 0x01D4 -#define REG_HMEBOX_2 0x01D8 -#define REG_HMEBOX_3 0x01DC - -#define REG_LLT_INIT 0x01E0 - -/* 0x0200h ~ 0x027Fh TXDMA Configuration */ -#define REG_RQPN 0x0200 -#define REG_FIFOPAGE 0x0204 -#define REG_TDECTRL 0x0208 -#define REG_TXDMA_OFFSET_CHK 0x020C -#define REG_TXDMA_STATUS 0x0210 -#define REG_RQPN_NPQ 0x0214 - -/* 0x0280h ~ 0x02FFh RXDMA Configuration */ -#define REG_RXDMA_AGG_PG_TH 0x0280 -#define REG_RXPKT_NUM 0x0284 -#define REG_RXDMA_STATUS 0x0288 - -/* 0x0300h ~ 0x03FFh PCIe */ -#define REG_PCIE_CTRL_REG 0x0300 -#define REG_INT_MIG 0x0304 /* Interrupt Migration */ -#define REG_BCNQ_DESA 0x0308 /* TX Beacon Descr Address */ -#define REG_HQ_DESA 0x0310 /* TX High Queue Descr Addr */ -#define REG_MGQ_DESA 0x0318 /* TX Manage Queue Descr Addr*/ -#define REG_VOQ_DESA 0x0320 /* TX VO Queue Descr Addr */ -#define REG_VIQ_DESA 0x0328 /* TX VI Queue Descr Addr */ -#define REG_BEQ_DESA 0x0330 /* TX BE Queue Descr Addr */ -#define REG_BKQ_DESA 0x0338 /* TX BK Queue Descr Addr */ -#define REG_RX_DESA 0x0340 /* RX Queue Descr Addr */ -#define REG_MDIO 0x0354 /* MDIO for Access PCIE PHY */ -#define REG_DBG_SEL 0x0360 /* Debug Selection Register */ -#define REG_PCIE_HRPWM 0x0361 /* PCIe RPWM */ -#define REG_PCIE_HCPWM 0x0363 /* PCIe CPWM */ -#define REG_WATCH_DOG 0x0368 - -/* RTL8723 series ------------------------------ */ -#define REG_PCIE_HISR 0x03A0 - -/* spec version 11 */ -/* 0x0400h ~ 0x047Fh Protocol Configuration */ -#define REG_VOQ_INFORMATION 0x0400 -#define REG_VIQ_INFORMATION 0x0404 -#define REG_BEQ_INFORMATION 0x0408 -#define REG_BKQ_INFORMATION 0x040C -#define REG_MGQ_INFORMATION 0x0410 -#define REG_HGQ_INFORMATION 0x0414 -#define REG_BCNQ_INFORMATION 0x0418 -#define REG_TXPKT_EMPTY 0x041A - -#define REG_CPU_MGQ_INFORMATION 0x041C -#define REG_FWHW_TXQ_CTRL 0x0420 -#define REG_HWSEQ_CTRL 0x0423 -#define REG_TXPKTBUF_BCNQ_BDNY 0x0424 -#define REG_TXPKTBUF_MGQ_BDNY 0x0425 -#define REG_LIFETIME_EN 0x0426 -#define REG_MULTI_BCNQ_OFFSET 0x0427 -#define REG_SPEC_SIFS 0x0428 -#define REG_RL 0x042A -#define REG_DARFRC 0x0430 -#define REG_RARFRC 0x0438 -#define REG_RRSR 0x0440 -#define REG_ARFR0 0x0444 -#define REG_ARFR1 0x0448 -#define REG_ARFR2 0x044C -#define REG_ARFR3 0x0450 -#define REG_AGGLEN_LMT 0x0458 -#define REG_AMPDU_MIN_SPACE 0x045C -#define REG_TXPKTBUF_WMAC_LBK_BF_HD 0x045D -#define REG_FAST_EDCA_CTRL 0x0460 -#define REG_RD_RESP_PKT_TH 0x0463 -#define REG_INIRTS_RATE_SEL 0x0480 -/* define REG_INIDATA_RATE_SEL 0x0484 */ -#define REG_POWER_STATUS 0x04A4 -#define REG_POWER_STAGE1 0x04B4 -#define REG_POWER_STAGE2 0x04B8 -#define REG_PKT_VO_VI_LIFE_TIME 0x04C0 -#define REG_PKT_BE_BK_LIFE_TIME 0x04C2 -#define REG_STBC_SETTING 0x04C4 -#define REG_PROT_MODE_CTRL 0x04C8 -#define REG_MAX_AGGR_NUM 0x04CA -#define REG_RTS_MAX_AGGR_NUM 0x04CB -#define REG_BAR_MODE_CTRL 0x04CC -#define REG_RA_TRY_RATE_AGG_LMT 0x04CF -#define REG_EARLY_MODE_CONTROL 0x4D0 -#define REG_NQOS_SEQ 0x04DC -#define REG_QOS_SEQ 0x04DE -#define REG_NEED_CPU_HANDLE 0x04E0 -#define REG_PKT_LOSE_RPT 0x04E1 -#define REG_PTCL_ERR_STATUS 0x04E2 -#define REG_TX_RPT_CTRL 0x04EC -#define REG_TX_RPT_TIME 0x04F0 /* 2 byte */ -#define REG_DUMMY 0x04FC - -/* 0x0500h ~ 0x05FFh EDCA Configuration */ -#define REG_EDCA_VO_PARAM 0x0500 -#define REG_EDCA_VI_PARAM 0x0504 -#define REG_EDCA_BE_PARAM 0x0508 -#define REG_EDCA_BK_PARAM 0x050C -#define REG_BCNTCFG 0x0510 -#define REG_PIFS 0x0512 -#define REG_RDG_PIFS 0x0513 -#define REG_SIFS_CTX 0x0514 -#define REG_SIFS_TRX 0x0516 -#define REG_TSFTR_SYN_OFFSET 0x0518 -#define REG_AGGR_BREAK_TIME 0x051A -#define REG_SLOT 0x051B -#define REG_TX_PTCL_CTRL 0x0520 -#define REG_TXPAUSE 0x0522 -#define REG_DIS_TXREQ_CLR 0x0523 -#define REG_RD_CTRL 0x0524 -/* Format for offset 540h-542h: */ -/* [3:0]: TBTT prohibit setup in unit of 32us. The time for HW getting - * beacon content before TBTT. */ -/* [7:4]: Reserved. */ -/* [19:8]: TBTT prohibit hold in unit of 32us. The time for HW holding - * to send the beacon packet. */ -/* [23:20]: Reserved */ -/* Description: */ -/* | */ -/* |<--Setup--|--Hold------------>| */ -/* --------------|---------------------- */ -/* | */ -/* TBTT */ -/* Note: We cannot update beacon content to HW or send any AC packets during - * the time between Setup and Hold. */ -#define REG_TBTT_PROHIBIT 0x0540 -#define REG_RD_NAV_NXT 0x0544 -#define REG_NAV_PROT_LEN 0x0546 -#define REG_BCN_CTRL 0x0550 -#define REG_BCN_CTRL_1 0x0551 -#define REG_MBID_NUM 0x0552 -#define REG_DUAL_TSF_RST 0x0553 -#define REG_BCN_INTERVAL 0x0554 -#define REG_DRVERLYINT 0x0558 -#define REG_BCNDMATIM 0x0559 -#define REG_ATIMWND 0x055A -#define REG_BCN_MAX_ERR 0x055D -#define REG_RXTSF_OFFSET_CCK 0x055E -#define REG_RXTSF_OFFSET_OFDM 0x055F -#define REG_TSFTR 0x0560 -#define REG_TSFTR1 0x0568 -#define REG_ATIMWND_1 0x0570 -#define REG_PSTIMER 0x0580 -#define REG_TIMER0 0x0584 -#define REG_TIMER1 0x0588 -#define REG_ACMHWCTRL 0x05C0 - -/* define REG_FW_TSF_SYNC_CNT 0x04A0 */ -#define REG_FW_RESET_TSF_CNT_1 0x05FC -#define REG_FW_RESET_TSF_CNT_0 0x05FD -#define REG_FW_BCN_DIS_CNT 0x05FE - -/* 0x0600h ~ 0x07FFh WMAC Configuration */ -#define REG_APSD_CTRL 0x0600 -#define REG_BWOPMODE 0x0603 -#define REG_TCR 0x0604 -#define REG_RCR 0x0608 -#define REG_RX_PKT_LIMIT 0x060C -#define REG_RX_DLK_TIME 0x060D -#define REG_RX_DRVINFO_SZ 0x060F - -#define REG_MACID 0x0610 -#define REG_BSSID 0x0618 -#define REG_MAR 0x0620 -#define REG_MBIDCAMCFG 0x0628 - -#define REG_USTIME_EDCA 0x0638 -#define REG_MAC_SPEC_SIFS 0x063A - -/* 20100719 Joseph: Hardware register definition change. (HW datasheet v54) */ -/* [15:8]SIFS_R2T_OFDM, [7:0]SIFS_R2T_CCK */ -#define REG_R2T_SIFS 0x063C -/* [15:8]SIFS_T2T_OFDM, [7:0]SIFS_T2T_CCK */ -#define REG_T2T_SIFS 0x063E -#define REG_ACKTO 0x0640 -#define REG_CTS2TO 0x0641 -#define REG_EIFS 0x0642 - -/* RXERR_RPT */ -#define RXERR_TYPE_OFDM_PPDU 0 -#define RXERR_TYPE_OFDM_false_ALARM 1 -#define RXERR_TYPE_OFDM_MPDU_OK 2 -#define RXERR_TYPE_OFDM_MPDU_FAIL 3 -#define RXERR_TYPE_CCK_PPDU 4 -#define RXERR_TYPE_CCK_false_ALARM 5 -#define RXERR_TYPE_CCK_MPDU_OK 6 -#define RXERR_TYPE_CCK_MPDU_FAIL 7 -#define RXERR_TYPE_HT_PPDU 8 -#define RXERR_TYPE_HT_false_ALARM 9 -#define RXERR_TYPE_HT_MPDU_TOTAL 10 -#define RXERR_TYPE_HT_MPDU_OK 11 -#define RXERR_TYPE_HT_MPDU_FAIL 12 -#define RXERR_TYPE_RX_FULL_DROP 15 - -#define RXERR_COUNTER_MASK 0xFFFFF -#define RXERR_RPT_RST BIT(27) -#define _RXERR_RPT_SEL(type) ((type) << 28) - -/* Note: */ -/* The NAV upper value is very important to WiFi 11n 5.2.3 NAV test. - * The default value is always too small, but the WiFi TestPlan test - * by 25,000 microseconds of NAV through sending CTS in the air. - * We must update this value greater than 25,000 microseconds to pass - * the item. The offset of NAV_UPPER in 8192C Spec is incorrect, and - * the offset should be 0x0652. */ -#define REG_NAV_UPPER 0x0652 /* unit of 128 */ - -/* WMA, BA, CCX */ -/* define REG_NAV_CTRL 0x0650 */ -#define REG_BACAMCMD 0x0654 -#define REG_BACAMCONTENT 0x0658 -#define REG_LBDLY 0x0660 -#define REG_FWDLY 0x0661 -#define REG_RXERR_RPT 0x0664 -#define REG_WMAC_TRXPTCL_CTL 0x0668 - -/* Security */ -#define REG_CAMCMD 0x0670 -#define REG_CAMWRITE 0x0674 -#define REG_CAMREAD 0x0678 -#define REG_CAMDBG 0x067C -#define REG_SECCFG 0x0680 - -/* Power */ -#define REG_WOW_CTRL 0x0690 -#define REG_PS_RX_INFO 0x0692 -#define REG_UAPSD_TID 0x0693 -#define REG_WKFMCAM_CMD 0x0698 -#define REG_WKFMCAM_NUM_88E 0x698 -#define REG_RXFLTMAP0 0x06A0 -#define REG_RXFLTMAP1 0x06A2 -#define REG_RXFLTMAP2 0x06A4 -#define REG_BCN_PSR_RPT 0x06A8 -#define REG_BT_COEX_TABLE 0x06C0 - -/* Hardware Port 2 */ -#define REG_MACID1 0x0700 -#define REG_BSSID1 0x0708 - -/* 0xFE00h ~ 0xFE55h USB Configuration */ -#define REG_USB_INFO 0xFE17 -#define REG_USB_SPECIAL_OPTION 0xFE55 -#define REG_USB_DMA_AGG_TO 0xFE5B -#define REG_USB_AGG_TO 0xFE5C -#define REG_USB_AGG_TH 0xFE5D - -/* For normal chip */ -#define REG_NORMAL_SIE_VID 0xFE60 /* 0xFE60~0xFE61 */ -#define REG_NORMAL_SIE_PID 0xFE62 /* 0xFE62~0xFE63 */ -#define REG_NORMAL_SIE_OPTIONAL 0xFE64 -#define REG_NORMAL_SIE_EP 0xFE65 /* 0xFE65~0xFE67 */ -#define REG_NORMAL_SIE_PHY 0xFE68 /* 0xFE68~0xFE6B */ -#define REG_NORMAL_SIE_OPTIONAL2 0xFE6C -#define REG_NORMAL_SIE_GPS_EP 0xFE6D /* 0xFE6D, for RTL8723 only. */ -#define REG_NORMAL_SIE_MAC_ADDR 0xFE70 /* 0xFE70~0xFE75 */ -#define REG_NORMAL_SIE_STRING 0xFE80 /* 0xFE80~0xFEDF */ - -/* TODO: use these definition when using REG_xxx naming rule. */ -/* NOTE: DO NOT Remove these definition. Use later. */ - -#define EFUSE_CTRL REG_EFUSE_CTRL /* E-Fuse Control. */ -#define EFUSE_TEST REG_EFUSE_TEST /* E-Fuse Test. */ -#define MSR (REG_CR + 2) /* Media Status reg */ -#define ISR REG_HISR_88E -/* Timing Sync Function Timer Register. */ -#define TSFR REG_TSFTR - -#define PBP REG_PBP - -/* Redifine MACID register, to compatible prior ICs. */ -/* MAC ID Register, Offset 0x0050-0x0053 */ -#define IDR0 REG_MACID -/* MAC ID Register, Offset 0x0054-0x0055 */ -#define IDR4 (REG_MACID + 4) - -/* 9. Security Control Registers (Offset: ) */ -/* IN 8190 Data Sheet is called CAMcmd */ -#define RWCAM REG_CAMCMD -/* Software write CAM input content */ -#define WCAMI REG_CAMWRITE -/* Software read/write CAM config */ -#define RCAMO REG_CAMREAD -#define CAMDBG REG_CAMDBG -/* Security Configuration Register */ -#define SECR REG_SECCFG - -/* Unused register */ -#define UnusedRegister 0x1BF -#define DCAM UnusedRegister -#define PSR UnusedRegister -#define BBAddr UnusedRegister -#define PhyDataR UnusedRegister - -/* Min Spacing related settings. */ -#define MAX_MSS_DENSITY_2T 0x13 -#define MAX_MSS_DENSITY_1T 0x0A - -/* 8192C GPIO MUX Configuration Register (offset 0x40, 4 byte) */ -#define GPIOSEL_GPIO 0 -#define GPIOSEL_ENBT BIT(5) - -/* 8192C GPIO PIN Control Register (offset 0x44, 4 byte) */ -/* GPIO pins input value */ -#define GPIO_IN REG_GPIO_PIN_CTRL -/* GPIO pins output value */ -#define GPIO_OUT (REG_GPIO_PIN_CTRL+1) -/* GPIO pins output enable when a bit is set to "1"; otherwise, - * input is configured. */ -#define GPIO_IO_SEL (REG_GPIO_PIN_CTRL+2) -#define GPIO_MOD (REG_GPIO_PIN_CTRL+3) - -/* 8723/8188E Host System Interrupt Mask Register (offset 0x58, 32 byte) */ -#define HSIMR_GPIO12_0_INT_EN BIT(0) -#define HSIMR_SPS_OCP_INT_EN BIT(5) -#define HSIMR_RON_INT_EN BIT(6) -#define HSIMR_PDN_INT_EN BIT(7) -#define HSIMR_GPIO9_INT_EN BIT(25) - -/* 8723/8188E Host System Interrupt Status Register (offset 0x5C, 32 byte) */ -#define HSISR_GPIO12_0_INT BIT(0) -#define HSISR_SPS_OCP_INT BIT(5) -#define HSISR_RON_INT_EN BIT(6) -#define HSISR_PDNINT BIT(7) -#define HSISR_GPIO9_INT BIT(25) - -/* 8192C (MSR) Media Status Register (Offset 0x4C, 8 bits) */ -/* -Network Type -00: No link -01: Link in ad hoc network -10: Link in infrastructure network -11: AP mode -Default: 00b. -*/ -#define MSR_NOLINK 0x00 -#define MSR_ADHOC 0x01 -#define MSR_INFRA 0x02 -#define MSR_AP 0x03 - -/* 88E Driver Initialization Offload REG_FDHM0(Offset 0x88, 8 bits) */ -/* IOL config for REG_FDHM0(Reg0x88) */ -#define CMD_INIT_LLT BIT(0) -#define CMD_READ_EFUSE_MAP BIT(1) -#define CMD_EFUSE_PATCH BIT(2) -#define CMD_IOCONFIG BIT(3) -#define CMD_INIT_LLT_ERR BIT(4) -#define CMD_READ_EFUSE_MAP_ERR BIT(5) -#define CMD_EFUSE_PATCH_ERR BIT(6) -#define CMD_IOCONFIG_ERR BIT(7) - -/* 6. Adaptive Control Registers (Offset: 0x0160 - 0x01CF) */ -/* 8192C Response Rate Set Register (offset 0x181, 24bits) */ -#define RRSR_1M BIT(0) -#define RRSR_2M BIT(1) -#define RRSR_5_5M BIT(2) -#define RRSR_11M BIT(3) -#define RRSR_6M BIT(4) -#define RRSR_9M BIT(5) -#define RRSR_12M BIT(6) -#define RRSR_18M BIT(7) -#define RRSR_24M BIT(8) -#define RRSR_36M BIT(9) -#define RRSR_48M BIT(10) -#define RRSR_54M BIT(11) -#define RRSR_MCS0 BIT(12) -#define RRSR_MCS1 BIT(13) -#define RRSR_MCS2 BIT(14) -#define RRSR_MCS3 BIT(15) -#define RRSR_MCS4 BIT(16) -#define RRSR_MCS5 BIT(17) -#define RRSR_MCS6 BIT(18) -#define RRSR_MCS7 BIT(19) - -/* 8192C Response Rate Set Register (offset 0x1BF, 8bits) */ -/* WOL bit information */ -#define HAL92C_WOL_PTK_UPDATE_EVENT BIT(0) -#define HAL92C_WOL_GTK_UPDATE_EVENT BIT(1) - -/* 8192C BW_OPMODE bits (Offset 0x203, 8bit) */ -#define BW_OPMODE_20MHZ BIT(2) - -#define CAM_WRITE BIT(16) -#define CAM_POLLINIG BIT(31) - -#define SCR_UseDK 0x01 -#define SCR_TxSecEnable 0x02 -#define SCR_RxSecEnable 0x04 - -/* 10. Power Save Control Registers (Offset: 0x0260 - 0x02DF) */ -#define WOW_PMEN BIT(0) /* Power management Enable. */ -#define WOW_WOMEN BIT(1) /* WoW function on or off. */ -#define WOW_MAGIC BIT(2) /* Magic packet */ -#define WOW_UWF BIT(3) /* Unicast Wakeup frame. */ - -/* 12. Host Interrupt Status Registers (Offset: 0x0300 - 0x030F) */ -/* 8188 IMR/ISR bits */ -#define IMR_DISABLED_88E 0x0 -/* IMR DW0(0x0060-0063) Bit 0-31 */ -#define IMR_TXCCK_88E BIT(30) /* TXRPT interrupt when CCX bit of the packet is set */ -#define IMR_PSTIMEOUT_88E BIT(29) /* Power Save Time Out Interrupt */ -#define IMR_GTINT4_88E BIT(28) /* When GTIMER4 expires, this bit is set to 1 */ -#define IMR_GTINT3_88E BIT(27) /* When GTIMER3 expires, this bit is set to 1 */ -#define IMR_TBDER_88E BIT(26) /* Transmit Beacon0 Error */ -#define IMR_TBDOK_88E BIT(25) /* Transmit Beacon0 OK */ -#define IMR_TSF_BIT32_TOGGLE_88E BIT(24) /* TSF Timer BIT32 toggle indication interrupt */ -#define IMR_BCNDMAINT0_88E BIT(20) /* Beacon DMA Interrupt 0 */ -#define IMR_BCNDERR0_88E BIT(16) /* Beacon Queue DMA Error 0 */ -#define IMR_HSISR_IND_ON_INT_88E BIT(15) /* HSISR Indicator (HSIMR & HSISR is true, this bit is set to 1) */ -#define IMR_BCNDMAINT_E_88E BIT(14) /* Beacon DMA Interrupt Extension for Win7 */ -#define IMR_ATIMEND_88E BIT(12) /* CTWidnow End or ATIM Window End */ -#define IMR_HISR1_IND_INT_88E BIT(11) /* HISR1 Indicator (HISR1 & HIMR1 is true, this bit is set to 1) */ -#define IMR_C2HCMD_88E BIT(10) /* CPU to Host Command INT Status, Write 1 clear */ -#define IMR_CPWM2_88E BIT(9) /* CPU power Mode exchange INT Status, Write 1 clear */ -#define IMR_CPWM_88E BIT(8) /* CPU power Mode exchange INT Status, Write 1 clear */ -#define IMR_HIGHDOK_88E BIT(7) /* High Queue DMA OK */ -#define IMR_MGNTDOK_88E BIT(6) /* Management Queue DMA OK */ -#define IMR_BKDOK_88E BIT(5) /* AC_BK DMA OK */ -#define IMR_BEDOK_88E BIT(4) /* AC_BE DMA OK */ -#define IMR_VIDOK_88E BIT(3) /* AC_VI DMA OK */ -#define IMR_VODOK_88E BIT(2) /* AC_VO DMA OK */ -#define IMR_RDU_88E BIT(1) /* Rx Descriptor Unavailable */ -#define IMR_ROK_88E BIT(0) /* Receive DMA OK */ - -/* IMR DW1(0x00B4-00B7) Bit 0-31 */ -#define IMR_BCNDMAINT7_88E BIT(27) /* Beacon DMA Interrupt 7 */ -#define IMR_BCNDMAINT6_88E BIT(26) /* Beacon DMA Interrupt 6 */ -#define IMR_BCNDMAINT5_88E BIT(25) /* Beacon DMA Interrupt 5 */ -#define IMR_BCNDMAINT4_88E BIT(24) /* Beacon DMA Interrupt 4 */ -#define IMR_BCNDMAINT3_88E BIT(23) /* Beacon DMA Interrupt 3 */ -#define IMR_BCNDMAINT2_88E BIT(22) /* Beacon DMA Interrupt 2 */ -#define IMR_BCNDMAINT1_88E BIT(21) /* Beacon DMA Interrupt 1 */ -#define IMR_BCNDERR7_88E BIT(20) /* Beacon DMA Error Int 7 */ -#define IMR_BCNDERR6_88E BIT(19) /* Beacon DMA Error Int 6 */ -#define IMR_BCNDERR5_88E BIT(18) /* Beacon DMA Error Int 5 */ -#define IMR_BCNDERR4_88E BIT(17) /* Beacon DMA Error Int 4 */ -#define IMR_BCNDERR3_88E BIT(16) /* Beacon DMA Error Int 3 */ -#define IMR_BCNDERR2_88E BIT(15) /* Beacon DMA Error Int 2 */ -#define IMR_BCNDERR1_88E BIT(14) /* Beacon DMA Error Int 1 */ -#define IMR_ATIMEND_E_88E BIT(13) /* ATIM Window End Ext for Win7 */ -#define IMR_TXERR_88E BIT(11) /* Tx Err Flag Int Status, write 1 clear. */ -#define IMR_RXERR_88E BIT(10) /* Rx Err Flag INT Status, Write 1 clear */ -#define IMR_TXFOVW_88E BIT(9) /* Transmit FIFO Overflow */ -#define IMR_RXFOVW_88E BIT(8) /* Receive FIFO Overflow */ - -#define HAL_NIC_UNPLUG_ISR 0xFFFFFFFF /* The value when the NIC is unplugged for PCI. */ - -/* 8192C EFUSE */ -#define HWSET_MAX_SIZE 256 -#define HWSET_MAX_SIZE_88E 512 - -/*=================================================================== -===================================================================== -Here the register defines are for 92C. When the define is as same with 92C, -we will use the 92C's define for the consistency -So the following defines for 92C is not entire!!!!!! -===================================================================== -=====================================================================*/ -/* -Based on Datasheet V33---090401 -Register Summary -Current IOREG MAP -0x0000h ~ 0x00FFh System Configuration (256 Bytes) -0x0100h ~ 0x01FFh MACTOP General Configuration (256 Bytes) -0x0200h ~ 0x027Fh TXDMA Configuration (128 Bytes) -0x0280h ~ 0x02FFh RXDMA Configuration (128 Bytes) -0x0300h ~ 0x03FFh PCIE EMAC Reserved Region (256 Bytes) -0x0400h ~ 0x04FFh Protocol Configuration (256 Bytes) -0x0500h ~ 0x05FFh EDCA Configuration (256 Bytes) -0x0600h ~ 0x07FFh WMAC Configuration (512 Bytes) -0x2000h ~ 0x3FFFh 8051 FW Download Region (8196 Bytes) -*/ -/* 8192C (TXPAUSE) transmission pause (Offset 0x522, 8 bits) */ -/* Note: */ -/* The bits of stopping AC(VO/VI/BE/BK) queue in datasheet - * RTL8192S/RTL8192C are wrong, */ -/* the correct arragement is VO - Bit0, VI - Bit1, BE - Bit2, - * and BK - Bit3. */ -/* 8723 and 88E may be not correct either in the earlier version. */ -#define StopBecon BIT(6) -#define StopHigh BIT(5) -#define StopMgt BIT(4) -#define StopBK BIT(3) -#define StopBE BIT(2) -#define StopVI BIT(1) -#define StopVO BIT(0) - -/* 8192C (RCR) Receive Configuration Register(Offset 0x608, 32 bits) */ -#define RCR_APPFCS BIT(31) /* WMAC append FCS after payload */ -#define RCR_APP_MIC BIT(30) -#define RCR_APP_PHYSTS BIT(28) -#define RCR_APP_ICV BIT(29) -#define RCR_APP_PHYST_RXFF BIT(28) -#define RCR_APP_BA_SSN BIT(27) /* Accept BA SSN */ -#define RCR_ENMBID BIT(24) /* Enable Multiple BssId. */ -#define RCR_LSIGEN BIT(23) -#define RCR_MFBEN BIT(22) -#define RCR_HTC_LOC_CTRL BIT(14) /* MFC<--HTC=1 MFC-->HTC=0 */ -#define RCR_AMF BIT(13) /* Accept management type frame */ -#define RCR_ACF BIT(12) /* Accept control type frame */ -#define RCR_ADF BIT(11) /* Accept data type frame */ -#define RCR_AICV BIT(9) /* Accept ICV error packet */ -#define RCR_ACRC32 BIT(8) /* Accept CRC32 error packet */ -#define RCR_CBSSID_BCN BIT(7) /* Accept BSSID match packet - * (Rx beacon, probe rsp) */ -#define RCR_CBSSID_DATA BIT(6) /* Accept BSSID match (Data)*/ -#define RCR_CBSSID RCR_CBSSID_DATA /* Accept BSSID match */ -#define RCR_APWRMGT BIT(5) /* Accept power management pkt*/ -#define RCR_ADD3 BIT(4) /* Accept address 3 match pkt */ -#define RCR_AB BIT(3) /* Accept broadcast packet */ -#define RCR_AM BIT(2) /* Accept multicast packet */ -#define RCR_APM BIT(1) /* Accept physical match pkt */ -#define RCR_AAP BIT(0) /* Accept all unicast packet */ -#define RCR_MXDMA_OFFSET 8 -#define RCR_FIFO_OFFSET 13 - -/* 0xFE00h ~ 0xFE55h USB Configuration */ -#define REG_USB_INFO 0xFE17 -#define REG_USB_SPECIAL_OPTION 0xFE55 -#define REG_USB_DMA_AGG_TO 0xFE5B -#define REG_USB_AGG_TO 0xFE5C -#define REG_USB_AGG_TH 0xFE5D - -#define REG_USB_HRPWM 0xFE58 -#define REG_USB_HCPWM 0xFE57 -/* 8192C Register Bit and Content definition */ -/* 0x0000h ~ 0x00FFh System Configuration */ - -/* 2 SYS_ISO_CTRL */ -#define ISO_MD2PP BIT(0) -#define ISO_UA2USB BIT(1) -#define ISO_UD2CORE BIT(2) -#define ISO_PA2PCIE BIT(3) -#define ISO_PD2CORE BIT(4) -#define ISO_IP2MAC BIT(5) -#define ISO_DIOP BIT(6) -#define ISO_DIOE BIT(7) -#define ISO_EB2CORE BIT(8) -#define ISO_DIOR BIT(9) -#define PWC_EV12V BIT(15) - -/* 2 SYS_FUNC_EN */ -#define FEN_BBRSTB BIT(0) -#define FEN_BB_GLB_RSTn BIT(1) -#define FEN_USBA BIT(2) -#define FEN_UPLL BIT(3) -#define FEN_USBD BIT(4) -#define FEN_DIO_PCIE BIT(5) -#define FEN_PCIEA BIT(6) -#define FEN_PPLL BIT(7) -#define FEN_PCIED BIT(8) -#define FEN_DIOE BIT(9) -#define FEN_CPUEN BIT(10) -#define FEN_DCORE BIT(11) -#define FEN_ELDR BIT(12) -#define FEN_DIO_RF BIT(13) -#define FEN_HWPDN BIT(14) -#define FEN_MREGEN BIT(15) - -/* 2 APS_FSMCO */ -#define PFM_LDALL BIT(0) -#define PFM_ALDN BIT(1) -#define PFM_LDKP BIT(2) -#define PFM_WOWL BIT(3) -#define EnPDN BIT(4) -#define PDN_PL BIT(5) -#define APFM_ONMAC BIT(8) -#define APFM_OFF BIT(9) -#define APFM_RSM BIT(10) -#define AFSM_HSUS BIT(11) -#define AFSM_PCIE BIT(12) -#define APDM_MAC BIT(13) -#define APDM_HOST BIT(14) -#define APDM_HPDN BIT(15) -#define RDY_MACON BIT(16) -#define SUS_HOST BIT(17) -#define ROP_ALD BIT(20) -#define ROP_PWR BIT(21) -#define ROP_SPS BIT(22) -#define SOP_MRST BIT(25) -#define SOP_FUSE BIT(26) -#define SOP_ABG BIT(27) -#define SOP_AMB BIT(28) -#define SOP_RCK BIT(29) -#define SOP_A8M BIT(30) -#define XOP_BTCK BIT(31) - -/* 2 SYS_CLKR */ -#define ANAD16V_EN BIT(0) -#define ANA8M BIT(1) -#define MACSLP BIT(4) -#define LOADER_CLK_EN BIT(5) - -/* 2 9346CR */ - -#define BOOT_FROM_EEPROM BIT(4) -#define EEPROM_EN BIT(5) - -/* 2 SPS0_CTRL */ - -/* 2 SPS_OCP_CFG */ - -/* 2 RF_CTRL */ -#define RF_EN BIT(0) -#define RF_RSTB BIT(1) -#define RF_SDMRSTB BIT(2) - -/* 2 LDOV12D_CTRL */ -#define LDV12_EN BIT(0) -#define LDV12_SDBY BIT(1) -#define LPLDO_HSM BIT(2) -#define LPLDO_LSM_DIS BIT(3) -#define _LDV12_VADJ(x) (((x) & 0xF) << 4) - -/* 2EFUSE_CTRL */ -#define ALD_EN BIT(18) -#define EF_PD BIT(19) -#define EF_FLAG BIT(31) - -/* 2 EFUSE_TEST (For RTL8723 partially) */ -#define EF_TRPT BIT(7) -/* 00: Wifi Efuse, 01: BT Efuse0, 10: BT Efuse1, 11: BT Efuse2 */ -#define EF_CELL_SEL (BIT(8)|BIT(9)) -#define LDOE25_EN BIT(31) -#define EFUSE_SEL(x) (((x) & 0x3) << 8) -#define EFUSE_SEL_MASK 0x300 -#define EFUSE_WIFI_SEL_0 0x0 -#define EFUSE_BT_SEL_0 0x1 -#define EFUSE_BT_SEL_1 0x2 -#define EFUSE_BT_SEL_2 0x3 - -#define EFUSE_ACCESS_ON 0x69 /* For RTL8723 only. */ -#define EFUSE_ACCESS_OFF 0x00 /* For RTL8723 only. */ - -/* 2 8051FWDL */ -/* 2 MCUFWDL */ -#define MCUFWDL_EN BIT(0) -#define MCUFWDL_RDY BIT(1) -#define FWDL_CHKSUM_RPT BIT(2) -#define MACINI_RDY BIT(3) -#define BBINI_RDY BIT(4) -#define RFINI_RDY BIT(5) -#define WINTINI_RDY BIT(6) -#define RAM_DL_SEL BIT(7) /* 1:RAM, 0:ROM */ -#define ROM_DLEN BIT(19) -#define CPRST BIT(23) - -/* 2 REG_SYS_CFG */ -#define XCLK_VLD BIT(0) -#define ACLK_VLD BIT(1) -#define UCLK_VLD BIT(2) -#define PCLK_VLD BIT(3) -#define PCIRSTB BIT(4) -#define V15_VLD BIT(5) -#define SW_OFFLOAD_EN BIT(7) -#define SIC_IDLE BIT(8) -#define BD_MAC2 BIT(9) -#define BD_MAC1 BIT(10) -#define IC_MACPHY_MODE BIT(11) -#define CHIP_VER (BIT(12)|BIT(13)|BIT(14)|BIT(15)) -#define BT_FUNC BIT(16) -#define VENDOR_ID BIT(19) -#define PAD_HWPD_IDN BIT(22) -#define TRP_VAUX_EN BIT(23) /* RTL ID */ -#define TRP_BT_EN BIT(24) -#define BD_PKG_SEL BIT(25) -#define BD_HCI_SEL BIT(26) -#define TYPE_ID BIT(27) - -#define CHIP_VER_RTL_MASK 0xF000 /* Bit 12 ~ 15 */ -#define CHIP_VER_RTL_SHIFT 12 - -/* 2REG_GPIO_OUTSTS (For RTL8723 only) */ -#define EFS_HCI_SEL (BIT(0)|BIT(1)) -#define PAD_HCI_SEL (BIT(2)|BIT(3)) -#define HCI_SEL (BIT(4)|BIT(5)) -#define PKG_SEL_HCI BIT(6) -#define FEN_GPS BIT(7) -#define FEN_BT BIT(8) -#define FEN_WL BIT(9) -#define FEN_PCI BIT(10) -#define FEN_USB BIT(11) -#define BTRF_HWPDN_N BIT(12) -#define WLRF_HWPDN_N BIT(13) -#define PDN_BT_N BIT(14) -#define PDN_GPS_N BIT(15) -#define BT_CTL_HWPDN BIT(16) -#define GPS_CTL_HWPDN BIT(17) -#define PPHY_SUSB BIT(20) -#define UPHY_SUSB BIT(21) -#define PCI_SUSEN BIT(22) -#define USB_SUSEN BIT(23) -#define RF_RL_ID (BIT(31)|BIT(30)|BIT(29)|BIT(28)) - -/* 2SYS_CFG */ -#define RTL_ID BIT(23) /* TestChip ID, 1:Test(RLE); 0:MP(RL) */ - -/* 0x0100h ~ 0x01FFh MACTOP General Configuration */ - -/* 2 Function Enable Registers */ -/* 2 CR */ - -#define HCI_TXDMA_EN BIT(0) -#define HCI_RXDMA_EN BIT(1) -#define TXDMA_EN BIT(2) -#define RXDMA_EN BIT(3) -#define PROTOCOL_EN BIT(4) -#define SCHEDULE_EN BIT(5) -#define MACTXEN BIT(6) -#define MACRXEN BIT(7) -#define ENSWBCN BIT(8) -#define ENSEC BIT(9) -#define CALTMR_EN BIT(10) /* 32k CAL TMR enable */ - -/* Network type */ -#define _NETTYPE(x) (((x) & 0x3) << 16) -#define MASK_NETTYPE 0x30000 -#define NT_NO_LINK 0x0 -#define NT_LINK_AD_HOC 0x1 -#define NT_LINK_AP 0x2 -#define NT_AS_AP 0x3 - -/* 2 PBP - Page Size Register */ -#define GET_RX_PAGE_SIZE(value) ((value) & 0xF) -#define GET_TX_PAGE_SIZE(value) (((value) & 0xF0) >> 4) -#define _PSRX_MASK 0xF -#define _PSTX_MASK 0xF0 -#define _PSRX(x) (x) -#define _PSTX(x) ((x) << 4) - -#define PBP_128 0x1 - -/* 2 TX/RXDMA */ -#define RXDMA_ARBBW_EN BIT(0) -#define RXSHFT_EN BIT(1) -#define RXDMA_AGG_EN BIT(2) -#define QS_VO_QUEUE BIT(8) -#define QS_VI_QUEUE BIT(9) -#define QS_BE_QUEUE BIT(10) -#define QS_BK_QUEUE BIT(11) -#define QS_MANAGER_QUEUE BIT(12) -#define QS_HIGH_QUEUE BIT(13) - -#define HQSEL_VOQ BIT(0) -#define HQSEL_VIQ BIT(1) -#define HQSEL_BEQ BIT(2) -#define HQSEL_BKQ BIT(3) -#define HQSEL_MGTQ BIT(4) -#define HQSEL_HIQ BIT(5) - -/* For normal driver, 0x10C */ -#define _TXDMA_HIQ_MAP(x) (((x) & 0x3) << 14) -#define _TXDMA_MGQ_MAP(x) (((x) & 0x3) << 12) -#define _TXDMA_BKQ_MAP(x) (((x) & 0x3) << 10) -#define _TXDMA_BEQ_MAP(x) (((x) & 0x3) << 8) -#define _TXDMA_VIQ_MAP(x) (((x) & 0x3) << 6) -#define _TXDMA_VOQ_MAP(x) (((x) & 0x3) << 4) - -#define QUEUE_LOW 1 -#define QUEUE_NORMAL 2 -#define QUEUE_HIGH 3 - -/* 2 TRXFF_BNDY */ - -/* 2 LLT_INIT */ -#define _LLT_NO_ACTIVE 0x0 -#define _LLT_WRITE_ACCESS 0x1 -#define _LLT_READ_ACCESS 0x2 - -#define _LLT_INIT_DATA(x) ((x) & 0xFF) -#define _LLT_INIT_ADDR(x) (((x) & 0xFF) << 8) -#define _LLT_OP(x) (((x) & 0x3) << 30) -#define _LLT_OP_VALUE(x) (((x) >> 30) & 0x3) - -/* 0x0200h ~ 0x027Fh TXDMA Configuration */ - -#define NUM_HQ 0x29 - -#define LD_RQPN BIT(31) - -/* 2TDECTRL */ -#define BCN_VALID BIT(16) -#define BCN_HEAD(x) (((x) & 0xFF) << 8) -#define BCN_HEAD_MASK 0xFF00 - -/* 2 TDECTL */ -#define BLK_DESC_NUM_SHIFT 4 -#define BLK_DESC_NUM_MASK 0xF - -/* 2 TXDMA_OFFSET_CHK */ -#define DROP_DATA_EN BIT(9) - -/* 0x0280h ~ 0x028Bh RX DMA Configuration */ - -/* REG_RXDMA_CONTROL, 0x0286h */ - -/* 2 REG_RXPKT_NUM, 0x0284 */ -#define RXPKT_RELEASE_POLL BIT(16) -#define RXDMA_IDLE BIT(17) -#define RW_RELEASE_EN BIT(18) - -/* 0x0400h ~ 0x047Fh Protocol Configuration */ -/* 2 FWHW_TXQ_CTRL */ -#define EN_AMPDU_RTY_NEW BIT(7) - -/* 2 SPEC SIFS */ -#define _SPEC_SIFS_CCK(x) ((x) & 0xFF) -#define _SPEC_SIFS_OFDM(x) (((x) & 0xFF) << 8) - -/* 2 RL */ -#define RETRY_LIMIT_SHORT_SHIFT 8 -#define RETRY_LIMIT_LONG_SHIFT 0 - -/* 0x0500h ~ 0x05FFh EDCA Configuration */ - -/* 2 EDCA setting */ -#define AC_PARAM_TXOP_LIMIT_OFFSET 16 -#define AC_PARAM_ECW_MAX_OFFSET 12 -#define AC_PARAM_ECW_MIN_OFFSET 8 -#define AC_PARAM_AIFS_OFFSET 0 - -#define _LRL(x) ((x) & 0x3F) -#define _SRL(x) (((x) & 0x3F) << 8) - -/* 2 BCN_CTRL */ -#define EN_MBSSID BIT(1) -#define EN_TXBCN_RPT BIT(2) -#define EN_BCN_FUNCTION BIT(3) -#define DIS_TSF_UPDATE BIT(3) - -/* The same function but different bit field. */ -#define DIS_TSF_UDT0_NORMAL_CHIP BIT(4) -#define DIS_TSF_UDT0_TEST_CHIP BIT(5) -#define STOP_BCNQ BIT(6) - -/* 2 ACMHWCTRL */ -#define ACMHW_BEQEN BIT(1) -#define ACMHW_VIQEN BIT(2) -#define ACMHW_VOQEN BIT(3) - -/* 0x0600h ~ 0x07FFh WMAC Configuration */ -/* 2APSD_CTRL */ -#define APSDOFF BIT(6) -#define APSDOFF_STATUS BIT(7) - -#define RATE_BITMAP_ALL 0xFFFFF - -/* Only use CCK 1M rate for ACK */ -#define RATE_RRSR_CCK_ONLY_1M 0xFFFF1 - -/* 2 TCR */ -#define TSFRST BIT(0) -#define DIS_GCLK BIT(1) -#define PAD_SEL BIT(2) -#define PWR_ST BIT(6) -#define PWRBIT_OW_EN BIT(7) -#define ACRC BIT(8) -#define CFENDFORM BIT(9) -#define ICV BIT(10) - -/* 2 RCR */ -#define AAP BIT(0) -#define APM BIT(1) -#define AM BIT(2) -#define AB BIT(3) -#define ADD3 BIT(4) -#define APWRMGT BIT(5) -#define CBSSID BIT(6) -#define CBSSID_DATA BIT(6) -#define CBSSID_BCN BIT(7) -#define ACRC32 BIT(8) -#define AICV BIT(9) -#define ADF BIT(11) -#define ACF BIT(12) -#define AMF BIT(13) -#define HTC_LOC_CTRL BIT(14) -#define UC_DATA_EN BIT(16) -#define BM_DATA_EN BIT(17) -#define MFBEN BIT(22) -#define LSIGEN BIT(23) -#define EnMBID BIT(24) -#define APP_BASSN BIT(27) -#define APP_PHYSTS BIT(28) -#define APP_ICV BIT(29) -#define APP_MIC BIT(30) -#define APP_FCS BIT(31) - -/* 2 SECCFG */ -#define SCR_TxUseDK BIT(0) /* Force Tx Use Default Key */ -#define SCR_RxUseDK BIT(1) /* Force Rx Use Default Key */ -#define SCR_TxEncEnable BIT(2) /* Enable Tx Encryption */ -#define SCR_RxDecEnable BIT(3) /* Enable Rx Decryption */ -#define SCR_SKByA2 BIT(4) /* Search kEY BY A2 */ -#define SCR_NoSKMC BIT(5) /* No Key Search Multicast */ -#define SCR_TXBCUSEDK BIT(6) /* Force Tx Bcast pkt Use Default Key */ -#define SCR_RXBCUSEDK BIT(7) /* Force Rx Bcast pkt Use Default Key */ - -/* 0xFE00h ~ 0xFE55h USB Configuration */ - -/* 2 USB Information (0xFE17) */ -#define USB_IS_HIGH_SPEED 0 -#define USB_IS_FULL_SPEED 1 -#define USB_SPEED_MASK BIT(5) - -#define USB_NORMAL_SIE_EP_MASK 0xF -#define USB_NORMAL_SIE_EP_SHIFT 4 - -/* 2 Special Option */ -#define USB_AGG_EN BIT(3) - -/* 0; Use interrupt endpoint to upload interrupt pkt */ -/* 1; Use bulk endpoint to upload interrupt pkt, */ -#define INT_BULK_SEL BIT(4) - -/* 2REG_C2HEVT_CLEAR */ -/* Set by driver and notify FW that the driver has read - * the C2H command message */ -#define C2H_EVT_HOST_CLOSE 0x00 -/* Set by FW indicating that FW had set the C2H command - * message and it's not yet read by driver. */ -#define C2H_EVT_FW_CLOSE 0xFF - -/* 2REG_MULTI_FUNC_CTRL(For RTL8723 Only) */ -/* Enable GPIO[9] as WiFi HW PDn source */ -#define WL_HWPDN_EN BIT(0) -/* WiFi HW PDn polarity control */ -#define WL_HWPDN_SL BIT(1) -/* WiFi function enable */ -#define WL_FUNC_EN BIT(2) -/* Enable GPIO[9] as WiFi RF HW PDn source */ -#define WL_HWROF_EN BIT(3) -/* Enable GPIO[11] as BT HW PDn source */ -#define BT_HWPDN_EN BIT(16) -/* BT HW PDn polarity control */ -#define BT_HWPDN_SL BIT(17) -/* BT function enable */ -#define BT_FUNC_EN BIT(18) -/* Enable GPIO[11] as BT/GPS RF HW PDn source */ -#define BT_HWROF_EN BIT(19) -/* Enable GPIO[10] as GPS HW PDn source */ -#define GPS_HWPDN_EN BIT(20) -/* GPS HW PDn polarity control */ -#define GPS_HWPDN_SL BIT(21) -/* GPS function enable */ -#define GPS_FUNC_EN BIT(22) - -/* 3 REG_LIFECTRL_CTRL */ -#define HAL92C_EN_PKT_LIFE_TIME_BK BIT(3) -#define HAL92C_EN_PKT_LIFE_TIME_BE BIT(2) -#define HAL92C_EN_PKT_LIFE_TIME_VI BIT(1) -#define HAL92C_EN_PKT_LIFE_TIME_VO BIT(0) - -#define HAL92C_MSDU_LIFE_TIME_UNIT 128 /* in us */ - -/* General definitions */ -#define LAST_ENTRY_OF_TX_PKT_BUFFER 176 /* 22k 22528 bytes */ - -#define POLLING_LLT_THRESHOLD 20 -#define POLLING_READY_TIMEOUT_COUNT 1000 -/* GPIO BIT */ -#define HAL_8192C_HW_GPIO_WPS_BIT BIT(2) - -/* 8192C EEPROM/EFUSE share register definition. */ - -/* EEPROM/Efuse PG Offset for 88EE/88EU/88ES */ -#define EEPROM_TX_PWR_INX_88E 0x10 - -#define EEPROM_ChannelPlan_88E 0xB8 -#define EEPROM_XTAL_88E 0xB9 -#define EEPROM_THERMAL_METER_88E 0xBA -#define EEPROM_IQK_LCK_88E 0xBB - -#define EEPROM_RF_BOARD_OPTION_88E 0xC1 -#define EEPROM_RF_FEATURE_OPTION_88E 0xC2 -#define EEPROM_RF_ANTENNA_OPT_88E 0xC9 - -/* RTL88EU */ -#define EEPROM_MAC_ADDR_88EU 0xD7 -#define EEPROM_USB_OPTIONAL_FUNCTION0 0xD4 - -/* RTL88ES */ -#define EEPROM_MAC_ADDR_88ES 0x11A - -#define EEPROM_Default_CrystalCap_88E 0x20 -#define EEPROM_Default_ThermalMeter_88E 0x18 - -/* New EFUSE default value */ -#define EEPROM_DEFAULT_24G_INDEX 0x2D -#define EEPROM_DEFAULT_24G_HT20_DIFF 0X02 -#define EEPROM_DEFAULT_24G_OFDM_DIFF 0X04 - -#define EEPROM_DEFAULT_DIFF 0XFE -#define EEPROM_DEFAULT_BOARD_OPTION 0x00 - -#define EEPROM_CHANNEL_PLAN_FCC 0x0 -#define EEPROM_CHANNEL_PLAN_IC 0x1 -#define EEPROM_CHANNEL_PLAN_ETSI 0x2 -#define EEPROM_CHANNEL_PLAN_SPA 0x3 -#define EEPROM_CHANNEL_PLAN_FRANCE 0x4 -#define EEPROM_CHANNEL_PLAN_MKK 0x5 -#define EEPROM_CHANNEL_PLAN_MKK1 0x6 -#define EEPROM_CHANNEL_PLAN_ISRAEL 0x7 -#define EEPROM_CHANNEL_PLAN_TELEC 0x8 -#define EEPROM_CHANNEL_PLAN_GLOBAL_DOMA 0x9 -#define EEPROM_CHANNEL_PLAN_WORLD_WIDE_13 0xA -#define EEPROM_CHANNEL_PLAN_NCC 0xB -#define EEPROM_USB_OPTIONAL1 0xE -#define EEPROM_CHANNEL_PLAN_BY_HW_MASK 0x80 - -#define RTL_EEPROM_ID 0x8129 - -#endif /* __RTL8188E_SPEC_H__ */ diff --git a/drivers/staging/r8188eu/include/rtl8188e_xmit.h b/drivers/staging/r8188eu/include/rtl8188e_xmit.h deleted file mode 100644 index a023dd792da7..000000000000 --- a/drivers/staging/r8188eu/include/rtl8188e_xmit.h +++ /dev/null @@ -1,130 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#ifndef __RTL8188E_XMIT_H__ -#define __RTL8188E_XMIT_H__ - -#define MAX_TX_AGG_PACKET_NUMBER 0xFF -#define QSLT_MGNT 0x12 - -/* For 88e early mode */ -#define SET_EARLYMODE_PKTNUM(__paddr, __value) \ - le32p_replace_bits((__le32 *)__paddr, __value, GENMASK(2, 0)) -#define SET_EARLYMODE_LEN0(__pAddr, __Value) \ - le32p_replace_bits((__le32 *)__paddr, __value, GENMASK(15, 4)) -#define SET_EARLYMODE_LEN1(__paddr, __value) \ - le32p_replace_bits((__le32 *)__paddr, __value, GENMASK(27, 16)) -#define SET_EARLYMODE_LEN2_1(__pdr, __vValue) \ - le32p_replace_bits((__le32 *)__paddr, __value, GENMASK(31, 28)) -#define SET_EARLYMODE_LEN2_2(__paddr, __value) \ - le32p_replace_bits((__le32 *)(__paddr + 4), __value, GENMASK(7, 0)) -#define SET_EARLYMODE_LEN3(__pAddr, __Value) \ - le32p_replace_bits((__le32 *)(__paddr + 4), __value, GENMASK(19, 8)) -#define SET_EARLYMODE_LEN4(__paAddr, __vValue) \ - le32p_replace_bits((__le32 *)(__paddr + 4), __value, GENMASK(31, 20)) - -/* defined for TX DESC Operation */ - -#define MAX_TID (15) - -/* OFFSET 0 */ -#define OFFSET_SZ 0 -#define OFFSET_SHT 16 -#define BMC BIT(24) -#define LSG BIT(26) -#define FSG BIT(27) -#define OWN BIT(31) - -/* OFFSET 4 */ -#define PKT_OFFSET_SZ 0 -#define QSEL_SHT 8 -#define RATE_ID_SHT 16 -#define NAVUSEHDR BIT(20) -#define SEC_TYPE_SHT 22 -#define PKT_OFFSET_SHT 26 - -/* OFFSET 8 */ -#define AGG_EN BIT(12) -#define AGG_BK BIT(16) -#define AMPDU_DENSITY_SHT 20 -#define ANTSEL_A BIT(24) -#define ANTSEL_B BIT(25) -#define TX_ANT_CCK_SHT 26 -#define TX_ANTL_SHT 28 -#define TX_ANT_HT_SHT 30 - -/* OFFSET 12 */ -#define SEQ_SHT 16 -#define EN_HWSEQ BIT(31) - -/* OFFSET 16 */ -#define QOS BIT(6) -#define HW_SSN BIT(7) -#define USERATE BIT(8) -#define DISDATAFB BIT(10) -#define CTS_2_SELF BIT(11) -#define RTS_EN BIT(12) -#define HW_RTS_EN BIT(13) -#define DATA_SHORT BIT(24) -#define PWR_STATUS_SHT 15 -#define DATA_SC_SHT 20 -#define DATA_BW BIT(25) - -/* OFFSET 20 */ -#define RTY_LMT_EN BIT(17) - -/* OFFSET 20 */ -#define SGI BIT(6) -#define USB_TXAGG_NUM_SHT 24 - -#define USB_TXAGG_DESC_NUM 0x6 - -#define txdesc_set_ccx_sw_88e(txdesc, value) \ - do { \ - ((struct txdesc_88e *)(txdesc))->sw1 = (((value)>>8) & 0x0f); \ - ((struct txdesc_88e *)(txdesc))->sw0 = ((value) & 0xff); \ - } while (0) - -struct txrpt_ccx_88e { - /* offset 0 */ - u8 tag1:1; - u8 pkt_num:3; - u8 txdma_underflow:1; - u8 int_bt:1; - u8 int_tri:1; - u8 int_ccx:1; - - /* offset 1 */ - u8 mac_id:6; - u8 pkt_ok:1; - u8 bmc:1; - - /* offset 2 */ - u8 retry_cnt:6; - u8 lifetime_over:1; - u8 retry_over:1; - - /* offset 3 */ - u8 ccx_qtime0; - u8 ccx_qtime1; - - /* offset 5 */ - u8 final_data_rate; - - /* offset 6 */ - u8 sw1:4; - u8 qsel:4; - - /* offset 7 */ - u8 sw0; -}; - -void rtl8188e_fill_fake_txdesc(struct adapter *padapter, u8 *pDesc, - u32 BufferLen, u8 IsPsPoll, u8 IsBTQosNull); -s32 rtl8188eu_hal_xmit(struct adapter *padapter, struct xmit_frame *frame); -s32 rtl8188eu_mgnt_xmit(struct adapter *padapter, struct xmit_frame *frame); -s32 rtl8188eu_xmit_buf_handler(struct adapter *padapter); -void rtl8188eu_xmit_tasklet(unsigned long priv); -bool rtl8188eu_xmitframe_complete(struct adapter *padapter); - -#endif /* __RTL8188E_XMIT_H__ */ diff --git a/drivers/staging/r8188eu/include/rtw_ap.h b/drivers/staging/r8188eu/include/rtw_ap.h deleted file mode 100644 index 89b02c97e041..000000000000 --- a/drivers/staging/r8188eu/include/rtw_ap.h +++ /dev/null @@ -1,34 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2007 - 2012 Realtek Corporation. */ - -#ifndef __RTW_AP_H_ -#define __RTW_AP_H_ - -#include "osdep_service.h" -#include "drv_types.h" - -/* external function */ -void rtw_indicate_sta_assoc_event(struct adapter *padapter, - struct sta_info *psta); -void init_mlme_ap_info(struct adapter *padapter); -void free_mlme_ap_info(struct adapter *padapter); -void update_beacon(struct adapter *padapter, u8 ie_id, - u8 *oui, u8 tx); -void add_RATid(struct adapter *padapter, struct sta_info *psta, - u8 rssi_level); -void expire_timeout_chk(struct adapter *padapter); -void update_sta_info_apmode(struct adapter *padapter, struct sta_info *psta); -void rtw_ap_restore_network(struct adapter *padapter); - -void associated_clients_update(struct adapter *padapter, u8 updated); -void bss_cap_update_on_sta_join(struct adapter *padapter, struct sta_info *psta); -u8 bss_cap_update_on_sta_leave(struct adapter *padapter, struct sta_info *psta); -void sta_info_update(struct adapter *padapter, struct sta_info *psta); -u8 ap_free_sta(struct adapter *padapter, struct sta_info *psta, - bool active, u16 reason); -void rtw_sta_flush(struct adapter *padapter); -void start_ap_mode(struct adapter *padapter); -void stop_ap_mode(struct adapter *padapter); -void update_bmc_sta(struct adapter *padapter); - -#endif diff --git a/drivers/staging/r8188eu/include/rtw_br_ext.h b/drivers/staging/r8188eu/include/rtw_br_ext.h deleted file mode 100644 index 56772af3bec5..000000000000 --- a/drivers/staging/r8188eu/include/rtw_br_ext.h +++ /dev/null @@ -1,43 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#ifndef _RTW_BR_EXT_H_ -#define _RTW_BR_EXT_H_ - -#define GET_MY_HWADDR(padapter) ((padapter)->eeprompriv.mac_addr) - -#define NAT25_HASH_BITS 4 -#define NAT25_HASH_SIZE (1 << NAT25_HASH_BITS) -#define NAT25_AGEING_TIME 300 - -#define MAX_NETWORK_ADDR_LEN 17 - -struct nat25_network_db_entry { - struct nat25_network_db_entry *next_hash; - struct nat25_network_db_entry **pprev_hash; - atomic_t use_count; - unsigned char macAddr[6]; - unsigned long ageing_timer; - unsigned char networkAddr[MAX_NETWORK_ADDR_LEN]; -}; - -enum NAT25_METHOD { - NAT25_MIN, - NAT25_CHECK, - NAT25_INSERT, - NAT25_PARSE, - NAT25_MAX -}; - -struct br_ext_info { - unsigned int nat25_disable; - unsigned int macclone_enable; - unsigned int dhcp_bcst_disable; - int addPPPoETag; /* 1: Add PPPoE relay-SID, 0: disable */ - unsigned char nat25_dmzMac[ETH_ALEN]; - unsigned int nat25sc_disable; -}; - -void nat25_db_cleanup(struct adapter *priv); - -#endif /* _RTW_BR_EXT_H_ */ diff --git a/drivers/staging/r8188eu/include/rtw_cmd.h b/drivers/staging/r8188eu/include/rtw_cmd.h deleted file mode 100644 index e8eecd52d1d8..000000000000 --- a/drivers/staging/r8188eu/include/rtw_cmd.h +++ /dev/null @@ -1,925 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#ifndef __RTW_CMD_H_ -#define __RTW_CMD_H_ - -#include "wlan_bssdef.h" -#include "rtw_rf.h" - -#include "osdep_service.h" -#include "ieee80211.h" /* */ - -#define MAX_CMDSZ 1024 -#define MAX_RSPSZ 512 -#define MAX_EVTSZ 1024 - -#define CMDBUFF_ALIGN_SZ 512 - -struct cmd_obj { - struct adapter *padapter; - u16 cmdcode; - u8 res; - u8 *parmbuf; - u32 cmdsz; - u8 *rsp; - u32 rspsz; - struct list_head list; -}; - -struct cmd_priv { - struct completion enqueue_cmd; - struct completion start_cmd_thread; - struct completion stop_cmd_thread; - struct __queue cmd_queue; - u8 *cmd_buf; /* shall be non-paged, and 4 bytes aligned */ - u8 *cmd_allocated_buf; - u8 *rsp_buf; /* shall be non-paged, and 4 bytes aligned */ - u8 *rsp_allocated_buf; - u32 cmd_done_cnt; - u32 rsp_cnt; - u8 cmdthd_running; - struct adapter *padapter; -}; - -struct evt_priv { - struct work_struct c2h_wk; - bool c2h_wk_alive; - struct rtw_cbuf *c2h_queue; - #define C2H_QUEUE_MAX_LEN 10 - atomic_t event_seq; - u8 *evt_buf; /* shall be non-paged, and 4 bytes aligned */ -}; - -#define init_h2fwcmd_w_parm_no_rsp(pcmd, pparm, code) \ -do {\ - INIT_LIST_HEAD(&pcmd->list);\ - pcmd->cmdcode = code;\ - pcmd->parmbuf = (u8 *)(pparm);\ - pcmd->cmdsz = sizeof(*pparm);\ - pcmd->rsp = NULL;\ - pcmd->rspsz = 0;\ -} while (0) - -struct c2h_evt_hdr { - u8 id:4; - u8 plen:4; - u8 seq; - u8 payload[]; -}; - -#define c2h_evt_exist(c2h_evt) ((c2h_evt)->id || (c2h_evt)->plen) - -u32 rtw_enqueue_cmd(struct cmd_priv *pcmdpriv, struct cmd_obj *obj); -struct cmd_obj *rtw_dequeue_cmd(struct cmd_priv *pcmdpriv); -void rtw_free_cmd_obj(struct cmd_obj *pcmd); - -int rtw_cmd_thread(void *context); - -int rtw_init_cmd_priv(struct cmd_priv *pcmdpriv); -void rtw_free_cmd_priv(struct cmd_priv *pcmdpriv); - -int rtw_init_evt_priv(struct evt_priv *pevtpriv); -void rtw_free_evt_priv(struct evt_priv *pevtpriv); -void rtw_evt_notify_isr(struct evt_priv *pevtpriv); -u8 p2p_protocol_wk_cmd(struct adapter *padapter, int intCmdType); - -enum rtw_drvextra_cmd_id { - NONE_WK_CID, - DYNAMIC_CHK_WK_CID, - DM_CTRL_WK_CID, - PBC_POLLING_WK_CID, - POWER_SAVING_CTRL_WK_CID,/* IPS,AUTOSuspend */ - LPS_CTRL_WK_CID, - ANT_SELECT_WK_CID, - P2P_PS_WK_CID, - P2P_PROTO_WK_CID, - CHECK_HIQ_WK_CID,/* for softap mode, check hi queue if empty */ - INTEl_WIDI_WK_CID, - C2H_WK_CID, - RTP_TIMER_CFG_WK_CID, - MAX_WK_CID -}; - -enum LPS_CTRL_TYPE { - LPS_CTRL_SCAN = 0, - LPS_CTRL_JOINBSS = 1, - LPS_CTRL_CONNECT = 2, - LPS_CTRL_DISCONNECT = 3, - LPS_CTRL_SPECIAL_PACKET = 4, - LPS_CTRL_LEAVE = 5, -}; - -enum RFINTFS { - SWSI, - HWSI, - HWPI, -}; - -/* -Caller Mode: Infra, Ad-HoC - -Notes: To join a known BSS. - -Command-Event Mode - -*/ - -/* -Caller Mode: Infra, Ad-Hoc - -Notes: To join the specified bss - -Command Event Mode - -*/ -struct joinbss_parm { - struct wlan_bssid_ex network; -}; - -/* -Caller Mode: Infra, Ad-HoC(C) - -Notes: To disconnect the current associated BSS - -Command Mode - -*/ -struct disconnect_parm { - u32 deauth_timeout_ms; -}; - -/* -Caller Mode: AP, Ad-HoC(M) - -Notes: To create a BSS - -Command Mode -*/ -struct createbss_parm { - struct wlan_bssid_ex network; -}; - -struct setopmode_parm { - u8 mode; - u8 rsvd[3]; -}; - -/* -Caller Mode: AP, Ad-HoC, Infra - -Notes: To ask RTL8711 performing site-survey - -Command-Event Mode - -*/ - -#define RTW_SSID_SCAN_AMOUNT 9 /* for WEXT_CSCAN_AMOUNT 9 */ -#define RTW_CHANNEL_SCAN_AMOUNT (14+37) -struct sitesurvey_parm { - int scan_mode; /* active: 1, passive: 0 */ - u8 ssid_num; - u8 ch_num; - struct ndis_802_11_ssid ssid[RTW_SSID_SCAN_AMOUNT]; - struct rtw_ieee80211_channel ch[RTW_CHANNEL_SCAN_AMOUNT]; -}; - -/* -Caller Mode: Any - -Notes: To set the auth type of RTL8711. open/shared/802.1x - -Command Mode - -*/ -struct setauth_parm { - u8 mode; /* 0: legacy open, 1: legacy shared 2: 802.1x */ - u8 _1x; /* 0: PSK, 1: TLS */ - u8 rsvd[2]; -}; - -/* -Caller Mode: Infra - -a. algorithm: wep40, wep104, tkip & aes -b. keytype: grp key/unicast key -c. key contents - -when shared key ==> keyid is the camid -when 802.1x ==> keyid [0:1] ==> grp key -when 802.1x ==> keyid > 2 ==> unicast key - -*/ -struct setkey_parm { - u8 algorithm; /* could be none, wep40, TKIP, CCMP, wep104 */ - u8 keyid; - u8 grpkey; /* 1: this is the grpkey for 802.1x. - * 0: this is the unicast key for 802.1x */ - u8 set_tx; /* 1: main tx key for wep. 0: other key. */ - u8 key[16]; /* this could be 40 or 104 */ -}; - -/* -When in AP or Ad-Hoc mode, this is used to -allocate an sw/hw entry for a newly associated sta. - -Command - -when shared key ==> algorithm/keyid - -*/ -struct set_stakey_parm { - u8 addr[ETH_ALEN]; - u8 algorithm; - u8 id;/* currently for erasing cam entry if - * algorithm == _NO_PRIVACY_ */ - u8 key[16]; -}; - -struct set_stakey_rsp { - u8 addr[ETH_ALEN]; - u8 keyid; - u8 rsvd; -}; - -/* -Caller Ad-Hoc/AP - -Command -Rsp(AID == CAMID) mode - -This is to force fw to add an sta_data entry per driver's request. - -FW will write an cam entry associated with it. - -*/ -struct set_assocsta_parm { - u8 addr[ETH_ALEN]; -}; - -struct set_assocsta_rsp { - u8 cam_id; - u8 rsvd[3]; -}; - -/* - Caller Ad-Hoc/AP - - Command mode - - This is to force fw to del an sta_data entry per driver's request - - FW will invalidate the cam entry associated with it. - -*/ -struct del_assocsta_parm { - u8 addr[ETH_ALEN]; -}; - -/* -Caller Mode: AP/Ad-HoC(M) - -Notes: To notify fw that given staid has changed its power state - -Command Mode - -*/ -struct setstapwrstate_parm { - u8 staid; - u8 status; - u8 hwaddr[6]; -}; - -/* -Caller Mode: Any - -Notes: To setup the basic rate of RTL8711 - -Command Mode - -*/ -struct setbasicrate_parm { - u8 basicrates[NumRates]; -}; - -/* -Caller Mode: Any - -Notes: To read the current basic rate - -Command-Rsp Mode - -*/ -struct getbasicrate_parm { - u32 rsvd; -}; - -struct getbasicrate_rsp { - u8 basicrates[NumRates]; -}; - -/* -Caller Mode: Any - -Notes: To setup the data rate of RTL8711 - -Command Mode - -*/ -struct setdatarate_parm { - u8 mac_id; - u8 datarates[NumRates]; -}; - -/* -Caller Mode: Any - -Notes: To read the current data rate - -Command-Rsp Mode - -*/ -struct getdatarate_parm { - u32 rsvd; - -}; -struct getdatarate_rsp { - u8 datarates[NumRates]; -}; - -/* -Caller Mode: Any -AP: AP can use the info for the contents of beacon frame -Infra: STA can use the info when sitesurveying -Ad-HoC(M): Like AP -Ad-HoC(C): Like STA - -Notes: To set the phy capability of the NIC - -Command Mode - -*/ - -struct setphyinfo_parm { - struct regulatory_class class_sets[NUM_REGULATORYS]; - u8 status; -}; - -struct getphyinfo_parm { - u32 rsvd; -}; - -struct getphyinfo_rsp { - struct regulatory_class class_sets[NUM_REGULATORYS]; - u8 status; -}; - -/* -Caller Mode: Any - -Notes: To set the channel/modem/band -This command will be used when channel/modem/band is changed. - -Command Mode - -*/ -struct setphy_parm { - u8 rfchannel; - u8 modem; -}; - -/* -Caller Mode: Any - -Notes: To get the current setting of channel/modem/band - -Command-Rsp Mode - -*/ -struct getphy_parm { - u32 rsvd; - -}; -struct getphy_rsp { - u8 rfchannel; - u8 modem; -}; - -struct readBB_parm { - u8 offset; -}; -struct readBB_rsp { - u8 value; -}; - -struct readTSSI_parm { - u8 offset; -}; -struct readTSSI_rsp { - u8 value; -}; - -struct writeBB_parm { - u8 offset; - u8 value; -}; - -struct readRF_parm { - u8 offset; -}; -struct readRF_rsp { - u32 value; -}; - -struct writeRF_parm { - u32 offset; - u32 value; -}; - -struct getrfintfs_parm { - u8 rfintfs; -}; - -struct Tx_Beacon_param { - struct wlan_bssid_ex network; -}; - -/* - Notes: This command is used for H2C/C2H loopback testing - - mac[0] == 0 - ==> CMD mode, return H2C_SUCCESS. - The following condition must be true under CMD mode - mac[1] == mac[4], mac[2] == mac[3], mac[0]=mac[5]= 0; - s0 == 0x1234, s1 == 0xabcd, w0 == 0x78563412, w1 == 0x5aa5def7; - s2 == (b1 << 8 | b0); - - mac[0] == 1 - ==> CMD_RSP mode, return H2C_SUCCESS_RSP - - The rsp layout shall be: - rsp: parm: - mac[0] = mac[5]; - mac[1] = mac[4]; - mac[2] = mac[3]; - mac[3] = mac[2]; - mac[4] = mac[1]; - mac[5] = mac[0]; - s0 = s1; - s1 = swap16(s0); - w0 = swap32(w1); - b0 = b1 - s2 = s0 + s1 - b1 = b0 - w1 = w0 - - mac[0] == 2 - ==> CMD_EVENT mode, return H2C_SUCCESS - The event layout shall be: - event: parm: - mac[0] = mac[5]; - mac[1] = mac[4]; - mac[2] = event's seq no, starting from 1 to parm's marc[3] - mac[3] = mac[2]; - mac[4] = mac[1]; - mac[5] = mac[0]; - s0 = swap16(s0) - event.mac[2]; - s1 = s1 + event.mac[2]; - w0 = swap32(w0); - b0 = b1 - s2 = s0 + event.mac[2] - b1 = b0 - w1 = swap32(w1) - event.mac[2]; - - parm->mac[3] is the total event counts that host requested. - event will be the same with the cmd's param. -*/ - -/* CMD param Format for driver extra cmd handler */ -struct drvextra_cmd_parm { - int ec_id; /* extra cmd id */ - int type_size; /* Can use this field as the type id or command size */ - unsigned char *pbuf; -}; - -/*------------------- Below are used for RF/BB tuning ---------------------*/ - -struct setantenna_parm { - u8 tx_antset; - u8 rx_antset; - u8 tx_antenna; - u8 rx_antenna; -}; - -struct enrateadaptive_parm { - u32 en; -}; - -struct settxagctbl_parm { - u32 txagc[MAX_RATES_LENGTH]; -}; - -struct gettxagctbl_parm { - u32 rsvd; -}; -struct gettxagctbl_rsp { - u32 txagc[MAX_RATES_LENGTH]; -}; - -struct setagcctrl_parm { - u32 agcctrl; /* 0: pure hw, 1: fw */ -}; - -struct setssup_parm { - u32 ss_ForceUp[MAX_RATES_LENGTH]; -}; - -struct getssup_parm { - u32 rsvd; -}; - -struct getssup_rsp { - u8 ss_ForceUp[MAX_RATES_LENGTH]; -}; - -struct setssdlevel_parm { - u8 ss_DLevel[MAX_RATES_LENGTH]; -}; - -struct getssdlevel_parm { - u32 rsvd; -}; - -struct getssdlevel_rsp { - u8 ss_DLevel[MAX_RATES_LENGTH]; -}; - -struct setssulevel_parm { - u8 ss_ULevel[MAX_RATES_LENGTH]; -}; - -struct getssulevel_parm { - u32 rsvd; -}; - -struct getssulevel_rsp { - u8 ss_ULevel[MAX_RATES_LENGTH]; -}; - -struct setcountjudge_parm { - u8 count_judge[MAX_RATES_LENGTH]; -}; - -struct getcountjudge_parm { - u32 rsvd; -}; - -struct getcountjudge_rsp { - u8 count_judge[MAX_RATES_LENGTH]; -}; - -struct setratable_parm { - u8 ss_ForceUp[NumRates]; - u8 ss_ULevel[NumRates]; - u8 ss_DLevel[NumRates]; - u8 count_judge[NumRates]; -}; - -struct getratable_parm { - uint rsvd; -}; - -struct getratable_rsp { - u8 ss_ForceUp[NumRates]; - u8 ss_ULevel[NumRates]; - u8 ss_DLevel[NumRates]; - u8 count_judge[NumRates]; -}; - -/* to get TX,RX retry count */ - -struct gettxretrycnt_parm { - unsigned int rsvd; -}; - -struct gettxretrycnt_rsp { - unsigned long tx_retrycnt; -}; - -struct getrxretrycnt_parm { - unsigned int rsvd; -}; - -struct getrxretrycnt_rsp { - unsigned long rx_retrycnt; -}; - -/* to get BCNOK,BCNERR count */ -struct getbcnokcnt_parm { - unsigned int rsvd; -}; - -struct getbcnokcnt_rsp { - unsigned long bcnokcnt; -}; - -struct getbcnerrcnt_parm { - unsigned int rsvd; -}; - -struct getbcnerrcnt_rsp { - unsigned long bcnerrcnt; -}; - -/* to get current TX power level */ -struct getcurtxpwrlevel_parm { - unsigned int rsvd; -}; -struct getcurtxpwrlevel_rspi { - unsigned short tx_power; -}; - -struct setprobereqextraie_parm { - unsigned char e_id; - unsigned char ie_len; - unsigned char ie[]; -}; - -struct setassocreqextraie_parm { - unsigned char e_id; - unsigned char ie_len; - unsigned char ie[]; -}; - -struct setproberspextraie_parm { - unsigned char e_id; - unsigned char ie_len; - unsigned char ie[]; -}; - -struct setassocrspextraie_parm { - unsigned char e_id; - unsigned char ie_len; - unsigned char ie[]; -}; - -struct addBaReq_parm { - unsigned int tid; - u8 addr[ETH_ALEN]; -}; - -/*H2C Handler index: 46 */ -struct set_ch_parm { - u8 ch; - u8 bw; - u8 ch_offset; -}; - -/*H2C Handler index: 59 */ -struct SetChannelPlan_param { - u8 channel_plan; -}; - -/*H2C Handler index: 60 */ -struct LedBlink_param { - struct LED_871x *pLed; -}; - -/*H2C Handler index: 61 */ -struct SetChannelSwitch_param { - u8 new_ch_no; -}; - -/*H2C Handler index: 62 */ -struct TDLSoption_param { - u8 addr[ETH_ALEN]; - u8 option; -}; - -#define GEN_CMD_CODE(cmd) cmd ## _CMD_ - -/* - -Result: -0x00: success -0x01: success, and check Response. -0x02: cmd ignored due to duplicated sequcne number -0x03: cmd dropped due to invalid cmd code -0x04: reserved. - -*/ - -#define H2C_RSP_OFFSET 512 - -#define H2C_SUCCESS 0x00 -#define H2C_SUCCESS_RSP 0x01 -#define H2C_DUPLICATED 0x02 -#define H2C_DROPPED 0x03 -#define H2C_PARAMETERS_ERROR 0x04 -#define H2C_REJECTED 0x05 -#define H2C_CMD_OVERFLOW 0x06 -#define H2C_RESERVED 0x07 - -u8 rtw_sitesurvey_cmd(struct adapter *padapter, struct ndis_802_11_ssid *ssid, int ssid_num); -u8 rtw_createbss_cmd(struct adapter *padapter); -u8 rtw_setstakey_cmd(struct adapter *padapter, u8 *psta, u8 unicast_key); -u8 rtw_clearstakey_cmd(struct adapter *padapter, u8 *psta, u8 entry, u8 enqueue); -u8 rtw_joinbss_cmd(struct adapter *padapter, struct wlan_network *pnetwork); -u8 rtw_disassoc_cmd(struct adapter *padapter, u32 deauth_timeout_ms, bool enqueue); -u8 rtw_setopmode_cmd(struct adapter *padapter, enum ndis_802_11_network_infra networktype); -int rtw_setdatarate_cmd(struct adapter *padapter, u8 *rateset); -u8 rtw_setrfintfs_cmd(struct adapter *padapter, u8 mode); - -u8 rtw_gettssi_cmd(struct adapter *padapter, u8 offset, u8 *pval); -u8 rtw_setfwdig_cmd(struct adapter *padapter, u8 type); -u8 rtw_setfwra_cmd(struct adapter *padapter, u8 type); - -u8 rtw_addbareq_cmd(struct adapter *padapter, u8 tid, u8 *addr); - -u8 rtw_dynamic_chk_wk_cmd(struct adapter *adapter); - -u8 rtw_lps_ctrl_wk_cmd(struct adapter *padapter, u8 lps_ctrl_type, u8 enqueue); -u8 rtw_rpt_timer_cfg_cmd(struct adapter *padapter, u16 minRptTime); - -u8 rtw_antenna_select_cmd(struct adapter *padapter, u8 antenna, u8 enqueue); -u8 rtw_ps_cmd(struct adapter *padapter); - -void rtw_chk_hi_queue_cmd(struct adapter *padapter); - -u8 rtw_set_chplan_cmd(struct adapter *padapter, u8 chplan); - -u8 rtw_c2h_wk_cmd(struct adapter *padapter, u8 *c2h_evt); - -u8 rtw_drvextra_cmd_hdl(struct adapter *padapter, unsigned char *pbuf); - -void rtw_survey_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd); -void rtw_disassoc_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd); -void rtw_joinbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd); -void rtw_createbss_cmd_callback(struct adapter *adapt, struct cmd_obj *pcmd); -void rtw_getbbrfreg_cmdrsp_callback(struct adapter *adapt, struct cmd_obj *cmd); - -void rtw_setstaKey_cmdrsp_callback(struct adapter *adapt, struct cmd_obj *cmd); -void rtw_setassocsta_cmdrsp_callback(struct adapter *adapt, struct cmd_obj *cm); -void rtw_getrttbl_cmdrsp_callback(struct adapter *adapt, struct cmd_obj *cmd); - -struct _cmd_callback { - u32 cmd_code; - void (*callback)(struct adapter *padapter, struct cmd_obj *cmd); -}; - -enum rtw_h2c_cmd { - GEN_CMD_CODE(_Read_MACREG), /*0*/ - GEN_CMD_CODE(_Write_MACREG), - GEN_CMD_CODE(_Read_BBREG), - GEN_CMD_CODE(_Write_BBREG), - GEN_CMD_CODE(_Read_RFREG), - GEN_CMD_CODE(_Write_RFREG), /*5*/ - GEN_CMD_CODE(_Read_EEPROM), - GEN_CMD_CODE(_Write_EEPROM), - GEN_CMD_CODE(_Read_EFUSE), - GEN_CMD_CODE(_Write_EFUSE), - - GEN_CMD_CODE(_Read_CAM), /*10*/ - GEN_CMD_CODE(_Write_CAM), - GEN_CMD_CODE(_setBCNITV), - GEN_CMD_CODE(_setMBIDCFG), - GEN_CMD_CODE(_JoinBss), /*14*/ - GEN_CMD_CODE(_DisConnect), /*15*/ - GEN_CMD_CODE(_CreateBss), - GEN_CMD_CODE(_SetOpMode), - GEN_CMD_CODE(_SiteSurvey), /*18*/ - GEN_CMD_CODE(_SetAuth), - - GEN_CMD_CODE(_SetKey), /*20*/ - GEN_CMD_CODE(_SetStaKey), - GEN_CMD_CODE(_SetAssocSta), - GEN_CMD_CODE(_DelAssocSta), - GEN_CMD_CODE(_SetStaPwrState), - GEN_CMD_CODE(_SetBasicRate), /*25*/ - GEN_CMD_CODE(_GetBasicRate), - GEN_CMD_CODE(_SetDataRate), - GEN_CMD_CODE(_GetDataRate), - GEN_CMD_CODE(_SetPhyInfo), - - GEN_CMD_CODE(_GetPhyInfo), /*30*/ - GEN_CMD_CODE(_SetPhy), - GEN_CMD_CODE(_GetPhy), - GEN_CMD_CODE(_readRssi), - GEN_CMD_CODE(_readGain), - GEN_CMD_CODE(_SetAtim), /*35*/ - GEN_CMD_CODE(_SetPwrMode), - GEN_CMD_CODE(_JoinbssRpt), - GEN_CMD_CODE(_SetRaTable), - GEN_CMD_CODE(_GetRaTable), - - GEN_CMD_CODE(_GetCCXReport), /*40*/ - GEN_CMD_CODE(_GetDTMReport), - GEN_CMD_CODE(_GetTXRateStatistics), - GEN_CMD_CODE(_SetUsbSuspend), - GEN_CMD_CODE(_SetH2cLbk), - GEN_CMD_CODE(_AddBAReq), /*45*/ - GEN_CMD_CODE(_SetChannel), /*46*/ - GEN_CMD_CODE(_SetTxPower), - GEN_CMD_CODE(_SwitchAntenna), - GEN_CMD_CODE(_SetCrystalCap), - GEN_CMD_CODE(_SetSingleCarrierTx), /*50*/ - - GEN_CMD_CODE(_SetSingleToneTx),/*51*/ - GEN_CMD_CODE(_SetCarrierSuppressionTx), - GEN_CMD_CODE(_SetContinuousTx), - GEN_CMD_CODE(_SwitchBandwidth), /*54*/ - GEN_CMD_CODE(_TX_Beacon), /*55*/ - - GEN_CMD_CODE(_Set_MLME_EVT), /*56*/ - GEN_CMD_CODE(_Set_Drv_Extra), /*57*/ - GEN_CMD_CODE(_Set_H2C_MSG), /*58*/ - - GEN_CMD_CODE(_SetChannelPlan), /*59*/ - GEN_CMD_CODE(_LedBlink), /*60*/ - - GEN_CMD_CODE(_SetChannelSwitch), /*61*/ - GEN_CMD_CODE(_TDLS), /*62*/ - - MAX_H2CCMD -}; - -#define _GetBBReg_CMD_ _Read_BBREG_CMD_ -#define _SetBBReg_CMD_ _Write_BBREG_CMD_ -#define _GetRFReg_CMD_ _Read_RFREG_CMD_ -#define _SetRFReg_CMD_ _Write_RFREG_CMD_ - -#ifdef _RTW_CMD_C_ -static struct _cmd_callback rtw_cmd_callback[] = { - {GEN_CMD_CODE(_Read_MACREG), NULL}, /*0*/ - {GEN_CMD_CODE(_Write_MACREG), NULL}, - {GEN_CMD_CODE(_Read_BBREG), &rtw_getbbrfreg_cmdrsp_callback}, - {GEN_CMD_CODE(_Write_BBREG), NULL}, - {GEN_CMD_CODE(_Read_RFREG), &rtw_getbbrfreg_cmdrsp_callback}, - {GEN_CMD_CODE(_Write_RFREG), NULL}, /*5*/ - {GEN_CMD_CODE(_Read_EEPROM), NULL}, - {GEN_CMD_CODE(_Write_EEPROM), NULL}, - {GEN_CMD_CODE(_Read_EFUSE), NULL}, - {GEN_CMD_CODE(_Write_EFUSE), NULL}, - - {GEN_CMD_CODE(_Read_CAM), NULL}, /*10*/ - {GEN_CMD_CODE(_Write_CAM), NULL}, - {GEN_CMD_CODE(_setBCNITV), NULL}, - {GEN_CMD_CODE(_setMBIDCFG), NULL}, - {GEN_CMD_CODE(_JoinBss), &rtw_joinbss_cmd_callback}, /*14*/ - {GEN_CMD_CODE(_DisConnect), &rtw_disassoc_cmd_callback}, /*15*/ - {GEN_CMD_CODE(_CreateBss), &rtw_createbss_cmd_callback}, - {GEN_CMD_CODE(_SetOpMode), NULL}, - {GEN_CMD_CODE(_SiteSurvey), &rtw_survey_cmd_callback}, /*18*/ - {GEN_CMD_CODE(_SetAuth), NULL}, - - {GEN_CMD_CODE(_SetKey), NULL}, /*20*/ - {GEN_CMD_CODE(_SetStaKey), &rtw_setstaKey_cmdrsp_callback}, - {GEN_CMD_CODE(_SetAssocSta), &rtw_setassocsta_cmdrsp_callback}, - {GEN_CMD_CODE(_DelAssocSta), NULL}, - {GEN_CMD_CODE(_SetStaPwrState), NULL}, - {GEN_CMD_CODE(_SetBasicRate), NULL}, /*25*/ - {GEN_CMD_CODE(_GetBasicRate), NULL}, - {GEN_CMD_CODE(_SetDataRate), NULL}, - {GEN_CMD_CODE(_GetDataRate), NULL}, - {GEN_CMD_CODE(_SetPhyInfo), NULL}, - - {GEN_CMD_CODE(_GetPhyInfo), NULL}, /*30*/ - {GEN_CMD_CODE(_SetPhy), NULL}, - {GEN_CMD_CODE(_GetPhy), NULL}, - {GEN_CMD_CODE(_readRssi), NULL}, - {GEN_CMD_CODE(_readGain), NULL}, - {GEN_CMD_CODE(_SetAtim), NULL}, /*35*/ - {GEN_CMD_CODE(_SetPwrMode), NULL}, - {GEN_CMD_CODE(_JoinbssRpt), NULL}, - {GEN_CMD_CODE(_SetRaTable), NULL}, - {GEN_CMD_CODE(_GetRaTable), NULL}, - - {GEN_CMD_CODE(_GetCCXReport), NULL}, /*40*/ - {GEN_CMD_CODE(_GetDTMReport), NULL}, - {GEN_CMD_CODE(_GetTXRateStatistics), NULL}, - {GEN_CMD_CODE(_SetUsbSuspend), NULL}, - {GEN_CMD_CODE(_SetH2cLbk), NULL}, - {GEN_CMD_CODE(_AddBAReq), NULL}, /*45*/ - {GEN_CMD_CODE(_SetChannel), NULL}, /*46*/ - {GEN_CMD_CODE(_SetTxPower), NULL}, - {GEN_CMD_CODE(_SwitchAntenna), NULL}, - {GEN_CMD_CODE(_SetCrystalCap), NULL}, - {GEN_CMD_CODE(_SetSingleCarrierTx), NULL}, /*50*/ - - {GEN_CMD_CODE(_SetSingleToneTx), NULL}, /*51*/ - {GEN_CMD_CODE(_SetCarrierSuppressionTx), NULL}, - {GEN_CMD_CODE(_SetContinuousTx), NULL}, - {GEN_CMD_CODE(_SwitchBandwidth), NULL}, /*54*/ - {GEN_CMD_CODE(_TX_Beacon), NULL},/*55*/ - - {GEN_CMD_CODE(_Set_MLME_EVT), NULL},/*56*/ - {GEN_CMD_CODE(_Set_Drv_Extra), NULL},/*57*/ - {GEN_CMD_CODE(_Set_H2C_MSG), NULL},/*58*/ - {GEN_CMD_CODE(_SetChannelPlan), NULL},/*59*/ - {GEN_CMD_CODE(_LedBlink), NULL},/*60*/ - - {GEN_CMD_CODE(_SetChannelSwitch), NULL},/*61*/ - {GEN_CMD_CODE(_TDLS), NULL},/*62*/ -}; -#endif - -#endif /* _CMD_H_ */ diff --git a/drivers/staging/r8188eu/include/rtw_eeprom.h b/drivers/staging/r8188eu/include/rtw_eeprom.h deleted file mode 100644 index 94d735b1d0db..000000000000 --- a/drivers/staging/r8188eu/include/rtw_eeprom.h +++ /dev/null @@ -1,15 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#ifndef __RTW_EEPROM_H__ -#define __RTW_EEPROM_H__ - -#include "osdep_service.h" -#include "drv_types.h" - -struct eeprom_priv { - u8 bautoload_fail_flag; - u8 mac_addr[ETH_ALEN] __aligned(2); /* PermanentAddress */ -}; - -#endif /* __RTL871X_EEPROM_H__ */ diff --git a/drivers/staging/r8188eu/include/rtw_efuse.h b/drivers/staging/r8188eu/include/rtw_efuse.h deleted file mode 100644 index 3d688a0e6dfb..000000000000 --- a/drivers/staging/r8188eu/include/rtw_efuse.h +++ /dev/null @@ -1,11 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#ifndef __RTW_EFUSE_H__ -#define __RTW_EFUSE_H__ - -#define EFUSE_MAX_WORD_UNIT 4 - -void ReadEFuseByte(struct adapter *adapter, u16 _offset, u8 *pbuf); - -#endif diff --git a/drivers/staging/r8188eu/include/rtw_event.h b/drivers/staging/r8188eu/include/rtw_event.h deleted file mode 100644 index 54dc1ea437fc..000000000000 --- a/drivers/staging/r8188eu/include/rtw_event.h +++ /dev/null @@ -1,97 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#ifndef _RTW_EVENT_H_ -#define _RTW_EVENT_H_ - -#include "osdep_service.h" - -#include "wlan_bssdef.h" -#include -#include - -/* -Used to report a bss has been scanned -*/ -struct survey_event { - struct wlan_bssid_ex bss; -}; - -/* -Used to report that the requested site survey has been done. - -bss_cnt indicates the number of bss that has been reported. - -*/ -struct surveydone_event { - unsigned int bss_cnt; - -}; - -/* -Used to report the link result of joinning the given bss - -join_res: --1: authentication fail --2: association fail -> 0: TID - -*/ -struct joinbss_event { - struct wlan_network network; -}; - -/* -Used to report a given STA has joinned the created BSS. -It is used in AP/Ad-HoC(M) mode. -*/ - -struct stassoc_event { - unsigned char macaddr[6]; - unsigned char rsvd[2]; - int cam_id; -}; - -struct stadel_event { - unsigned char macaddr[6]; - unsigned char rsvd[2]; /* for reason */ - int mac_id; -}; - -struct addba_event { - unsigned int tid; -}; - -#define GEN_EVT_CODE(event) event ## _EVT_ - -struct fwevent { - u32 parmsize; - void (*event_callback)(struct adapter *dev, u8 *pbuf); -}; - -#define C2HEVENT_SZ 32 - -struct event_node { - unsigned char *node; - unsigned char evt_code; - unsigned short evt_sz; - int *caller_ff_tail; - int caller_ff_sz; -}; - -struct c2hevent_queue { - int head; - int tail; - struct event_node nodes[C2HEVENT_SZ]; - unsigned char seq; -}; - -#define NETWORK_QUEUE_SZ 4 - -struct network_queue { - int head; - int tail; - struct wlan_bssid_ex networks[NETWORK_QUEUE_SZ]; -}; - -#endif /* _WLANEVENT_H_ */ diff --git a/drivers/staging/r8188eu/include/rtw_fw.h b/drivers/staging/r8188eu/include/rtw_fw.h deleted file mode 100644 index 8f74157ee9ac..000000000000 --- a/drivers/staging/r8188eu/include/rtw_fw.h +++ /dev/null @@ -1,17 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#ifndef __RTW_FW_H__ -#define __RTW_FW_H__ - -struct rt_firmware { - u8 *data; - u32 size; -}; - -#include "drv_types.h" - -int rtl8188e_firmware_download(struct adapter *padapter); -void rtw_reset_8051(struct adapter *padapter); - -#endif diff --git a/drivers/staging/r8188eu/include/rtw_ht.h b/drivers/staging/r8188eu/include/rtw_ht.h deleted file mode 100644 index 2b56b7c38c86..000000000000 --- a/drivers/staging/r8188eu/include/rtw_ht.h +++ /dev/null @@ -1,28 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#ifndef _RTW_HT_H_ -#define _RTW_HT_H_ - -#include "osdep_service.h" -#include "wifi.h" - -struct ht_priv { - u32 ht_option; - u32 ampdu_enable;/* for enable Tx A-MPDU */ - u32 tx_amsdu_enable;/* for enable Tx A-MSDU */ - u32 tx_amdsu_maxlen; /* 1: 8k, 0:4k ; default:8k, for tx */ - u32 rx_ampdu_maxlen; /* for rx reordering ctrl win_sz, - * updated when join_callback. */ - u8 bwmode;/* */ - u8 ch_offset;/* PRIME_CHNL_OFFSET */ - u8 sgi;/* short GI */ - - /* for processing Tx A-MPDU */ - u8 agg_enable_bitmap; - u8 candidate_tid_bitmap; - - struct ieee80211_ht_cap ht_cap; -}; - -#endif /* _RTL871X_HT_H_ */ diff --git a/drivers/staging/r8188eu/include/rtw_io.h b/drivers/staging/r8188eu/include/rtw_io.h deleted file mode 100644 index e1718f739cc9..000000000000 --- a/drivers/staging/r8188eu/include/rtw_io.h +++ /dev/null @@ -1,33 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#ifndef _RTW_IO_H_ -#define _RTW_IO_H_ - -#include "osdep_service.h" -#include "osdep_intf.h" - -#include -#include -#include -#include -#include - -#include -#include - -int __must_check rtw_read8(struct adapter *adapter, u32 addr, u8 *data); -int __must_check rtw_read16(struct adapter *adapter, u32 addr, u16 *data); -int __must_check rtw_read32(struct adapter *adapter, u32 addr, u32 *data); -int rtw_read_port(struct adapter *adapter, struct recv_buf *precvbuf); -void rtw_read_port_cancel(struct adapter *adapter); - -int rtw_write8(struct adapter *adapter, u32 addr, u8 val); -int rtw_write16(struct adapter *adapter, u32 addr, u16 val); -int rtw_write32(struct adapter *adapter, u32 addr, u32 val); -int rtw_writeN(struct adapter *adapter, u32 addr, u32 length, u8 *pdata); - -u32 rtw_write_port(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem); -void rtw_write_port_cancel(struct adapter *adapter); - -#endif /* _RTL8711_IO_H_ */ diff --git a/drivers/staging/r8188eu/include/rtw_ioctl.h b/drivers/staging/r8188eu/include/rtw_ioctl.h deleted file mode 100644 index c704f3040ac8..000000000000 --- a/drivers/staging/r8188eu/include/rtw_ioctl.h +++ /dev/null @@ -1,13 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#ifndef _RTW_IOCTL_H_ -#define _RTW_IOCTL_H_ - -#include "osdep_service.h" -#include "drv_types.h" - -extern struct iw_handler_def rtw_handlers_def; -extern int ui_pid[3]; - -#endif /* #ifndef __INC_CEINFO_ */ diff --git a/drivers/staging/r8188eu/include/rtw_ioctl_set.h b/drivers/staging/r8188eu/include/rtw_ioctl_set.h deleted file mode 100644 index c3eb2479f27b..000000000000 --- a/drivers/staging/r8188eu/include/rtw_ioctl_set.h +++ /dev/null @@ -1,25 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#ifndef __RTW_IOCTL_SET_H_ -#define __RTW_IOCTL_SET_H_ - -#include "drv_types.h" - -typedef u8 NDIS_802_11_PMKID_VALUE[16]; - -u8 rtw_set_802_11_authentication_mode(struct adapter *adapt, - enum ndis_802_11_auth_mode authmode); -u8 rtw_set_802_11_bssid(struct adapter *adapter, u8 *bssid); -u8 rtw_set_802_11_add_wep(struct adapter *adapter, struct ndis_802_11_wep *wep); -void rtw_set_802_11_disassociate(struct adapter *adapter); -u8 rtw_set_802_11_bssid_list_scan(struct adapter *adapter, - struct ndis_802_11_ssid *pssid, - int ssid_max_num); -u8 rtw_set_802_11_infrastructure_mode(struct adapter *adapter, - enum ndis_802_11_network_infra type); -u8 rtw_set_802_11_ssid(struct adapter *adapt, struct ndis_802_11_ssid *ssid); -u16 rtw_get_cur_max_rate(struct adapter *adapter); -int rtw_change_ifname(struct adapter *padapter, const char *ifname); - -#endif diff --git a/drivers/staging/r8188eu/include/rtw_iol.h b/drivers/staging/r8188eu/include/rtw_iol.h deleted file mode 100644 index 099f5a075274..000000000000 --- a/drivers/staging/r8188eu/include/rtw_iol.h +++ /dev/null @@ -1,55 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#ifndef __RTW_IOL_H_ -#define __RTW_IOL_H_ - -#include "osdep_service.h" -#include "drv_types.h" - -#define IOREG_CMD_END_LEN 4 - -struct ioreg_cfg { - u8 length; - u8 cmd_id; - __le16 address; - __le32 data; - __le32 mask; -}; - -enum ioreg_cmd { - IOREG_CMD_LLT = 0x01, - IOREG_CMD_REFUSE = 0x02, - IOREG_CMD_EFUSE_PATH = 0x03, - IOREG_CMD_WB_REG = 0x04, - IOREG_CMD_WW_REG = 0x05, - IOREG_CMD_WD_REG = 0x06, - IOREG_CMD_W_RF = 0x07, - IOREG_CMD_DELAY_US = 0x10, - IOREG_CMD_DELAY_MS = 0x11, - IOREG_CMD_END = 0xFF, -}; - -struct xmit_frame *rtw_IOL_accquire_xmit_frame(struct adapter *adapter); -int rtw_IOL_append_cmds(struct xmit_frame *xmit_frame, u8 *IOL_cmds, - u32 cmd_len); -bool rtw_IOL_applied(struct adapter *adapter); -int rtw_IOL_append_DELAY_US_cmd(struct xmit_frame *xmit_frame, u16 us); -int rtw_IOL_append_DELAY_MS_cmd(struct xmit_frame *xmit_frame, u16 ms); -int rtw_IOL_append_END_cmd(struct xmit_frame *xmit_frame); - -void read_efuse_from_txpktbuf(struct adapter *adapter, int bcnhead, - u8 *content, u16 *size); - -int rtw_IOL_append_WB_cmd(struct xmit_frame *xmit_frame, u16 addr, - u8 value, u8 mask); -int rtw_IOL_append_WW_cmd(struct xmit_frame *xmit_frame, u16 addr, - u16 value, u16 mask); -int rtw_IOL_append_WD_cmd(struct xmit_frame *xmit_frame, u16 addr, - u32 value, u32 mask); -int rtw_IOL_append_WRF_cmd(struct xmit_frame *xmit_frame, u8 rf_path, - u16 addr, u32 value, u32 mask); - -u8 rtw_IOL_cmd_boundary_handle(struct xmit_frame *pxmit_frame); - -#endif /* __RTW_IOL_H_ */ diff --git a/drivers/staging/r8188eu/include/rtw_led.h b/drivers/staging/r8188eu/include/rtw_led.h deleted file mode 100644 index ea5f5edd9013..000000000000 --- a/drivers/staging/r8188eu/include/rtw_led.h +++ /dev/null @@ -1,57 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#ifndef __RTW_LED_H_ -#define __RTW_LED_H_ - -#include "osdep_service.h" -#include "drv_types.h" - -enum LED_CTL_MODE { - LED_CTL_LINK = 2, - LED_CTL_NO_LINK = 3, - LED_CTL_TX = 4, - LED_CTL_RX = 5, - LED_CTL_SITE_SURVEY = 6, - LED_CTL_POWER_OFF = 7, - LED_CTL_START_TO_LINK = 8, - LED_CTL_START_WPS = 9, - LED_CTL_STOP_WPS = 10, - LED_CTL_STOP_WPS_FAIL = 12, -}; - -enum LED_STATE_871x { - RTW_LED_OFF = 2, - LED_BLINK_NORMAL = 3, - LED_BLINK_SLOWLY = 4, - LED_BLINK_SCAN = 6, /* LED is blinking during scanning period, - * the # of times to blink is depend on time - * for scanning. */ - LED_BLINK_TXRX = 9, - LED_BLINK_WPS = 10, /* LED is blinkg during WPS communication */ - LED_BLINK_WPS_STOP = 11, -}; - -struct led_priv { - bool bRegUseLed; - - enum LED_STATE_871x CurrLedState; /* Current LED state. */ - - bool bLedOn; /* true if LED is ON, false if LED is OFF. */ - - bool bLedBlinkInProgress; /* true if it is blinking, false o.w.. */ - - bool bLedWPSBlinkInProgress; - - u32 BlinkTimes; /* Number of times to toggle led state for blinking. */ - - bool bLedScanBlinkInProgress; - struct delayed_work blink_work; -}; - -void rtl8188eu_InitSwLeds(struct adapter *padapter); -void rtl8188eu_DeInitSwLeds(struct adapter *padapter); - -void rtw_led_control(struct adapter *padapter, enum LED_CTL_MODE LedAction); - -#endif /* __RTW_LED_H_ */ diff --git a/drivers/staging/r8188eu/include/rtw_mlme.h b/drivers/staging/r8188eu/include/rtw_mlme.h deleted file mode 100644 index 3ff653ff1d81..000000000000 --- a/drivers/staging/r8188eu/include/rtw_mlme.h +++ /dev/null @@ -1,574 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#ifndef __RTW_MLME_H_ -#define __RTW_MLME_H_ - -#include "osdep_service.h" -#include "drv_types.h" -#include "wlan_bssdef.h" - -#define MAX_BSS_CNT 128 -#define MAX_JOIN_TIMEOUT 6500 - -/* Increase the scanning timeout because of increasing the SURVEY_TO value. */ - -#define SCANNING_TIMEOUT 8000 - -#define SCAN_INTERVAL (30) /* unit:2sec, 30*2=60sec */ - -#define SCANQUEUE_LIFETIME 20 /* unit:sec */ - -#define WIFI_NULL_STATE 0x00000000 - -#define WIFI_ASOC_STATE 0x00000001 /* Under Linked state */ -#define WIFI_REASOC_STATE 0x00000002 -#define WIFI_SLEEP_STATE 0x00000004 -#define WIFI_STATION_STATE 0x00000008 - -#define WIFI_AP_STATE 0x00000010 -#define WIFI_ADHOC_STATE 0x00000020 -#define WIFI_ADHOC_MASTER_STATE 0x00000040 -#define WIFI_UNDER_LINKING 0x00000080 - -#define WIFI_UNDER_WPS 0x00000100 -#define WIFI_STA_ALIVE_CHK_STATE 0x00000400 -#define WIFI_SITE_MONITOR 0x00000800 /* to indicate the station is under site surveying */ - -#define WIFI_MP_STATE 0x00010000 -#define WIFI_MP_CTX_BACKGROUND 0x00020000 /* in continuous tx background */ -#define WIFI_MP_CTX_ST 0x00040000 /* in continuous tx with single-tone */ -#define WIFI_MP_CTX_BACKGROUND_PENDING 0x00080000 /* pending in continuous tx background due to out of skb */ -#define WIFI_MP_CTX_CCK_HW 0x00100000 /* in continuous tx */ -#define WIFI_MP_CTX_CCK_CS 0x00200000 /* in continuous tx with carrier suppression */ -#define WIFI_MP_LPBK_STATE 0x00400000 - -#define _FW_UNDER_LINKING WIFI_UNDER_LINKING -#define _FW_LINKED WIFI_ASOC_STATE -#define _FW_UNDER_SURVEY WIFI_SITE_MONITOR - -enum dot11AuthAlgrthmNum { - dot11AuthAlgrthm_Open = 0, - dot11AuthAlgrthm_Shared, - dot11AuthAlgrthm_8021X, - dot11AuthAlgrthm_Auto, - dot11AuthAlgrthm_WAPI, - dot11AuthAlgrthm_MaxNum -}; - -/* Scan type including active and passive scan. */ -enum rt_scan_type { - SCAN_PASSIVE, - SCAN_ACTIVE, - SCAN_MIX, -}; - -/* -there are several "locks" in mlme_priv, -since mlme_priv is a shared resource between many threads, -like ISR/Call-Back functions, the OID handlers, and even timer functions. - -Each _queue has its own locks, already. -Other items are protected by mlme_priv.lock. - -To avoid possible dead lock, any thread trying to modifiying mlme_priv -SHALL not lock up more than one lock at a time! -*/ - -#define traffic_threshold 10 -#define traffic_scan_period 500 - -struct sitesurvey_ctrl { - u64 last_tx_pkts; - uint last_rx_pkts; - int traffic_busy; - struct timer_list sitesurvey_ctrl_timer; -}; - -struct rt_link_detect { - u32 NumTxOkInPeriod; - u32 NumRxOkInPeriod; - u32 NumRxUnicastOkInPeriod; - bool bBusyTraffic; - bool bTxBusyTraffic; - bool bRxBusyTraffic; - bool bHigherBusyTraffic; /* For interrupt migration purpose. */ - bool bHigherBusyRxTraffic; /* We may disable Tx interrupt according - * to Rx traffic. */ - bool bHigherBusyTxTraffic; /* We may disable Tx interrupt according - * to Tx traffic. */ -}; - -struct profile_info { - u8 ssidlen; - u8 ssid[WLAN_SSID_MAXLEN]; - u8 peermac[ETH_ALEN]; -}; - -struct tx_invite_req_info { - u8 token; - u8 benable; - u8 go_ssid[WLAN_SSID_MAXLEN]; - u8 ssidlen; - u8 go_bssid[ETH_ALEN]; - u8 peer_macaddr[ETH_ALEN]; - u8 operating_ch; /* This information will be set by using the - * p2p_set op_ch=x */ - u8 peer_ch; /* The listen channel for peer P2P device */ -}; - -struct tx_invite_resp_info { - u8 token; /* Used to record the dialog token of p2p invitation - * request frame. */ -}; - -struct tx_provdisc_req_info { - u16 wps_config_method_request; /* Used when sending the - * provisioning request frame*/ - u16 peer_channel_num[2]; /* The channel number which the - * receiver stands. */ - struct ndis_802_11_ssid ssid; - u8 peerDevAddr[ETH_ALEN]; /* Peer device address */ - u8 peerIFAddr[ETH_ALEN]; /* Peer interface address */ - u8 benable; /* This provision discovery - * request frame is trigger - * to send or not */ -}; - -/* When peer device issue prov_disc_req first, we should store the following - * information */ -/* The UI must know this information to know which config method the - * remote p2p device needs. */ -struct rx_provdisc_req_info { - u8 peerDevAddr[ETH_ALEN]; /* Peer device address */ - u8 strconfig_method_desc_of_prov_disc_req[4]; /* description - * for the config method located in the provisioning - * discovery request frame. */ -}; - -struct tx_nego_req_info { - u16 peer_channel_num[2]; /* The channel number. */ - u8 peerDevAddr[ETH_ALEN]; /* Peer device address */ - u8 benable; /* This negotiation request frame is - * trigger to send or not */ -}; - -struct group_id_info { - u8 go_device_addr[ETH_ALEN]; /* The GO's device address of - * this P2P group */ - u8 ssid[WLAN_SSID_MAXLEN]; /* The SSID of this P2P group */ -}; - -struct scan_limit_info { - u8 scan_op_ch_only; /* When this flag is set, the driver - * should only scan the op. channel */ - u8 operation_ch[2]; /* Store the op. chan of invitation */ -}; - -struct wifidirect_info { - struct adapter *padapter; - struct timer_list find_phase_timer; - struct timer_list restore_p2p_state_timer; - - /* Used to do the scanning. After confirming the peer is availalble, - * the driver transmits the P2P frame to peer. */ - struct timer_list pre_tx_scan_timer; - struct timer_list reset_ch_sitesurvey; - struct timer_list reset_ch_sitesurvey2; /* Just for resetting the scan - * limit function by using p2p nego */ - struct tx_provdisc_req_info tx_prov_disc_info; - struct rx_provdisc_req_info rx_prov_disc_info; - struct tx_invite_req_info invitereq_info; - /* Store the profile information of persistent group */ - struct profile_info profileinfo[P2P_MAX_PERSISTENT_GROUP_NUM]; - struct tx_invite_resp_info inviteresp_info; - struct tx_nego_req_info nego_req_info; - /* Store the group id info when doing the group negot handshake. */ - struct group_id_info groupid_info; - /* Used for get the limit scan channel from the Invitation procedure */ - struct scan_limit_info rx_invitereq_info; - /* Used for get the limit scan chan from the P2P negotiation handshake*/ - struct scan_limit_info p2p_info; - enum P2P_ROLE role; - enum P2P_STATE pre_p2p_state; - enum P2P_STATE p2p_state; - /* The device address should be the mac address of this device. */ - u8 device_addr[ETH_ALEN]; - u8 interface_addr[ETH_ALEN]; - u8 social_chan[4]; - u8 listen_channel; - u8 operating_channel; - u8 listen_dwell; /* This value should be between 1 and 3 */ - u8 support_rate[8]; - u8 p2p_wildcard_ssid[P2P_WILDCARD_SSID_LEN]; - u8 intent; /* should only include the intent value. */ - u8 p2p_peer_interface_addr[ETH_ALEN]; - u8 p2p_peer_device_addr[ETH_ALEN]; - u8 peer_intent; /* Included the intent value and tie breaker value. */ - /* Device name for displaying on searching device screen */ - u8 device_name[WPS_MAX_DEVICE_NAME_LEN]; - u8 device_name_len; - u8 profileindex; /* Used to point to the index of profileinfo array */ - u8 peer_operating_ch; - u8 find_phase_state_exchange_cnt; - /* The device password ID for group negotiation */ - u16 device_password_id_for_nego; - u8 negotiation_dialog_token; - /* SSID information for group negotitation */ - u8 nego_ssid[WLAN_SSID_MAXLEN]; - u8 nego_ssidlen; - u8 p2p_group_ssid[WLAN_SSID_MAXLEN]; - u8 p2p_group_ssid_len; - /* Flag to know if the persistent function should be supported or not.*/ - u8 persistent_supported; - /* In the Sigma test, the Sigma will provide this enable from the - * sta_set_p2p CAPI. */ - /* 0: disable */ - /* 1: enable */ - u8 session_available; /* Flag to set the WFD session available to - * enable or disable "by Sigma" */ - /* In the Sigma test, the Sigma will disable the session available - * by using the sta_preset CAPI. */ - /* 0: disable */ - /* 1: enable */ - - /* This field will store the WPS value (PIN value or PBC) that UI had - * got from the user. */ - enum P2P_WPSINFO ui_got_wps_info; - u16 supported_wps_cm; /* This field describes the WPS config method - * which this driver supported. */ - /* The value should be the combination of config - * method defined in page104 of WPS v2.0 spec.*/ - /* This field will contain the length of body of P2P Channel List - * attribute of group negotiation response frame. */ - uint channel_list_attr_len; - /* This field will contain the body of P2P Channel List attribute of - * group negotitation response frame. */ - /* We will use the channel_cnt and channel_list fields when constructing - * the group negotiation confirm frame. */ - u8 channel_list_attr[100]; - enum P2P_PS_MODE p2p_ps_mode; /* indicate p2p ps mode */ - enum P2P_PS_STATE p2p_ps_state; /* indicate p2p ps state */ - u8 noa_index; /* Identifies and instance of Notice of Absence timing. */ - u8 ctwindow; /* Client traffic window. A period of time in TU after TBTT. */ - u8 opp_ps; /* opportunistic power save. */ - u8 noa_num; /* number of NoA descriptor in P2P IE. */ - u8 noa_count[P2P_MAX_NOA_NUM]; /* Count for owner, Type of client. */ - /* Max duration for owner, preferred or min acceptable duration for - * client. */ - u32 noa_duration[P2P_MAX_NOA_NUM]; - /* Length of interval for owner, preferred or max acceptable interval - * of client. */ - u32 noa_interval[P2P_MAX_NOA_NUM]; - /* schedule expressed in terms of the lower 4 bytes of the TSF timer. */ - u32 noa_start_time[P2P_MAX_NOA_NUM]; -}; - -struct tdls_ss_record { /* signal strength record */ - u8 macaddr[ETH_ALEN]; - u8 RxPWDBAll; - u8 is_tdls_sta; /* true: direct link sta, false: else */ -}; - -struct tdls_info { - u8 ap_prohibited; - uint setup_state; - u8 sta_cnt; - u8 sta_maximum; /* 1:tdls sta is equal (NUM_STA-1), reach max direct link number; 0: else; */ - struct tdls_ss_record ss_record; - u8 macid_index; /* macid entry that is ready to write */ - u8 clear_cam; /* cam entry that is trying to clear, using it in direct link teardown */ - u8 ch_sensing; - u8 cur_channel; - u8 candidate_ch; - u8 collect_pkt_num[MAX_CHANNEL_NUM]; - spinlock_t cmd_lock; - spinlock_t hdl_lock; - u8 watchdog_count; - u8 dev_discovered; /* WFD_TDLS: for sigma test */ - u8 enable; -}; - -struct qos_priv { - /* bit mask option: u-apsd, - * s-apsd, ts, block ack... */ - unsigned int qos_option; -}; - -struct mlme_priv { - spinlock_t lock; - int fw_state; /* shall we protect this variable? maybe not necessarily... */ - bool bScanInProcess; - u8 to_join; /* flag */ - u8 to_roaming; /* roaming trying times */ - - u8 *nic_hdl; - - struct list_head *pscanned; - struct __queue free_bss_pool; - struct __queue scanned_queue; - u8 *free_bss_buf; - u8 key_mask; /* use to restore wep key after hal_init */ - u32 num_of_scanned; - - struct ndis_802_11_ssid assoc_ssid; - u8 assoc_bssid[6]; - - struct wlan_network cur_network; - struct wlan_network *cur_network_scanned; - - u32 scan_interval; - - struct timer_list assoc_timer; - - uint assoc_by_bssid; - uint assoc_by_rssi; - - struct timer_list scan_to_timer; /* driver itself handles scan_timeout status. */ - u32 scan_start_time; /* used to evaluate the time spent in scanning */ - - struct qos_priv qospriv; - - /* Number of non-HT AP/stations */ - int num_sta_no_ht; - - /* Number of HT AP/stations 20 MHz */ - /* int num_sta_ht_20mhz; */ - - int num_FortyMHzIntolerant; - struct ht_priv htpriv; - struct rt_link_detect LinkDetectInfo; - struct timer_list dynamic_chk_timer; /* dynamic/periodic check timer */ - - u8 acm_mask; /* for wmm acm mask */ - u8 ChannelPlan; - enum rt_scan_type scan_mode; /* active: 1, passive: 0 */ - - /* u8 probereq_wpsie[MAX_WPS_IE_LEN];added in probe req */ - /* int probereq_wpsie_len; */ - u8 *wps_probe_req_ie; - u32 wps_probe_req_ie_len; - - u8 *assoc_req; - u32 assoc_req_len; - - /* Number of associated Non-ERP stations (i.e., stations using 802.11b - * in 802.11g BSS) */ - int num_sta_non_erp; - - /* Number of associated stations that do not support Short Slot Time */ - int num_sta_no_short_slot_time; - - /* Number of associated stations that do not support Short Preamble */ - int num_sta_no_short_preamble; - - int olbc; /* Overlapping Legacy BSS Condition */ - - /* Number of HT assoc sta that do not support greenfield */ - int num_sta_ht_no_gf; - - /* Number of associated non-HT stations */ - /* int num_sta_no_ht; */ - - /* Number of HT associated stations 20 MHz */ - int num_sta_ht_20mhz; - - /* Overlapping BSS information */ - int olbc_ht; - - u16 ht_op_mode; - - u8 *wps_beacon_ie; - /* u8 *wps_probe_req_ie; */ - u8 *wps_probe_resp_ie; - u8 *wps_assoc_resp_ie; - - u32 wps_beacon_ie_len; - u32 wps_probe_resp_ie_len; - u32 wps_assoc_resp_ie_len; - - u8 *p2p_beacon_ie; - u8 *p2p_probe_req_ie; - u8 *p2p_probe_resp_ie; - u8 *p2p_go_probe_resp_ie; /* for GO */ - u8 *p2p_assoc_req_ie; - - u32 p2p_beacon_ie_len; - u32 p2p_probe_req_ie_len; - u32 p2p_probe_resp_ie_len; - u32 p2p_go_probe_resp_ie_len; /* for GO */ - u32 p2p_assoc_req_ie_len; - spinlock_t bcn_update_lock; - u8 update_bcn; -}; - -int hostapd_mode_init(struct adapter *padapter); -void hostapd_mode_unload(struct adapter *padapter); - -extern unsigned char WPA_TKIP_CIPHER[4]; -extern unsigned char RSN_TKIP_CIPHER[4]; -extern unsigned char REALTEK_96B_IE[]; -extern unsigned char MCS_rate_2R[16]; -extern unsigned char MCS_rate_1R[16]; - -void rtw_joinbss_event_prehandle(struct adapter *adapter, u8 *pbuf); -void rtw_survey_event_callback(struct adapter *adapter, u8 *pbuf); -void rtw_surveydone_event_callback(struct adapter *adapter, u8 *pbuf); -void rtw_joinbss_event_callback(struct adapter *adapter, u8 *pbuf); -void rtw_stassoc_event_callback(struct adapter *adapter, u8 *pbuf); -void rtw_stadel_event_callback(struct adapter *adapter, u8 *pbuf); -void indicate_wx_scan_complete_event(struct adapter *padapter); -void rtw_indicate_wx_assoc_event(struct adapter *padapter); -void rtw_indicate_wx_disassoc_event(struct adapter *padapter); -int event_thread(void *context); -void rtw_free_network_queue(struct adapter *adapter, u8 isfreeall); -int rtw_init_mlme_priv(struct adapter *adapter); -void rtw_free_mlme_priv (struct mlme_priv *pmlmepriv); -int rtw_select_and_join_from_scanned_queue(struct mlme_priv *pmlmepriv); -int rtw_set_key(struct adapter *adapter, struct security_priv *psecuritypriv, - int keyid, u8 set_tx); -int rtw_set_auth(struct adapter *adapter, struct security_priv *psecuritypriv); - -static inline u8 *get_bssid(struct mlme_priv *pmlmepriv) -{ /* if sta_mode:pmlmepriv->cur_network.network.MacAddress=> bssid */ - /* if adhoc_mode:pmlmepriv->cur_network.network.MacAddress=> ibss mac address */ - return pmlmepriv->cur_network.network.MacAddress; -} - -static inline bool check_fwstate(struct mlme_priv *pmlmepriv, int state) -{ - if (pmlmepriv->fw_state & state) - return true; - - return false; -} - -/* - * No Limit on the calling context, - * therefore set it to be the critical section... - * - * ### NOTE:#### (!!!!) - * MUST TAKE CARE THAT BEFORE CALLING THIS FUNC, YOU SHOULD HAVE LOCKED pmlmepriv->lock - */ -static inline void set_fwstate(struct mlme_priv *pmlmepriv, int state) -{ - pmlmepriv->fw_state |= state; - /* FOR HW integration */ - if (_FW_UNDER_SURVEY == state) - pmlmepriv->bScanInProcess = true; -} - -static inline void _clr_fwstate_(struct mlme_priv *pmlmepriv, int state) -{ - pmlmepriv->fw_state &= ~state; - /* FOR HW integration */ - if (_FW_UNDER_SURVEY == state) - pmlmepriv->bScanInProcess = false; -} - -/* - * No Limit on the calling context, - * therefore set it to be the critical section... - */ -static inline void clr_fwstate(struct mlme_priv *pmlmepriv, int state) -{ - spin_lock_bh(&pmlmepriv->lock); - if (check_fwstate(pmlmepriv, state)) - pmlmepriv->fw_state ^= state; - spin_unlock_bh(&pmlmepriv->lock); -} - -static inline void clr_fwstate_ex(struct mlme_priv *pmlmepriv, int state) -{ - spin_lock_bh(&pmlmepriv->lock); - _clr_fwstate_(pmlmepriv, state); - spin_unlock_bh(&pmlmepriv->lock); -} - -static inline void up_scanned_network(struct mlme_priv *pmlmepriv) -{ - spin_lock_bh(&pmlmepriv->lock); - pmlmepriv->num_of_scanned++; - spin_unlock_bh(&pmlmepriv->lock); -} - -static inline void down_scanned_network(struct mlme_priv *pmlmepriv) -{ - spin_lock_bh(&pmlmepriv->lock); - pmlmepriv->num_of_scanned--; - spin_unlock_bh(&pmlmepriv->lock); -} - -static inline void set_scanned_network_val(struct mlme_priv *pmlmepriv, int val) -{ - spin_lock_bh(&pmlmepriv->lock); - pmlmepriv->num_of_scanned = val; - spin_unlock_bh(&pmlmepriv->lock); -} - -u16 rtw_get_capability(struct wlan_bssid_ex *bss); -void rtw_update_scanned_network(struct adapter *adapter, - struct wlan_bssid_ex *target); -void rtw_disconnect_hdl_under_linked(struct adapter *adapter, - struct sta_info *psta, u8 free_assoc); -void rtw_generate_random_ibss(u8 *pibss); -struct wlan_network *rtw_find_network(struct __queue *scanned_queue, u8 *addr); -struct wlan_network *rtw_get_oldest_wlan_network(struct __queue *scanned_queue); - -void rtw_free_assoc_resources(struct adapter *adapter, int lock_scanned_queue); -void rtw_indicate_disconnect(struct adapter *adapter); -void rtw_indicate_connect(struct adapter *adapter); -void rtw_indicate_scan_done(struct adapter *padapter); - -int rtw_restruct_sec_ie(struct adapter *adapter, u8 *in_ie, u8 *out_ie, - uint in_len); -int rtw_restruct_wmm_ie(struct adapter *adapter, u8 *in_ie, u8 *out_ie, - uint in_len, uint initial_out_len); -void rtw_init_registrypriv_dev_network(struct adapter *adapter); - -void rtw_update_registrypriv_dev_network(struct adapter *adapter); - -void _rtw_join_timeout_handler(struct adapter *adapter); -void rtw_scan_timeout_handler(struct adapter *adapter); - - void rtw_dynamic_check_timer_handlder(struct adapter *adapter); - -void rtw_free_mlme_priv_ie_data(struct mlme_priv *pmlmepriv); - -struct wlan_network *rtw_alloc_network(struct mlme_priv *pmlmepriv); - -void _rtw_free_network(struct mlme_priv *pmlmepriv, - struct wlan_network *pnetwork, u8 isfreeall); - -struct wlan_network *_rtw_find_network(struct __queue *scanned_queue, u8 *addr); - -void _rtw_free_network_queue(struct adapter *padapter, u8 isfreeall); - -int rtw_if_up(struct adapter *padapter); - -u8 *rtw_get_capability_from_ie(u8 *ie); -u8 *rtw_get_beacon_interval_from_ie(u8 *ie); - -void rtw_joinbss_reset(struct adapter *padapter); - -unsigned int rtw_restructure_ht_ie(struct adapter *padapter, u8 *in_ie, - u8 *out_ie, uint in_len, uint *pout_len); -void rtw_update_ht_cap(struct adapter *padapter, u8 *pie, uint ie_len); -void rtw_issue_addbareq_cmd(struct adapter *padapter, - struct xmit_frame *pxmitframe); - -int rtw_is_same_ibss(struct adapter *adapter, struct wlan_network *pnetwork); -int is_same_network(struct wlan_bssid_ex *src, struct wlan_bssid_ex *dst); - -void rtw_roaming(struct adapter *padapter, struct wlan_network *tgt_network); -void _rtw_roaming(struct adapter *padapter, struct wlan_network *tgt_network); -void rtw_set_roaming(struct adapter *adapter, u8 to_roaming); -u8 rtw_to_roaming(struct adapter *adapter); - -void rtw_set_max_rpt_macid(struct adapter *adapter, u8 macid); -void rtw_sta_media_status_rpt(struct adapter *adapter, struct sta_info *psta, - u32 mstatus); - -u8 rtw_current_antenna(struct adapter *adapter); - -#endif /* __RTL871X_MLME_H_ */ diff --git a/drivers/staging/r8188eu/include/rtw_mlme_ext.h b/drivers/staging/r8188eu/include/rtw_mlme_ext.h deleted file mode 100644 index 589de7c54d93..000000000000 --- a/drivers/staging/r8188eu/include/rtw_mlme_ext.h +++ /dev/null @@ -1,753 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#ifndef __RTW_MLME_EXT_H_ -#define __RTW_MLME_EXT_H_ - -#include "osdep_service.h" -#include "drv_types.h" -#include "wlan_bssdef.h" - -/* Commented by Albert 20101105 */ -/* Increase the SURVEY_TO value from 100 to 150 ( 100ms to 150ms ) */ -/* The Realtek 8188CE SoftAP will spend around 100ms to send the probe response after receiving the probe request. */ -/* So, this driver tried to extend the dwell time for each scanning channel. */ -/* This will increase the chance to receive the probe response from SoftAP. */ - -#define SURVEY_TO (100) -#define REAUTH_TO (300) /* 50) */ -#define REASSOC_TO (300) /* 50) */ -/* define DISCONNECT_TO (3000) */ -#define ADDBA_TO (2000) - -#define LINKED_TO (1) /* unit:2 sec, 1x2=2 sec */ - -#define REAUTH_LIMIT (4) -#define REASSOC_LIMIT (4) - -#define DYNAMIC_FUNC_DISABLE (0x0) - -/* ====== ODM_ABILITY_E ======== */ -/* BB ODM section BIT 0-15 */ -#define DYNAMIC_BB_DIG BIT(0) - -#define DYNAMIC_ALL_FUNC_ENABLE 0xFFFFFFF - -#define _HW_STATE_NOLINK_ 0x00 -#define _HW_STATE_ADHOC_ 0x01 -#define _HW_STATE_STATION_ 0x02 -#define _HW_STATE_AP_ 0x03 - -#define _1M_RATE_ 0 -#define _2M_RATE_ 1 -#define _5M_RATE_ 2 -#define _11M_RATE_ 3 -#define _6M_RATE_ 4 -#define _9M_RATE_ 5 -#define _12M_RATE_ 6 -#define _18M_RATE_ 7 -#define _24M_RATE_ 8 -#define _36M_RATE_ 9 -#define _48M_RATE_ 10 -#define _54M_RATE_ 11 - -extern unsigned char RTW_WPA_OUI[]; -extern unsigned char WMM_OUI[]; -extern unsigned char WPS_OUI[]; -extern unsigned char WFD_OUI[]; -extern unsigned char P2P_OUI[]; - -extern unsigned char WMM_INFO_OUI[]; -extern unsigned char WMM_PARA_OUI[]; - -/* Channel Plan Type. */ -/* Note: */ -/* We just add new channel plan when the new channel plan is different - * from any of the following channel plan. */ -/* If you just want to customize the actions(scan period or join actions) - * about one of the channel plan, */ -/* customize them in struct rt_channel_info in the RT_CHANNEL_LIST. */ -enum RT_CHANNEL_DOMAIN { - /* old channel plan mapping ===== */ - RT_CHANNEL_DOMAIN_FCC = 0x00, - RT_CHANNEL_DOMAIN_IC = 0x01, - RT_CHANNEL_DOMAIN_ETSI = 0x02, - RT_CHANNEL_DOMAIN_SPAIN = 0x03, - RT_CHANNEL_DOMAIN_FRANCE = 0x04, - RT_CHANNEL_DOMAIN_MKK = 0x05, - RT_CHANNEL_DOMAIN_MKK1 = 0x06, - RT_CHANNEL_DOMAIN_ISRAEL = 0x07, - RT_CHANNEL_DOMAIN_TELEC = 0x08, - RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN = 0x09, - RT_CHANNEL_DOMAIN_WORLD_WIDE_13 = 0x0A, - RT_CHANNEL_DOMAIN_TAIWAN = 0x0B, - RT_CHANNEL_DOMAIN_CHINA = 0x0C, - RT_CHANNEL_DOMAIN_SINGAPORE_INDIA_MEXICO = 0x0D, - RT_CHANNEL_DOMAIN_KOREA = 0x0E, - RT_CHANNEL_DOMAIN_TURKEY = 0x0F, - RT_CHANNEL_DOMAIN_JAPAN = 0x10, - RT_CHANNEL_DOMAIN_FCC_NO_DFS = 0x11, - RT_CHANNEL_DOMAIN_JAPAN_NO_DFS = 0x12, - RT_CHANNEL_DOMAIN_TAIWAN_NO_DFS = 0x14, - - /* new channel plan mapping, (2GDOMAIN_5GDOMAIN) ===== */ - RT_CHANNEL_DOMAIN_WORLD_NULL = 0x20, - RT_CHANNEL_DOMAIN_ETSI1_NULL = 0x21, - RT_CHANNEL_DOMAIN_FCC1_NULL = 0x22, - RT_CHANNEL_DOMAIN_MKK1_NULL = 0x23, - RT_CHANNEL_DOMAIN_ETSI2_NULL = 0x24, - RT_CHANNEL_DOMAIN_FCC1_FCC1 = 0x25, - RT_CHANNEL_DOMAIN_WORLD_ETSI1 = 0x26, - RT_CHANNEL_DOMAIN_MKK1_MKK1 = 0x27, - RT_CHANNEL_DOMAIN_WORLD_KCC1 = 0x28, - RT_CHANNEL_DOMAIN_WORLD_FCC2 = 0x29, - RT_CHANNEL_DOMAIN_WORLD_FCC3 = 0x30, - RT_CHANNEL_DOMAIN_WORLD_FCC4 = 0x31, - RT_CHANNEL_DOMAIN_WORLD_FCC5 = 0x32, - RT_CHANNEL_DOMAIN_WORLD_FCC6 = 0x33, - RT_CHANNEL_DOMAIN_FCC1_FCC7 = 0x34, - RT_CHANNEL_DOMAIN_WORLD_ETSI2 = 0x35, - RT_CHANNEL_DOMAIN_WORLD_ETSI3 = 0x36, - RT_CHANNEL_DOMAIN_MKK1_MKK2 = 0x37, - RT_CHANNEL_DOMAIN_MKK1_MKK3 = 0x38, - RT_CHANNEL_DOMAIN_FCC1_NCC1 = 0x39, - RT_CHANNEL_DOMAIN_FCC1_NCC2 = 0x40, - RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G = 0x41, - /* Add new channel plan above this line=============== */ - RT_CHANNEL_DOMAIN_MAX, - RT_CHANNEL_DOMAIN_REALTEK_DEFINE = 0x7F, -}; - -enum RT_CHANNEL_DOMAIN_2G { - RT_CHANNEL_DOMAIN_2G_WORLD = 0x00, /* Worldwide 13 */ - RT_CHANNEL_DOMAIN_2G_ETSI1 = 0x01, /* Europe */ - RT_CHANNEL_DOMAIN_2G_FCC1 = 0x02, /* US */ - RT_CHANNEL_DOMAIN_2G_MKK1 = 0x03, /* Japan */ - RT_CHANNEL_DOMAIN_2G_ETSI2 = 0x04, /* France */ - RT_CHANNEL_DOMAIN_2G_NULL = 0x05, - /* Add new channel plan above this line=============== */ - RT_CHANNEL_DOMAIN_2G_MAX, -}; - -#define rtw_is_channel_plan_valid(chplan) \ - (chplan < RT_CHANNEL_DOMAIN_MAX || \ - chplan == RT_CHANNEL_DOMAIN_REALTEK_DEFINE) - -struct rt_channel_plan { - unsigned char Channel[MAX_CHANNEL_NUM]; - unsigned char Len; -}; - -struct rt_channel_plan_map { - unsigned char Index2G; -}; - -enum Associated_AP { - atherosAP = 0, - broadcomAP = 1, - ciscoAP = 2, - marvellAP = 3, - ralinkAP = 4, - realtekAP = 5, - airgocapAP = 6, - unknownAP = 7, - maxAP, -}; - -enum HT_IOT_PEER { - HT_IOT_PEER_UNKNOWN = 0, - HT_IOT_PEER_REALTEK = 1, - HT_IOT_PEER_REALTEK_92SE = 2, - HT_IOT_PEER_BROADCOM = 3, - HT_IOT_PEER_RALINK = 4, - HT_IOT_PEER_ATHEROS = 5, - HT_IOT_PEER_CISCO = 6, - HT_IOT_PEER_MERU = 7, - HT_IOT_PEER_MARVELL = 8, - HT_IOT_PEER_REALTEK_SOFTAP = 9,/* peer is RealTek SOFT_AP */ - HT_IOT_PEER_SELF_SOFTAP = 10, /* Self is SoftAP */ - HT_IOT_PEER_AIRGO = 11, - HT_IOT_PEER_INTEL = 12, - HT_IOT_PEER_RTK_APCLIENT = 13, - HT_IOT_PEER_REALTEK_81XX = 14, - HT_IOT_PEER_REALTEK_WOW = 15, - HT_IOT_PEER_TENDA = 16, - HT_IOT_PEER_MAX = 17 -}; - -enum SCAN_STATE { - SCAN_DISABLE = 0, - SCAN_START = 1, - SCAN_TXNULL = 2, - SCAN_PROCESS = 3, - SCAN_COMPLETE = 4, - SCAN_STATE_MAX, -}; - -typedef void (*mlme_handler)(struct adapter *adapt, struct recv_frame *frame); - -struct ss_res { - int state; - int bss_cnt; - int channel_idx; - int scan_mode; - u8 ssid_num; - u8 ch_num; - struct ndis_802_11_ssid ssid[RTW_SSID_SCAN_AMOUNT]; - struct rtw_ieee80211_channel ch[RTW_CHANNEL_SCAN_AMOUNT]; -}; - -/* define AP_MODE 0x0C */ -/* define STATION_MODE 0x08 */ -/* define AD_HOC_MODE 0x04 */ -/* define NO_LINK_MODE 0x00 */ - -#define WIFI_FW_NULL_STATE _HW_STATE_NOLINK_ -#define WIFI_FW_STATION_STATE _HW_STATE_STATION_ -#define WIFI_FW_AP_STATE _HW_STATE_AP_ -#define WIFI_FW_ADHOC_STATE _HW_STATE_ADHOC_ - -#define WIFI_FW_AUTH_NULL 0x00000100 -#define WIFI_FW_AUTH_STATE 0x00000200 -#define WIFI_FW_AUTH_SUCCESS 0x00000400 - -#define WIFI_FW_ASSOC_STATE 0x00002000 -#define WIFI_FW_ASSOC_SUCCESS 0x00004000 - -#define WIFI_FW_LINKING_STATE (WIFI_FW_AUTH_NULL | \ - WIFI_FW_AUTH_STATE | \ - WIFI_FW_AUTH_SUCCESS | \ - WIFI_FW_ASSOC_STATE) - -struct FW_Sta_Info { - struct sta_info *psta; - u32 status; - u32 rx_pkt; - u32 retry; - unsigned char SupportedRates[NDIS_802_11_LENGTH_RATES_EX]; -}; - -/* - * Usage: - * When one iface acted as AP mode and the other iface is STA mode and scanning, - * it should switch back to AP's operating channel periodically. - * Parameters info: - * When the driver scanned RTW_SCAN_NUM_OF_CH channels, it would switch back to - * AP's operating channel for - * RTW_STAY_AP_CH_MILLISECOND * SURVEY_TO milliseconds. - * Example: - * For chip supports 2.4G + 5GHz and AP mode is operating in channel 1, - * RTW_SCAN_NUM_OF_CH is 8, RTW_STAY_AP_CH_MS is 3 and SURVEY_TO is 100. - * When it's STA mode gets set_scan command, - * it would - * 1. Doing the scan on channel 1.2.3.4.5.6.7.8 - * 2. Back to channel 1 for 300 milliseconds - * 3. Go through doing site survey on channel 9.10.11.36.40.44.48.52 - * 4. Back to channel 1 for 300 milliseconds - * 5. ... and so on, till survey done. - */ - -struct mlme_ext_info { - u32 state; - u32 reauth_count; - u32 reassoc_count; - u32 link_count; - u32 auth_seq; - u32 auth_algo; /* 802.11 auth, could be open, shared, auto */ - u32 authModeToggle; - u32 enc_algo;/* encrypt algorithm; */ - u32 key_index; /* this is only valid for legacy wep, - * 0~3 for key id. */ - u32 iv; - u8 chg_txt[128]; - u16 aid; - u16 bcn_interval; - u16 capability; - u8 assoc_AP_vendor; - u8 slotTime; - u8 preamble_mode; - u8 WMM_enable; - u8 ERP_enable; - u8 ERP_IE; - u8 HT_enable; - u8 HT_caps_enable; - u8 HT_info_enable; - u8 HT_protection; - u8 turboMode_cts2self; - u8 turboMode_rtsen; - u8 SM_PS; - u8 agg_enable_bitmap; - u8 ADDBA_retry_count; - u8 candidate_tid_bitmap; - u8 dialogToken; - /* Accept ADDBA Request */ - bool bAcceptAddbaReq; - u8 bwmode_updated; - u8 hidden_ssid_mode; - - struct WMM_para_element WMM_param; - struct HT_caps_element HT_caps; - struct HT_info_element HT_info; - struct wlan_bssid_ex network;/* join network or bss_network, - * if in ap mode, it is the same - * as cur_network.network */ - struct FW_Sta_Info FW_sta_info[NUM_STA]; -}; - -/* The channel information about this channel including joining, - * scanning, and power constraints. */ -struct rt_channel_info { - u8 ChannelNum; /* The channel number. */ - enum rt_scan_type ScanType; /* Scan type such as passive - * or active scan. */ - u32 rx_count; -}; - -int rtw_ch_set_search_ch(struct rt_channel_info *ch_set, const u32 ch); - -/* P2P_MAX_REG_CLASSES - Maximum number of regulatory classes */ -#define P2P_MAX_REG_CLASSES 10 - -/* P2P_MAX_REG_CLASS_CHANNELS - Maximum number of chan per regulatory class */ -#define P2P_MAX_REG_CLASS_CHANNELS 20 - -/* struct p2p_channels - List of supported channels */ -struct p2p_channels { - /* struct p2p_reg_class - Supported regulatory class */ - struct p2p_reg_class { - /* reg_class - Regulatory class (IEEE 802.11-2007, Annex J) */ - u8 reg_class; - - /* channel - Supported channels */ - u8 channel[P2P_MAX_REG_CLASS_CHANNELS]; - - /* channels - Number of channel entries in use */ - size_t channels; - } reg_class[P2P_MAX_REG_CLASSES]; - - /* reg_classes - Number of reg_class entries in use */ - size_t reg_classes; -}; - -struct p2p_oper_class_map { - enum hw_mode {IEEE80211G} mode; - u8 op_class; - u8 min_chan; - u8 max_chan; - u8 inc; - enum {BW20, BW40PLUS, BW40MINUS} bw; -}; - -struct mlme_ext_priv { - struct adapter *padapter; - u8 mlmeext_init; - atomic_t event_seq; - u16 mgnt_seq; - - unsigned char cur_channel; - unsigned char cur_bwmode; - unsigned char cur_ch_offset;/* PRIME_CHNL_OFFSET */ - unsigned char cur_wireless_mode; /* NETWORK_TYPE */ - - unsigned char oper_channel; /* saved chan info when call - * set_channel_bw */ - unsigned char oper_bwmode; - unsigned char oper_ch_offset;/* PRIME_CHNL_OFFSET */ - - unsigned char max_chan_nums; - struct rt_channel_info channel_set[MAX_CHANNEL_NUM]; - struct p2p_channels channel_list; - unsigned char basicrate[NumRates]; - unsigned char datarate[NumRates]; - - struct ss_res sitesurvey_res; - struct mlme_ext_info mlmext_info;/* for sta/adhoc mode, including - * current scan/connecting/connected - * related info. For ap mode, - * network includes ap's cap_info*/ - struct timer_list survey_timer; - struct timer_list link_timer; - u16 chan_scan_time; - - u8 scan_abort; - u8 tx_rate; /* TXRATE when USERATE is set. */ - - u32 retry; /* retry for issue probereq */ - - u64 TSFValue; - - unsigned char bstart_bss; - u8 update_channel_plan_by_ap_done; - /* recv_decache check for Action_public frame */ - u8 action_public_dialog_token; - u16 action_public_rxseq; - u8 active_keep_alive_check; -}; - -void init_mlme_ext_priv(struct adapter *adapter); -int init_hw_mlme_ext(struct adapter *padapter); -void free_mlme_ext_priv (struct mlme_ext_priv *pmlmeext); -struct xmit_frame *alloc_mgtxmitframe(struct xmit_priv *pxmitpriv); - -unsigned char networktype_to_raid(unsigned char network_type); -u8 judge_network_type(struct adapter *padapter, unsigned char *rate, int len); -void get_rate_set(struct adapter *padapter, unsigned char *pbssrate, int *len); - -void Save_DM_Func_Flag(struct adapter *padapter); -void Restore_DM_Func_Flag(struct adapter *padapter); - -void Set_MSR(struct adapter *padapter, u8 type); - -u8 rtw_get_oper_ch(struct adapter *adapter); -void rtw_set_oper_ch(struct adapter *adapter, u8 ch); -void rtw_set_oper_bw(struct adapter *adapter, u8 bw); -void rtw_set_oper_choffset(struct adapter *adapter, u8 offset); - -void set_channel_bwmode(struct adapter *padapter, unsigned char channel, - unsigned char channel_offset, unsigned short bwmode); -void SelectChannel(struct adapter *padapter, unsigned char channel); -void SetBWMode(struct adapter *padapter, unsigned short bwmode, - unsigned char channel_offset); - -unsigned int decide_wait_for_beacon_timeout(unsigned int bcn_interval); - -void write_cam(struct adapter *padapter, u8 entry, u16 ctrl, u8 *mac, u8 *key); -void clear_cam_entry(struct adapter *padapter, u8 entry); - -void invalidate_cam_all(struct adapter *padapter); - -int allocate_fw_sta_entry(struct adapter *padapter); -void flush_all_cam_entry(struct adapter *padapter); - -void rtw_mlme_under_site_survey(struct adapter *adapter); -void rtw_mlme_site_survey_done(struct adapter *adapter); - -void site_survey(struct adapter *padapter); -u8 collect_bss_info(struct adapter *padapter, struct recv_frame *precv_frame, - struct wlan_bssid_ex *bssid); -void update_network(struct wlan_bssid_ex *dst, struct wlan_bssid_ex *src, - struct adapter *adapter, bool update_ie); - -u8 *get_my_bssid(struct wlan_bssid_ex *pnetwork); -u16 get_beacon_interval(struct wlan_bssid_ex *bss); - -bool r8188eu_is_client_associated_to_ap(struct adapter *padapter); -bool r8188eu_is_client_associated_to_ibss(struct adapter *padapter); -bool r8188eu_is_ibss_empty(struct adapter *padapter); - -unsigned char check_assoc_AP(u8 *pframe, uint len); - -int WMM_param_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE); -void WMMOnAssocRsp(struct adapter *padapter); - -void HT_caps_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE); -void HT_info_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE); -void HTOnAssocRsp(struct adapter *padapter); - -void ERP_IE_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE); -void VCS_update(struct adapter *padapter, struct sta_info *psta); - -void update_beacon_info(struct adapter *padapter, u8 *ie_ptr, uint ie_len, struct sta_info *psta); -int rtw_check_bcn_info(struct adapter *Adapter, u8 *pframe, u32 packet_len); -void update_IOT_info(struct adapter *padapter); -void update_capinfo(struct adapter *adapter, u16 updatecap); -void update_wireless_mode(struct adapter *padapter); -void rtw_set_basic_rate(struct adapter *adapter, u8 *rates); -void update_tx_basic_rate(struct adapter *padapter, u8 modulation); -void update_bmc_sta_support_rate(struct adapter *padapter, u32 mac_id); -int update_sta_support_rate(struct adapter *padapter, u8 *pvar_ie, - uint var_ie_len, int cam_idx); - -/* for sta/adhoc mode */ -void update_sta_info(struct adapter *padapter, struct sta_info *psta); -unsigned int update_basic_rate(unsigned char *ptn, unsigned int ptn_sz); -unsigned int update_supported_rate(unsigned char *ptn, unsigned int ptn_sz); -unsigned int update_MSC_rate(struct HT_caps_element *pHT_caps); -void Update_RA_Entry(struct adapter *padapter, u32 mac_id); -void set_sta_rate(struct adapter *padapter, struct sta_info *psta); - -void receive_disconnect(struct adapter *padapter, unsigned char *macaddr, unsigned short reason); - -unsigned char get_highest_rate_idx(u32 mask); -int support_short_GI(struct adapter *padapter, struct HT_caps_element *caps); -bool is_ap_in_tkip(struct adapter *padapter); - -void report_join_res(struct adapter *padapter, int res); -void report_survey_event(struct adapter *padapter, struct recv_frame *precv_frame); -void report_surveydone_event(struct adapter *padapter); -void report_del_sta_event(struct adapter *padapter, - unsigned char *addr, unsigned short reason); -void report_add_sta_event(struct adapter *padapter, unsigned char *addr, - int cam_idx); - -void beacon_timing_control(struct adapter *padapter); -u8 set_tx_beacon_cmd(struct adapter *padapter); -unsigned int setup_beacon_frame(struct adapter *padapter, - unsigned char *beacon_frame); -void update_mgnt_tx_rate(struct adapter *padapter, u8 rate); -void update_mgntframe_attrib(struct adapter *padapter, - struct pkt_attrib *pattrib); -void dump_mgntframe(struct adapter *padapter, struct xmit_frame *pmgntframe); -s32 dump_mgntframe_and_wait(struct adapter *padapter, - struct xmit_frame *pmgntframe, int timeout_ms); -s32 dump_mgntframe_and_wait_ack(struct adapter *padapter, - struct xmit_frame *pmgntframe); - -void issue_probersp_p2p(struct adapter *padapter, unsigned char *da); -void issue_p2p_provision_request(struct adapter *padapter, u8 *pssid, - u8 ussidlen, u8 *pdev_raddr); -void issue_p2p_GO_request(struct adapter *padapter, u8 *raddr); -void issue_probereq_p2p(struct adapter *padapter); -void issue_p2p_invitation_response(struct adapter *padapter, u8 *raddr, - u8 dialogToken, u8 success); -void issue_p2p_invitation_request(struct adapter *padapter, u8 *raddr); -void issue_beacon(struct adapter *padapter, int timeout_ms); -void issue_probersp(struct adapter *padapter, unsigned char *da, - u8 is_valid_p2p_probereq); -void issue_assocreq(struct adapter *padapter); -void issue_asocrsp(struct adapter *padapter, unsigned short status, - struct sta_info *pstat, int pkt_type); -void issue_auth(struct adapter *padapter, struct sta_info *psta, - unsigned short status); -void issue_probereq(struct adapter *padapter, struct ndis_802_11_ssid *pssid, - u8 *da); -void issue_probereq_ex(struct adapter *padapter, struct ndis_802_11_ssid *pssid, u8 *da); -int issue_nulldata(struct adapter *padapter, unsigned char *da, - unsigned int power_mode, int try_cnt, int wait_ms); -int issue_qos_nulldata(struct adapter *padapter, unsigned char *da, - u16 tid, int try_cnt, int wait_ms); -int issue_deauth(struct adapter *padapter, unsigned char *da, - unsigned short reason); -int issue_deauth_ex(struct adapter *padapter, u8 *da, unsigned short reason, - int try_cnt, int wait_ms); -void issue_action_BA(struct adapter *padapter, unsigned char *raddr, u8 action, - u16 status, struct ieee80211_mgmt *mgmt_req); -unsigned int send_delba(struct adapter *padapter, u8 initiator, u8 *addr); -unsigned int send_beacon(struct adapter *padapter); -bool get_beacon_valid_bit(struct adapter *adapter); -void clear_beacon_valid_bit(struct adapter *adapter); -void rtw_resume_tx_beacon(struct adapter *adapt); -void rtw_stop_tx_beacon(struct adapter *adapt); - -void start_clnt_assoc(struct adapter *padapter); -void start_clnt_auth(struct adapter *padapter); -void start_clnt_join(struct adapter *padapter); -void start_create_ibss(struct adapter *padapter); - -void mlmeext_joinbss_event_callback(struct adapter *padapter, int join_res); -void mlmeext_sta_del_event_callback(struct adapter *padapter); -void mlmeext_sta_add_event_callback(struct adapter *padapter, - struct sta_info *psta); - -void linked_status_chk(struct adapter *padapter); - -void survey_timer_hdl (struct adapter *padapter); -void link_timer_hdl (struct adapter *padapter); -void addba_timer_hdl(struct sta_info *psta); - -#define set_survey_timer(mlmeext, ms) \ - do { \ - _set_timer(&(mlmeext)->survey_timer, (ms)); \ - } while (0) - -#define set_link_timer(mlmeext, ms) \ - do { \ - _set_timer(&(mlmeext)->link_timer, (ms)); \ - } while (0) - -bool cckrates_included(unsigned char *rate, int ratelen); -bool cckratesonly_included(unsigned char *rate, int ratelen); - -struct cmd_hdl { - uint parmsize; - u8 (*h2cfuns)(struct adapter *padapter, u8 *pbuf); -}; - -u8 read_macreg_hdl(struct adapter *padapter, u8 *pbuf); -u8 write_macreg_hdl(struct adapter *padapter, u8 *pbuf); -u8 read_bbreg_hdl(struct adapter *padapter, u8 *pbuf); -u8 write_bbreg_hdl(struct adapter *padapter, u8 *pbuf); -u8 read_rfreg_hdl(struct adapter *padapter, u8 *pbuf); -u8 write_rfreg_hdl(struct adapter *padapter, u8 *pbuf); -u8 NULL_hdl(struct adapter *padapter, u8 *pbuf); -u8 join_cmd_hdl(struct adapter *padapter, u8 *pbuf); -u8 disconnect_hdl(struct adapter *padapter, u8 *pbuf); -u8 createbss_hdl(struct adapter *padapter, u8 *pbuf); -u8 setopmode_hdl(struct adapter *padapter, u8 *pbuf); -u8 sitesurvey_cmd_hdl(struct adapter *padapter, u8 *pbuf); -u8 setauth_hdl(struct adapter *padapter, u8 *pbuf); -u8 setkey_hdl(struct adapter *padapter, u8 *pbuf); -u8 set_stakey_hdl(struct adapter *padapter, u8 *pbuf); -u8 set_assocsta_hdl(struct adapter *padapter, u8 *pbuf); -u8 del_assocsta_hdl(struct adapter *padapter, u8 *pbuf); -u8 add_ba_hdl(struct adapter *padapter, unsigned char *pbuf); - -u8 mlme_evt_hdl(struct adapter *padapter, unsigned char *pbuf); -u8 h2c_msg_hdl(struct adapter *padapter, unsigned char *pbuf); -u8 tx_beacon_hdl(struct adapter *padapter, unsigned char *pbuf); -u8 set_ch_hdl(struct adapter *padapter, u8 *pbuf); -u8 set_chplan_hdl(struct adapter *padapter, unsigned char *pbuf); -u8 led_blink_hdl(struct adapter *padapter, unsigned char *pbuf); -/* Handling DFS channel switch announcement ie. */ -u8 set_csa_hdl(struct adapter *padapter, unsigned char *pbuf); -u8 tdls_hdl(struct adapter *padapter, unsigned char *pbuf); - -#define GEN_DRV_CMD_HANDLER(size, cmd) {size, &cmd ## _hdl}, -#define GEN_MLME_EXT_HANDLER(size, cmd) {size, cmd}, - -#ifdef _RTW_CMD_C_ - -static struct cmd_hdl wlancmds[] = { - GEN_DRV_CMD_HANDLER(0, NULL) /*0*/ - GEN_DRV_CMD_HANDLER(0, NULL) - GEN_DRV_CMD_HANDLER(0, NULL) - GEN_DRV_CMD_HANDLER(0, NULL) - GEN_DRV_CMD_HANDLER(0, NULL) - GEN_DRV_CMD_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) /*10*/ - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(sizeof (struct joinbss_parm), join_cmd_hdl) /*14*/ - GEN_MLME_EXT_HANDLER(sizeof (struct disconnect_parm), disconnect_hdl) - GEN_MLME_EXT_HANDLER(sizeof (struct createbss_parm), createbss_hdl) - GEN_MLME_EXT_HANDLER(sizeof (struct setopmode_parm), setopmode_hdl) - GEN_MLME_EXT_HANDLER(sizeof (struct sitesurvey_parm), - sitesurvey_cmd_hdl) /*18*/ - GEN_MLME_EXT_HANDLER(sizeof (struct setauth_parm), setauth_hdl) - GEN_MLME_EXT_HANDLER(sizeof (struct setkey_parm), setkey_hdl) /*20*/ - GEN_MLME_EXT_HANDLER(sizeof (struct set_stakey_parm), set_stakey_hdl) - GEN_MLME_EXT_HANDLER(sizeof (struct set_assocsta_parm), NULL) - GEN_MLME_EXT_HANDLER(sizeof (struct del_assocsta_parm), NULL) - GEN_MLME_EXT_HANDLER(sizeof (struct setstapwrstate_parm), NULL) - GEN_MLME_EXT_HANDLER(sizeof (struct setbasicrate_parm), NULL) - GEN_MLME_EXT_HANDLER(sizeof (struct getbasicrate_parm), NULL) - GEN_MLME_EXT_HANDLER(sizeof (struct setdatarate_parm), NULL) - GEN_MLME_EXT_HANDLER(sizeof (struct getdatarate_parm), NULL) - GEN_MLME_EXT_HANDLER(sizeof (struct setphyinfo_parm), NULL) - GEN_MLME_EXT_HANDLER(sizeof (struct getphyinfo_parm), NULL) /*30*/ - GEN_MLME_EXT_HANDLER(sizeof (struct setphy_parm), NULL) - GEN_MLME_EXT_HANDLER(sizeof (struct getphy_parm), NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) /*40*/ - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(sizeof(struct addBaReq_parm), add_ba_hdl) - GEN_MLME_EXT_HANDLER(sizeof(struct set_ch_parm), set_ch_hdl) /* 46 */ - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) /*50*/ - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(sizeof(struct Tx_Beacon_param), - tx_beacon_hdl) /*55*/ - - GEN_MLME_EXT_HANDLER(0, mlme_evt_hdl) /*56*/ - GEN_MLME_EXT_HANDLER(0, rtw_drvextra_cmd_hdl) /*57*/ - - GEN_MLME_EXT_HANDLER(0, h2c_msg_hdl) /*58*/ - GEN_MLME_EXT_HANDLER(sizeof(struct SetChannelPlan_param), - set_chplan_hdl) /*59*/ - GEN_MLME_EXT_HANDLER(sizeof(struct LedBlink_param), - led_blink_hdl) /*60*/ - - GEN_MLME_EXT_HANDLER(sizeof(struct SetChannelSwitch_param), - set_csa_hdl) /*61*/ - GEN_MLME_EXT_HANDLER(sizeof(struct TDLSoption_param), - tdls_hdl) /*62*/ -}; - -#endif - -struct C2HEvent_Header { -#ifdef __LITTLE_ENDIAN - unsigned int len:16; - unsigned int ID:8; - unsigned int seq:8; -#elif defined(__BIG_ENDIAN) - unsigned int seq:8; - unsigned int ID:8; - unsigned int len:16; -#endif - unsigned int rsvd; -}; - -enum rtw_c2h_event { - GEN_EVT_CODE(_Read_MACREG) = 0, /*0*/ - GEN_EVT_CODE(_Read_BBREG), - GEN_EVT_CODE(_Read_RFREG), - GEN_EVT_CODE(_Read_EEPROM), - GEN_EVT_CODE(_Read_EFUSE), - GEN_EVT_CODE(_Read_CAM), /*5*/ - GEN_EVT_CODE(_Get_BasicRate), - GEN_EVT_CODE(_Get_DataRate), - GEN_EVT_CODE(_Survey), /*8*/ - GEN_EVT_CODE(_SurveyDone), /*9*/ - - GEN_EVT_CODE(_JoinBss), /*10*/ - GEN_EVT_CODE(_AddSTA), - GEN_EVT_CODE(_DelSTA), - GEN_EVT_CODE(_AtimDone), - GEN_EVT_CODE(_TX_Report), - GEN_EVT_CODE(_CCX_Report), /*15*/ - GEN_EVT_CODE(_DTM_Report), - GEN_EVT_CODE(_TX_Rate_Statistics), - GEN_EVT_CODE(_C2HLBK), - GEN_EVT_CODE(_FWDBG), - GEN_EVT_CODE(_C2HFEEDBACK), /*20*/ - GEN_EVT_CODE(_ADDBA), - GEN_EVT_CODE(_C2HBCN), - GEN_EVT_CODE(_ReportPwrState), /* filen: only for PCIE, USB */ - GEN_EVT_CODE(_CloseRF), /* filen: only for PCIE, - * work around ASPM */ - MAX_C2HEVT -}; - -#ifdef _RTW_MLME_EXT_C_ - -static struct fwevent wlanevents[] = { - {0, NULL}, /*0*/ - {0, NULL}, - {0, NULL}, - {0, NULL}, - {0, NULL}, - {0, NULL}, - {0, NULL}, - {0, NULL}, - {0, &rtw_survey_event_callback}, /*8*/ - {sizeof (struct surveydone_event), &rtw_surveydone_event_callback},/*9*/ - {0, &rtw_joinbss_event_callback}, /*10*/ - {sizeof(struct stassoc_event), &rtw_stassoc_event_callback}, - {sizeof(struct stadel_event), &rtw_stadel_event_callback}, - {0, NULL}, - {0, NULL}, - {0, NULL}, /*15*/ - {0, NULL}, - {0, NULL}, - {0, NULL}, - {0, NULL}, - {0, NULL}, /*20*/ - {0, NULL}, - {0, NULL}, - {0, NULL}, - {0, NULL}, -}; - -#endif/* _RTL_MLME_EXT_C_ */ - -#endif /* __RTW_MLME_EXT_H_ */ diff --git a/drivers/staging/r8188eu/include/rtw_p2p.h b/drivers/staging/r8188eu/include/rtw_p2p.h deleted file mode 100644 index b91322a1fe10..000000000000 --- a/drivers/staging/r8188eu/include/rtw_p2p.h +++ /dev/null @@ -1,118 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#ifndef __RTW_P2P_H_ -#define __RTW_P2P_H_ - -#include "drv_types.h" - -u32 build_beacon_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf); -u32 build_probe_resp_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf); -u32 build_prov_disc_request_p2p_ie(struct wifidirect_info *pwdinfo, - u8 *pbuf, u8 *pssid, u8 ussidlen, - u8 *pdev_raddr); -u32 build_assoc_resp_p2p_ie(struct wifidirect_info *pwdinfo, - u8 *pbuf, u8 status_code); -u32 process_probe_req_p2p_ie(struct wifidirect_info *pwdinfo, - u8 *pframe, uint len); -u32 process_assoc_req_p2p_ie(struct wifidirect_info *pwdinfo, - u8 *pframe, uint len, struct sta_info *psta); -u32 process_p2p_devdisc_req(struct wifidirect_info *pwdinfo, - u8 *pframe, uint len); -u32 process_p2p_devdisc_resp(struct wifidirect_info *pwdinfo, - u8 *pframe, uint len); -u8 process_p2p_provdisc_req(struct wifidirect_info *pwdinfo, - u8 *pframe, uint len); -u8 process_p2p_provdisc_resp(struct wifidirect_info *pwdinfo, u8 *pframe); -u8 process_p2p_group_negotation_req(struct wifidirect_info *pwdinfo, - u8 *pframe, uint len); -u8 process_p2p_group_negotation_resp(struct wifidirect_info *pwdinfo, - u8 *pframe, uint len); -u8 process_p2p_group_negotation_confirm(struct wifidirect_info *pwdinfo, - u8 *pframe, uint len); -u8 process_p2p_presence_req(struct wifidirect_info *pwdinfo, u8 *pframe, - uint len); -void p2p_protocol_wk_hdl(struct adapter *padapter, int intcmdtype); -void process_p2p_ps_ie(struct adapter *padapter, u8 *ies, u32 ielength); -void p2p_ps_wk_hdl(struct adapter *padapter, u8 p2p_ps_state); -u8 p2p_ps_wk_cmd(struct adapter *padapter, u8 p2p_ps_state, u8 enqueue); -void reset_global_wifidirect_info(struct adapter *padapter); -int rtw_init_wifi_display_info(struct adapter *padapter); -void rtw_init_wifidirect_timers(struct adapter *padapter); -void rtw_init_wifidirect_addrs(struct adapter *padapter, u8 *dev_addr, - u8 *iface_addr); -void init_wifidirect_info(struct adapter *padapter, enum P2P_ROLE role); -int rtw_p2p_enable(struct adapter *padapter, enum P2P_ROLE role); - -static inline void _rtw_p2p_set_state(struct wifidirect_info *wdinfo, - enum P2P_STATE state) -{ - if (wdinfo->p2p_state != state) - wdinfo->p2p_state = state; -} - -static inline void _rtw_p2p_set_pre_state(struct wifidirect_info *wdinfo, - enum P2P_STATE state) -{ - if (wdinfo->pre_p2p_state != state) - wdinfo->pre_p2p_state = state; -} - -static inline void _rtw_p2p_set_role(struct wifidirect_info *wdinfo, - enum P2P_ROLE role) -{ - if (wdinfo->role != role) - wdinfo->role = role; -} - -static inline int _rtw_p2p_state(struct wifidirect_info *wdinfo) -{ - return wdinfo->p2p_state; -} - -static inline int _rtw_p2p_pre_state(struct wifidirect_info *wdinfo) -{ - return wdinfo->pre_p2p_state; -} - -static inline int _rtw_p2p_role(struct wifidirect_info *wdinfo) -{ - return wdinfo->role; -} - -static inline bool _rtw_p2p_chk_state(struct wifidirect_info *wdinfo, - enum P2P_STATE state) -{ - return wdinfo->p2p_state == state; -} - -static inline bool _rtw_p2p_chk_role(struct wifidirect_info *wdinfo, - enum P2P_ROLE role) -{ - return wdinfo->role == role; -} - -#define rtw_p2p_set_state(wdinfo, state) _rtw_p2p_set_state(wdinfo, state) -#define rtw_p2p_set_pre_state(wdinfo, state) \ - _rtw_p2p_set_pre_state(wdinfo, state) -#define rtw_p2p_set_role(wdinfo, role) _rtw_p2p_set_role(wdinfo, role) - -#define rtw_p2p_state(wdinfo) _rtw_p2p_state(wdinfo) -#define rtw_p2p_pre_state(wdinfo) _rtw_p2p_pre_state(wdinfo) -#define rtw_p2p_role(wdinfo) _rtw_p2p_role(wdinfo) -#define rtw_p2p_chk_state(wdinfo, state) _rtw_p2p_chk_state(wdinfo, state) -#define rtw_p2p_chk_role(wdinfo, role) _rtw_p2p_chk_role(wdinfo, role) - -#define rtw_p2p_findphase_ex_set(wdinfo, value) \ - ((wdinfo)->find_phase_state_exchange_cnt = (value)) - -/* is this find phase exchange for social channel scan? */ -#define rtw_p2p_findphase_ex_is_social(wdinfo) \ -((wdinfo)->find_phase_state_exchange_cnt >= P2P_FINDPHASE_EX_SOCIAL_FIRST) - -/* should we need find phase exchange anymore? */ -#define rtw_p2p_findphase_ex_is_needed(wdinfo) \ - ((wdinfo)->find_phase_state_exchange_cnt < P2P_FINDPHASE_EX_MAX && \ - (wdinfo)->find_phase_state_exchange_cnt != P2P_FINDPHASE_EX_NONE) - -#endif diff --git a/drivers/staging/r8188eu/include/rtw_pwrctrl.h b/drivers/staging/r8188eu/include/rtw_pwrctrl.h deleted file mode 100644 index 9f5cffd8bfb1..000000000000 --- a/drivers/staging/r8188eu/include/rtw_pwrctrl.h +++ /dev/null @@ -1,111 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2007 - 2012 Realtek Corporation. */ - -#ifndef __RTW_PWRCTRL_H_ -#define __RTW_PWRCTRL_H_ - -#include "osdep_service.h" -#include "drv_types.h" - -#define XMIT_ALIVE BIT(0) -#define RECV_ALIVE BIT(1) -#define CMD_ALIVE BIT(2) -#define EVT_ALIVE BIT(3) - -enum power_mgnt { - PS_MODE_ACTIVE = 0, - PS_MODE_MIN, - PS_MODE_MAX, - PS_MODE_DTIM, - PS_MODE_VOIP, - PS_MODE_UAPSD_WMM, - PM_Card_Disable, - PS_MODE_NUM -}; - -#define LPS_DELAY_TIME 1*HZ /* 1 sec */ - -/* RF state. */ -enum rt_rf_power_state { - rf_on, /* RF is on after RFSleep or RFOff */ - rf_sleep, /* 802.11 Power Save mode */ - rf_off, /* HW/SW Radio OFF or Inactive Power Save */ - /* Add the new RF state above this line===== */ - rf_max -}; - -enum { /* for ips_mode */ - IPS_NONE = 0, - IPS_NORMAL, - IPS_LEVEL_2, -}; - -struct pwrctrl_priv { - struct mutex lock; /* Mutex used to protect struct pwrctrl_priv */ - - u8 pwr_mode; - u8 smart_ps; - u8 bcn_ant_mode; - - bool bpower_saving; - - uint ips_enter_cnts; - uint ips_leave_cnts; - - u8 ips_mode; - u8 ips_mode_req; /* used to accept the mode setting request, - * will update to ipsmode later */ - uint bips_processing; - unsigned long ips_deny_time; /* will deny IPS when system time less than this */ - u8 ps_processing; /* temp used to mark whether in rtw_ps_processor */ - - u8 bLeisurePs; - u8 LpsIdleCount; - u8 power_mgnt; - u8 bFwCurrentInPSMode; - u32 DelayLPSLastTimeStamp; - - u8 bInSuspend; - u8 bSupportRemoteWakeup; - struct timer_list pwr_state_check_timer; - int pwr_state_check_interval; - - enum rt_rf_power_state rf_pwrstate;/* cur power state */ - - u8 bkeepfwalive; -}; - -#define rtw_get_ips_mode_req(pwrctrlpriv) \ - (pwrctrlpriv)->ips_mode_req - -#define rtw_ips_mode_req(pwrctrlpriv, ips_mode) \ - ((pwrctrlpriv)->ips_mode_req = (ips_mode)) - -#define RTW_PWR_STATE_CHK_INTERVAL 2000 - -#define _rtw_set_pwr_state_check_timer(pwrctrlpriv, ms) \ - do { \ - _set_timer(&(pwrctrlpriv)->pwr_state_check_timer, (ms)); \ - } while (0) - -#define rtw_set_pwr_state_check_timer(pwrctrl) \ - _rtw_set_pwr_state_check_timer((pwrctrl), \ - (pwrctrl)->pwr_state_check_interval) - -void rtw_init_pwrctrl_priv(struct adapter *adapter); - -void rtw_set_firmware_ps_mode(struct adapter *adapter, u8 mode); -void rtw_set_ps_mode(struct adapter *adapter, u8 ps_mode, u8 smart_ps, - u8 bcn_ant_mode); -void LeaveAllPowerSaveMode(struct adapter *adapter); - -void rtw_ps_processor(struct adapter *padapter); - -void LPS_Enter(struct adapter *adapter); -void LPS_Leave(struct adapter *adapter); - -int rtw_pwr_wakeup(struct adapter *adapter); -int rtw_pm_set_ips(struct adapter *adapter, u8 mode); -int rtw_pm_set_lps(struct adapter *adapter, u8 mode); - -#endif /* __RTL871X_PWRCTRL_H_ */ diff --git a/drivers/staging/r8188eu/include/rtw_recv.h b/drivers/staging/r8188eu/include/rtw_recv.h deleted file mode 100644 index 12026431a3d2..000000000000 --- a/drivers/staging/r8188eu/include/rtw_recv.h +++ /dev/null @@ -1,347 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2007 - 2012 Realtek Corporation. */ - -#ifndef _RTW_RECV_H_ -#define _RTW_RECV_H_ - -#include "osdep_service.h" -#include "drv_types.h" - -#define NR_RECVFRAME 256 - -#define RXFRAME_ALIGN 8 -#define RXFRAME_ALIGN_SZ (1<signal_stat_timer, \ - (recvpriv)->signal_stat_sampling_interval) - -struct sta_recv_priv { - spinlock_t lock; - int option; - struct __queue defrag_q; /* keeping the fragment frame until defrag */ - struct stainfo_rxcache rxcache; -}; - -struct recv_buf { - struct adapter *adapter; - struct urb *purb; - struct sk_buff *pskb; - u8 reuse; -}; - -/* - head -----> - - data -----> - - payload - - tail -----> - - end -----> - - len = (unsigned int )(tail - data); - -*/ -struct recv_frame { - struct list_head list; - struct sk_buff *pkt; - struct adapter *adapter; - u8 fragcnt; - int frame_tag; - struct rx_pkt_attrib attrib; - uint len; - u8 *rx_head; - u8 *rx_data; - u8 *rx_tail; - u8 *rx_end; - void *precvbuf; - struct sta_info *psta; - /* for A-MPDU Rx reordering buffer control */ - struct recv_reorder_ctrl *preorder_ctrl; -}; - -int _rtw_init_recv_priv(struct recv_priv *precvpriv, struct adapter *padapter); -void _rtw_free_recv_priv(struct recv_priv *precvpriv); -s32 rtw_recv_entry(struct recv_frame *precv_frame); -struct recv_frame *_rtw_alloc_recvframe(struct __queue *pfree_recv_queue); -struct recv_frame *rtw_alloc_recvframe(struct __queue *pfree_recv_queue); -int rtw_free_recvframe(struct recv_frame *precvframe, - struct __queue *pfree_recv_queue); -int _rtw_enqueue_recvframe(struct recv_frame *precvframe, struct __queue *queue); -int rtw_enqueue_recvframe(struct recv_frame *precvframe, struct __queue *queue); -void rtw_free_recvframe_queue(struct __queue *pframequeue, - struct __queue *pfree_recv_queue); -u32 rtw_free_uc_swdec_pending_queue(struct adapter *adapter); - -void rtw_reordering_ctrl_timeout_handler(void *pcontext); - -static inline u8 *get_rxmem(struct recv_frame *precvframe) -{ - /* always return rx_head... */ - if (precvframe == NULL) - return NULL; - return precvframe->rx_head; -} - -static inline u8 *recvframe_pull(struct recv_frame *precvframe, int sz) -{ - /* rx_data += sz; move rx_data sz bytes hereafter */ - - /* used for extract sz bytes from rx_data, update rx_data and return - * the updated rx_data to the caller */ - - if (precvframe == NULL) - return NULL; - precvframe->rx_data += sz; - if (precvframe->rx_data > precvframe->rx_tail) { - precvframe->rx_data -= sz; - return NULL; - } - precvframe->len -= sz; - return precvframe->rx_data; -} - -static inline u8 *recvframe_put(struct recv_frame *precvframe, int sz) -{ - /* used for append sz bytes from ptr to rx_tail, update rx_tail - * and return the updated rx_tail to the caller */ - /* after putting, rx_tail must be still larger than rx_end. */ - - if (precvframe == NULL) - return NULL; - - precvframe->rx_tail += sz; - - if (precvframe->rx_tail > precvframe->rx_end) { - precvframe->rx_tail -= sz; - return NULL; - } - precvframe->len += sz; - return precvframe->rx_tail; -} - -static inline u8 *recvframe_pull_tail(struct recv_frame *precvframe, int sz) -{ - /* rmv data from rx_tail (by yitsen) */ - - /* used for extract sz bytes from rx_end, update rx_end and return - * the updated rx_end to the caller */ - /* after pulling, rx_end must be still larger than rx_data. */ - - if (precvframe == NULL) - return NULL; - precvframe->rx_tail -= sz; - if (precvframe->rx_tail < precvframe->rx_data) { - precvframe->rx_tail += sz; - return NULL; - } - precvframe->len -= sz; - return precvframe->rx_tail; -} - -static inline int get_recvframe_len(struct recv_frame *precvframe) -{ - return precvframe->len; -} - -static inline s32 translate_percentage_to_dbm(u32 sig_stren_index) -{ - s32 power; /* in dBm. */ - - /* Translate to dBm (x=0.5y-95). */ - power = (s32)((sig_stren_index + 1) >> 1); - power -= 95; - - return power; -} - -struct sta_info; - -void _rtw_init_sta_recv_priv(struct sta_recv_priv *psta_recvpriv); - -void mgt_dispatcher(struct adapter *padapter, struct recv_frame *precv_frame); - -#endif diff --git a/drivers/staging/r8188eu/include/rtw_rf.h b/drivers/staging/r8188eu/include/rtw_rf.h deleted file mode 100644 index b7267e75346c..000000000000 --- a/drivers/staging/r8188eu/include/rtw_rf.h +++ /dev/null @@ -1,80 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#ifndef __RTW_RF_H_ -#define __RTW_RF_H_ - -#include "rtw_cmd.h" - -#define NumRates (13) - -/* slot time for 11g */ -#define SHORT_SLOT_TIME 9 -#define NON_SHORT_SLOT_TIME 20 - -#define MAX_CHANNEL_NUM 14 /* 2.4 GHz only */ - -#define NUM_REGULATORYS 1 - -struct regulatory_class { - u32 starting_freq; /* MHz, */ - u8 channel_set[MAX_CHANNEL_NUM]; - u8 channel_cck_power[MAX_CHANNEL_NUM]; /* dbm */ - u8 channel_ofdm_power[MAX_CHANNEL_NUM]; /* dbm */ - u8 txpower_limit; /* dbm */ - u8 channel_spacing; /* MHz */ - u8 modem; -}; - -enum capability { - cESS = 0x0001, - cIBSS = 0x0002, - cPollable = 0x0004, - cPollReq = 0x0008, - cPrivacy = 0x0010, - cShortPreamble = 0x0020, - cPBCC = 0x0040, - cChannelAgility = 0x0080, - cSpectrumMgnt = 0x0100, - cQos = 0x0200, /* For HCCA, use with CF-Pollable - * and CF-PollReq */ - cShortSlotTime = 0x0400, - cAPSD = 0x0800, - cRM = 0x1000, /* RRM (Radio Request Measurement) */ - cDSSS_OFDM = 0x2000, - cDelayedBA = 0x4000, - cImmediateBA = 0x8000, -}; - -enum _REG_PREAMBLE_MODE { - PREAMBLE_LONG = 1, - PREAMBLE_AUTO = 2, - PREAMBLE_SHORT = 3, -}; - -/* Bandwidth Offset */ -#define HAL_PRIME_CHNL_OFFSET_DONT_CARE 0 -#define HAL_PRIME_CHNL_OFFSET_LOWER 1 -#define HAL_PRIME_CHNL_OFFSET_UPPER 2 - -/* Represent Channel Width in HT Capabilities */ -/* */ -enum ht_channel_width { - HT_CHANNEL_WIDTH_20 = 0, - HT_CHANNEL_WIDTH_40 = 1, -}; - -/* */ -/* Represent Extension Channel Offset in HT Capabilities */ -/* This is available only in 40Mhz mode. */ -/* */ -enum ht_extchnl_offset { - HT_EXTCHNL_OFFSET_NO_EXT = 0, - HT_EXTCHNL_OFFSET_UPPER = 1, - HT_EXTCHNL_OFFSET_NO_DEF = 2, - HT_EXTCHNL_OFFSET_LOWER = 3, -}; - -u32 rtw_ch2freq(u32 ch); - -#endif /* _RTL8711_RF_H_ */ diff --git a/drivers/staging/r8188eu/include/rtw_security.h b/drivers/staging/r8188eu/include/rtw_security.h deleted file mode 100644 index 783ae18a122a..000000000000 --- a/drivers/staging/r8188eu/include/rtw_security.h +++ /dev/null @@ -1,231 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#ifndef __RTW_SECURITY_H_ -#define __RTW_SECURITY_H_ - -#include "osdep_service.h" -#include "drv_types.h" -#include - -#define _NO_PRIVACY_ 0x0 -#define _WEP40_ 0x1 -#define _TKIP_ 0x2 -#define _TKIP_WTMIC_ 0x3 -#define _AES_ 0x4 -#define _WEP104_ 0x5 -#define _SMS4_ 0x06 - -#define _WPA_IE_ID_ 0xdd -#define _WPA2_IE_ID_ 0x30 - -enum { - ENCRYP_PROTOCOL_OPENSYS, /* open system */ - ENCRYP_PROTOCOL_WEP, /* WEP */ - ENCRYP_PROTOCOL_WPA, /* WPA */ - ENCRYP_PROTOCOL_WPA2, /* WPA2 */ - ENCRYP_PROTOCOL_WAPI, /* WAPI: Not support in this version */ - ENCRYP_PROTOCOL_MAX -}; - -#ifndef Ndis802_11AuthModeWPA2 -#define Ndis802_11AuthModeWPA2 (Ndis802_11AuthModeWPANone + 1) -#endif - -#ifndef Ndis802_11AuthModeWPA2PSK -#define Ndis802_11AuthModeWPA2PSK (Ndis802_11AuthModeWPANone + 2) -#endif - -union pn48 { - u64 val; - -#ifdef __LITTLE_ENDIAN - struct { - u8 TSC0; - u8 TSC1; - u8 TSC2; - u8 TSC3; - u8 TSC4; - u8 TSC5; - u8 TSC6; - u8 TSC7; - } _byte_; - -#elif defined(__BIG_ENDIAN) - - struct { - u8 TSC7; - u8 TSC6; - u8 TSC5; - u8 TSC4; - u8 TSC3; - u8 TSC2; - u8 TSC1; - u8 TSC0; - } _byte_; -#endif -}; - -union Keytype { - u8 skey[16]; - u32 lkey[4]; -}; - -struct rt_pmkid_list { - u8 bUsed; - u8 Bssid[6]; - u8 PMKID[16]; - u8 SsidBuf[33]; - u8 *ssid_octet; - u16 ssid_length; -}; - -struct security_priv { - u32 dot11AuthAlgrthm; /* 802.11 auth, could be open, - * shared, 8021x and authswitch */ - u32 dot11PrivacyAlgrthm; /* This specify the privacy for - * shared auth. algorithm. */ - /* WEP */ - u32 dot11PrivacyKeyIndex; /* this is only valid for legendary - * wep, 0~3 for key id.(tx key index) */ - union Keytype dot11DefKey[4]; /* this is only valid for def. key */ - u32 dot11DefKeylen[4]; - u32 dot118021XGrpPrivacy; /* This specify the privacy algthm. - * used for Grp key */ - u32 dot118021XGrpKeyid; /* key id used for Grp Key - * ( tx key index) */ - union Keytype dot118021XGrpKey[4]; /* 802.1x Group Key, - * for inx0 and inx1 */ - union Keytype dot118021XGrptxmickey[4]; - union Keytype dot118021XGrprxmickey[4]; - union pn48 dot11Grptxpn; /* PN48 used for Grp Key xmit.*/ - union pn48 dot11Grprxpn; /* PN48 used for Grp Key recv.*/ - - struct arc4_ctx xmit_arc4_ctx; - struct arc4_ctx recv_arc4_ctx; - - /* extend security capabilities for AP_MODE */ - unsigned int dot8021xalg;/* 0:disable, 1:psk, 2:802.1x */ - unsigned int wpa_psk;/* 0:disable, bit(0): WPA, bit(1):WPA2 */ - unsigned int wpa_group_cipher; - unsigned int wpa2_group_cipher; - unsigned int wpa_pairwise_cipher; - unsigned int wpa2_pairwise_cipher; - u8 wps_ie[MAX_WPS_IE_LEN];/* added in assoc req */ - int wps_ie_len; - u8 binstallGrpkey; - u8 busetkipkey; - u8 bcheck_grpkey; - u8 bgrpkey_handshake; - s32 sw_encrypt;/* from registry_priv */ - s32 sw_decrypt;/* from registry_priv */ - s32 hw_decrypted;/* if the rx packets is hw_decrypted==false,i - * it means the hw has not been ready. */ - - /* keeps the auth_type & enc_status from upper layer - * ioctl(wpa_supplicant or wzc) */ - u32 ndisauthtype; /* NDIS_802_11_AUTHENTICATION_MODE */ - u32 ndisencryptstatus; /* NDIS_802_11_ENCRYPTION_STATUS */ - struct wlan_bssid_ex sec_bss; /* for joinbss (h2c buffer) usage */ - struct ndis_802_11_wep ndiswep; - u8 assoc_info[600]; - u8 szofcapability[256]; /* for wpa2 usage */ - u8 oidassociation[512]; /* for wpa/wpa2 usage */ - u8 authenticator_ie[256]; /* store ap security information element */ - u8 supplicant_ie[256]; /* store sta security information element */ - - /* for tkip countermeasure */ - u32 last_mic_err_time; - u8 btkip_countermeasure; - u8 btkip_wait_report; - u32 btkip_countermeasure_time; - - /* */ - /* For WPA2 Pre-Authentication. */ - /* */ - struct rt_pmkid_list PMKIDList[NUM_PMKID_CACHE]; - u8 PMKIDIndex; - u8 bWepDefaultKeyIdxSet; -}; - -#define GET_ENCRY_ALGO(psecuritypriv, psta, encry_algo, bmcst) \ -do { \ - switch (psecuritypriv->dot11AuthAlgrthm) { \ - case dot11AuthAlgrthm_Open: \ - case dot11AuthAlgrthm_Shared: \ - case dot11AuthAlgrthm_Auto: \ - encry_algo = (u8)psecuritypriv->dot11PrivacyAlgrthm; \ - break; \ - case dot11AuthAlgrthm_8021X: \ - if (bmcst) \ - encry_algo = (u8)psecuritypriv->dot118021XGrpPrivacy;\ - else \ - encry_algo = (u8)psta->dot118021XPrivacy; \ - break; \ - case dot11AuthAlgrthm_WAPI: \ - encry_algo = (u8)psecuritypriv->dot11PrivacyAlgrthm; \ - break; \ - } \ -} while (0) - -#define SET_ICE_IV_LEN(iv_len, icv_len, encrypt) \ -do { \ - switch (encrypt) { \ - case _WEP40_: \ - case _WEP104_: \ - iv_len = 4; \ - icv_len = 4; \ - break; \ - case _TKIP_: \ - iv_len = 8; \ - icv_len = 4; \ - break; \ - case _AES_: \ - iv_len = 8; \ - icv_len = 8; \ - break; \ - case _SMS4_: \ - iv_len = 18; \ - icv_len = 16; \ - break; \ - default: \ - iv_len = 0; \ - icv_len = 0; \ - break; \ - } \ -} while (0) - -#define GET_TKIP_PN(iv, dot11txpn) \ -do { \ - dot11txpn._byte_.TSC0 = iv[2]; \ - dot11txpn._byte_.TSC1 = iv[0]; \ - dot11txpn._byte_.TSC2 = iv[4]; \ - dot11txpn._byte_.TSC3 = iv[5]; \ - dot11txpn._byte_.TSC4 = iv[6]; \ - dot11txpn._byte_.TSC5 = iv[7]; \ -} while (0) - -#define ROL32(A, n) (((A) << (n)) | (((A)>>(32-(n))) & ((1UL << (n)) - 1))) -#define ROR32(A, n) ROL32((A), 32-(n)) - -struct mic_data { - u32 K0, K1; /* Key */ - u32 L, R; /* Current state */ - u32 M; /* Message accumulator (single word) */ - u32 nBytesInM; /* # bytes in M */ -}; - -void rtw_secmicsetkey(struct mic_data *pmicdata, u8 *key); -void rtw_secmicappendbyte(struct mic_data *pmicdata, u8 b); -void rtw_secmicappend(struct mic_data *pmicdata, u8 *src, u32 nBytes); -void rtw_secgetmic(struct mic_data *pmicdata, u8 *dst); -void rtw_seccalctkipmic(u8 *key, u8 *header, u8 *data, u32 data_len, - u8 *Miccode, u8 priority); -u32 rtw_aes_encrypt(struct adapter *padapter, struct xmit_frame *pxmitframe); -u32 rtw_tkip_encrypt(struct adapter *padapter, struct xmit_frame *pxmitframe); -void rtw_wep_encrypt(struct adapter *padapter, struct xmit_frame *pxmitframe); -u32 rtw_aes_decrypt(struct adapter *padapter, struct recv_frame *precvframe); -u32 rtw_tkip_decrypt(struct adapter *padapter, struct recv_frame *precvframe); -void rtw_wep_decrypt(struct adapter *padapter, struct recv_frame *precvframe); - -#endif /* __RTL871X_SECURITY_H_ */ diff --git a/drivers/staging/r8188eu/include/rtw_xmit.h b/drivers/staging/r8188eu/include/rtw_xmit.h deleted file mode 100644 index feeac85aedb0..000000000000 --- a/drivers/staging/r8188eu/include/rtw_xmit.h +++ /dev/null @@ -1,334 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#ifndef _RTW_XMIT_H_ -#define _RTW_XMIT_H_ - -#include "osdep_service.h" -#include "drv_types.h" - -#define NR_XMITFRAME 256 -#define WMM_XMIT_THRESHOLD (NR_XMITFRAME * 2 / 5) - -#define MAX_XMITBUF_SZ (20480) /* 20k */ -#define NR_XMITBUFF (4) - -#define XMITBUF_ALIGN_SZ 4 - -/* xmit extension buff defination */ -#define MAX_XMIT_EXTBUF_SZ (1536) -#define NR_XMIT_EXTBUFF (32) - -#define MAX_NUMBLKS (1) - -#define XMIT_VO_QUEUE (0) -#define XMIT_VI_QUEUE (1) -#define XMIT_BE_QUEUE (2) -#define XMIT_BK_QUEUE (3) - -#define VO_QUEUE_INX 0 -#define VI_QUEUE_INX 1 -#define BE_QUEUE_INX 2 -#define BK_QUEUE_INX 3 -#define BCN_QUEUE_INX 4 -#define MGT_QUEUE_INX 5 -#define HIGH_QUEUE_INX 6 -#define TXCMD_QUEUE_INX 7 - -#define HW_QUEUE_ENTRY 8 - -#define WEP_IV(pattrib_iv, dot11txpn, keyidx)\ -do {\ - pattrib_iv[0] = dot11txpn._byte_.TSC0;\ - pattrib_iv[1] = dot11txpn._byte_.TSC1;\ - pattrib_iv[2] = dot11txpn._byte_.TSC2;\ - pattrib_iv[3] = ((keyidx & 0x3)<<6);\ - dot11txpn.val = (dot11txpn.val == 0xffffff) ? 0 : (dot11txpn.val+1);\ -} while (0) - -#define TKIP_IV(pattrib_iv, dot11txpn, keyidx)\ -do {\ - pattrib_iv[0] = dot11txpn._byte_.TSC1;\ - pattrib_iv[1] = (dot11txpn._byte_.TSC1 | 0x20) & 0x7f;\ - pattrib_iv[2] = dot11txpn._byte_.TSC0;\ - pattrib_iv[3] = BIT(5) | ((keyidx & 0x3)<<6);\ - pattrib_iv[4] = dot11txpn._byte_.TSC2;\ - pattrib_iv[5] = dot11txpn._byte_.TSC3;\ - pattrib_iv[6] = dot11txpn._byte_.TSC4;\ - pattrib_iv[7] = dot11txpn._byte_.TSC5;\ - dot11txpn.val = dot11txpn.val == 0xffffffffffffULL ? 0 : (dot11txpn.val+1);\ -} while (0) - -#define AES_IV(pattrib_iv, dot11txpn, keyidx)\ -do { \ - pattrib_iv[0] = dot11txpn._byte_.TSC0; \ - pattrib_iv[1] = dot11txpn._byte_.TSC1; \ - pattrib_iv[2] = 0; \ - pattrib_iv[3] = BIT(5) | ((keyidx & 0x3)<<6); \ - pattrib_iv[4] = dot11txpn._byte_.TSC2; \ - pattrib_iv[5] = dot11txpn._byte_.TSC3; \ - pattrib_iv[6] = dot11txpn._byte_.TSC4; \ - pattrib_iv[7] = dot11txpn._byte_.TSC5; \ - dot11txpn.val = dot11txpn.val == 0xffffffffffffULL ? 0 : (dot11txpn.val+1);\ -} while (0) - -#define HWXMIT_ENTRY 4 - -#define TXDESC_SIZE 32 - -#define PACKET_OFFSET_SZ (8) -#define TXDESC_OFFSET (TXDESC_SIZE + PACKET_OFFSET_SZ) - -struct tx_desc { - /* DWORD 0 */ - __le32 txdw0; - __le32 txdw1; - __le32 txdw2; - __le32 txdw3; - __le32 txdw4; - __le32 txdw5; - __le32 txdw6; - __le32 txdw7; -}; - -union txdesc { - struct tx_desc txdesc; - unsigned int value[TXDESC_SIZE>>2]; -}; - -struct hw_xmit { - struct list_head *sta_list; - int accnt; -}; - -/* reduce size */ -struct pkt_attrib { - u8 type; - u8 subtype; - u8 bswenc; - u8 dhcp_pkt; - u16 ether_type; - u16 seqnum; - u16 pkt_hdrlen; /* the original 802.3 pkt header len */ - u16 hdrlen; /* the WLAN Header Len */ - u32 pktlen; /* the original 802.3 pkt raw_data len (not include - * ether_hdr data) */ - u32 last_txcmdsz; - u8 nr_frags; - u8 encrypt; /* when 0 indicate no encrypt. when non-zero, - * indicate the encrypt algorithm */ - u8 iv_len; - u8 icv_len; - u8 iv[18]; - u8 icv[16]; - u8 priority; - u8 ack_policy; - u8 mac_id; - u8 vcs_mode; /* virtual carrier sense method */ - u8 dst[ETH_ALEN] __aligned(2); - u8 src[ETH_ALEN] __aligned(2); - u8 ta[ETH_ALEN] __aligned(2); - u8 ra[ETH_ALEN] __aligned(2); - u8 key_idx; - u8 qos_en; - u8 ht_en; - u8 raid;/* rate adpative id */ - u8 bwmode; - u8 ch_offset;/* PRIME_CHNL_OFFSET */ - u8 sgi;/* short GI */ - u8 ampdu_en;/* tx ampdu enable */ - u8 mdata;/* more data bit */ - u8 pctrl;/* per packet txdesc control enable */ - u8 triggered;/* for ap mode handling Power Saving sta */ - u8 qsel; - u8 eosp; - u8 rate; - u8 intel_proxim; - u8 retry_ctrl; - struct sta_info *psta; -}; - -#define WLANHDR_OFFSET 64 - -#define NULL_FRAMETAG (0x0) -#define DATA_FRAMETAG 0x01 -#define MGNT_FRAMETAG 0x03 - -#define TXAGG_FRAMETAG 0x08 - -struct submit_ctx { - u32 submit_time; /* */ - u32 timeout_ms; /* <0: not synchronous, 0: wait forever, >0: up to ms waiting */ - int status; /* status for operation */ - struct completion done; -}; - -enum { - RTW_SCTX_SUBMITTED = -1, - RTW_SCTX_DONE_SUCCESS = 0, - RTW_SCTX_DONE_UNKNOWN, - RTW_SCTX_DONE_TIMEOUT, - RTW_SCTX_DONE_BUF_ALLOC, - RTW_SCTX_DONE_BUF_FREE, - RTW_SCTX_DONE_WRITE_PORT_ERR, - RTW_SCTX_DONE_TX_DESC_NA, - RTW_SCTX_DONE_TX_DENY, - RTW_SCTX_DONE_CCX_PKT_FAIL, - RTW_SCTX_DONE_DRV_STOP, - RTW_SCTX_DONE_DEV_REMOVE, -}; - -void rtw_sctx_init(struct submit_ctx *sctx, int timeout_ms); -int rtw_sctx_wait(struct submit_ctx *sctx); -void rtw_sctx_done_err(struct submit_ctx **sctx, int status); - -struct xmit_buf { - struct list_head list; - struct adapter *padapter; - u8 *pallocated_buf; - u8 *pbuf; - void *priv_data; - u16 ext_tag; /* 0: Normal xmitbuf, 1: extension xmitbuf. */ - bool high_queue; - u32 alloc_sz; - u32 len; - struct submit_ctx *sctx; - struct urb *pxmit_urb; - int last[8]; -}; - -struct xmit_frame { - struct list_head list; - struct pkt_attrib attrib; - struct sk_buff *pkt; - int frame_tag; - struct adapter *padapter; - u8 *buf_addr; - struct xmit_buf *pxmitbuf; - - u8 agg_num; - s8 pkt_offset; - u8 ack_report; -}; - -struct tx_servq { - struct list_head tx_pending; - struct list_head sta_pending; - int qcnt; -}; - -struct sta_xmit_priv { - spinlock_t lock; - struct tx_servq be_q; /* priority == 0,3 */ - struct tx_servq bk_q; /* priority == 1,2 */ - struct tx_servq vi_q; /* priority == 4,5 */ - struct tx_servq vo_q; /* priority == 6,7 */ - u16 txseq_tid[16]; -}; - -struct hw_txqueue { - volatile int head; - volatile int tail; - volatile int free_sz; /* in units of 64 bytes */ - volatile int free_cmdsz; - volatile int txsz[8]; - uint ff_hwaddr; - uint cmd_hwaddr; - int ac_tag; -}; - -struct xmit_priv { - spinlock_t lock; - struct list_head be_pending; - struct list_head bk_pending; - struct list_head vi_pending; - struct list_head vo_pending; - u8 *pallocated_frame_buf; - u8 *pxmit_frame_buf; - uint free_xmitframe_cnt; - struct __queue free_xmit_queue; - uint frag_len; - struct adapter *adapter; - u64 tx_bytes; - u64 tx_pkts; - u64 tx_drop; - u64 last_tx_bytes; - u64 last_tx_pkts; - struct hw_xmit *hwxmits; - u8 wmm_para_seq[4];/* sequence for wmm ac parameter strength - * from large to small. it's value is 0->vo, - * 1->vi, 2->be, 3->bk. */ - struct tasklet_struct xmit_tasklet; - struct __queue free_xmitbuf_queue; - struct __queue pending_xmitbuf_queue; - u8 *pallocated_xmitbuf; - u8 *pxmitbuf; - uint free_xmitbuf_cnt; - struct __queue free_xmit_extbuf_queue; - u8 *pallocated_xmit_extbuf; - u8 *pxmit_extbuf; - uint free_xmit_extbuf_cnt; - u16 nqos_ssn; - int ack_tx; - struct mutex ack_tx_mutex; - struct submit_ctx ack_tx_ops; -}; - -struct pkt_file { - struct sk_buff *pkt; - size_t pkt_len; /* the remainder length of the open_file */ - unsigned char *cur_buffer; - u8 *buf_start; - u8 *cur_addr; - size_t buf_len; -}; - -struct xmit_buf *rtw_alloc_xmitbuf_ext(struct xmit_priv *pxmitpriv); -s32 rtw_free_xmitbuf_ext(struct xmit_priv *pxmitpriv, - struct xmit_buf *pxmitbuf); -struct xmit_buf *rtw_alloc_xmitbuf(struct xmit_priv *pxmitpriv); -s32 rtw_free_xmitbuf(struct xmit_priv *pxmitpriv, - struct xmit_buf *pxmitbuf); -void rtw_count_tx_stats(struct adapter *padapter, - struct xmit_frame *pxmitframe, int sz); -s32 rtw_make_wlanhdr(struct adapter *padapter, u8 *hdr, - struct pkt_attrib *pattrib); -s32 rtw_put_snap(u8 *data, u16 h_proto); - -struct xmit_frame *rtw_alloc_xmitframe(struct xmit_priv *pxmitpriv); -s32 rtw_free_xmitframe(struct xmit_priv *pxmitpriv, - struct xmit_frame *pxmitframe); -void rtw_free_xmitframe_list(struct xmit_priv *pxmitpriv, struct list_head *xframe_list); -struct tx_servq *rtw_get_sta_pending(struct adapter *padapter, - struct sta_info *psta, int up, u8 *ac); -struct xmit_frame *rtw_dequeue_xframe(struct xmit_priv *pxmitpriv, - struct hw_xmit *phwxmit_i); - -s32 rtw_xmit_classifier(struct adapter *padapter, - struct xmit_frame *pxmitframe); -s32 rtw_xmitframe_coalesce(struct adapter *padapter, struct sk_buff *pkt, - struct xmit_frame *pxmitframe); -s32 _rtw_init_hw_txqueue(struct hw_txqueue *phw_txqueue, u8 ac_tag); -void _rtw_init_sta_xmit_priv(struct sta_xmit_priv *psta_xmitpriv); -s32 rtw_txframes_pending(struct adapter *padapter); -s32 rtw_txframes_sta_ac_pending(struct adapter *padapter, - struct pkt_attrib *pattrib); -int _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter); -void _rtw_free_xmit_priv(struct xmit_priv *pxmitpriv); -int rtw_alloc_hwxmits(struct adapter *padapter); -s32 rtw_xmit(struct adapter *padapter, struct sk_buff **pkt); - -int xmitframe_enqueue_for_sleeping_sta(struct adapter *padapter, struct xmit_frame *pxmitframe); -void stop_sta_xmit(struct adapter *padapter, struct sta_info *psta); -void wakeup_sta_to_xmit(struct adapter *padapter, struct sta_info *psta); -void xmit_delivery_enabled_frames(struct adapter *padapter, struct sta_info *psta); - -u8 qos_acm(u8 acm_mask, u8 priority); -u32 rtw_get_ff_hwaddr(struct xmit_frame *pxmitframe); -int rtw_ack_tx_wait(struct xmit_priv *pxmitpriv, u32 timeout_ms); -void rtw_ack_tx_done(struct xmit_priv *pxmitpriv, int status); - -void rtw_xmit_complete(struct adapter *padapter, struct xmit_frame *pxframe); -netdev_tx_t rtw_xmit_entry(struct sk_buff *pkt, struct net_device *pnetdev); - -#endif /* _RTL871X_XMIT_H_ */ diff --git a/drivers/staging/r8188eu/include/sta_info.h b/drivers/staging/r8188eu/include/sta_info.h deleted file mode 100644 index e42f4b4c6e24..000000000000 --- a/drivers/staging/r8188eu/include/sta_info.h +++ /dev/null @@ -1,313 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#ifndef __STA_INFO_H_ -#define __STA_INFO_H_ - -#include "osdep_service.h" -#include "drv_types.h" -#include "wifi.h" - -#define IBSS_START_MAC_ID 2 -#define NUM_STA 32 -#define NUM_ACL 16 - -/* if mode ==0, then the sta is allowed once the addr is hit. */ -/* if mode ==1, then the sta is rejected once the addr is non-hit. */ -struct rtw_wlan_acl_node { - struct list_head list; - u8 addr[ETH_ALEN]; - u8 valid; -}; - -/* mode=0, disable */ -/* mode=1, accept unless in deny list */ -/* mode=2, deny unless in accept list */ -struct wlan_acl_pool { - int mode; - int num; - struct rtw_wlan_acl_node aclnode[NUM_ACL]; - struct __queue acl_node_q; -}; - -struct rssi_sta { - s32 UndecoratedSmoothedPWDB; - s32 UndecoratedSmoothedCCK; - s32 UndecoratedSmoothedOFDM; - u64 PacketMap; - u8 ValidBit; -}; - -struct stainfo_stats { - u64 rx_mgnt_pkts; - u64 rx_beacon_pkts; - u64 rx_probereq_pkts; - u64 rx_probersp_pkts; - u64 rx_probersp_bm_pkts; - u64 rx_probersp_uo_pkts; - u64 rx_ctrl_pkts; - u64 rx_data_pkts; - - u64 last_rx_beacon_pkts; - u64 last_rx_probereq_pkts; - u64 last_rx_probersp_pkts; - u64 last_rx_probersp_bm_pkts; - u64 last_rx_probersp_uo_pkts; - u64 last_rx_ctrl_pkts; - u64 last_rx_data_pkts; - u64 rx_bytes; - u64 rx_drops; - u64 tx_pkts; - u64 tx_bytes; - u64 tx_drops; -}; - -struct sta_info { - spinlock_t lock; - struct list_head list; /* free_sta_queue */ - struct list_head hash_list; /* sta_hash */ - - struct sta_xmit_priv sta_xmitpriv; - struct sta_recv_priv sta_recvpriv; - - struct __queue sleep_q; - unsigned int sleepq_len; - - uint state; - uint aid; - uint mac_id; - uint qos_option; - u8 hwaddr[ETH_ALEN]; - - uint ieee8021x_blocked; /* 0: allowed, 1:blocked */ - uint dot118021XPrivacy; /* aes, tkip... */ - union Keytype dot11tkiptxmickey; - union Keytype dot11tkiprxmickey; - union Keytype dot118021x_UncstKey; - union pn48 dot11txpn; /* PN48 used for Unicast xmit. */ - union pn48 dot11rxpn; /* PN48 used for Unicast recv. */ - u8 bssrateset[16]; - u32 bssratelen; - s32 rssi; - s32 signal_quality; - - u8 cts2self; - u8 rtsen; - - u8 raid; - u8 init_rate; - u32 ra_mask; - u8 wireless_mode; /* NETWORK_TYPE */ - struct stainfo_stats sta_stats; - - /* for A-MPDU TX, ADDBA timeout check */ - struct timer_list addba_retry_timer; - - /* for A-MPDU Rx reordering buffer control */ - struct recv_reorder_ctrl recvreorder_ctrl[16]; - - /* for A-MPDU Tx */ - /* unsigned char ampdu_txen_bitmap; */ - u16 BA_starting_seqctrl[16]; - - struct ht_priv htpriv; - - /* Notes: */ - /* STA_Mode: */ - /* curr_network(mlme_priv/security_priv/qos/ht) + - * sta_info: (STA & AP) CAP/INFO */ - /* scan_q: AP CAP/INFO */ - - /* AP_Mode: */ - /* curr_network(mlme_priv/security_priv/qos/ht) : AP CAP/INFO */ - /* sta_info: (AP & STA) CAP/INFO */ - - struct list_head asoc_list; - struct list_head auth_list; - - unsigned int expire_to; - unsigned int auth_seq; - unsigned int authalg; - unsigned char chg_txt[128]; - - u16 capability; - int flags; - - int dot8021xalg;/* 0:disable, 1:psk, 2:802.1x */ - int wpa_psk;/* 0:disable, bit(0): WPA, bit(1):WPA2 */ - int wpa_group_cipher; - int wpa2_group_cipher; - int wpa_pairwise_cipher; - int wpa2_pairwise_cipher; - - u8 bpairwise_key_installed; - - u8 wpa_ie[32]; - - u8 nonerp_set; - u8 no_short_slot_time_set; - u8 no_short_preamble_set; - u8 no_ht_gf_set; - u8 no_ht_set; - u8 ht_20mhz_set; - - unsigned int tx_ra_bitmap; - u8 qos_info; - - u8 max_sp_len; - u8 uapsd_bk;/* BIT(0): Delivery enabled, BIT(1): Trigger enabled */ - u8 uapsd_be; - u8 uapsd_vi; - u8 uapsd_vo; - - u8 has_legacy_ac; - unsigned int sleepq_ac_len; - - /* p2p priv data */ - u8 is_p2p_device; - u8 p2p_status_code; - - /* p2p client info */ - u8 dev_addr[ETH_ALEN]; - u8 dev_cap; - u16 config_methods; - u8 primary_dev_type[8]; - u8 num_of_secdev_type; - u8 secdev_types_list[32];/* 32/8 == 4; */ - u16 dev_name_len; - u8 dev_name[32]; - u8 under_exist_checking; - u8 keep_alive_trycnt; - - /* for DM */ - struct rssi_sta rssi_stat; - - /* ================ODM Relative Info======================= */ - /* Please be careful, don't declare too much structure here. - * It will cost memory * STA support num. */ - /* 2011/10/20 MH Add for ODM STA info. */ - /* Driver Write */ - u8 bValid; /* record the sta status link or not? */ - u8 IOTPeer; /* Enum value. HT_IOT_PEER_E */ - u8 rssi_level; /* for Refresh RA mask */ - /* ODM Write */ - /* 1 PHY_STATUS_INFO */ - u8 RSSI_Path[4]; /* */ - u8 RSSI_Ave; - u8 RXEVM[4]; - u8 RXSNR[4]; - - /* ================ODM Relative Info======================= */ - /* */ - - /* To store the sequence number of received management frame */ - u16 RxMgmtFrameSeqNum; -}; - -#define sta_rx_pkts(sta) \ - (sta->sta_stats.rx_mgnt_pkts \ - + sta->sta_stats.rx_ctrl_pkts \ - + sta->sta_stats.rx_data_pkts) - -#define sta_rx_data_pkts(sta) \ - (sta->sta_stats.rx_data_pkts) - -#define sta_last_rx_data_pkts(sta) \ - (sta->sta_stats.last_rx_data_pkts) - -#define sta_rx_beacon_pkts(sta) \ - (sta->sta_stats.rx_beacon_pkts) - -#define sta_last_rx_beacon_pkts(sta) \ - (sta->sta_stats.last_rx_beacon_pkts) - -#define sta_rx_probersp_pkts(sta) \ - (sta->sta_stats.rx_probersp_pkts) - -#define sta_last_rx_probersp_pkts(sta) \ - (sta->sta_stats.last_rx_probersp_pkts) - -#define sta_update_last_rx_pkts(sta) \ -do { \ - sta->sta_stats.last_rx_beacon_pkts = sta->sta_stats.rx_beacon_pkts; \ - sta->sta_stats.last_rx_probereq_pkts = sta->sta_stats.rx_probereq_pkts; \ - sta->sta_stats.last_rx_probersp_pkts = sta->sta_stats.rx_probersp_pkts; \ - sta->sta_stats.last_rx_probersp_bm_pkts = sta->sta_stats.rx_probersp_bm_pkts; \ - sta->sta_stats.last_rx_probersp_uo_pkts = sta->sta_stats.rx_probersp_uo_pkts; \ - sta->sta_stats.last_rx_ctrl_pkts = sta->sta_stats.rx_ctrl_pkts; \ - sta->sta_stats.last_rx_data_pkts = sta->sta_stats.rx_data_pkts; \ -} while (0) - -struct sta_priv { - u8 *pallocated_stainfo_buf; - u8 *pstainfo_buf; - struct __queue free_sta_queue; - - spinlock_t sta_hash_lock; - struct list_head sta_hash[NUM_STA]; - int asoc_sta_count; - struct __queue sleep_q; - struct __queue wakeup_q; - - struct adapter *padapter; - - spinlock_t asoc_list_lock; - struct list_head asoc_list; - - struct list_head auth_list; - spinlock_t auth_list_lock; - u8 asoc_list_cnt; - u8 auth_list_cnt; - - unsigned int auth_to; /* sec, time to expire in authenticating. */ - unsigned int assoc_to; /* sec, time to expire before associating. */ - unsigned int expire_to; /* sec , time to expire after associated. */ - - /* pointers to STA info; based on allocated AID or NULL if AID free - * AID is in the range 1-2007, so sta_aid[0] corresponders to AID 1 - * and so on - */ - struct sta_info *sta_aid[NUM_STA]; - - u16 sta_dz_bitmap;/* only support 15 stations, station aid bitmap - * for sleeping sta. */ - u16 tim_bitmap; /* only support 15 stations, aid=0~15 mapping - * bit0~bit15 */ - - u16 max_num_sta; - - struct wlan_acl_pool acl_list; -}; - -static inline u32 wifi_mac_hash(u8 *mac) -{ - u32 x; - - x = mac[0]; - x = (x << 2) ^ mac[1]; - x = (x << 2) ^ mac[2]; - x = (x << 2) ^ mac[3]; - x = (x << 2) ^ mac[4]; - x = (x << 2) ^ mac[5]; - - x ^= x >> 8; - x = x & (NUM_STA - 1); - return x; -} - -int _rtw_init_sta_priv(struct sta_priv *pstapriv); -void _rtw_free_sta_priv(struct sta_priv *pstapriv); - -#define stainfo_offset_valid(offset) (offset < NUM_STA && offset >= 0) -int rtw_stainfo_offset(struct sta_priv *stapriv, struct sta_info *sta); -struct sta_info *rtw_get_stainfo_by_offset(struct sta_priv *stapriv, int off); - -struct sta_info *rtw_alloc_stainfo(struct sta_priv *stapriv, u8 *hwaddr); -void rtw_free_stainfo(struct adapter *adapt, struct sta_info *psta); -void rtw_free_all_stainfo(struct adapter *adapt); -struct sta_info *rtw_get_stainfo(struct sta_priv *stapriv, u8 *hwaddr); -u32 rtw_init_bcmc_stainfo(struct adapter *adapt); -struct sta_info *rtw_get_bcmc_stainfo(struct adapter *padapter); -u8 rtw_access_ctrl(struct adapter *padapter, u8 *mac_addr); - -#endif /* _STA_INFO_H_ */ diff --git a/drivers/staging/r8188eu/include/usb_ops.h b/drivers/staging/r8188eu/include/usb_ops.h deleted file mode 100644 index 5bd8ce37aebf..000000000000 --- a/drivers/staging/r8188eu/include/usb_ops.h +++ /dev/null @@ -1,57 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#ifndef __USB_OPS_H_ -#define __USB_OPS_H_ - -#include "osdep_service.h" -#include "drv_types.h" -#include "osdep_intf.h" - -#define REALTEK_USB_VENQT_READ (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE) -#define REALTEK_USB_VENQT_WRITE (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE) -#define REALTEK_USB_VENQT_CMD_REQ 0x05 -#define REALTEK_USB_VENQT_CMD_IDX 0x00 - -#define ALIGNMENT_UNIT 16 -#define MAX_VENDOR_REQ_CMD_SIZE 254 /* 8188cu SIE Support */ -#define MAX_USB_IO_CTL_SIZE (MAX_VENDOR_REQ_CMD_SIZE + ALIGNMENT_UNIT) - -/* - * Increase and check if the continual_urb_error of this @param dvobjprivei - * is larger than MAX_CONTINUAL_URB_ERR - * @return true: - * @return false: - */ -static inline bool rtw_inc_and_chk_continual_urb_error(struct dvobj_priv *dvobj) -{ - int value = atomic_inc_return(&dvobj->continual_urb_error); - - if (value > MAX_CONTINUAL_URB_ERR) - return true; - - return false; -} - -/* -* Set the continual_urb_error of this @param dvobjprive to 0 -*/ -static inline void rtw_reset_continual_urb_error(struct dvobj_priv *dvobj) -{ - atomic_set(&dvobj->continual_urb_error, 0); -} - -#define USB_HIGH_SPEED_BULK_SIZE 512 -#define USB_FULL_SPEED_BULK_SIZE 64 - -static inline bool rtw_usb_bulk_size_boundary(struct adapter *padapter, int buf_len) -{ - struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter); - - if (pdvobjpriv->pusbdev->speed == USB_SPEED_HIGH) - return buf_len % USB_HIGH_SPEED_BULK_SIZE == 0; - else - return buf_len % USB_FULL_SPEED_BULK_SIZE == 0; -} - -#endif /* __USB_OPS_H_ */ diff --git a/drivers/staging/r8188eu/include/usb_osintf.h b/drivers/staging/r8188eu/include/usb_osintf.h deleted file mode 100644 index f271e93e9ab9..000000000000 --- a/drivers/staging/r8188eu/include/usb_osintf.h +++ /dev/null @@ -1,21 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#ifndef __USB_OSINTF_H -#define __USB_OSINTF_H - -#include "osdep_service.h" -#include "drv_types.h" - -extern char *rtw_initmac; -extern int rtw_mc2u_disable; - -#define USBD_HALTED(Status) ((u32)(Status) >> 30 == 3) - -void netdev_br_init(struct net_device *netdev); -void dhcp_flag_bcast(struct adapter *priv, struct sk_buff *skb); -void *scdb_findEntry(struct adapter *priv, unsigned char *ipAddr); -void nat25_db_expire(struct adapter *priv); -int nat25_db_handle(struct adapter *priv, struct sk_buff *skb, int method); - -#endif diff --git a/drivers/staging/r8188eu/include/wifi.h b/drivers/staging/r8188eu/include/wifi.h deleted file mode 100644 index 254a4bc1a141..000000000000 --- a/drivers/staging/r8188eu/include/wifi.h +++ /dev/null @@ -1,773 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2007 - 2012 Realtek Corporation. */ - -#ifndef _WIFI_H_ -#define _WIFI_H_ - -#include -#include - -#define WLAN_ETHHDR_LEN 14 -#define WLAN_HDR_A3_LEN 24 -#define WLAN_HDR_A3_QOS_LEN 26 -#define WLAN_SSID_MAXLEN 32 - -enum WIFI_FRAME_SUBTYPE { - /* below is for mgt frame */ - WIFI_ASSOCREQ = (0 | IEEE80211_FTYPE_MGMT), - WIFI_ASSOCRSP = (BIT(4) | IEEE80211_FTYPE_MGMT), - WIFI_REASSOCREQ = (BIT(5) | IEEE80211_FTYPE_MGMT), - WIFI_REASSOCRSP = (BIT(5) | BIT(4) | IEEE80211_FTYPE_MGMT), - WIFI_PROBEREQ = (BIT(6) | IEEE80211_FTYPE_MGMT), - WIFI_PROBERSP = (BIT(6) | BIT(4) | IEEE80211_FTYPE_MGMT), - WIFI_BEACON = (BIT(7) | IEEE80211_FTYPE_MGMT), - WIFI_ATIM = (BIT(7) | BIT(4) | IEEE80211_FTYPE_MGMT), - WIFI_DISASSOC = (BIT(7) | BIT(5) | IEEE80211_FTYPE_MGMT), - WIFI_AUTH = (BIT(7) | BIT(5) | BIT(4) | IEEE80211_FTYPE_MGMT), - WIFI_DEAUTH = (BIT(7) | BIT(6) | IEEE80211_FTYPE_MGMT), - WIFI_ACTION = (BIT(7) | BIT(6) | BIT(4) | IEEE80211_FTYPE_MGMT), - - /* below is for control frame */ - WIFI_PSPOLL = (BIT(7) | BIT(5) | IEEE80211_FTYPE_CTL), - - /* below is for data frame */ - WIFI_DATA = (0 | IEEE80211_FTYPE_DATA), - WIFI_DATA_CFACK = (BIT(4) | IEEE80211_FTYPE_DATA), - WIFI_DATA_CFPOLL = (BIT(5) | IEEE80211_FTYPE_DATA), - WIFI_DATA_CFACKPOLL = (BIT(5) | BIT(4) | IEEE80211_FTYPE_DATA), - WIFI_DATA_NULL = (BIT(6) | IEEE80211_FTYPE_DATA), - WIFI_QOS_DATA_NULL = (BIT(6) | IEEE80211_STYPE_QOS_DATA | IEEE80211_FTYPE_DATA), -}; - -enum WIFI_REASON_CODE { - _RSON_RESERVED_ = 0, - _RSON_UNSPECIFIED_ = 1, - _RSON_AUTH_NO_LONGER_VALID_ = 2, - _RSON_DEAUTH_STA_LEAVING_ = 3, - _RSON_INACTIVITY_ = 4, - _RSON_UNABLE_HANDLE_ = 5, - _RSON_CLS2_ = 6, - _RSON_CLS3_ = 7, - _RSON_DISAOC_STA_LEAVING_ = 8, - _RSON_ASOC_NOT_AUTH_ = 9, - - /* WPA reason */ - _RSON_INVALID_IE_ = 13, - _RSON_MIC_FAILURE_ = 14, - _RSON_4WAY_HNDSHK_TIMEOUT_ = 15, - _RSON_GROUP_KEY_UPDATE_TIMEOUT_ = 16, - _RSON_DIFF_IE_ = 17, - _RSON_MLTCST_CIPHER_NOT_VALID_ = 18, - _RSON_UNICST_CIPHER_NOT_VALID_ = 19, - _RSON_AKMP_NOT_VALID_ = 20, - _RSON_UNSUPPORT_RSNE_VER_ = 21, - _RSON_INVALID_RSNE_CAP_ = 22, - _RSON_IEEE_802DOT1X_AUTH_FAIL_ = 23, - - /* belowing are Realtek definition */ - _RSON_PMK_NOT_AVAILABLE_ = 24, - _RSON_TDLS_TEAR_TOOFAR_ = 25, - _RSON_TDLS_TEAR_UN_RSN_ = 26, -}; - -enum WIFI_STATUS_CODE { - _STATS_SUCCESSFUL_ = 0, - _STATS_FAILURE_ = 1, - _STATS_CAP_FAIL_ = 10, - _STATS_NO_ASOC_ = 11, - _STATS_OTHER_ = 12, - _STATS_NO_SUPP_ALG_ = 13, - _STATS_OUT_OF_AUTH_SEQ_ = 14, - _STATS_CHALLENGE_FAIL_ = 15, - _STATS_AUTH_TIMEOUT_ = 16, - _STATS_UNABLE_HANDLE_STA_ = 17, - _STATS_RATE_FAIL_ = 18, -}; - -/* entended */ -/* IEEE 802.11b */ -#define WLAN_STATUS_ASSOC_DENIED_NOSHORT 19 -#define WLAN_STATUS_ASSOC_DENIED_NOPBCC 20 -#define WLAN_STATUS_ASSOC_DENIED_NOAGILITY 21 -/* IEEE 802.11h */ -#define WLAN_STATUS_SPEC_MGMT_REQUIRED 22 -#define WLAN_STATUS_PWR_CAPABILITY_NOT_VALID 23 -#define WLAN_STATUS_SUPPORTED_CHANNEL_NOT_VALID 24 -/* IEEE 802.11g */ -#define WLAN_STATUS_ASSOC_DENIED_NO_SHORT_SLOT_TIME 25 -#define WLAN_STATUS_ASSOC_DENIED_NO_ER_PBCC 26 -#define WLAN_STATUS_ASSOC_DENIED_NO_DSSS_OFDM 27 -/* IEEE 802.11w */ -#define WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY 30 -#define WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION 31 -/* IEEE 802.11i */ -#define WLAN_STATUS_INVALID_IE 40 -#define WLAN_STATUS_GROUP_CIPHER_NOT_VALID 41 -#define WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID 42 -#define WLAN_STATUS_AKMP_NOT_VALID 43 -#define WLAN_STATUS_UNSUPPORTED_RSN_IE_VERSION 44 -#define WLAN_STATUS_INVALID_RSN_IE_CAPAB 45 -#define WLAN_STATUS_CIPHER_REJECTED_PER_POLICY 46 -#define WLAN_STATUS_TS_NOT_CREATED 47 -#define WLAN_STATUS_DIRECT_LINK_NOT_ALLOWED 48 -#define WLAN_STATUS_DEST_STA_NOT_PRESENT 49 -#define WLAN_STATUS_DEST_STA_NOT_QOS_STA 50 -#define WLAN_STATUS_ASSOC_DENIED_LISTEN_INT_TOO_LARGE 51 -/* IEEE 802.11r */ -#define WLAN_STATUS_INVALID_FT_ACTION_FRAME_COUNT 52 -#define WLAN_STATUS_INVALID_PMKID 53 -#define WLAN_STATUS_INVALID_MDIE 54 -#define WLAN_STATUS_INVALID_FTIE 55 - -enum WIFI_REG_DOMAIN { - DOMAIN_FCC = 1, - DOMAIN_IC = 2, - DOMAIN_ETSI = 3, - DOMAIN_SPA = 4, - DOMAIN_FRANCE = 5, - DOMAIN_MKK = 6, - DOMAIN_ISRAEL = 7, - DOMAIN_MKK1 = 8, - DOMAIN_MKK2 = 9, - DOMAIN_MKK3 = 10, - DOMAIN_MAX -}; - -#define _TO_DS_ BIT(8) -#define _FROM_DS_ BIT(9) -#define _MORE_FRAG_ BIT(10) -#define _RETRY_ BIT(11) -#define _PWRMGT_ BIT(12) -#define _MORE_DATA_ BIT(13) -#define _PRIVACY_ BIT(14) - -#define SetToDs(pbuf) \ - *(__le16 *)(pbuf) |= cpu_to_le16(_TO_DS_) - -#define GetToDs(pbuf) (((*(__le16 *)(pbuf)) & cpu_to_le16(_TO_DS_)) != 0) - -#define SetFrDs(pbuf) \ - *(__le16 *)(pbuf) |= cpu_to_le16(_FROM_DS_) - -#define GetFrDs(pbuf) (((*(__le16 *)(pbuf)) & cpu_to_le16(_FROM_DS_)) != 0) - -#define SetMFrag(pbuf) \ - *(__le16 *)(pbuf) |= cpu_to_le16(_MORE_FRAG_) - -#define ClearMFrag(pbuf) \ - *(__le16 *)(pbuf) &= (~cpu_to_le16(_MORE_FRAG_)) - -#define GetRetry(pbuf) (((*(__le16 *)(pbuf)) & cpu_to_le16(_RETRY_)) != 0) - -#define SetPwrMgt(pbuf) \ - *(__le16 *)(pbuf) |= cpu_to_le16(_PWRMGT_) - -#define GetPwrMgt(pbuf) (((*(__le16 *)(pbuf)) & cpu_to_le16(_PWRMGT_)) != 0) - -#define SetMData(pbuf) \ - *(__le16 *)(pbuf) |= cpu_to_le16(_MORE_DATA_) - -#define SetPrivacy(pbuf) \ - *(__le16 *)(pbuf) |= cpu_to_le16(_PRIVACY_) - -#define GetFrameType(pbuf) \ - (le16_to_cpu(*(__le16 *)(pbuf)) & (BIT(3) | BIT(2))) - -#define GetFrameSubType(pbuf) (le16_to_cpu(*(__le16 *)(pbuf)) & (BIT(7) |\ - BIT(6) | BIT(5) | BIT(4) | BIT(3) | BIT(2))) - -#define SetFrameSubType(pbuf, type) \ - do { \ - *(__le16 *)(pbuf) &= cpu_to_le16(~(BIT(7) | BIT(6) | \ - BIT(5) | BIT(4) | BIT(3) | BIT(2))); \ - *(__le16 *)(pbuf) |= cpu_to_le16(type); \ - } while (0) - -#define SetSeqNum(pbuf, num) \ - do { \ - *(__le16 *)((size_t)(pbuf) + 22) = \ - ((*(__le16 *)((size_t)(pbuf) + 22)) & cpu_to_le16((unsigned short)0x000f)) | \ - cpu_to_le16((unsigned short)(0xfff0 & (num << 4))); \ - } while (0) - -#define SetDuration(pbuf, dur) \ - *(__le16 *)((size_t)(pbuf) + 2) = cpu_to_le16(0xffff & (dur)) - -#define SetPriority(pbuf, tid) \ - *(__le16 *)(pbuf) |= cpu_to_le16(tid & 0xf) - -#define SetEOSP(pbuf, eosp) \ - *(__le16 *)(pbuf) |= cpu_to_le16((eosp & 1) << 4) - -#define SetAckpolicy(pbuf, ack) \ - *(__le16 *)(pbuf) |= cpu_to_le16((ack & 3) << 5) - -#define GetAckpolicy(pbuf) (((le16_to_cpu(*(__le16 *)pbuf)) >> 5) & 0x3) - -#define GetAMsdu(pbuf) (((le16_to_cpu(*(__le16 *)pbuf)) >> 7) & 0x1) - -#define GetAddr1Ptr(pbuf) ((unsigned char *)((size_t)(pbuf) + 4)) - -#define GetAddr2Ptr(pbuf) ((unsigned char *)((size_t)(pbuf) + 10)) - -#define GetAddr3Ptr(pbuf) ((unsigned char *)((size_t)(pbuf) + 16)) - -#define GetAddr4Ptr(pbuf) ((unsigned char *)((size_t)(pbuf) + 24)) - -static inline unsigned char *get_sa(unsigned char *pframe) -{ - unsigned char *sa; - unsigned int to_fr_ds = (GetToDs(pframe) << 1) | GetFrDs(pframe); - - switch (to_fr_ds) { - case 0x00: /* ToDs=0, FromDs=0 */ - sa = GetAddr2Ptr(pframe); - break; - case 0x01: /* ToDs=0, FromDs=1 */ - sa = GetAddr3Ptr(pframe); - break; - case 0x02: /* ToDs=1, FromDs=0 */ - sa = GetAddr2Ptr(pframe); - break; - default: /* ToDs=1, FromDs=1 */ - sa = GetAddr4Ptr(pframe); - break; - } - return sa; -} - -static inline unsigned char *get_hdr_bssid(unsigned char *pframe) -{ - unsigned char *sa; - unsigned int to_fr_ds = (GetToDs(pframe) << 1) | GetFrDs(pframe); - - switch (to_fr_ds) { - case 0x00: /* ToDs=0, FromDs=0 */ - sa = GetAddr3Ptr(pframe); - break; - case 0x01: /* ToDs=0, FromDs=1 */ - sa = GetAddr2Ptr(pframe); - break; - case 0x02: /* ToDs=1, FromDs=0 */ - sa = GetAddr1Ptr(pframe); - break; - case 0x03: /* ToDs=1, FromDs=1 */ - sa = GetAddr1Ptr(pframe); - break; - default: - sa = NULL; /* */ - break; - } - return sa; -} - -/*----------------------------------------------------------------------------- - Below is for the security related definition -------------------------------------------------------------------------------*/ -#define _RESERVED_FRAME_TYPE_ 0 -#define _SKB_FRAME_TYPE_ 2 -#define _PRE_ALLOCMEM_ 1 -#define _PRE_ALLOCHDR_ 3 -#define _PRE_ALLOCLLCHDR_ 4 -#define _PRE_ALLOCICVHDR_ 5 -#define _PRE_ALLOCMICHDR_ 6 - -#define _SIFSTIME_ \ - (priv->pmib->dot11BssType.net_work_type = 10) -#define _ACKCTSLNG_ 14 /* 14 bytes long, including crclng */ -#define _CRCLNG_ 4 - -#define _ASOCREQ_IE_OFFSET_ 4 /* excluding wlan_hdr */ -#define _ASOCRSP_IE_OFFSET_ 6 -#define _REASOCREQ_IE_OFFSET_ 10 -#define _REASOCRSP_IE_OFFSET_ 6 -#define _PROBEREQ_IE_OFFSET_ 0 -#define _PROBERSP_IE_OFFSET_ 12 -#define _AUTH_IE_OFFSET_ 6 -#define _DEAUTH_IE_OFFSET_ 0 -#define _BEACON_IE_OFFSET_ 12 -#define _PUBLIC_ACTION_IE_OFFSET_ 8 - -#define _FIXED_IE_LENGTH_ _BEACON_IE_OFFSET_ - -#define _SSID_IE_ 0 -#define _SUPPORTEDRATES_IE_ 1 -#define _DSSET_IE_ 3 -#define _TIM_IE_ 5 -#define _IBSS_PARA_IE_ 6 -#define _COUNTRY_IE_ 7 -#define _CHLGETXT_IE_ 16 -#define _SUPPORTED_CH_IE_ 36 -#define _CH_SWTICH_ANNOUNCE_ 37 /* Secondary Channel Offset */ -#define _RSN_IE_2_ 48 -#define _SSN_IE_1_ 221 -#define _ERPINFO_IE_ 42 -#define _EXT_SUPPORTEDRATES_IE_ 50 - -#define _HT_CAPABILITY_IE_ 45 -#define _FTIE_ 55 -#define _TIMEOUT_ITVL_IE_ 56 -#define _SRC_IE_ 59 -#define _HT_EXTRA_INFO_IE_ 61 -#define _HT_ADD_INFO_IE_ 61 /* _HT_EXTRA_INFO_IE_ */ -#define _WAPI_IE_ 68 - -#define EID_BSSCoexistence 72 /* 20/40 BSS Coexistence */ -#define EID_BSSIntolerantChlReport 73 -#define _RIC_Descriptor_IE_ 75 - -#define _LINK_ID_IE_ 101 -#define _CH_SWITCH_TIMING_ 104 -#define _PTI_BUFFER_STATUS_ 106 -#define _EXT_CAP_IE_ 127 -#define _VENDOR_SPECIFIC_IE_ 221 - -#define _RESERVED47_ 47 - -/* --------------------------------------------------------------------------- - Below is the fixed elements... ------------------------------------------------------------------------------*/ -#define _AUTH_ALGM_NUM_ 2 -#define _AUTH_SEQ_NUM_ 2 -#define _BEACON_ITERVAL_ 2 -#define _CAPABILITY_ 2 -#define _CURRENT_APADDR_ 6 -#define _LISTEN_INTERVAL_ 2 -#define _RSON_CODE_ 2 -#define _ASOC_ID_ 2 -#define _STATUS_CODE_ 2 -#define _TIMESTAMP_ 8 - -#define cap_ESS BIT(0) -#define cap_IBSS BIT(1) -#define cap_CFPollable BIT(2) -#define cap_CFRequest BIT(3) -#define cap_Privacy BIT(4) -#define cap_ShortPremble BIT(5) -#define cap_PBCC BIT(6) -#define cap_ChAgility BIT(7) -#define cap_SpecMgmt BIT(8) -#define cap_QoSi BIT(9) -#define cap_ShortSlot BIT(10) - -/*----------------------------------------------------------------------------- - Below is the definition for 802.11i / 802.1x -------------------------------------------------------------------------------*/ -#define _IEEE8021X_MGT_ 1 /* WPA */ -#define _IEEE8021X_PSK_ 2 /* WPA with pre-shared key */ - -/*----------------------------------------------------------------------------- - Below is the definition for WMM -------------------------------------------------------------------------------*/ -#define _WMM_IE_Length_ 7 /* for WMM STA */ -#define _WMM_Para_Element_Length_ 24 - -/*----------------------------------------------------------------------------- - Below is the definition for 802.11n -------------------------------------------------------------------------------*/ - -/** - * struct rtw_ieee80211_bar - HT Block Ack Request - * - * This structure refers to "HT BlockAckReq" as - * described in 802.11n draft section 7.2.1.7.1 - */ -struct rtw_ieee80211_bar { - __le16 frame_control; - __le16 duration; - unsigned char ra[ETH_ALEN]; - unsigned char ta[ETH_ALEN]; - __le16 control; - __le16 start_seq_num; -} __packed; - -/** - * struct ieee80211_ht_cap - HT additional information - * - * This structure refers to "HT information element" as - * described in 802.11n draft section 7.3.2.53 - */ -struct ieee80211_ht_addt_info { - unsigned char control_chan; - unsigned char ht_param; - __le16 operation_mode; - __le16 stbc_param; - unsigned char basic_set[16]; -} __packed; - -struct HT_caps_element { - union { - struct { - __le16 HT_caps_info; - unsigned char AMPDU_para; - unsigned char MCS_rate[16]; - __le16 HT_ext_caps; - __le16 Beamforming_caps; - unsigned char ASEL_caps; - } HT_cap_element; - unsigned char HT_cap[26]; - } u; -} __packed; - -struct HT_info_element { - unsigned char primary_channel; - unsigned char infos[5]; - unsigned char MCS_rate[16]; -} __packed; - -struct AC_param { - unsigned char ACI_AIFSN; - unsigned char CW; - __le16 TXOP_limit; -} __packed; - -struct WMM_para_element { - unsigned char QoS_info; - unsigned char reserved; - struct AC_param ac_param[4]; -} __packed; - -#define MAX_AMPDU_FACTOR_64K 3 - -/* Spatial Multiplexing Power Save Modes */ -#define WLAN_HT_CAP_SM_PS_STATIC 0 -#define WLAN_HT_CAP_SM_PS_DYNAMIC 1 -#define WLAN_HT_CAP_SM_PS_INVALID 2 -#define WLAN_HT_CAP_SM_PS_DISABLED 3 - -#define OP_MODE_PURE 0 -#define OP_MODE_MAY_BE_LEGACY_STAS 1 -#define OP_MODE_20MHZ_HT_STA_ASSOCED 2 -#define OP_MODE_MIXED 3 - -#define HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK ((u8) BIT(0) | BIT(1)) -#define HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE ((u8) BIT(0)) -#define HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW ((u8) BIT(0) | BIT(1)) -#define HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH ((u8) BIT(2)) -#define HT_INFO_HT_PARAM_RIFS_MODE ((u8) BIT(3)) -#define HT_INFO_HT_PARAM_CTRL_ACCESS_ONLY ((u8) BIT(4)) -#define HT_INFO_HT_PARAM_SRV_INTERVAL_GRANULARITY ((u8) BIT(5)) - -#define HT_INFO_OPERATION_MODE_OP_MODE_MASK \ - ((u16) (0x0001 | 0x0002)) -#define HT_INFO_OPERATION_MODE_OP_MODE_OFFSET 0 -#define HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT ((u8) BIT(2)) -#define HT_INFO_OPERATION_MODE_TRANSMIT_BURST_LIMIT ((u8) BIT(3)) -#define HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT ((u8) BIT(4)) - -/* ===============WPS Section=============== */ -/* For WPSv1.0 */ -#define WPSOUI 0x0050f204 -/* WPS attribute ID */ -#define WPS_ATTR_VER1 0x104A -#define WPS_ATTR_SIMPLE_CONF_STATE 0x1044 -#define WPS_ATTR_RESP_TYPE 0x103B -#define WPS_ATTR_UUID_E 0x1047 -#define WPS_ATTR_MANUFACTURER 0x1021 -#define WPS_ATTR_MODEL_NAME 0x1023 -#define WPS_ATTR_MODEL_NUMBER 0x1024 -#define WPS_ATTR_SERIAL_NUMBER 0x1042 -#define WPS_ATTR_PRIMARY_DEV_TYPE 0x1054 -#define WPS_ATTR_SEC_DEV_TYPE_LIST 0x1055 -#define WPS_ATTR_DEVICE_NAME 0x1011 -#define WPS_ATTR_CONF_METHOD 0x1008 -#define WPS_ATTR_RF_BANDS 0x103C -#define WPS_ATTR_DEVICE_PWID 0x1012 -#define WPS_ATTR_REQUEST_TYPE 0x103A -#define WPS_ATTR_ASSOCIATION_STATE 0x1002 -#define WPS_ATTR_CONFIG_ERROR 0x1009 -#define WPS_ATTR_VENDOR_EXT 0x1049 -#define WPS_ATTR_SELECTED_REGISTRAR 0x1041 - -/* Value of WPS attribute "WPS_ATTR_DEVICE_NAME */ -#define WPS_MAX_DEVICE_NAME_LEN 32 - -/* Value of WPS Request Type Attribute */ -#define WPS_REQ_TYPE_ENROLLEE_INFO_ONLY 0x00 -#define WPS_REQ_TYPE_ENROLLEE_OPEN_8021X 0x01 -#define WPS_REQ_TYPE_REGISTRAR 0x02 -#define WPS_REQ_TYPE_WLAN_MANAGER_REGISTRAR 0x03 - -/* Value of WPS Response Type Attribute */ -#define WPS_RESPONSE_TYPE_INFO_ONLY 0x00 -#define WPS_RESPONSE_TYPE_8021X 0x01 -#define WPS_RESPONSE_TYPE_REGISTRAR 0x02 -#define WPS_RESPONSE_TYPE_AP 0x03 - -/* Value of WPS WiFi Simple Configuration State Attribute */ -#define WPS_WSC_STATE_NOT_CONFIG 0x01 -#define WPS_WSC_STATE_CONFIG 0x02 - -/* Value of WPS Version Attribute */ -#define WPS_VERSION_1 0x10 - -/* Value of WPS Configuration Method Attribute */ -#define WPS_CONFIG_METHOD_FLASH 0x0001 -#define WPS_CONFIG_METHOD_ETHERNET 0x0002 -#define WPS_CONFIG_METHOD_LABEL 0x0004 -#define WPS_CONFIG_METHOD_DISPLAY 0x0008 -#define WPS_CONFIG_METHOD_E_NFC 0x0010 -#define WPS_CONFIG_METHOD_I_NFC 0x0020 -#define WPS_CONFIG_METHOD_NFC 0x0040 -#define WPS_CONFIG_METHOD_PBC 0x0080 -#define WPS_CONFIG_METHOD_KEYPAD 0x0100 -#define WPS_CONFIG_METHOD_VPBC 0x0280 -#define WPS_CONFIG_METHOD_PPBC 0x0480 -#define WPS_CONFIG_METHOD_VDISPLAY 0x2008 -#define WPS_CONFIG_METHOD_PDISPLAY 0x4008 - -/* Value of Category ID of WPS Primary Device Type Attribute */ -#define WPS_PDT_CID_DISPLAYS 0x0007 -#define WPS_PDT_CID_MULIT_MEDIA 0x0008 -#define WPS_PDT_CID_RTK_WIDI WPS_PDT_CID_MULIT_MEDIA - -/* Value of Sub Category ID of WPS Primary Device Type Attribute */ -#define WPS_PDT_SCID_MEDIA_SERVER 0x0005 -#define WPS_PDT_SCID_RTK_DMP WPS_PDT_SCID_MEDIA_SERVER - -/* Value of Device Password ID */ -#define WPS_DPID_P 0x0000 -#define WPS_DPID_USER_SPEC 0x0001 -#define WPS_DPID_MACHINE_SPEC 0x0002 -#define WPS_DPID_REKEY 0x0003 -#define WPS_DPID_PBC 0x0004 -#define WPS_DPID_REGISTRAR_SPEC 0x0005 - -/* Value of WPS RF Bands Attribute */ -#define WPS_RF_BANDS_2_4_GHZ 0x01 -#define WPS_RF_BANDS_5_GHZ 0x02 - -/* Value of WPS Association State Attribute */ -#define WPS_ASSOC_STATE_NOT_ASSOCIATED 0x00 -#define WPS_ASSOC_STATE_CONNECTION_SUCCESS 0x01 -#define WPS_ASSOC_STATE_CONFIGURATION_FAILURE 0x02 -#define WPS_ASSOC_STATE_ASSOCIATION_FAILURE 0x03 -#define WPS_ASSOC_STATE_IP_FAILURE 0x04 - -/* =====================P2P Section===================== */ -/* For P2P */ -#define P2POUI 0x506F9A09 - -/* P2P Attribute ID */ -#define P2P_ATTR_STATUS 0x00 -#define P2P_ATTR_MINOR_REASON_CODE 0x01 -#define P2P_ATTR_CAPABILITY 0x02 -#define P2P_ATTR_DEVICE_ID 0x03 -#define P2P_ATTR_GO_INTENT 0x04 -#define P2P_ATTR_CONF_TIMEOUT 0x05 -#define P2P_ATTR_LISTEN_CH 0x06 -#define P2P_ATTR_GROUP_BSSID 0x07 -#define P2P_ATTR_EX_LISTEN_TIMING 0x08 -#define P2P_ATTR_INTENTED_IF_ADDR 0x09 -#define P2P_ATTR_MANAGEABILITY 0x0A -#define P2P_ATTR_CH_LIST 0x0B -#define P2P_ATTR_NOA 0x0C -#define P2P_ATTR_DEVICE_INFO 0x0D -#define P2P_ATTR_GROUP_INFO 0x0E -#define P2P_ATTR_GROUP_ID 0x0F -#define P2P_ATTR_INTERFACE 0x10 -#define P2P_ATTR_OPERATING_CH 0x11 -#define P2P_ATTR_INVITATION_FLAGS 0x12 - -/* Value of Status Attribute */ -#define P2P_STATUS_SUCCESS 0x00 -#define P2P_STATUS_FAIL_INFO_UNAVAILABLE 0x01 -#define P2P_STATUS_FAIL_INCOMPATIBLE_PARAM 0x02 -#define P2P_STATUS_FAIL_LIMIT_REACHED 0x03 -#define P2P_STATUS_FAIL_INVALID_PARAM 0x04 -#define P2P_STATUS_FAIL_REQUEST_UNABLE 0x05 -#define P2P_STATUS_FAIL_PREVOUS_PROTO_ERR 0x06 -#define P2P_STATUS_FAIL_NO_COMMON_CH 0x07 -#define P2P_STATUS_FAIL_UNKNOWN_P2PGROUP 0x08 -#define P2P_STATUS_FAIL_BOTH_GOINTENT_15 0x09 -#define P2P_STATUS_FAIL_INCOMPATIBLE_PROVSION 0x0A -#define P2P_STATUS_FAIL_USER_REJECT 0x0B - -/* Value of Inviation Flags Attribute */ -#define P2P_INVITATION_FLAGS_PERSISTENT BIT(0) - -#define DMP_P2P_DEVCAP_SUPPORT (P2P_DEVCAP_SERVICE_DISCOVERY | \ - P2P_DEVCAP_CLIENT_DISCOVERABILITY | \ - P2P_DEVCAP_CONCURRENT_OPERATION | \ - P2P_DEVCAP_INVITATION_PROC) - -#define DMP_P2P_GRPCAP_SUPPORT (P2P_GRPCAP_INTRABSS) - -/* Value of Device Capability Bitmap */ -#define P2P_DEVCAP_SERVICE_DISCOVERY BIT(0) -#define P2P_DEVCAP_CLIENT_DISCOVERABILITY BIT(1) -#define P2P_DEVCAP_CONCURRENT_OPERATION BIT(2) -#define P2P_DEVCAP_INFRA_MANAGED BIT(3) -#define P2P_DEVCAP_DEVICE_LIMIT BIT(4) -#define P2P_DEVCAP_INVITATION_PROC BIT(5) - -/* Value of Group Capability Bitmap */ -#define P2P_GRPCAP_GO BIT(0) -#define P2P_GRPCAP_PERSISTENT_GROUP BIT(1) -#define P2P_GRPCAP_GROUP_LIMIT BIT(2) -#define P2P_GRPCAP_INTRABSS BIT(3) -#define P2P_GRPCAP_CROSS_CONN BIT(4) -#define P2P_GRPCAP_PERSISTENT_RECONN BIT(5) -#define P2P_GRPCAP_GROUP_FORMATION BIT(6) - -/* P2P Public Action Frame (Management Frame) */ -#define P2P_PUB_ACTION_ACTION 0x09 - -/* P2P Public Action Frame Type */ -#define P2P_GO_NEGO_REQ 0 -#define P2P_GO_NEGO_RESP 1 -#define P2P_GO_NEGO_CONF 2 -#define P2P_INVIT_REQ 3 -#define P2P_INVIT_RESP 4 -#define P2P_DEVDISC_REQ 5 -#define P2P_DEVDISC_RESP 6 -#define P2P_PROVISION_DISC_REQ 7 -#define P2P_PROVISION_DISC_RESP 8 - -/* P2P Action Frame Type */ -#define P2P_NOTICE_OF_ABSENCE 0 -#define P2P_PRESENCE_REQUEST 1 -#define P2P_PRESENCE_RESPONSE 2 -#define P2P_GO_DISC_REQUEST 3 - -#define P2P_MAX_PERSISTENT_GROUP_NUM 10 - -#define P2P_PROVISIONING_SCAN_CNT 3 - -#define P2P_WILDCARD_SSID_LEN 7 - -/* default value, used when: (1)p2p disabled or (2)p2p enabled - * but only do 1 scan phase */ -#define P2P_FINDPHASE_EX_NONE 0 -/* used when p2p enabled and want to do 1 scan phase and - * P2P_FINDPHASE_EX_MAX-1 find phase */ -#define P2P_FINDPHASE_EX_FULL 1 -#define P2P_FINDPHASE_EX_SOCIAL_FIRST (P2P_FINDPHASE_EX_FULL+1) -#define P2P_FINDPHASE_EX_MAX 4 -#define P2P_FINDPHASE_EX_SOCIAL_LAST P2P_FINDPHASE_EX_MAX - -/* 5 seconds timeout for sending the provision discovery request */ -#define P2P_PROVISION_TIMEOUT 5000 -/* 3 seconds timeout for sending the prov disc request concurrent mode */ -#define P2P_CONCURRENT_PROVISION_TIME 3000 -/* 5 seconds timeout for receiving the group negotiation response */ -#define P2P_GO_NEGO_TIMEOUT 5000 -/* 3 seconds timeout for sending the negotiation request under concurrent mode */ -#define P2P_CONCURRENT_GO_NEGO_TIME 3000 -/* 100ms */ -#define P2P_TX_PRESCAN_TIMEOUT 100 -/* 5 seconds timeout for sending the invitation request */ -#define P2P_INVITE_TIMEOUT 5000 -/* 3 seconds timeout for sending the invitation request under concurrent mode */ -#define P2P_CONCURRENT_INVITE_TIME 3000 -/* 25 seconds timeout to reset the scan channel (based on channel plan) */ -#define P2P_RESET_SCAN_CH 25000 -#define P2P_MAX_INTENT 15 - -#define P2P_MAX_NOA_NUM 2 - -/* WPS Configuration Method */ -#define WPS_CM_NONE 0x0000 -#define WPS_CM_LABEL 0x0004 -#define WPS_CM_DISPLYA 0x0008 -#define WPS_CM_EXTERNAL_NFC_TOKEN 0x0010 -#define WPS_CM_INTEGRATED_NFC_TOKEN 0x0020 -#define WPS_CM_NFC_INTERFACE 0x0040 -#define WPS_CM_PUSH_BUTTON 0x0080 -#define WPS_CM_KEYPAD 0x0100 -#define WPS_CM_SW_PUHS_BUTTON 0x0280 -#define WPS_CM_HW_PUHS_BUTTON 0x0480 -#define WPS_CM_SW_DISPLAY_P 0x2008 -#define WPS_CM_LCD_DISPLAY_P 0x4008 - -enum P2P_ROLE { - P2P_ROLE_DISABLE = 0, - P2P_ROLE_DEVICE = 1, - P2P_ROLE_CLIENT = 2, - P2P_ROLE_GO = 3 -}; - -enum P2P_STATE { - P2P_STATE_NONE = 0, /* P2P disable */ - /* P2P had enabled and do nothing */ - P2P_STATE_IDLE = 1, - P2P_STATE_LISTEN = 2, /* In pure listen state */ - P2P_STATE_SCAN = 3, /* In scan phase */ - /* In the listen state of find phase */ - P2P_STATE_FIND_PHASE_LISTEN = 4, - /* In the search state of find phase */ - P2P_STATE_FIND_PHASE_SEARCH = 5, - /* In P2P provisioning discovery */ - P2P_STATE_TX_PROVISION_DIS_REQ = 6, - P2P_STATE_RX_PROVISION_DIS_RSP = 7, - P2P_STATE_RX_PROVISION_DIS_REQ = 8, - /* Doing the group owner negotiation handshake */ - P2P_STATE_GONEGO_ING = 9, - /* finish the group negotiation handshake with success */ - P2P_STATE_GONEGO_OK = 10, - /* finish the group negotiation handshake with failure */ - P2P_STATE_GONEGO_FAIL = 11, - /* receiving the P2P Inviation request and match with the profile. */ - P2P_STATE_RECV_INVITE_REQ_MATCH = 12, - /* Doing the P2P WPS */ - P2P_STATE_PROVISIONING_ING = 13, - /* Finish the P2P WPS */ - P2P_STATE_PROVISIONING_DONE = 14, - /* Transmit the P2P Invitation request */ - P2P_STATE_TX_INVITE_REQ = 15, - /* Receiving the P2P Invitation response */ - P2P_STATE_RX_INVITE_RESP_OK = 16, - /* receiving the P2P Inviation request and dismatch with the profile. */ - P2P_STATE_RECV_INVITE_REQ_DISMATCH = 17, - /* receiving the P2P Inviation request and this wifi is GO. */ - P2P_STATE_RECV_INVITE_REQ_GO = 18, - /* receiving the P2P Inviation request to join an existing P2P Group. */ - P2P_STATE_RECV_INVITE_REQ_JOIN = 19, - /* recveing the P2P Inviation response with failure */ - P2P_STATE_RX_INVITE_RESP_FAIL = 20, - /* receiving p2p negotiation response with information is not available */ - P2P_STATE_RX_INFOR_NOREADY = 21, - /* sending p2p negotiation response with information is not available */ - P2P_STATE_TX_INFOR_NOREADY = 22, -}; - -enum P2P_WPSINFO { - P2P_NO_WPSINFO = 0, - P2P_GOT_WPSINFO_PEER_DISPLAY_PIN = 1, - P2P_GOT_WPSINFO_SELF_DISPLAY_PIN = 2, - P2P_GOT_WPSINFO_PBC = 3, -}; - -#define P2P_PRIVATE_IOCTL_SET_LEN 64 - -enum P2P_PROTO_WK_ID { - P2P_FIND_PHASE_WK = 0, - P2P_RESTORE_STATE_WK = 1, - P2P_PRE_TX_PROVDISC_PROCESS_WK = 2, - P2P_PRE_TX_NEGOREQ_PROCESS_WK = 3, - P2P_PRE_TX_INVITEREQ_PROCESS_WK = 4, - P2P_AP_P2P_CH_SWITCH_PROCESS_WK = 5, - P2P_RO_CH_WK = 6, -}; - -enum P2P_PS_STATE { - P2P_PS_DISABLE = 0, - P2P_PS_ENABLE = 1, - P2P_PS_SCAN = 2, - P2P_PS_SCAN_DONE = 3, - P2P_PS_ALLSTASLEEP = 4, /* for P2P GO */ -}; - -enum P2P_PS_MODE { - P2P_PS_NONE = 0, - P2P_PS_CTWINDOW = 1, - P2P_PS_NOA = 2, - P2P_PS_MIX = 3, /* CTWindow and NoA */ -}; - -#define IP_MCAST_MAC(mac) \ - ((mac[0] == 0x01) && (mac[1] == 0x00) && (mac[2] == 0x5e)) -#define ICMPV6_MCAST_MAC(mac) \ - ((mac[0] == 0x33) && (mac[1] == 0x33) && (mac[2] != 0xff)) - -#endif /* _WIFI_H_ */ diff --git a/drivers/staging/r8188eu/include/wlan_bssdef.h b/drivers/staging/r8188eu/include/wlan_bssdef.h deleted file mode 100644 index ffeafa19ef26..000000000000 --- a/drivers/staging/r8188eu/include/wlan_bssdef.h +++ /dev/null @@ -1,272 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#ifndef __WLAN_BSSDEF_H__ -#define __WLAN_BSSDEF_H__ - -#define MAX_IE_SZ 768 - -#define NDIS_802_11_LENGTH_SSID 32 -#define NDIS_802_11_LENGTH_RATES 8 -#define NDIS_802_11_LENGTH_RATES_EX 16 - -#define NDIS_802_11_RSSI long /* in dBm */ - -struct ndis_802_11_ssid { - u32 SsidLength; - u8 Ssid[32]; -}; - -struct ndis_802_11_config_fh { - u32 Length; /* Length of structure */ - u32 HopPattern; /* As defined by 802.11, MSB set */ - u32 HopSet; /* to one if non-802.11 */ - u32 DwellTime; /* units are Kusec */ -}; - -/* - * FW will only save the channel number in DSConfig. - * ODI Handler will convert the channel number to freq. number. - */ -struct ndis_802_11_config { - u32 Length; /* Length of structure */ - u32 BeaconPeriod; /* units are Kusec */ - u32 ATIMWindow; /* units are Kusec */ - u32 DSConfig; /* Frequency, units are kHz */ - struct ndis_802_11_config_fh FHConfig; -}; - -enum ndis_802_11_network_infra { - Ndis802_11IBSS, - Ndis802_11Infrastructure, - Ndis802_11AutoUnknown, - Ndis802_11InfrastructureMax, /* dummy upper bound */ - Ndis802_11APMode -}; - -struct ndis_802_11_fixed_ie { - u8 Timestamp[8]; - u16 BeaconInterval; - u16 Capabilities; -}; - -struct ndis_802_11_var_ie { - u8 ElementID; - u8 Length; - u8 data[]; -}; - -/* - * Length is the 4 bytes multiples of the sume of - * [ETH_ALEN] + 2 + sizeof (struct ndis_802_11_ssid) + sizeof (u32) - * + sizeof (NDIS_802_11_RSSI) + sizeof (enum NDIS_802_11_NETWORK_TYPE) - * + sizeof (struct ndis_802_11_config) - * + NDIS_802_11_LENGTH_RATES_EX + IELength - * - * Except the IELength, all other fields are fixed length. - * Therefore, we can define a macro to represent the partial sum. */ - -enum ndis_802_11_auth_mode { - Ndis802_11AuthModeOpen, - Ndis802_11AuthModeShared, - Ndis802_11AuthModeAutoSwitch, - Ndis802_11AuthModeWPA, - Ndis802_11AuthModeWPAPSK, - Ndis802_11AuthModeWPANone, - Ndis802_11AuthModeWAPI, - Ndis802_11AuthModeMax /* Not a real mode, upper bound */ -}; - -enum ndis_802_11_wep_status { - Ndis802_11WEPEnabled, - Ndis802_11Encryption1Enabled = Ndis802_11WEPEnabled, - Ndis802_11WEPDisabled, - Ndis802_11EncryptionDisabled = Ndis802_11WEPDisabled, - Ndis802_11WEPKeyAbsent, - Ndis802_11Encryption1KeyAbsent = Ndis802_11WEPKeyAbsent, - Ndis802_11WEPNotSupported, - Ndis802_11EncryptionNotSupported = Ndis802_11WEPNotSupported, - Ndis802_11Encryption2Enabled, - Ndis802_11Encryption2KeyAbsent, - Ndis802_11Encryption3Enabled, - Ndis802_11Encryption3KeyAbsent, - Ndis802_11_EncryptionWAPI -}; - -#define NDIS_802_11_AI_REQFI_CAPABILITIES 1 -#define NDIS_802_11_AI_REQFI_LISTENINTERVAL 2 -#define NDIS_802_11_AI_REQFI_CURRENTAPADDRESS 4 - -#define NDIS_802_11_AI_RESFI_CAPABILITIES 1 -#define NDIS_802_11_AI_RESFI_STATUSCODE 2 -#define NDIS_802_11_AI_RESFI_ASSOCIATIONID 4 - -struct ndis_802_11_ai_reqfi { - u16 Capabilities; - u16 ListenInterval; - unsigned char CurrentAPAddress[ETH_ALEN]; -}; - -struct ndis_802_11_ai_resfi { - u16 Capabilities; - u16 StatusCode; - u16 AssociationId; -}; - -struct ndis_802_11_assoc_info { - u32 Length; - u16 AvailableRequestFixedIEs; - struct ndis_802_11_ai_reqfi RequestFixedIEs; - u32 RequestIELength; - u32 OffsetRequestIEs; - u16 AvailableResponseFixedIEs; - struct ndis_802_11_ai_resfi ResponseFixedIEs; - u32 ResponseIELength; - u32 OffsetResponseIEs; -}; - -/* Key mapping keys require a BSSID */ -struct ndis_802_11_key { - u32 Length; /* Length of this structure */ - u32 KeyIndex; - u32 KeyLength; /* length of key in bytes */ - unsigned char BSSID[ETH_ALEN]; - unsigned long long KeyRSC; - u8 KeyMaterial[32]; /* var len depending on above field */ -}; - -struct ndis_802_11_remove_key { - u32 Length; /* Length */ - u32 KeyIndex; - unsigned char BSSID[ETH_ALEN]; -}; - -struct ndis_802_11_wep { - u32 Length; /* Length of this structure */ - u32 KeyIndex; /* 0 is the per-client key, - * 1-N are the global keys */ - u32 KeyLength; /* length of key in bytes */ - u8 KeyMaterial[16];/* variable len depending on above field */ -}; - -struct ndis_802_11_auth_req { - u32 Length; /* Length of structure */ - unsigned char Bssid[ETH_ALEN]; - u32 Flags; -}; - -enum ndis_802_11_status_type { - Ndis802_11StatusType_Authentication, - Ndis802_11StatusType_MediaStreamMode, - Ndis802_11StatusType_PMKID_CandidateList, - Ndis802_11StatusTypeMax /* not a real type, defined as - * an upper bound */ -}; - -struct ndis_802_11_status_ind { - enum ndis_802_11_status_type StatusType; -}; - -/* mask for authentication/integrity fields */ -#define NDIS_802_11_AUTH_REQUEST_AUTH_FIELDS 0x0f -#define NDIS_802_11_AUTH_REQUEST_REAUTH 0x01 -#define NDIS_802_11_AUTH_REQUEST_KEYUPDATE 0x02 -#define NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR 0x06 -#define NDIS_802_11_AUTH_REQUEST_GROUP_ERROR 0x0E - -/* MIC check time, 60 seconds. */ -#define MIC_CHECK_TIME 60000000 - -#ifndef Ndis802_11APMode -#define Ndis802_11APMode (Ndis802_11InfrastructureMax+1) -#endif - -struct wlan_phy_info { - u8 SignalStrength;/* in percentage) */ - u8 SignalQuality;/* in percentage) */ - u8 Optimum_antenna; /* for Antenna diversity */ - u8 Reserved_0; -}; - -struct wlan_bcn_info { - /* these infor get from rtw_get_encrypt_info when - * * translate scan to UI */ - u8 encryp_protocol;/* ENCRYP_PROTOCOL_E: OPEN/WEP/WPA/WPA2/WAPI */ - int group_cipher; /* WPA/WPA2 group cipher */ - int pairwise_cipher;/* WPA/WPA2/WEP pairwise cipher */ - int is_8021x; - - /* bwmode 20/40 and ch_offset UP/LOW */ - unsigned short ht_cap_info; - unsigned char ht_info_infos_0; -}; - -/* temporally add #pragma pack for structure alignment issue of -* struct wlan_bssid_ex and get_struct wlan_bssid_ex_sz() -*/ -struct wlan_bssid_ex { - u32 Length; - unsigned char MacAddress[ETH_ALEN]; - u8 Reserved[2];/* 0]: IS beacon frame */ - struct ndis_802_11_ssid Ssid; - u32 Privacy; - NDIS_802_11_RSSI Rssi;/* in dBM,raw data ,get from PHY) */ - struct ndis_802_11_config Configuration; - enum ndis_802_11_network_infra InfrastructureMode; - unsigned char SupportedRates[NDIS_802_11_LENGTH_RATES_EX]; - struct wlan_phy_info PhyInfo; - u32 IELength; - u8 IEs[MAX_IE_SZ]; /* timestamp, beacon interval, and - * capability information) */ -} __packed; - -static inline uint get_wlan_bssid_ex_sz(struct wlan_bssid_ex *bss) -{ - return sizeof(struct wlan_bssid_ex) - MAX_IE_SZ + bss->IELength; -} - -struct wlan_network { - struct list_head list; - int network_type; /* refer to ieee80211.h for WIRELESS_11B/G */ - int fixed; /* set fixed when not to be removed - * in site-surveying */ - unsigned long last_scanned; /* timestamp for the network */ - int aid; /* will only be valid when a BSS is joinned. */ - int join_res; - struct wlan_bssid_ex network; /* must be the last item */ - struct wlan_bcn_info BcnInfo; -}; - -enum VRTL_CARRIER_SENSE { - DISABLE_VCS, - ENABLE_VCS, - AUTO_VCS -}; - -enum VCS_TYPE { - NONE_VCS, - RTS_CTS, - CTS_TO_SELF -}; - -#define PWR_CAM 0 -#define PWR_MINPS 1 -#define PWR_MAXPS 2 -#define PWR_UAPSD 3 -#define PWR_VOIP 4 - -enum UAPSD_MAX_SP { - NO_LIMIT, - TWO_MSDU, - FOUR_MSDU, - SIX_MSDU -}; - -#define NUM_PRE_AUTH_KEY 16 -#define NUM_PMKID_CACHE NUM_PRE_AUTH_KEY - -u8 key_2char2num(u8 hch, u8 lch); -u8 key_char2num(u8 ch); -u8 str_2char2num(u8 hch, u8 lch); - -#endif /* ifndef WLAN_BSSDEF_H_ */ diff --git a/drivers/staging/r8188eu/os_dep/ioctl_linux.c b/drivers/staging/r8188eu/os_dep/ioctl_linux.c deleted file mode 100644 index e0a819970546..000000000000 --- a/drivers/staging/r8188eu/os_dep/ioctl_linux.c +++ /dev/null @@ -1,3775 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2007 - 2012 Realtek Corporation. */ - -#include "../include/osdep_service.h" -#include "../include/drv_types.h" -#include "../include/wlan_bssdef.h" -#include "../include/wifi.h" -#include "../include/rtw_mlme.h" -#include "../include/rtw_mlme_ext.h" -#include "../include/rtw_ioctl.h" -#include "../include/rtw_ioctl_set.h" -#include "../include/usb_ops.h" -#include "../include/rtl8188e_hal.h" -#include "../include/rtw_led.h" - -#include "../include/rtw_iol.h" - -#define RTL_IOCTL_WPA_SUPPLICANT (SIOCIWFIRSTPRIV + 30) - -#define SCAN_ITEM_SIZE 768 -#define MAX_CUSTOM_LEN 64 -#define RATE_COUNT 4 - -/* combo scan */ -#define WEXT_CSCAN_AMOUNT 9 -#define WEXT_CSCAN_BUF_LEN 360 -#define WEXT_CSCAN_HEADER "CSCAN S\x01\x00\x00S\x00" -#define WEXT_CSCAN_HEADER_SIZE 12 -#define WEXT_CSCAN_SSID_SECTION 'S' -#define WEXT_CSCAN_CHANNEL_SECTION 'C' -#define WEXT_CSCAN_NPROBE_SECTION 'N' -#define WEXT_CSCAN_ACTV_DWELL_SECTION 'A' -#define WEXT_CSCAN_PASV_DWELL_SECTION 'P' -#define WEXT_CSCAN_HOME_DWELL_SECTION 'H' -#define WEXT_CSCAN_TYPE_SECTION 'T' - -static u32 rtw_rates[] = {1000000, 2000000, 5500000, 11000000, - 6000000, 9000000, 12000000, 18000000, 24000000, 36000000, - 48000000, 54000000}; - -void indicate_wx_scan_complete_event(struct adapter *padapter) -{ - union iwreq_data wrqu; - - memset(&wrqu, 0, sizeof(union iwreq_data)); - wireless_send_event(padapter->pnetdev, SIOCGIWSCAN, &wrqu, NULL); -} - -void rtw_indicate_wx_assoc_event(struct adapter *padapter) -{ - union iwreq_data wrqu; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - memset(&wrqu, 0, sizeof(union iwreq_data)); - - wrqu.ap_addr.sa_family = ARPHRD_ETHER; - - memcpy(wrqu.ap_addr.sa_data, pmlmepriv->cur_network.network.MacAddress, ETH_ALEN); - - wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL); -} - -void rtw_indicate_wx_disassoc_event(struct adapter *padapter) -{ - union iwreq_data wrqu; - - memset(&wrqu, 0, sizeof(union iwreq_data)); - - wrqu.ap_addr.sa_family = ARPHRD_ETHER; - memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN); - - wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL); -} - -static char *translate_scan(struct adapter *padapter, - struct iw_request_info *info, - struct wlan_network *pnetwork, - char *start, char *stop) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct iw_event iwe; - u16 cap; - __le16 le_tmp; - u32 ht_ielen = 0; - char *custom; - char *p; - u16 max_rate = 0, rate, ht_cap = false; - u32 i = 0; - u8 bw_40MHz = 0, short_GI = 0; - u16 mcs_rate = 0; - u8 ss, sq; - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - - if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) { - u32 blnGotP2PIE = false; - - /* User is doing the P2P device discovery */ - /* The prefix of SSID should be "DIRECT-" and the IE should contains the P2P IE. */ - /* If not, the driver should ignore this AP and go to the next AP. */ - - /* Verifying the SSID */ - if (!memcmp(pnetwork->network.Ssid.Ssid, pwdinfo->p2p_wildcard_ssid, P2P_WILDCARD_SSID_LEN)) { - u32 p2pielen = 0; - - if (pnetwork->network.Reserved[0] == 2) {/* Probe Request */ - /* Verifying the P2P IE */ - if (rtw_get_p2p_ie(pnetwork->network.IEs, pnetwork->network.IELength, NULL, &p2pielen)) - blnGotP2PIE = true; - } else {/* Beacon or Probe Respones */ - /* Verifying the P2P IE */ - if (rtw_get_p2p_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &p2pielen)) - blnGotP2PIE = true; - } - } - - if (!blnGotP2PIE) - return start; - } - - /* AP MAC address */ - iwe.cmd = SIOCGIWAP; - iwe.u.ap_addr.sa_family = ARPHRD_ETHER; - - memcpy(iwe.u.ap_addr.sa_data, pnetwork->network.MacAddress, ETH_ALEN); - start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN); - - /* Add the ESSID */ - iwe.cmd = SIOCGIWESSID; - iwe.u.data.flags = 1; - iwe.u.data.length = min_t(u16, pnetwork->network.Ssid.SsidLength, 32); - start = iwe_stream_add_point(info, start, stop, &iwe, pnetwork->network.Ssid.Ssid); - - /* parsing HT_CAP_IE */ - p = rtw_get_ie(&pnetwork->network.IEs[12], _HT_CAPABILITY_IE_, &ht_ielen, pnetwork->network.IELength - 12); - - if (p && ht_ielen > 0) { - struct ieee80211_ht_cap *pht_capie; - - ht_cap = true; - pht_capie = (struct ieee80211_ht_cap *)(p + 2); - memcpy(&mcs_rate, pht_capie->mcs.rx_mask, 2); - bw_40MHz = (le16_to_cpu(pht_capie->cap_info) & - IEEE80211_HT_CAP_SUP_WIDTH_20_40) ? 1 : 0; - short_GI = (le16_to_cpu(pht_capie->cap_info) & - (IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40)) ? 1 : 0; - } - - /* Add the protocol name */ - iwe.cmd = SIOCGIWNAME; - if ((rtw_is_cckratesonly_included((u8 *)&pnetwork->network.SupportedRates))) { - if (ht_cap) - snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bn"); - else - snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11b"); - } else if ((rtw_is_cckrates_included((u8 *)&pnetwork->network.SupportedRates))) { - if (ht_cap) - snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bgn"); - else - snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bg"); - } else { - if (ht_cap) - snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11gn"); - else - snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11g"); - } - - start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN); - - /* Add mode */ - iwe.cmd = SIOCGIWMODE; - memcpy(&le_tmp, rtw_get_capability_from_ie(pnetwork->network.IEs), 2); - - cap = le16_to_cpu(le_tmp); - - if (cap & (WLAN_CAPABILITY_IBSS | WLAN_CAPABILITY_BSS)) { - if (cap & WLAN_CAPABILITY_BSS) - iwe.u.mode = IW_MODE_MASTER; - else - iwe.u.mode = IW_MODE_ADHOC; - - start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_UINT_LEN); - } - - if (pnetwork->network.Configuration.DSConfig < 1) - pnetwork->network.Configuration.DSConfig = 1; - - /* Add frequency/channel */ - iwe.cmd = SIOCGIWFREQ; - iwe.u.freq.m = rtw_ch2freq(pnetwork->network.Configuration.DSConfig) * 100000; - iwe.u.freq.e = 1; - iwe.u.freq.i = pnetwork->network.Configuration.DSConfig; - start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN); - - /* Add encryption capability */ - iwe.cmd = SIOCGIWENCODE; - if (cap & WLAN_CAPABILITY_PRIVACY) - iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; - else - iwe.u.data.flags = IW_ENCODE_DISABLED; - iwe.u.data.length = 0; - start = iwe_stream_add_point(info, start, stop, &iwe, pnetwork->network.Ssid.Ssid); - - /*Add basic and extended rates */ - max_rate = 0; - custom = kzalloc(MAX_CUSTOM_LEN, GFP_ATOMIC); - if (!custom) - return start; - p = custom; - p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): "); - while (pnetwork->network.SupportedRates[i] != 0) { - rate = pnetwork->network.SupportedRates[i] & 0x7F; - if (rate > max_rate) - max_rate = rate; - p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), - "%d%s ", rate >> 1, (rate & 1) ? ".5" : ""); - i++; - } - - if (ht_cap) { - if (mcs_rate & 0x8000)/* MCS15 */ - max_rate = (bw_40MHz) ? ((short_GI) ? 300 : 270) : ((short_GI) ? 144 : 130); - else if (mcs_rate & 0x0080)/* MCS7 */ - ; - else/* default MCS7 */ - max_rate = (bw_40MHz) ? ((short_GI) ? 150 : 135) : ((short_GI) ? 72 : 65); - - max_rate = max_rate * 2;/* Mbps/2; */ - } - - iwe.cmd = SIOCGIWRATE; - iwe.u.bitrate.fixed = 0; - iwe.u.bitrate.disabled = 0; - iwe.u.bitrate.value = max_rate * 500000; - start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_PARAM_LEN); - - /* parsing WPA/WPA2 IE */ - { - u8 *buf; - u8 *wpa_ie, *rsn_ie; - u16 wpa_len = 0, rsn_len = 0; - u8 *p; - - buf = kzalloc(MAX_WPA_IE_LEN, GFP_ATOMIC); - if (!buf) - goto exit; - wpa_ie = kzalloc(255, GFP_ATOMIC); - if (!wpa_ie) { - kfree(buf); - goto exit; - } - rsn_ie = kzalloc(255, GFP_ATOMIC); - if (!rsn_ie) { - kfree(buf); - kfree(wpa_ie); - goto exit; - } - rtw_get_sec_ie(pnetwork->network.IEs, pnetwork->network.IELength, rsn_ie, &rsn_len, wpa_ie, &wpa_len); - - if (wpa_len > 0) { - p = buf; - memset(buf, 0, MAX_WPA_IE_LEN); - p += sprintf(p, "wpa_ie ="); - for (i = 0; i < wpa_len; i++) - p += sprintf(p, "%02x", wpa_ie[i]); - - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = IWEVCUSTOM; - iwe.u.data.length = strlen(buf); - start = iwe_stream_add_point(info, start, stop, &iwe, buf); - - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = IWEVGENIE; - iwe.u.data.length = wpa_len; - start = iwe_stream_add_point(info, start, stop, &iwe, wpa_ie); - } - if (rsn_len > 0) { - p = buf; - memset(buf, 0, MAX_WPA_IE_LEN); - p += sprintf(p, "rsn_ie ="); - for (i = 0; i < rsn_len; i++) - p += sprintf(p, "%02x", rsn_ie[i]); - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = IWEVCUSTOM; - iwe.u.data.length = strlen(buf); - start = iwe_stream_add_point(info, start, stop, &iwe, buf); - - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = IWEVGENIE; - iwe.u.data.length = rsn_len; - start = iwe_stream_add_point(info, start, stop, &iwe, rsn_ie); - } - kfree(buf); - kfree(wpa_ie); - kfree(rsn_ie); - } - - {/* parsing WPS IE */ - uint cnt = 0, total_ielen; - u8 *wpsie_ptr = NULL; - uint wps_ielen = 0; - - u8 *ie_ptr = pnetwork->network.IEs + _FIXED_IE_LENGTH_; - total_ielen = pnetwork->network.IELength - _FIXED_IE_LENGTH_; - - while (cnt < total_ielen) { - if (rtw_is_wps_ie(&ie_ptr[cnt], &wps_ielen) && (wps_ielen > 2)) { - wpsie_ptr = &ie_ptr[cnt]; - iwe.cmd = IWEVGENIE; - iwe.u.data.length = (u16)wps_ielen; - start = iwe_stream_add_point(info, start, stop, &iwe, wpsie_ptr); - } - cnt += ie_ptr[cnt + 1] + 2; /* goto next */ - } - } - - /* Add quality statistics */ - iwe.cmd = IWEVQUAL; - iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_INVALID; - - if (check_fwstate(pmlmepriv, _FW_LINKED) && - is_same_network(&pmlmepriv->cur_network.network, &pnetwork->network)) { - ss = padapter->recvpriv.signal_strength; - sq = padapter->recvpriv.signal_qual; - } else { - ss = pnetwork->network.PhyInfo.SignalStrength; - sq = pnetwork->network.PhyInfo.SignalQuality; - } - - iwe.u.qual.level = (u8)ss; - iwe.u.qual.qual = (u8)sq; /* signal quality */ - iwe.u.qual.noise = 0; /* noise level */ - start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN); -exit: - kfree(custom); - return start; -} - -static int wpa_set_auth_algs(struct net_device *dev, u32 value) -{ - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - int ret = 0; - - if ((value & AUTH_ALG_SHARED_KEY) && (value & AUTH_ALG_OPEN_SYSTEM)) { - padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled; - padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeAutoSwitch; - padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Auto; - } else if (value & AUTH_ALG_SHARED_KEY) { - padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled; - - padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeShared; - padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Shared; - } else if (value & AUTH_ALG_OPEN_SYSTEM) { - if (padapter->securitypriv.ndisauthtype < Ndis802_11AuthModeWPAPSK) { - padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen; - padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; - } - } else if (!(value & AUTH_ALG_LEAP)) { - ret = -EINVAL; - } - return ret; -} - -static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len) -{ - int ret = 0; - u32 wep_key_idx, wep_key_len, wep_total_len; - struct ndis_802_11_wep *pwep = NULL; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - - param->u.crypt.err = 0; - param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0'; - - if (param_len < (u32)((u8 *)param->u.crypt.key - (u8 *)param) + param->u.crypt.key_len) { - ret = -EINVAL; - goto exit; - } - - if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff && - param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff && - param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) { - if (param->u.crypt.idx >= WEP_KEYS) { - ret = -EINVAL; - goto exit; - } - } else { - ret = -EINVAL; - goto exit; - } - - if (strcmp(param->u.crypt.alg, "WEP") == 0) { - padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled; - padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_; - padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_; - - wep_key_idx = param->u.crypt.idx; - wep_key_len = param->u.crypt.key_len; - - if (wep_key_idx > WEP_KEYS) - return -EINVAL; - - if (wep_key_len > 0) { - wep_key_len = wep_key_len <= 5 ? 5 : 13; - wep_total_len = wep_key_len + sizeof(*pwep); - pwep = kzalloc(wep_total_len, GFP_KERNEL); - if (!pwep) - goto exit; - - pwep->KeyLength = wep_key_len; - pwep->Length = wep_total_len; - if (wep_key_len == 13) { - padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_; - padapter->securitypriv.dot118021XGrpPrivacy = _WEP104_; - } - } else { - ret = -EINVAL; - goto exit; - } - pwep->KeyIndex = wep_key_idx; - pwep->KeyIndex |= 0x80000000; - memcpy(pwep->KeyMaterial, param->u.crypt.key, pwep->KeyLength); - if (param->u.crypt.set_tx) { - if (rtw_set_802_11_add_wep(padapter, pwep) == (u8)_FAIL) - ret = -EOPNOTSUPP; - } else { - if (wep_key_idx >= WEP_KEYS) { - ret = -EOPNOTSUPP; - goto exit; - } - memcpy(&psecuritypriv->dot11DefKey[wep_key_idx].skey[0], pwep->KeyMaterial, pwep->KeyLength); - psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength; - rtw_set_key(padapter, psecuritypriv, wep_key_idx, 0); - } - goto exit; - } - - if (padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) { /* 802_1x */ - struct sta_info *psta, *pbcmc_sta; - struct sta_priv *pstapriv = &padapter->stapriv; - - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_MP_STATE)) { /* sta mode */ - psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv)); - if (!psta) { - ; - } else { - if (strcmp(param->u.crypt.alg, "none") != 0) - psta->ieee8021x_blocked = false; - - if ((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled) || - (padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption3Enabled)) - psta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm; - - if (param->u.crypt.set_tx == 1) { /* pairwise key */ - memcpy(psta->dot118021x_UncstKey.skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len)); - - if (strcmp(param->u.crypt.alg, "TKIP") == 0) { /* set mic key */ - memcpy(psta->dot11tkiptxmickey.skey, ¶m->u.crypt.key[16], 8); - memcpy(psta->dot11tkiprxmickey.skey, ¶m->u.crypt.key[24], 8); - padapter->securitypriv.busetkipkey = false; - } - - rtw_setstakey_cmd(padapter, (unsigned char *)psta, true); - } else { /* group key */ - memcpy(padapter->securitypriv.dot118021XGrpKey[param->u.crypt.idx].skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len)); - memcpy(padapter->securitypriv.dot118021XGrptxmickey[param->u.crypt.idx].skey, ¶m->u.crypt.key[16], 8); - memcpy(padapter->securitypriv.dot118021XGrprxmickey[param->u.crypt.idx].skey, ¶m->u.crypt.key[24], 8); - padapter->securitypriv.binstallGrpkey = true; - - padapter->securitypriv.dot118021XGrpKeyid = param->u.crypt.idx; - - rtw_set_key(padapter, &padapter->securitypriv, param->u.crypt.idx, 1); - if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_PROVISIONING_ING)) - rtw_p2p_set_state(pwdinfo, P2P_STATE_PROVISIONING_DONE); - } - } - pbcmc_sta = rtw_get_bcmc_stainfo(padapter); - if (!pbcmc_sta) { - ; - } else { - /* Jeff: don't disable ieee8021x_blocked while clearing key */ - if (strcmp(param->u.crypt.alg, "none") != 0) - pbcmc_sta->ieee8021x_blocked = false; - - if ((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled) || - (padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption3Enabled)) - pbcmc_sta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm; - } - } - } - -exit: - - kfree(pwep); - - return ret; -} - -static int rtw_set_wpa_ie(struct adapter *padapter, char *pie, unsigned short ielen) -{ - u8 *buf = NULL; - int group_cipher = 0, pairwise_cipher = 0; - int ret = 0; - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - - if (ielen > MAX_WPA_IE_LEN || !pie) { - _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS); - if (!pie) - return ret; - else - return -EINVAL; - } - - if (ielen) { - buf = kmemdup(pie, ielen, GFP_KERNEL); - if (!buf) { - ret = -ENOMEM; - goto exit; - } - - if (ielen < RSN_HEADER_LEN) { - ret = -1; - goto exit; - } - - if (rtw_parse_wpa_ie(buf, ielen, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) { - padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; - padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPAPSK; - memcpy(padapter->securitypriv.supplicant_ie, &buf[0], ielen); - } - - if (rtw_parse_wpa2_ie(buf, ielen, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) { - padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; - padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPA2PSK; - memcpy(padapter->securitypriv.supplicant_ie, &buf[0], ielen); - } - - switch (group_cipher) { - case WPA_CIPHER_NONE: - padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_; - padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled; - break; - case WPA_CIPHER_WEP40: - padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_; - padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled; - break; - case WPA_CIPHER_TKIP: - padapter->securitypriv.dot118021XGrpPrivacy = _TKIP_; - padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled; - break; - case WPA_CIPHER_CCMP: - padapter->securitypriv.dot118021XGrpPrivacy = _AES_; - padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled; - break; - case WPA_CIPHER_WEP104: - padapter->securitypriv.dot118021XGrpPrivacy = _WEP104_; - padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled; - break; - } - - switch (pairwise_cipher) { - case WPA_CIPHER_NONE: - padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_; - padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled; - break; - case WPA_CIPHER_WEP40: - padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_; - padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled; - break; - case WPA_CIPHER_TKIP: - padapter->securitypriv.dot11PrivacyAlgrthm = _TKIP_; - padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled; - break; - case WPA_CIPHER_CCMP: - padapter->securitypriv.dot11PrivacyAlgrthm = _AES_; - padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled; - break; - case WPA_CIPHER_WEP104: - padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_; - padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled; - break; - } - - _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS); - {/* set wps_ie */ - u16 cnt = 0; - u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04}; - - while (cnt < ielen) { - eid = buf[cnt]; - if ((eid == _VENDOR_SPECIFIC_IE_) && (!memcmp(&buf[cnt + 2], wps_oui, 4))) { - padapter->securitypriv.wps_ie_len = ((buf[cnt + 1] + 2) < (MAX_WPA_IE_LEN << 2)) ? (buf[cnt + 1] + 2) : (MAX_WPA_IE_LEN << 2); - - memcpy(padapter->securitypriv.wps_ie, &buf[cnt], padapter->securitypriv.wps_ie_len); - - set_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS); - if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_OK)) - rtw_p2p_set_state(pwdinfo, P2P_STATE_PROVISIONING_ING); - cnt += buf[cnt + 1] + 2; - break; - } else { - cnt += buf[cnt + 1] + 2; /* goto next */ - } - } - } - } - -exit: - kfree(buf); - return ret; -} - -typedef unsigned char NDIS_802_11_RATES_EX[NDIS_802_11_LENGTH_RATES_EX]; - -static int rtw_wx_get_name(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - u32 ht_ielen = 0; - char *p; - u8 ht_cap = false; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network; - NDIS_802_11_RATES_EX *prates = NULL; - - if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE)) { - /* parsing HT_CAP_IE */ - p = rtw_get_ie(&pcur_bss->IEs[12], _HT_CAPABILITY_IE_, &ht_ielen, pcur_bss->IELength - 12); - if (p && ht_ielen > 0) - ht_cap = true; - - prates = &pcur_bss->SupportedRates; - - if (rtw_is_cckratesonly_included((u8 *)prates)) { - if (ht_cap) - snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bn"); - else - snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11b"); - } else if (rtw_is_cckrates_included((u8 *)prates)) { - if (ht_cap) - snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bgn"); - else - snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bg"); - } else { - if (ht_cap) - snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11gn"); - else - snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11g"); - } - } else { - snprintf(wrqu->name, IFNAMSIZ, "unassociated"); - } - - - - return 0; -} - -static int rtw_wx_get_freq(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network; - - if (check_fwstate(pmlmepriv, _FW_LINKED)) { - /* wrqu->freq.m = ieee80211_wlan_frequencies[pcur_bss->Configuration.DSConfig-1] * 100000; */ - wrqu->freq.m = rtw_ch2freq(pcur_bss->Configuration.DSConfig) * 100000; - wrqu->freq.e = 1; - wrqu->freq.i = pcur_bss->Configuration.DSConfig; - } else { - wrqu->freq.m = rtw_ch2freq(padapter->mlmeextpriv.cur_channel) * 100000; - wrqu->freq.e = 1; - wrqu->freq.i = padapter->mlmeextpriv.cur_channel; - } - - return 0; -} - -static int rtw_wx_set_mode(struct net_device *dev, struct iw_request_info *a, - union iwreq_data *wrqu, char *b) -{ - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - enum ndis_802_11_network_infra networkType; - int ret = 0; - - ret = rtw_pwr_wakeup(padapter); - if (ret) - goto exit; - - if (!padapter->hw_init_completed) { - ret = -EPERM; - goto exit; - } - - switch (wrqu->mode) { - case IW_MODE_AUTO: - networkType = Ndis802_11AutoUnknown; - break; - case IW_MODE_ADHOC: - networkType = Ndis802_11IBSS; - break; - case IW_MODE_MASTER: - networkType = Ndis802_11APMode; - break; - case IW_MODE_INFRA: - networkType = Ndis802_11Infrastructure; - break; - default: - ret = -EINVAL; - goto exit; - } - if (!rtw_set_802_11_infrastructure_mode(padapter, networkType)) { - ret = -EPERM; - goto exit; - } - rtw_setopmode_cmd(padapter, networkType); -exit: - - return ret; -} - -static int rtw_wx_get_mode(struct net_device *dev, struct iw_request_info *a, - union iwreq_data *wrqu, char *b) -{ - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) - wrqu->mode = IW_MODE_INFRA; - else if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) || - (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE))) - wrqu->mode = IW_MODE_ADHOC; - else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) - wrqu->mode = IW_MODE_MASTER; - else - wrqu->mode = IW_MODE_AUTO; - - - - return 0; -} - -static int rtw_wx_set_pmkid(struct net_device *dev, - struct iw_request_info *a, - union iwreq_data *wrqu, char *extra) -{ - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - u8 j, blInserted = false; - int ret = false; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct iw_pmksa *pPMK = (struct iw_pmksa *)extra; - u8 strZeroMacAddress[ETH_ALEN] = {0x00}; - u8 strIssueBssid[ETH_ALEN] = {0x00}; - - memcpy(strIssueBssid, pPMK->bssid.sa_data, ETH_ALEN); - if (pPMK->cmd == IW_PMKSA_ADD) { - if (!memcmp(strIssueBssid, strZeroMacAddress, ETH_ALEN)) - return ret; - else - ret = true; - blInserted = false; - - /* overwrite PMKID */ - for (j = 0; j < NUM_PMKID_CACHE; j++) { - if (!memcmp(psecuritypriv->PMKIDList[j].Bssid, strIssueBssid, ETH_ALEN)) { - /* BSSID is matched, the same AP => rewrite with new PMKID. */ - memcpy(psecuritypriv->PMKIDList[j].PMKID, pPMK->pmkid, IW_PMKID_LEN); - psecuritypriv->PMKIDList[j].bUsed = true; - psecuritypriv->PMKIDIndex = j + 1; - blInserted = true; - break; - } - } - - if (!blInserted) { - /* Find a new entry */ - memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].Bssid, strIssueBssid, ETH_ALEN); - memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].PMKID, pPMK->pmkid, IW_PMKID_LEN); - - psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].bUsed = true; - psecuritypriv->PMKIDIndex++; - if (psecuritypriv->PMKIDIndex == 16) - psecuritypriv->PMKIDIndex = 0; - } - } else if (pPMK->cmd == IW_PMKSA_REMOVE) { - ret = true; - for (j = 0; j < NUM_PMKID_CACHE; j++) { - if (!memcmp(psecuritypriv->PMKIDList[j].Bssid, strIssueBssid, ETH_ALEN)) { - /* BSSID is matched, the same AP => Remove this PMKID information and reset it. */ - memset(psecuritypriv->PMKIDList[j].Bssid, 0x00, ETH_ALEN); - psecuritypriv->PMKIDList[j].bUsed = false; - break; - } - } - } else if (pPMK->cmd == IW_PMKSA_FLUSH) { - memset(&psecuritypriv->PMKIDList[0], 0x00, sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE); - psecuritypriv->PMKIDIndex = 0; - ret = true; - } - return ret; -} - -static int rtw_wx_get_sens(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - wrqu->sens.value = 0; - wrqu->sens.fixed = 0; /* no auto select */ - wrqu->sens.disabled = 1; - return 0; -} - -static int rtw_wx_get_range(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct iw_range *range = (struct iw_range *)extra; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - u16 val; - int i; - - wrqu->data.length = sizeof(*range); - memset(range, 0, sizeof(*range)); - - /* Let's try to keep this struct in the same order as in - * linux/include/wireless.h - */ - - /* TODO: See what values we can set, and remove the ones we can't - * set, or fill them with some default data. - */ - - /* ~5 Mb/s real (802.11b) */ - range->throughput = 5 * 1000 * 1000; - - /* signal level threshold range */ - - /* percent values between 0 and 100. */ - range->max_qual.qual = 100; - range->max_qual.level = 100; - range->max_qual.noise = 100; - range->max_qual.updated = 7; /* Updated all three */ - - range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */ - /* TODO: Find real 'good' to 'bad' threshol value for RSSI */ - range->avg_qual.level = 178; /* -78 dBm */ - range->avg_qual.noise = 0; - range->avg_qual.updated = 7; /* Updated all three */ - - range->num_bitrates = RATE_COUNT; - - for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++) - range->bitrate[i] = rtw_rates[i]; - - range->min_frag = MIN_FRAG_THRESHOLD; - range->max_frag = MAX_FRAG_THRESHOLD; - - range->pm_capa = 0; - - range->we_version_compiled = WIRELESS_EXT; - range->we_version_source = 16; - - for (i = 0, val = 0; i < MAX_CHANNEL_NUM; i++) { - /* Include only legal frequencies for some countries */ - if (pmlmeext->channel_set[i].ChannelNum != 0) { - range->freq[val].i = pmlmeext->channel_set[i].ChannelNum; - range->freq[val].m = rtw_ch2freq(pmlmeext->channel_set[i].ChannelNum) * 100000; - range->freq[val].e = 1; - val++; - } - - if (val == IW_MAX_FREQUENCIES) - break; - } - - range->num_channels = val; - range->num_frequency = val; - -/* The following code will proivde the security capability to network manager. */ -/* If the driver doesn't provide this capability to network manager, */ -/* the WPA/WPA2 routers can't be chosen in the network manager. */ - -/* -#define IW_SCAN_CAPA_NONE 0x00 -#define IW_SCAN_CAPA_ESSID 0x01 -#define IW_SCAN_CAPA_BSSID 0x02 -#define IW_SCAN_CAPA_CHANNEL 0x04 -#define IW_SCAN_CAPA_MODE 0x08 -#define IW_SCAN_CAPA_RATE 0x10 -#define IW_SCAN_CAPA_TYPE 0x20 -#define IW_SCAN_CAPA_TIME 0x40 -*/ - - range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | - IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; - - range->scan_capa = IW_SCAN_CAPA_ESSID | IW_SCAN_CAPA_TYPE | - IW_SCAN_CAPA_BSSID | IW_SCAN_CAPA_CHANNEL | - IW_SCAN_CAPA_MODE | IW_SCAN_CAPA_RATE; - - - return 0; -} - -/* set bssid flow */ -/* s1. rtw_set_802_11_infrastructure_mode() */ -/* s2. rtw_set_802_11_authentication_mode() */ -/* s3. set_802_11_encryption_mode() */ -/* s4. rtw_set_802_11_bssid() */ -static int rtw_wx_set_wap(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *awrq, - char *extra) -{ - uint ret = 0; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct sockaddr *temp = (struct sockaddr *)awrq; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct list_head *phead; - u8 *dst_bssid, *src_bssid; - struct __queue *queue = &pmlmepriv->scanned_queue; - struct wlan_network *pnetwork = NULL; - enum ndis_802_11_auth_mode authmode; - - ret = rtw_pwr_wakeup(padapter); - if (ret) - goto exit; - - if (!padapter->bup) { - ret = -1; - goto exit; - } - - if (temp->sa_family != ARPHRD_ETHER) { - ret = -EINVAL; - goto exit; - } - - authmode = padapter->securitypriv.ndisauthtype; - spin_lock_bh(&queue->lock); - phead = get_list_head(queue); - pmlmepriv->pscanned = phead->next; - - while (phead != pmlmepriv->pscanned) { - - pnetwork = container_of(pmlmepriv->pscanned, struct wlan_network, list); - - pmlmepriv->pscanned = pmlmepriv->pscanned->next; - - dst_bssid = pnetwork->network.MacAddress; - - src_bssid = temp->sa_data; - - if ((!memcmp(dst_bssid, src_bssid, ETH_ALEN))) { - if (!rtw_set_802_11_infrastructure_mode(padapter, pnetwork->network.InfrastructureMode)) { - ret = -1; - spin_unlock_bh(&queue->lock); - goto exit; - } - - break; - } - } - spin_unlock_bh(&queue->lock); - - rtw_set_802_11_authentication_mode(padapter, authmode); - /* set_802_11_encryption_mode(padapter, padapter->securitypriv.ndisencryptstatus); */ - if (!rtw_set_802_11_bssid(padapter, temp->sa_data)) { - ret = -1; - goto exit; - } - -exit: - - - - return ret; -} - -static int rtw_wx_get_wap(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network; - - wrqu->ap_addr.sa_family = ARPHRD_ETHER; - - memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN); - - if (check_fwstate(pmlmepriv, _FW_LINKED) || - check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) || - check_fwstate(pmlmepriv, WIFI_AP_STATE)) - memcpy(wrqu->ap_addr.sa_data, pcur_bss->MacAddress, ETH_ALEN); - else - memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN); - - - - return 0; -} - -static int rtw_wx_set_mlme(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct iw_mlme *mlme = (struct iw_mlme *)extra; - - if (!mlme) - return -1; - - switch (mlme->cmd) { - case IW_MLME_DEAUTH: - rtw_set_802_11_disassociate(padapter); - break; - case IW_MLME_DISASSOC: - rtw_set_802_11_disassociate(padapter); - break; - default: - return -EOPNOTSUPP; - } - return 0; -} - -static int rtw_wx_set_scan(struct net_device *dev, struct iw_request_info *a, - union iwreq_data *wrqu, char *extra) -{ - u8 _status = false; - int ret = 0; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct ndis_802_11_ssid ssid[RTW_SSID_SCAN_AMOUNT]; - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - - ret = rtw_pwr_wakeup(padapter); - if (ret) - goto exit; - - if (padapter->bDriverStopped) { - ret = -1; - goto exit; - } - - if (!padapter->bup) { - ret = -1; - goto exit; - } - - if (!padapter->hw_init_completed) { - ret = -1; - goto exit; - } - - /* When Busy Traffic, driver do not site survey. So driver return success. */ - /* wpa_supplicant will not issue SIOCSIWSCAN cmd again after scan timeout. */ - /* modify by thomas 2011-02-22. */ - if (pmlmepriv->LinkDetectInfo.bBusyTraffic) { - indicate_wx_scan_complete_event(padapter); - goto exit; - } - - if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING)) { - indicate_wx_scan_complete_event(padapter); - goto exit; - } - -/* For the DMP WiFi Display project, the driver won't to scan because */ -/* the pmlmepriv->scan_interval is always equal to 3. */ -/* So, the wpa_supplicant won't find out the WPS SoftAP. */ - - if (pwdinfo->p2p_state != P2P_STATE_NONE) { - rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo)); - rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH); - rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_FULL); - rtw_free_network_queue(padapter, true); - } - - memset(ssid, 0, sizeof(struct ndis_802_11_ssid) * RTW_SSID_SCAN_AMOUNT); - - if (wrqu->data.length == sizeof(struct iw_scan_req)) { - struct iw_scan_req *req = (struct iw_scan_req *)extra; - - if (wrqu->data.flags & IW_SCAN_THIS_ESSID) { - int len = min((int)req->essid_len, IW_ESSID_MAX_SIZE); - - memcpy(ssid[0].Ssid, req->essid, len); - ssid[0].SsidLength = len; - - spin_lock_bh(&pmlmepriv->lock); - - _status = rtw_sitesurvey_cmd(padapter, ssid, 1); - - spin_unlock_bh(&pmlmepriv->lock); - } - } else { - if (wrqu->data.length >= WEXT_CSCAN_HEADER_SIZE && - !memcmp(extra, WEXT_CSCAN_HEADER, WEXT_CSCAN_HEADER_SIZE)) { - int len = wrqu->data.length - WEXT_CSCAN_HEADER_SIZE; - char *pos = extra + WEXT_CSCAN_HEADER_SIZE; - char section; - char sec_len; - int ssid_index = 0; - - while (len >= 1) { - section = *(pos++); - len -= 1; - - switch (section) { - case WEXT_CSCAN_SSID_SECTION: - if (len < 1) { - len = 0; - break; - } - sec_len = *(pos++); len -= 1; - if (sec_len > 0 && - sec_len <= len && - sec_len <= 32) { - ssid[ssid_index].SsidLength = sec_len; - memcpy(ssid[ssid_index].Ssid, pos, sec_len); - ssid_index++; - } - pos += sec_len; - len -= sec_len; - break; - case WEXT_CSCAN_TYPE_SECTION: - case WEXT_CSCAN_CHANNEL_SECTION: - pos += 1; - len -= 1; - break; - case WEXT_CSCAN_PASV_DWELL_SECTION: - case WEXT_CSCAN_HOME_DWELL_SECTION: - case WEXT_CSCAN_ACTV_DWELL_SECTION: - pos += 2; - len -= 2; - break; - default: - len = 0; /* stop parsing */ - } - } - - /* it has still some scan parameter to parse, we only do this now... */ - _status = rtw_set_802_11_bssid_list_scan(padapter, ssid, RTW_SSID_SCAN_AMOUNT); - } else { - _status = rtw_set_802_11_bssid_list_scan(padapter, NULL, 0); - } - } - - if (!_status) - ret = -1; - -exit: - - return ret; -} - -static int rtw_wx_get_scan(struct net_device *dev, struct iw_request_info *a, - union iwreq_data *wrqu, char *extra) -{ - struct list_head *plist, *phead; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct __queue *queue = &pmlmepriv->scanned_queue; - struct wlan_network *pnetwork = NULL; - char *ev = extra; - char *stop = ev + wrqu->data.length; - u32 ret = 0; - u32 cnt = 0; - u32 wait_for_surveydone; - int wait_status; - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - - if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) { - /* P2P is enabled */ - wait_for_surveydone = 200; - } else { - /* P2P is disabled */ - wait_for_surveydone = 100; - } - - wait_status = _FW_UNDER_SURVEY | _FW_UNDER_LINKING; - - while (check_fwstate(pmlmepriv, wait_status)) { - msleep(30); - cnt++; - if (cnt > wait_for_surveydone) - break; - } - - spin_lock_bh(&pmlmepriv->scanned_queue.lock); - - phead = get_list_head(queue); - plist = phead->next; - - while (phead != plist) { - if ((stop - ev) < SCAN_ITEM_SIZE) { - ret = -E2BIG; - break; - } - - pnetwork = container_of(plist, struct wlan_network, list); - - /* report network only if the current channel set contains the channel to which this network belongs */ - if (rtw_ch_set_search_ch(padapter->mlmeextpriv.channel_set, pnetwork->network.Configuration.DSConfig) >= 0) - ev = translate_scan(padapter, a, pnetwork, ev, stop); - - plist = plist->next; - } - - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - - wrqu->data.length = ev - extra; - wrqu->data.flags = 0; - - return ret; -} - -/* set ssid flow */ -/* s1. rtw_set_802_11_infrastructure_mode() */ -/* s2. set_802_11_authenticaion_mode() */ -/* s3. set_802_11_encryption_mode() */ -/* s4. rtw_set_802_11_ssid() */ -static int rtw_wx_set_essid(struct net_device *dev, - struct iw_request_info *a, - union iwreq_data *wrqu, char *extra) -{ - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct __queue *queue = &pmlmepriv->scanned_queue; - struct list_head *phead; - struct wlan_network *pnetwork = NULL; - enum ndis_802_11_auth_mode authmode; - struct ndis_802_11_ssid ndis_ssid; - u8 *dst_ssid, *src_ssid; - - uint ret = 0, len; - - ret = rtw_pwr_wakeup(padapter); - if (ret) - goto exit; - - if (!padapter->bup) { - ret = -1; - goto exit; - } - - if (wrqu->essid.length > IW_ESSID_MAX_SIZE) { - ret = -E2BIG; - goto exit; - } - - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - ret = -1; - goto exit; - } - - authmode = padapter->securitypriv.ndisauthtype; - if (wrqu->essid.flags && wrqu->essid.length) { - len = (wrqu->essid.length < IW_ESSID_MAX_SIZE) ? wrqu->essid.length : IW_ESSID_MAX_SIZE; - - memset(&ndis_ssid, 0, sizeof(struct ndis_802_11_ssid)); - ndis_ssid.SsidLength = len; - memcpy(ndis_ssid.Ssid, extra, len); - src_ssid = ndis_ssid.Ssid; - - spin_lock_bh(&queue->lock); - phead = get_list_head(queue); - pmlmepriv->pscanned = phead->next; - - while (phead != pmlmepriv->pscanned) { - pnetwork = container_of(pmlmepriv->pscanned, struct wlan_network, list); - - pmlmepriv->pscanned = pmlmepriv->pscanned->next; - - dst_ssid = pnetwork->network.Ssid.Ssid; - - if ((!memcmp(dst_ssid, src_ssid, ndis_ssid.SsidLength)) && - (pnetwork->network.Ssid.SsidLength == ndis_ssid.SsidLength)) { - - if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) { - if (pnetwork->network.InfrastructureMode != pmlmepriv->cur_network.network.InfrastructureMode) - continue; - } - - if (!rtw_set_802_11_infrastructure_mode(padapter, pnetwork->network.InfrastructureMode)) { - ret = -1; - spin_unlock_bh(&queue->lock); - goto exit; - } - - break; - } - } - spin_unlock_bh(&queue->lock); - rtw_set_802_11_authentication_mode(padapter, authmode); - if (!rtw_set_802_11_ssid(padapter, &ndis_ssid)) { - ret = -1; - goto exit; - } - } - -exit: - return ret; -} - -static int rtw_wx_get_essid(struct net_device *dev, - struct iw_request_info *a, - union iwreq_data *wrqu, char *extra) -{ - u32 len; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network; - - if ((check_fwstate(pmlmepriv, _FW_LINKED)) || - (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))) { - len = pcur_bss->Ssid.SsidLength; - memcpy(extra, pcur_bss->Ssid.Ssid, len); - } else { - len = 0; - *extra = 0; - } - wrqu->essid.length = len; - wrqu->essid.flags = 1; - - return 0; -} - -static int rtw_wx_set_rate(struct net_device *dev, - struct iw_request_info *a, - union iwreq_data *wrqu, char *extra) -{ - int i; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - u8 datarates[NumRates]; - u32 target_rate = wrqu->bitrate.value; - u32 fixed = wrqu->bitrate.fixed; - u32 ratevalue = 0; - u8 mpdatarate[NumRates] = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0xff}; - - if (target_rate == -1) { - ratevalue = 11; - goto set_rate; - } - target_rate = target_rate / 100000; - - switch (target_rate) { - case 10: - ratevalue = 0; - break; - case 20: - ratevalue = 1; - break; - case 55: - ratevalue = 2; - break; - case 60: - ratevalue = 3; - break; - case 90: - ratevalue = 4; - break; - case 110: - ratevalue = 5; - break; - case 120: - ratevalue = 6; - break; - case 180: - ratevalue = 7; - break; - case 240: - ratevalue = 8; - break; - case 360: - ratevalue = 9; - break; - case 480: - ratevalue = 10; - break; - case 540: - ratevalue = 11; - break; - default: - ratevalue = 11; - break; - } - -set_rate: - - for (i = 0; i < NumRates; i++) { - if (ratevalue == mpdatarate[i]) { - datarates[i] = mpdatarate[i]; - if (fixed == 0) - break; - } else { - datarates[i] = 0xff; - } - } - - return rtw_setdatarate_cmd(padapter, datarates); -} - -static int rtw_wx_get_rate(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - u16 max_rate = 0; - - max_rate = rtw_get_cur_max_rate((struct adapter *)rtw_netdev_priv(dev)); - - if (max_rate == 0) - return -EPERM; - - wrqu->bitrate.fixed = 0; /* no auto select */ - wrqu->bitrate.value = max_rate * 100000; - - return 0; -} - -static int rtw_wx_set_rts(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - - - - if (wrqu->rts.disabled) { - padapter->registrypriv.rts_thresh = 2347; - } else { - if (wrqu->rts.value < 0 || - wrqu->rts.value > 2347) - return -EINVAL; - - padapter->registrypriv.rts_thresh = wrqu->rts.value; - } - - return 0; -} - -static int rtw_wx_get_rts(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - - - - wrqu->rts.value = padapter->registrypriv.rts_thresh; - wrqu->rts.fixed = 0; /* no auto select */ - /* wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD); */ - - - - return 0; -} - -static int rtw_wx_set_frag(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - - - - if (wrqu->frag.disabled) { - padapter->xmitpriv.frag_len = MAX_FRAG_THRESHOLD; - } else { - if (wrqu->frag.value < MIN_FRAG_THRESHOLD || - wrqu->frag.value > MAX_FRAG_THRESHOLD) - return -EINVAL; - - padapter->xmitpriv.frag_len = wrqu->frag.value & ~0x1; - } - - return 0; -} - -static int rtw_wx_get_frag(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - - - - wrqu->frag.value = padapter->xmitpriv.frag_len; - wrqu->frag.fixed = 0; /* no auto select */ - - - - return 0; -} - -static int rtw_wx_get_retry(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - wrqu->retry.value = 7; - wrqu->retry.fixed = 0; /* no auto select */ - wrqu->retry.disabled = 1; - - return 0; -} - -static int rtw_wx_set_enc(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *keybuf) -{ - u32 key, ret = 0; - u32 keyindex_provided; - struct ndis_802_11_wep wep; - enum ndis_802_11_auth_mode authmode; - - struct iw_point *erq = &wrqu->encoding; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - - memset(&wep, 0, sizeof(struct ndis_802_11_wep)); - - key = erq->flags & IW_ENCODE_INDEX; - - - - if (erq->flags & IW_ENCODE_DISABLED) { - padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled; - padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_; - padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_; - padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */ - authmode = Ndis802_11AuthModeOpen; - padapter->securitypriv.ndisauthtype = authmode; - - goto exit; - } - - if (key) { - if (key > WEP_KEYS) - return -EINVAL; - key--; - keyindex_provided = 1; - } else { - keyindex_provided = 0; - key = padapter->securitypriv.dot11PrivacyKeyIndex; - } - - /* set authentication mode */ - if (erq->flags & IW_ENCODE_OPEN) { - padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;/* Ndis802_11EncryptionDisabled; */ - padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; - padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_; - padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_; - authmode = Ndis802_11AuthModeOpen; - padapter->securitypriv.ndisauthtype = authmode; - } else if (erq->flags & IW_ENCODE_RESTRICTED) { - padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled; - padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Shared; - padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_; - padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_; - authmode = Ndis802_11AuthModeShared; - padapter->securitypriv.ndisauthtype = authmode; - } else { - padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;/* Ndis802_11EncryptionDisabled; */ - padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */ - padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_; - padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_; - authmode = Ndis802_11AuthModeOpen; - padapter->securitypriv.ndisauthtype = authmode; - } - - wep.KeyIndex = key; - if (erq->length > 0) { - wep.KeyLength = erq->length <= 5 ? 5 : 13; - - wep.Length = wep.KeyLength + offsetof(struct ndis_802_11_wep, KeyMaterial); - } else { - wep.KeyLength = 0; - - if (keyindex_provided == 1) { - /* set key_id only, no given KeyMaterial(erq->length == 0). */ - padapter->securitypriv.dot11PrivacyKeyIndex = key; - - switch (padapter->securitypriv.dot11DefKeylen[key]) { - case 5: - padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_; - break; - case 13: - padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_; - break; - default: - padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_; - break; - } - - goto exit; - } - } - - wep.KeyIndex |= 0x80000000; - - memcpy(wep.KeyMaterial, keybuf, wep.KeyLength); - - if (!rtw_set_802_11_add_wep(padapter, &wep)) { - if (rf_on == pwrpriv->rf_pwrstate) - ret = -EOPNOTSUPP; - goto exit; - } - -exit: - - - - return ret; -} - -static int rtw_wx_get_enc(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *keybuf) -{ - uint key; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct iw_point *erq = &wrqu->encoding; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - - - if (check_fwstate(pmlmepriv, _FW_LINKED) != true) { - if (!check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) { - erq->length = 0; - erq->flags |= IW_ENCODE_DISABLED; - return 0; - } - } - - key = erq->flags & IW_ENCODE_INDEX; - - if (key) { - if (key > WEP_KEYS) - return -EINVAL; - key--; - } else { - key = padapter->securitypriv.dot11PrivacyKeyIndex; - } - - erq->flags = key + 1; - - switch (padapter->securitypriv.ndisencryptstatus) { - case Ndis802_11EncryptionNotSupported: - case Ndis802_11EncryptionDisabled: - erq->length = 0; - erq->flags |= IW_ENCODE_DISABLED; - break; - case Ndis802_11Encryption1Enabled: - erq->length = padapter->securitypriv.dot11DefKeylen[key]; - if (erq->length) { - memcpy(keybuf, padapter->securitypriv.dot11DefKey[key].skey, padapter->securitypriv.dot11DefKeylen[key]); - - erq->flags |= IW_ENCODE_ENABLED; - - if (padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeOpen) - erq->flags |= IW_ENCODE_OPEN; - else if (padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeShared) - erq->flags |= IW_ENCODE_RESTRICTED; - } else { - erq->length = 0; - erq->flags |= IW_ENCODE_DISABLED; - } - break; - case Ndis802_11Encryption2Enabled: - case Ndis802_11Encryption3Enabled: - erq->length = 16; - erq->flags |= (IW_ENCODE_ENABLED | IW_ENCODE_OPEN | IW_ENCODE_NOKEY); - break; - default: - erq->length = 0; - erq->flags |= IW_ENCODE_DISABLED; - break; - } - - - return 0; -} - -static int rtw_wx_get_power(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - wrqu->power.value = 0; - wrqu->power.fixed = 0; /* no auto select */ - wrqu->power.disabled = 1; - - return 0; -} - -static int rtw_wx_set_gen_ie(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - int ret; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - - ret = rtw_set_wpa_ie(padapter, extra, wrqu->data.length); - return ret; -} - -static int rtw_wx_set_auth(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct iw_param *param = (struct iw_param *)&wrqu->param; - int ret = 0; - - switch (param->flags & IW_AUTH_INDEX) { - case IW_AUTH_WPA_VERSION: - break; - case IW_AUTH_CIPHER_PAIRWISE: - - break; - case IW_AUTH_CIPHER_GROUP: - - break; - case IW_AUTH_KEY_MGMT: - /* - * ??? does not use these parameters - */ - break; - case IW_AUTH_TKIP_COUNTERMEASURES: - if (param->value) { - /* wpa_supplicant is enabling the tkip countermeasure. */ - padapter->securitypriv.btkip_countermeasure = true; - } else { - /* wpa_supplicant is disabling the tkip countermeasure. */ - padapter->securitypriv.btkip_countermeasure = false; - } - break; - case IW_AUTH_DROP_UNENCRYPTED: - /* HACK: - * - * wpa_supplicant calls set_wpa_enabled when the driver - * is loaded and unloaded, regardless of if WPA is being - * used. No other calls are made which can be used to - * determine if encryption will be used or not prior to - * association being expected. If encryption is not being - * used, drop_unencrypted is set to false, else true -- we - * can use this to determine if the CAP_PRIVACY_ON bit should - * be set. - */ - - if (padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption1Enabled) - break;/* it means init value, or using wep, ndisencryptstatus = Ndis802_11Encryption1Enabled, */ - /* then it needn't reset it; */ - - if (param->value) { - padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled; - padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_; - padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_; - padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */ - padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen; - } - - break; - case IW_AUTH_80211_AUTH_ALG: - /* - * It's the starting point of a link layer connection using wpa_supplicant - */ - if (check_fwstate(&padapter->mlmepriv, _FW_LINKED)) { - LeaveAllPowerSaveMode(padapter); - rtw_disassoc_cmd(padapter, 500, false); - rtw_indicate_disconnect(padapter); - rtw_free_assoc_resources(padapter, 1); - } - ret = wpa_set_auth_algs(dev, (u32)param->value); - break; - case IW_AUTH_WPA_ENABLED: - break; - case IW_AUTH_RX_UNENCRYPTED_EAPOL: - break; - case IW_AUTH_PRIVACY_INVOKED: - break; - default: - return -EOPNOTSUPP; - } - - return ret; -} - -static int rtw_wx_set_enc_ext(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - char *alg_name; - u32 param_len; - struct ieee_param *param = NULL; - struct iw_point *pencoding = &wrqu->encoding; - struct iw_encode_ext *pext = (struct iw_encode_ext *)extra; - int ret = -1; - - param_len = sizeof(struct ieee_param) + pext->key_len; - param = kzalloc(param_len, GFP_KERNEL); - if (!param) - return -ENOMEM; - - param->cmd = IEEE_CMD_SET_ENCRYPTION; - memset(param->sta_addr, 0xff, ETH_ALEN); - - switch (pext->alg) { - case IW_ENCODE_ALG_NONE: - /* todo: remove key */ - /* remove = 1; */ - alg_name = "none"; - break; - case IW_ENCODE_ALG_WEP: - alg_name = "WEP"; - break; - case IW_ENCODE_ALG_TKIP: - alg_name = "TKIP"; - break; - case IW_ENCODE_ALG_CCMP: - alg_name = "CCMP"; - break; - default: - goto out; - } - - strscpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN); - - if (pext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) - param->u.crypt.set_tx = 1; - - /* cliW: WEP does not have group key - * just not checking GROUP key setting - */ - if ((pext->alg != IW_ENCODE_ALG_WEP) && - (pext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)) - param->u.crypt.set_tx = 0; - - param->u.crypt.idx = (pencoding->flags & 0x00FF) - 1; - - if (pext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) - memcpy(param->u.crypt.seq, pext->rx_seq, 8); - - if (pext->key_len) { - param->u.crypt.key_len = pext->key_len; - memcpy(param->u.crypt.key, pext + 1, pext->key_len); - } - - ret = wpa_set_encryption(dev, param, param_len); - -out: - kfree(param); - return ret; -} - -static int rtw_wx_get_nick(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - if (extra) { - wrqu->data.length = 14; - wrqu->data.flags = 1; - memcpy(extra, "", 14); - } - - /* dump debug info here */ - return 0; -} - -static int rtw_wx_read_rf(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - u32 path, addr, data32; - - path = *(u32 *)extra; - if (path != RF_PATH_A) - return -EINVAL; - - addr = *((u32 *)extra + 1); - data32 = rtl8188e_PHY_QueryRFReg(padapter, addr, 0xFFFFF); - /* - * IMPORTANT!! - * Only when wireless private ioctl is at odd order, - * "extra" would be copied to user space. - */ - sprintf(extra, "0x%05x", data32); - - return 0; -} - -static int rtw_wx_write_rf(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - u32 path, addr, data32; - - path = *(u32 *)extra; - if (path != RF_PATH_A) - return -EINVAL; - - addr = *((u32 *)extra + 1); - data32 = *((u32 *)extra + 2); - rtl8188e_PHY_SetRFReg(padapter, addr, 0xFFFFF, data32); - - return 0; -} - -static int rtw_wx_set_channel_plan(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - u8 channel_plan_req = (u8)(*((int *)wrqu)); - - if (rtw_set_chplan_cmd(padapter, channel_plan_req) != _SUCCESS) - return -EPERM; - - return 0; -} - -static int rtw_get_ap_info(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - int ret = 0; - u32 cnt = 0, wpa_ielen; - struct list_head *plist, *phead; - unsigned char *pbuf; - u8 bssid[ETH_ALEN]; - char data[32]; - struct wlan_network *pnetwork = NULL; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct __queue *queue = &pmlmepriv->scanned_queue; - struct iw_point *pdata = &wrqu->data; - - if (padapter->bDriverStopped || !pdata) { - ret = -EINVAL; - goto exit; - } - - while ((check_fwstate(pmlmepriv, (_FW_UNDER_SURVEY | _FW_UNDER_LINKING)))) { - msleep(30); - cnt++; - if (cnt > 100) - break; - } - pdata->flags = 0; - if (pdata->length >= 32) { - if (copy_from_user(data, pdata->pointer, 32)) { - ret = -EINVAL; - goto exit; - } - } else { - ret = -EINVAL; - goto exit; - } - - spin_lock_bh(&pmlmepriv->scanned_queue.lock); - - phead = get_list_head(queue); - plist = phead->next; - - while (phead != plist) { - pnetwork = container_of(plist, struct wlan_network, list); - - if (!mac_pton(data, bssid)) { - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - return -EINVAL; - } - - if (!memcmp(bssid, pnetwork->network.MacAddress, ETH_ALEN)) { - /* BSSID match, then check if supporting wpa/wpa2 */ - pbuf = rtw_get_wpa_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength - 12); - if (pbuf && (wpa_ielen > 0)) { - pdata->flags = 1; - break; - } - - pbuf = rtw_get_wpa2_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength - 12); - if (pbuf && (wpa_ielen > 0)) { - pdata->flags = 2; - break; - } - } - - plist = plist->next; - } - - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - - if (pdata->length >= 34) { - if (copy_to_user(pdata->pointer + 32, (u8 *)&pdata->flags, 1)) { - ret = -EINVAL; - goto exit; - } - } - -exit: - - return ret; -} - -static int rtw_set_pid(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - int ret = 0; - struct adapter *padapter = rtw_netdev_priv(dev); - int *pdata = (int *)wrqu; - int selector; - - if (padapter->bDriverStopped || !pdata) { - ret = -EINVAL; - goto exit; - } - - selector = *pdata; - if (selector < 3 && selector >= 0) { - padapter->pid[selector] = *(pdata + 1); - ui_pid[selector] = *(pdata + 1); - } -exit: - return ret; -} - -static int rtw_wps_start(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - int ret = 0; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct iw_point *pdata = &wrqu->data; - u32 u32wps_start = 0; - - if (!pdata) - return -EINVAL; - ret = copy_from_user((void *)&u32wps_start, pdata->pointer, 4); - if (ret) { - ret = -EINVAL; - goto exit; - } - - if (padapter->bDriverStopped) { - ret = -EINVAL; - goto exit; - } - - if (u32wps_start == 0) - u32wps_start = *extra; - - if (u32wps_start == 1) /* WPS Start */ - rtw_led_control(padapter, LED_CTL_START_WPS); - else if (u32wps_start == 2) /* WPS Stop because of wps success */ - rtw_led_control(padapter, LED_CTL_STOP_WPS); - else if (u32wps_start == 3) /* WPS Stop because of wps fail */ - rtw_led_control(padapter, LED_CTL_STOP_WPS_FAIL); - -exit: - return ret; -} - -static int rtw_wext_p2p_enable(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - int ret; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - enum P2P_ROLE init_role = P2P_ROLE_DISABLE; - - if (*extra == '0') - init_role = P2P_ROLE_DISABLE; - else if (*extra == '1') - init_role = P2P_ROLE_DEVICE; - else if (*extra == '2') - init_role = P2P_ROLE_CLIENT; - else if (*extra == '3') - init_role = P2P_ROLE_GO; - - ret = rtw_p2p_enable(padapter, init_role); - if (ret) - return ret; - - /* set channel/bandwidth */ - if (init_role != P2P_ROLE_DISABLE) { - u8 channel, ch_offset; - u16 bwmode; - - if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_LISTEN)) { - /* Stay at the listen state and wait for discovery. */ - channel = pwdinfo->listen_channel; - pwdinfo->operating_channel = pwdinfo->listen_channel; - ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - bwmode = HT_CHANNEL_WIDTH_20; - } else { - pwdinfo->operating_channel = pmlmeext->cur_channel; - - channel = pwdinfo->operating_channel; - ch_offset = pmlmeext->cur_ch_offset; - bwmode = pmlmeext->cur_bwmode; - } - - set_channel_bwmode(padapter, channel, ch_offset, bwmode); - } - - return 0; -} - -static void rtw_p2p_set_go_nego_ssid(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - - memcpy(pwdinfo->nego_ssid, extra, strlen(extra)); - pwdinfo->nego_ssidlen = strlen(extra); -} - -static int rtw_p2p_set_intent(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - int ret = 0; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - u8 intent = pwdinfo->intent; - - switch (wrqu->data.length) { - case 1: - intent = extra[0] - '0'; - break; - case 2: - intent = str_2char2num(extra[0], extra[1]); - break; - } - if (intent <= 15) - pwdinfo->intent = intent; - else - ret = -1; - return ret; -} - -static int rtw_p2p_set_listen_ch(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - int ret = 0; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - u8 listen_ch = pwdinfo->listen_channel; /* Listen channel number */ - - switch (wrqu->data.length) { - case 1: - listen_ch = extra[0] - '0'; - break; - case 2: - listen_ch = str_2char2num(extra[0], extra[1]); - break; - } - - if ((listen_ch == 1) || (listen_ch == 6) || (listen_ch == 11)) { - pwdinfo->listen_channel = listen_ch; - set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20); - } else { - ret = -1; - } - - return ret; -} - -static int rtw_p2p_set_op_ch(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ -/* Commented by Albert 20110524 */ -/* This function is used to set the operating channel if the driver will become the group owner */ - - int ret = 0; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - u8 op_ch = pwdinfo->operating_channel; /* Operating channel number */ - - switch (wrqu->data.length) { - case 1: - op_ch = extra[0] - '0'; - break; - case 2: - op_ch = str_2char2num(extra[0], extra[1]); - break; - } - - if (op_ch > 0) - pwdinfo->operating_channel = op_ch; - else - ret = -1; - - return ret; -} - -static int rtw_p2p_profilefound(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - int ret = 0; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - - /* Comment by Albert 2010/10/13 */ - /* Input data format: */ - /* Ex: 0 */ - /* Ex: 1XX:XX:XX:XX:XX:XXYYSSID */ - /* 0 => Reflush the profile record list. */ - /* 1 => Add the profile list */ - /* XX:XX:XX:XX:XX:XX => peer's MAC Address (ex: 00:E0:4C:00:00:01) */ - /* YY => SSID Length */ - /* SSID => SSID for persistence group */ - - /* The upper application should pass the SSID to driver by using this rtw_p2p_profilefound function. */ - if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) { - if (extra[0] == '0') { - /* Remove all the profile information of wifidirect_info structure. */ - memset(&pwdinfo->profileinfo[0], 0x00, sizeof(struct profile_info) * P2P_MAX_PERSISTENT_GROUP_NUM); - pwdinfo->profileindex = 0; - } else { - if (pwdinfo->profileindex >= P2P_MAX_PERSISTENT_GROUP_NUM) { - ret = -1; - } else { - int jj, kk; - - /* Add this profile information into pwdinfo->profileinfo */ - /* Ex: 1XX:XX:XX:XX:XX:XXYYSSID */ - for (jj = 0, kk = 1; jj < ETH_ALEN; jj++, kk += 3) - pwdinfo->profileinfo[pwdinfo->profileindex].peermac[jj] = key_2char2num(extra[kk], extra[kk + 1]); - - pwdinfo->profileinfo[pwdinfo->profileindex].ssidlen = (extra[18] - '0') * 10 + (extra[19] - '0'); - memcpy(pwdinfo->profileinfo[pwdinfo->profileindex].ssid, &extra[20], pwdinfo->profileinfo[pwdinfo->profileindex].ssidlen); - pwdinfo->profileindex++; - } - } - } - - return ret; -} - -static void rtw_p2p_setDN(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - - memset(pwdinfo->device_name, 0x00, WPS_MAX_DEVICE_NAME_LEN); - memcpy(pwdinfo->device_name, extra, wrqu->data.length - 1); - pwdinfo->device_name_len = wrqu->data.length - 1; -} - -static int rtw_p2p_get_wps_configmethod(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - u8 peerMAC[ETH_ALEN] = {0x00}; - int jj, kk; - u8 peerMACStr[17] = {0x00}; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct list_head *plist, *phead; - struct __queue *queue = &pmlmepriv->scanned_queue; - struct wlan_network *pnetwork = NULL; - u8 blnMatch = 0; - u16 attr_content = 0; - uint attr_contentlen = 0; - /* 6 is the string "wpsCM =", 17 is the MAC addr, we have to clear it at wrqu->data.pointer */ - u8 attr_content_str[6 + 17] = {0x00}; - - /* Commented by Albert 20110727 */ - /* The input data is the MAC address which the application wants to know its WPS config method. */ - /* After knowing its WPS config method, the application can decide the config method for provisioning discovery. */ - /* Format: iwpriv wlanx p2p_get_wpsCM 00:E0:4C:00:00:05 */ - - if (copy_from_user(peerMACStr, wrqu->data.pointer + 6, 17)) - return -EFAULT; - - for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3) - peerMAC[jj] = key_2char2num(peerMACStr[kk], peerMACStr[kk + 1]); - - spin_lock_bh(&pmlmepriv->scanned_queue.lock); - - phead = get_list_head(queue); - plist = phead->next; - - while (phead != plist) { - pnetwork = container_of(plist, struct wlan_network, list); - if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) { - u8 *wpsie; - uint wpsie_len = 0; - __be16 be_tmp; - - /* The mac address is matched. */ - wpsie = rtw_get_wps_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &wpsie_len); - if (wpsie) { - rtw_get_wps_attr_content(wpsie, wpsie_len, WPS_ATTR_CONF_METHOD, (u8 *)&be_tmp, &attr_contentlen); - if (attr_contentlen) { - attr_content = be16_to_cpu(be_tmp); - sprintf(attr_content_str, "\n\nM =%.4d", attr_content); - blnMatch = 1; - } - } - break; - } - plist = plist->next; - } - - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - - if (!blnMatch) - sprintf(attr_content_str, "\n\nM = 0000"); - - if (copy_to_user(wrqu->data.pointer, attr_content_str, 6 + 17)) - return -EFAULT; - return 0; -} - -static int rtw_p2p_get_go_device_address(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - u8 peerMAC[ETH_ALEN] = {0x00}; - int jj, kk; - u8 peerMACStr[17] = {0x00}; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct list_head *plist, *phead; - struct __queue *queue = &pmlmepriv->scanned_queue; - struct wlan_network *pnetwork = NULL; - u8 blnMatch = 0; - u8 *p2pie; - uint p2pielen = 0, attr_contentlen = 0; - u8 attr_content[100] = {0x00}; - - u8 go_devadd_str[100 + 10] = {0x00}; - /* +10 is for the str "go_devadd =", we have to clear it at wrqu->data.pointer */ - - /* Commented by Albert 20121209 */ - /* The input data is the GO's interface address which the application wants to know its device address. */ - /* Format: iwpriv wlanx p2p_get2 go_devadd = 00:E0:4C:00:00:05 */ - - if (copy_from_user(peerMACStr, wrqu->data.pointer + 10, 17)) - return -EFAULT; - - for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3) - peerMAC[jj] = key_2char2num(peerMACStr[kk], peerMACStr[kk + 1]); - - spin_lock_bh(&pmlmepriv->scanned_queue.lock); - - phead = get_list_head(queue); - plist = phead->next; - - while (phead != plist) { - pnetwork = container_of(plist, struct wlan_network, list); - if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) { - /* Commented by Albert 2011/05/18 */ - /* Match the device address located in the P2P IE */ - /* This is for the case that the P2P device address is not the same as the P2P interface address. */ - - p2pie = rtw_get_p2p_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &p2pielen); - if (p2pie) { - while (p2pie) { - /* The P2P Device ID attribute is included in the Beacon frame. */ - /* The P2P Device Info attribute is included in the probe response frame. */ - - memset(attr_content, 0x00, 100); - if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_ID, attr_content, &attr_contentlen)) { - /* Handle the P2P Device ID attribute of Beacon first */ - blnMatch = 1; - break; - } else if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_INFO, attr_content, &attr_contentlen)) { - /* Handle the P2P Device Info attribute of probe response */ - blnMatch = 1; - break; - } - - /* Get the next P2P IE */ - p2pie = rtw_get_p2p_ie(p2pie + p2pielen, pnetwork->network.IELength - 12 - (p2pie - &pnetwork->network.IEs[12] + p2pielen), NULL, &p2pielen); - } - } - } - - plist = plist->next; - } - - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - - if (!blnMatch) - sprintf(go_devadd_str, "\n\ndev_add = NULL"); - else - sprintf(go_devadd_str, "\ndev_add =%.2X:%.2X:%.2X:%.2X:%.2X:%.2X", - attr_content[0], attr_content[1], attr_content[2], attr_content[3], attr_content[4], attr_content[5]); - - if (copy_to_user(wrqu->data.pointer, go_devadd_str, 10 + 17)) - return -EFAULT; - return 0; -} - -static int rtw_p2p_get_device_type(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - u8 peerMAC[ETH_ALEN] = {0x00}; - int jj, kk; - u8 peerMACStr[17] = {0x00}; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct list_head *plist, *phead; - struct __queue *queue = &pmlmepriv->scanned_queue; - struct wlan_network *pnetwork = NULL; - u8 blnMatch = 0; - u8 dev_type[8] = {0x00}; - uint dev_type_len = 0; - u8 dev_type_str[17 + 9] = {0x00}; /* +9 is for the str "dev_type =", we have to clear it at wrqu->data.pointer */ - - /* Commented by Albert 20121209 */ - /* The input data is the MAC address which the application wants to know its device type. */ - /* Such user interface could know the device type. */ - /* Format: iwpriv wlanx p2p_get2 dev_type = 00:E0:4C:00:00:05 */ - - if (copy_from_user(peerMACStr, wrqu->data.pointer + 9, 17)) - return -EFAULT; - - for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3) - peerMAC[jj] = key_2char2num(peerMACStr[kk], peerMACStr[kk + 1]); - - spin_lock_bh(&pmlmepriv->scanned_queue.lock); - - phead = get_list_head(queue); - plist = phead->next; - - while (phead != plist) { - pnetwork = container_of(plist, struct wlan_network, list); - if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) { - u8 *wpsie; - uint wpsie_len = 0; - - /* The mac address is matched. */ - - wpsie = rtw_get_wps_ie(&pnetwork->network.IEs[12], - pnetwork->network.IELength - 12, - NULL, &wpsie_len); - if (wpsie) { - rtw_get_wps_attr_content(wpsie, wpsie_len, WPS_ATTR_PRIMARY_DEV_TYPE, dev_type, &dev_type_len); - if (dev_type_len) { - u16 type = 0; - __be16 be_tmp; - - memcpy(&be_tmp, dev_type, 2); - type = be16_to_cpu(be_tmp); - sprintf(dev_type_str, "\n\nN =%.2d", type); - blnMatch = 1; - } - } - break; - } - - plist = plist->next; - } - - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - - if (!blnMatch) - sprintf(dev_type_str, "\n\nN = 00"); - - if (copy_to_user(wrqu->data.pointer, dev_type_str, 9 + 17)) { - return -EFAULT; - } - - return 0; -} - -static int rtw_p2p_get_device_name(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - u8 peerMAC[ETH_ALEN] = {0x00}; - int jj, kk; - u8 peerMACStr[17] = {0x00}; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct list_head *plist, *phead; - struct __queue *queue = &pmlmepriv->scanned_queue; - struct wlan_network *pnetwork = NULL; - u8 blnMatch = 0; - u8 dev_name[WPS_MAX_DEVICE_NAME_LEN] = {0x00}; - uint dev_len = 0; - u8 dev_name_str[WPS_MAX_DEVICE_NAME_LEN + 5] = {0x00}; /* +5 is for the str "devN =", we have to clear it at wrqu->data.pointer */ - - /* Commented by Albert 20121225 */ - /* The input data is the MAC address which the application wants to know its device name. */ - /* Such user interface could show peer device's device name instead of ssid. */ - /* Format: iwpriv wlanx p2p_get2 devN = 00:E0:4C:00:00:05 */ - - if (copy_from_user(peerMACStr, wrqu->data.pointer + 5, 17)) - return -EFAULT; - - for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3) - peerMAC[jj] = key_2char2num(peerMACStr[kk], peerMACStr[kk + 1]); - - spin_lock_bh(&pmlmepriv->scanned_queue.lock); - - phead = get_list_head(queue); - plist = phead->next; - - while (phead != plist) { - pnetwork = container_of(plist, struct wlan_network, list); - if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) { - u8 *wpsie; - uint wpsie_len = 0; - - /* The mac address is matched. */ - wpsie = rtw_get_wps_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &wpsie_len); - if (wpsie) { - rtw_get_wps_attr_content(wpsie, wpsie_len, WPS_ATTR_DEVICE_NAME, dev_name, &dev_len); - if (dev_len) { - sprintf(dev_name_str, "\n\nN =%s", dev_name); - blnMatch = 1; - } - } - break; - } - - plist = plist->next; - } - - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - - if (!blnMatch) - sprintf(dev_name_str, "\n\nN = 0000"); - - if (copy_to_user(wrqu->data.pointer, dev_name_str, 5 + ((dev_len > 17) ? dev_len : 17))) - return -EFAULT; - return 0; -} - -static int rtw_p2p_get_invitation_procedure(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - u8 peerMAC[ETH_ALEN] = {0x00}; - int jj, kk; - u8 peerMACStr[17] = {0x00}; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct list_head *plist, *phead; - struct __queue *queue = &pmlmepriv->scanned_queue; - struct wlan_network *pnetwork = NULL; - u8 blnMatch = 0; - u8 *p2pie; - uint p2pielen = 0, attr_contentlen = 0; - u8 attr_content[2] = {0x00}; - - u8 inv_proc_str[17 + 8] = {0x00}; - /* +8 is for the str "InvProc =", we have to clear it at wrqu->data.pointer */ - - /* Commented by Ouden 20121226 */ - /* The application wants to know P2P initiation procedure is supported or not. */ - /* Format: iwpriv wlanx p2p_get2 InvProc = 00:E0:4C:00:00:05 */ - - if (copy_from_user(peerMACStr, wrqu->data.pointer + 8, 17)) - return -EFAULT; - - for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3) - peerMAC[jj] = key_2char2num(peerMACStr[kk], peerMACStr[kk + 1]); - - spin_lock_bh(&pmlmepriv->scanned_queue.lock); - - phead = get_list_head(queue); - plist = phead->next; - - while (phead != plist) { - pnetwork = container_of(plist, struct wlan_network, list); - if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) { - /* Commented by Albert 20121226 */ - /* Match the device address located in the P2P IE */ - /* This is for the case that the P2P device address is not the same as the P2P interface address. */ - - p2pie = rtw_get_p2p_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &p2pielen); - if (p2pie) { - while (p2pie) { - if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_CAPABILITY, attr_content, &attr_contentlen)) { - /* Handle the P2P capability attribute */ - blnMatch = 1; - break; - } - - /* Get the next P2P IE */ - p2pie = rtw_get_p2p_ie(p2pie + p2pielen, pnetwork->network.IELength - 12 - (p2pie - &pnetwork->network.IEs[12] + p2pielen), NULL, &p2pielen); - } - } - } - plist = plist->next; - } - - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - - if (!blnMatch) { - sprintf(inv_proc_str, "\nIP =-1"); - } else { - if (attr_content[0] & 0x20) - sprintf(inv_proc_str, "\nIP = 1"); - else - sprintf(inv_proc_str, "\nIP = 0"); - } - if (copy_to_user(wrqu->data.pointer, inv_proc_str, 8 + 17)) - return -EFAULT; - return 0; -} - -static int rtw_p2p_connect(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - int ret = 0; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - u8 peerMAC[ETH_ALEN] = {0x00}; - int jj, kk; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct list_head *plist, *phead; - struct __queue *queue = &pmlmepriv->scanned_queue; - struct wlan_network *pnetwork = NULL; - u32 peer_channel = 0; - - /* Commented by Albert 20110304 */ - /* The input data contains two information. */ - /* 1. First information is the MAC address which wants to formate with */ - /* 2. Second information is the WPS PINCode or "pbc" string for push button method */ - /* Format: 00:E0:4C:00:00:05 */ - /* Format: 00:E0:4C:00:00:05 */ - - if (pwdinfo->p2p_state == P2P_STATE_NONE) - return ret; - - if (pwdinfo->ui_got_wps_info == P2P_NO_WPSINFO) - return -1; - - for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3) - peerMAC[jj] = key_2char2num(extra[kk], extra[kk + 1]); - - spin_lock_bh(&pmlmepriv->scanned_queue.lock); - - phead = get_list_head(queue); - plist = phead->next; - - while (phead != plist) { - pnetwork = container_of(plist, struct wlan_network, list); - if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) { - peer_channel = pnetwork->network.Configuration.DSConfig; - break; - } - - plist = plist->next; - } - - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - - if (peer_channel) { - memset(&pwdinfo->nego_req_info, 0x00, sizeof(struct tx_nego_req_info)); - memset(&pwdinfo->groupid_info, 0x00, sizeof(struct group_id_info)); - - pwdinfo->nego_req_info.peer_channel_num[0] = peer_channel; - memcpy(pwdinfo->nego_req_info.peerDevAddr, pnetwork->network.MacAddress, ETH_ALEN); - pwdinfo->nego_req_info.benable = true; - - _cancel_timer_ex(&pwdinfo->restore_p2p_state_timer); - if (rtw_p2p_state(pwdinfo) != P2P_STATE_GONEGO_OK) { - /* Restore to the listen state if the current p2p state is not nego OK */ - rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN); - } - - rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo)); - rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_ING); - - _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT); - _set_timer(&pwdinfo->restore_p2p_state_timer, P2P_GO_NEGO_TIMEOUT); - } else { - ret = -1; - } - return ret; -} - -static void rtw_p2p_invite_req(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - int jj, kk; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct list_head *plist, *phead; - struct __queue *queue = &pmlmepriv->scanned_queue; - struct wlan_network *pnetwork = NULL; - uint peer_channel = 0; - u8 attr_content[50] = {0x00}; - u8 *p2pie; - uint p2pielen = 0, attr_contentlen = 0; - struct tx_invite_req_info *pinvite_req_info = &pwdinfo->invitereq_info; - - /* The input data contains two information items. */ - /* 1. First information is the P2P device address which you want to send to. */ - /* 2. Second information is the group id which combines with GO's mac address, space and GO's ssid. */ - /* Command line sample: iwpriv wlan0 p2p_set invite ="00:11:22:33:44:55 00:E0:4C:00:00:05 DIRECT-xy" */ - /* Format: 00:11:22:33:44:55 00:E0:4C:00:00:05 DIRECT-xy */ - - if (wrqu->data.length <= 37) - return; - - if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) { - return; - } else { - /* Reset the content of struct tx_invite_req_info */ - pinvite_req_info->benable = false; - memset(pinvite_req_info->go_bssid, 0x00, ETH_ALEN); - memset(pinvite_req_info->go_ssid, 0x00, WLAN_SSID_MAXLEN); - pinvite_req_info->ssidlen = 0x00; - pinvite_req_info->operating_ch = pwdinfo->operating_channel; - memset(pinvite_req_info->peer_macaddr, 0x00, ETH_ALEN); - pinvite_req_info->token = 3; - } - - for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3) - pinvite_req_info->peer_macaddr[jj] = key_2char2num(extra[kk], extra[kk + 1]); - - spin_lock_bh(&pmlmepriv->scanned_queue.lock); - - phead = get_list_head(queue); - plist = phead->next; - - while (phead != plist) { - pnetwork = container_of(plist, struct wlan_network, list); - - /* Commented by Albert 2011/05/18 */ - /* Match the device address located in the P2P IE */ - /* This is for the case that the P2P device address is not the same as the P2P interface address. */ - - p2pie = rtw_get_p2p_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &p2pielen); - if (p2pie) { - /* The P2P Device ID attribute is included in the Beacon frame. */ - /* The P2P Device Info attribute is included in the probe response frame. */ - - if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_ID, attr_content, &attr_contentlen)) { - /* Handle the P2P Device ID attribute of Beacon first */ - if (!memcmp(attr_content, pinvite_req_info->peer_macaddr, ETH_ALEN)) { - peer_channel = pnetwork->network.Configuration.DSConfig; - break; - } - } else if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_INFO, attr_content, &attr_contentlen)) { - /* Handle the P2P Device Info attribute of probe response */ - if (!memcmp(attr_content, pinvite_req_info->peer_macaddr, ETH_ALEN)) { - peer_channel = pnetwork->network.Configuration.DSConfig; - break; - } - } - } - plist = plist->next; - } - - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - - if (peer_channel) { - /* Store the GO's bssid */ - for (jj = 0, kk = 18; jj < ETH_ALEN; jj++, kk += 3) - pinvite_req_info->go_bssid[jj] = key_2char2num(extra[kk], extra[kk + 1]); - - /* Store the GO's ssid */ - pinvite_req_info->ssidlen = wrqu->data.length - 36; - memcpy(pinvite_req_info->go_ssid, &extra[36], (u32)pinvite_req_info->ssidlen); - pinvite_req_info->benable = true; - pinvite_req_info->peer_ch = peer_channel; - - rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo)); - rtw_p2p_set_state(pwdinfo, P2P_STATE_TX_INVITE_REQ); - - set_channel_bwmode(padapter, peer_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20); - - _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT); - - _set_timer(&pwdinfo->restore_p2p_state_timer, P2P_INVITE_TIMEOUT); - } -} - -static void rtw_p2p_set_persistent(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - - /* The input data is 0 or 1 */ - /* 0: disable persistent group functionality */ - /* 1: enable persistent group founctionality */ - - if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) { - return; - } else { - if (extra[0] == '0') /* Disable the persistent group function. */ - pwdinfo->persistent_supported = false; - else if (extra[0] == '1') /* Enable the persistent group function. */ - pwdinfo->persistent_supported = true; - else - pwdinfo->persistent_supported = false; - } - pr_info("[%s] persistent_supported = %d\n", __func__, pwdinfo->persistent_supported); -} - -static void rtw_p2p_prov_disc(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - u8 peerMAC[ETH_ALEN] = {0x00}; - int jj, kk; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct list_head *plist, *phead; - struct __queue *queue = &pmlmepriv->scanned_queue; - struct wlan_network *pnetwork = NULL; - uint peer_channel = 0; - u8 attr_content[100] = {0x00}; - u8 *p2pie; - uint p2pielen = 0, attr_contentlen = 0; - - /* The input data contains two information items. */ - /* 1. First information is the MAC address which wants to issue the provisioning discovery request frame. */ - /* 2. Second information is the WPS configuration method which wants to discovery */ - /* Format: 00:E0:4C:00:00:05_display */ - /* Format: 00:E0:4C:00:00:05_keypad */ - /* Format: 00:E0:4C:00:00:05_pbc */ - /* Format: 00:E0:4C:00:00:05_label */ - - if (pwdinfo->p2p_state == P2P_STATE_NONE) { - return; - } else { - /* Reset the content of struct tx_provdisc_req_info excluded the wps_config_method_request. */ - memset(pwdinfo->tx_prov_disc_info.peerDevAddr, 0x00, ETH_ALEN); - memset(pwdinfo->tx_prov_disc_info.peerIFAddr, 0x00, ETH_ALEN); - memset(&pwdinfo->tx_prov_disc_info.ssid, 0x00, sizeof(struct ndis_802_11_ssid)); - pwdinfo->tx_prov_disc_info.peer_channel_num[0] = 0; - pwdinfo->tx_prov_disc_info.peer_channel_num[1] = 0; - pwdinfo->tx_prov_disc_info.benable = false; - } - - for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3) - peerMAC[jj] = key_2char2num(extra[kk], extra[kk + 1]); - - if (!memcmp(&extra[18], "display", 7)) - pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_DISPLYA; - else if (!memcmp(&extra[18], "keypad", 7)) - pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_KEYPAD; - else if (!memcmp(&extra[18], "pbc", 3)) - pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_PUSH_BUTTON; - else if (!memcmp(&extra[18], "label", 5)) - pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_LABEL; - else - return; - - spin_lock_bh(&pmlmepriv->scanned_queue.lock); - - phead = get_list_head(queue); - plist = phead->next; - - while (phead != plist) { - if (peer_channel != 0) - break; - - pnetwork = container_of(plist, struct wlan_network, list); - - /* Commented by Albert 2011/05/18 */ - /* Match the device address located in the P2P IE */ - /* This is for the case that the P2P device address is not the same as the P2P interface address. */ - - p2pie = rtw_get_p2p_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &p2pielen); - if (p2pie) { - while (p2pie) { - /* The P2P Device ID attribute is included in the Beacon frame. */ - /* The P2P Device Info attribute is included in the probe response frame. */ - - if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_ID, attr_content, &attr_contentlen)) { - /* Handle the P2P Device ID attribute of Beacon first */ - if (!memcmp(attr_content, peerMAC, ETH_ALEN)) { - peer_channel = pnetwork->network.Configuration.DSConfig; - break; - } - } else if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_INFO, attr_content, &attr_contentlen)) { - /* Handle the P2P Device Info attribute of probe response */ - if (!memcmp(attr_content, peerMAC, ETH_ALEN)) { - peer_channel = pnetwork->network.Configuration.DSConfig; - break; - } - } - - /* Get the next P2P IE */ - p2pie = rtw_get_p2p_ie(p2pie + p2pielen, pnetwork->network.IELength - 12 - (p2pie - &pnetwork->network.IEs[12] + p2pielen), NULL, &p2pielen); - } - } - - plist = plist->next; - } - - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - - if (peer_channel) { - memcpy(pwdinfo->tx_prov_disc_info.peerIFAddr, pnetwork->network.MacAddress, ETH_ALEN); - memcpy(pwdinfo->tx_prov_disc_info.peerDevAddr, peerMAC, ETH_ALEN); - pwdinfo->tx_prov_disc_info.peer_channel_num[0] = (u16)peer_channel; - pwdinfo->tx_prov_disc_info.benable = true; - rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo)); - rtw_p2p_set_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ); - - if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) { - memcpy(&pwdinfo->tx_prov_disc_info.ssid, &pnetwork->network.Ssid, sizeof(struct ndis_802_11_ssid)); - } else if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE) || rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) { - memcpy(pwdinfo->tx_prov_disc_info.ssid.Ssid, pwdinfo->p2p_wildcard_ssid, P2P_WILDCARD_SSID_LEN); - pwdinfo->tx_prov_disc_info.ssid.SsidLength = P2P_WILDCARD_SSID_LEN; - } - - set_channel_bwmode(padapter, peer_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20); - - _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT); - - _set_timer(&pwdinfo->restore_p2p_state_timer, P2P_PROVISION_TIMEOUT); - } -} - -/* This function is used to inform the driver the user had specified the pin code value or pbc */ -/* to application. */ - -static void rtw_p2p_got_wpsinfo(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - - /* Added by Albert 20110328 */ - /* if the input data is P2P_NO_WPSINFO -> reset the wpsinfo */ - /* if the input data is P2P_GOT_WPSINFO_PEER_DISPLAY_PIN -> the utility just input the PIN code got from the peer P2P device. */ - /* if the input data is P2P_GOT_WPSINFO_SELF_DISPLAY_PIN -> the utility just got the PIN code from itself. */ - /* if the input data is P2P_GOT_WPSINFO_PBC -> the utility just determine to use the PBC */ - - if (*extra == '0') - pwdinfo->ui_got_wps_info = P2P_NO_WPSINFO; - else if (*extra == '1') - pwdinfo->ui_got_wps_info = P2P_GOT_WPSINFO_PEER_DISPLAY_PIN; - else if (*extra == '2') - pwdinfo->ui_got_wps_info = P2P_GOT_WPSINFO_SELF_DISPLAY_PIN; - else if (*extra == '3') - pwdinfo->ui_got_wps_info = P2P_GOT_WPSINFO_PBC; - else - pwdinfo->ui_got_wps_info = P2P_NO_WPSINFO; -} - -static int rtw_p2p_set(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - if (!memcmp(extra, "enable =", 7)) { - rtw_wext_p2p_enable(dev, info, wrqu, &extra[7]); - } else if (!memcmp(extra, "setDN =", 6)) { - wrqu->data.length -= 6; - rtw_p2p_setDN(dev, info, wrqu, &extra[6]); - } else if (!memcmp(extra, "profilefound =", 13)) { - wrqu->data.length -= 13; - rtw_p2p_profilefound(dev, info, wrqu, &extra[13]); - } else if (!memcmp(extra, "prov_disc =", 10)) { - wrqu->data.length -= 10; - rtw_p2p_prov_disc(dev, info, wrqu, &extra[10]); - } else if (!memcmp(extra, "nego =", 5)) { - wrqu->data.length -= 5; - rtw_p2p_connect(dev, info, wrqu, &extra[5]); - } else if (!memcmp(extra, "intent =", 7)) { - /* Commented by Albert 2011/03/23 */ - /* The wrqu->data.length will include the null character */ - /* So, we will decrease 7 + 1 */ - wrqu->data.length -= 8; - rtw_p2p_set_intent(dev, info, wrqu, &extra[7]); - } else if (!memcmp(extra, "ssid =", 5)) { - wrqu->data.length -= 5; - rtw_p2p_set_go_nego_ssid(dev, info, wrqu, &extra[5]); - } else if (!memcmp(extra, "got_wpsinfo =", 12)) { - wrqu->data.length -= 12; - rtw_p2p_got_wpsinfo(dev, info, wrqu, &extra[12]); - } else if (!memcmp(extra, "listen_ch =", 10)) { - /* Commented by Albert 2011/05/24 */ - /* The wrqu->data.length will include the null character */ - /* So, we will decrease (10 + 1) */ - wrqu->data.length -= 11; - rtw_p2p_set_listen_ch(dev, info, wrqu, &extra[10]); - } else if (!memcmp(extra, "op_ch =", 6)) { - /* Commented by Albert 2011/05/24 */ - /* The wrqu->data.length will include the null character */ - /* So, we will decrease (6 + 1) */ - wrqu->data.length -= 7; - rtw_p2p_set_op_ch(dev, info, wrqu, &extra[6]); - } else if (!memcmp(extra, "invite =", 7)) { - wrqu->data.length -= 8; - rtw_p2p_invite_req(dev, info, wrqu, &extra[7]); - } else if (!memcmp(extra, "persistent =", 11)) { - wrqu->data.length -= 11; - rtw_p2p_set_persistent(dev, info, wrqu, &extra[11]); - } - - return 0; -} - -static int rtw_p2p_get2(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - int ret = 0; - - if (!memcmp(extra, "wpsCM =", 6)) { - wrqu->data.length -= 6; - ret = rtw_p2p_get_wps_configmethod(dev, info, wrqu, &extra[6]); - } else if (!memcmp(extra, "devN =", 5)) { - wrqu->data.length -= 5; - ret = rtw_p2p_get_device_name(dev, info, wrqu, &extra[5]); - } else if (!memcmp(extra, "dev_type =", 9)) { - wrqu->data.length -= 9; - ret = rtw_p2p_get_device_type(dev, info, wrqu, &extra[9]); - } else if (!memcmp(extra, "go_devadd =", 10)) { - wrqu->data.length -= 10; - ret = rtw_p2p_get_go_device_address(dev, info, wrqu, &extra[10]); - } else if (!memcmp(extra, "InvProc =", 8)) { - wrqu->data.length -= 8; - ret = rtw_p2p_get_invitation_procedure(dev, info, wrqu, &extra[8]); - } - - return ret; -} - -static int rtw_rereg_nd_name(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - int ret = 0; - struct adapter *padapter = rtw_netdev_priv(dev); - struct rereg_nd_name_data *rereg_priv = &padapter->rereg_nd_name_priv; - char new_ifname[IFNAMSIZ]; - - if (rereg_priv->old_ifname[0] == 0) { - char *reg_ifname; - reg_ifname = padapter->registrypriv.if2name; - - strscpy(rereg_priv->old_ifname, reg_ifname, IFNAMSIZ); - } - - if (wrqu->data.length > IFNAMSIZ) - return -EFAULT; - - if (copy_from_user(new_ifname, wrqu->data.pointer, IFNAMSIZ)) - return -EFAULT; - - if (0 == strcmp(rereg_priv->old_ifname, new_ifname)) - return ret; - - ret = rtw_change_ifname(padapter, new_ifname); - if (0 != ret) - goto exit; - - if (!memcmp(rereg_priv->old_ifname, "disable%d", 9)) { - padapter->ledpriv.bRegUseLed = rereg_priv->old_bRegUseLed; - rtl8188eu_InitSwLeds(padapter); - rtw_ips_mode_req(&padapter->pwrctrlpriv, rereg_priv->old_ips_mode); - } - - strscpy(rereg_priv->old_ifname, new_ifname, IFNAMSIZ); - - if (!memcmp(new_ifname, "disable%d", 9)) { - /* free network queue for Android's timming issue */ - rtw_free_network_queue(padapter, true); - - /* close led */ - rtw_led_control(padapter, LED_CTL_POWER_OFF); - rereg_priv->old_bRegUseLed = padapter->ledpriv.bRegUseLed; - padapter->ledpriv.bRegUseLed = false; - rtl8188eu_DeInitSwLeds(padapter); - - /* the interface is being "disabled", we can do deeper IPS */ - rereg_priv->old_ips_mode = rtw_get_ips_mode_req(&padapter->pwrctrlpriv); - rtw_ips_mode_req(&padapter->pwrctrlpriv, IPS_NORMAL); - } -exit: - return ret; -} - -static void mac_reg_dump(struct adapter *padapter) -{ - int i, j = 1; - u32 reg; - int res; - - pr_info("\n ======= MAC REG =======\n"); - for (i = 0x0; i < 0x300; i += 4) { - if (j % 4 == 1) - pr_info("0x%02x", i); - - res = rtw_read32(padapter, i, ®); - if (!res) - pr_info(" 0x%08x ", reg); - - if ((j++) % 4 == 0) - pr_info("\n"); - } - for (i = 0x400; i < 0x800; i += 4) { - if (j % 4 == 1) - pr_info("0x%02x", i); - - res = rtw_read32(padapter, i, ®); - if (!res) - pr_info(" 0x%08x ", reg); - - if ((j++) % 4 == 0) - pr_info("\n"); - } -} - -static void bb_reg_dump(struct adapter *padapter) -{ - int i, j = 1, res; - u32 reg; - - pr_info("\n ======= BB REG =======\n"); - for (i = 0x800; i < 0x1000; i += 4) { - if (j % 4 == 1) - pr_info("0x%02x", i); - - res = rtw_read32(padapter, i, ®); - if (!res) - pr_info(" 0x%08x ", reg); - - if ((j++) % 4 == 0) - pr_info("\n"); - } -} - -static void rf_reg_dump(struct adapter *padapter) -{ - int i, j = 1; - u32 value; - - pr_info("\n ======= RF REG =======\n"); - pr_info("\nRF_Path(%x)\n", RF_PATH_A); - for (i = 0; i < 0x100; i++) { - value = rtl8188e_PHY_QueryRFReg(padapter, i, 0xffffffff); - if (j % 4 == 1) - pr_info("0x%02x ", i); - pr_info(" 0x%08x ", value); - if ((j++) % 4 == 0) - pr_info("\n"); - } -} - -static void rtw_set_dynamic_functions(struct adapter *adapter, u8 dm_func) -{ - struct hal_data_8188e *haldata = &adapter->haldata; - struct odm_dm_struct *odmpriv = &haldata->odmpriv; - int res; - - switch (dm_func) { - case 0: - /* disable all dynamic func */ - odmpriv->SupportAbility = DYNAMIC_FUNC_DISABLE; - break; - case 1: - /* disable DIG */ - odmpriv->SupportAbility &= (~DYNAMIC_BB_DIG); - break; - case 6: - /* turn on all dynamic func */ - if (!(odmpriv->SupportAbility & DYNAMIC_BB_DIG)) { - struct rtw_dig *digtable = &odmpriv->DM_DigTable; - - res = rtw_read8(adapter, 0xc50, &digtable->CurIGValue); - (void)res; - /* FIXME: return an error to caller */ - } - odmpriv->SupportAbility = DYNAMIC_ALL_FUNC_ENABLE; - break; - default: - break; - } -} - -static void rtw_set_dm_func_flag(struct adapter *adapter, u32 odm_flag) -{ - struct hal_data_8188e *haldata = &adapter->haldata; - struct odm_dm_struct *odmpriv = &haldata->odmpriv; - - odmpriv->SupportAbility = odm_flag; -} - -static int rtw_dbg_port(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - int ret = 0; - u8 major_cmd, minor_cmd; - u16 arg; - s32 extra_arg; - u32 *pdata, val32; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_network *cur_network = &pmlmepriv->cur_network; - struct sta_priv *pstapriv = &padapter->stapriv; - - pdata = (u32 *)&wrqu->data; - - val32 = *pdata; - arg = (u16)(val32 & 0x0000ffff); - major_cmd = (u8)(val32 >> 24); - minor_cmd = (u8)((val32 >> 16) & 0x00ff); - - extra_arg = *(pdata + 1); - - switch (major_cmd) { - case 0x70:/* read_reg */ - switch (minor_cmd) { - case 1: - break; - case 2: - break; - case 4: - break; - } - break; - case 0x71:/* write_reg */ - switch (minor_cmd) { - case 1: - rtw_write8(padapter, arg, extra_arg); - break; - case 2: - rtw_write16(padapter, arg, extra_arg); - break; - case 4: - rtw_write32(padapter, arg, extra_arg); - break; - } - break; - case 0x72:/* read_bb */ - break; - case 0x73:/* write_bb */ - rtl8188e_PHY_SetBBReg(padapter, arg, 0xffffffff, extra_arg); - break; - case 0x74:/* read_rf */ - if (minor_cmd != RF_PATH_A) { - ret = -EINVAL; - break; - } - break; - case 0x75:/* write_rf */ - if (minor_cmd != RF_PATH_A) { - ret = -EINVAL; - break; - } - rtl8188e_PHY_SetRFReg(padapter, arg, 0xffffffff, extra_arg); - break; - - case 0x76: - switch (minor_cmd) { - case 0x00: /* normal mode, */ - padapter->recvpriv.is_signal_dbg = 0; - break; - case 0x01: /* dbg mode */ - padapter->recvpriv.is_signal_dbg = 1; - extra_arg = extra_arg > 100 ? 100 : extra_arg; - extra_arg = extra_arg < 0 ? 0 : extra_arg; - padapter->recvpriv.signal_strength_dbg = extra_arg; - break; - } - break; - case 0x78: /* IOL test */ - switch (minor_cmd) { - case 0x04: /* LLT table initialization test */ - { - struct xmit_frame *xmit_frame; - - xmit_frame = rtw_IOL_accquire_xmit_frame(padapter); - if (!xmit_frame) { - ret = -ENOMEM; - break; - } - - if (rtl8188e_IOL_exec_cmds_sync(padapter, xmit_frame, 500, 0) != _SUCCESS) - ret = -EPERM; - } - break; - case 0x05: /* blink LED test */ - { - u16 reg = 0x4c; - u32 blink_num = 50; - u32 blink_delay_ms = 200; - int i; - struct xmit_frame *xmit_frame; - - xmit_frame = rtw_IOL_accquire_xmit_frame(padapter); - if (!xmit_frame) { - ret = -ENOMEM; - break; - } - - for (i = 0; i < blink_num; i++) { - rtw_IOL_append_WB_cmd(xmit_frame, reg, 0x00, 0xff); - rtw_IOL_append_DELAY_MS_cmd(xmit_frame, blink_delay_ms); - rtw_IOL_append_WB_cmd(xmit_frame, reg, 0x08, 0xff); - rtw_IOL_append_DELAY_MS_cmd(xmit_frame, blink_delay_ms); - } - if (rtl8188e_IOL_exec_cmds_sync(padapter, xmit_frame, (blink_delay_ms * blink_num * 2) + 200, 0) != _SUCCESS) - ret = -EPERM; - } - break; - - case 0x06: /* continuous write byte test */ - { - u16 reg = arg; - u16 start_value = 0; - u32 write_num = extra_arg; - int i, res; - struct xmit_frame *xmit_frame; - u8 val8; - - xmit_frame = rtw_IOL_accquire_xmit_frame(padapter); - if (!xmit_frame) { - ret = -ENOMEM; - break; - } - - for (i = 0; i < write_num; i++) - rtw_IOL_append_WB_cmd(xmit_frame, reg, i + start_value, 0xFF); - if (rtl8188e_IOL_exec_cmds_sync(padapter, xmit_frame, 5000, 0) != _SUCCESS) - ret = -EPERM; - - /* FIXME: is this read necessary? */ - res = rtw_read8(padapter, reg, &val8); - (void)res; - } - break; - - case 0x07: /* continuous write word test */ - { - u16 reg = arg; - u16 start_value = 200; - u32 write_num = extra_arg; - u16 val16; - int i, res; - struct xmit_frame *xmit_frame; - - xmit_frame = rtw_IOL_accquire_xmit_frame(padapter); - if (!xmit_frame) { - ret = -ENOMEM; - break; - } - - for (i = 0; i < write_num; i++) - rtw_IOL_append_WW_cmd(xmit_frame, reg, i + start_value, 0xFFFF); - if (rtl8188e_IOL_exec_cmds_sync(padapter, xmit_frame, 5000, 0) != _SUCCESS) - ret = -EPERM; - - /* FIXME: is this read necessary? */ - res = rtw_read16(padapter, reg, &val16); - (void)res; - } - break; - case 0x08: /* continuous write dword test */ - { - u16 reg = arg; - u32 start_value = 0x110000c7; - u32 write_num = extra_arg; - - int i; - struct xmit_frame *xmit_frame; - - xmit_frame = rtw_IOL_accquire_xmit_frame(padapter); - if (!xmit_frame) { - ret = -ENOMEM; - break; - } - - for (i = 0; i < write_num; i++) - rtw_IOL_append_WD_cmd(xmit_frame, reg, i + start_value, 0xFFFFFFFF); - if (rtl8188e_IOL_exec_cmds_sync(padapter, xmit_frame, 5000, 0) != _SUCCESS) - ret = -EPERM; - - /* FIXME: is this read necessary? */ - ret = rtw_read32(padapter, reg, &write_num); - } - break; - } - break; - case 0x79: - { - /* - * dbg 0x79000000 [value], set RESP_TXAGC to + value, value:0~15 - * dbg 0x79010000 [value], set RESP_TXAGC to - value, value:0~15 - */ - u8 value = extra_arg & 0x0f; - u8 sign = minor_cmd; - u16 write_value = 0; - - if (sign) - value = value | 0x10; - - write_value = value | (value << 5); - rtw_write16(padapter, 0x6d9, write_value); - } - break; - case 0x7a: - receive_disconnect(padapter, pmlmeinfo->network.MacAddress - , WLAN_REASON_EXPIRATION_CHK); - break; - case 0x7F: - switch (minor_cmd) { - case 0x0: - break; - case 0x01: - break; - case 0x02: - break; - case 0x03: - break; - case 0x04: - break; - case 0x05: - rtw_get_stainfo(pstapriv, cur_network->network.MacAddress); - break; - case 0x06: - { - u32 ODMFlag = (u32)(0x0f & arg); - rtw_set_dm_func_flag(padapter, ODMFlag); - } - break; - case 0x07: - break; - case 0x08: - break; - case 0x09: - break; - case 0x15: - break; - case 0x10:/* driver version display */ - break; - case 0x11: - padapter->bRxRSSIDisplay = extra_arg; - break; - case 0x12: /* set rx_stbc */ - { - struct registry_priv *pregpriv = &padapter->registrypriv; - /* 0: disable, bit(0):enable 2.4g, bit(1):enable 5g, 0x3: enable both 2.4g and 5g */ - /* default is set to enable 2.4GHZ for IOT issue with bufflao's AP at 5GHZ */ - if (extra_arg == 0 || - extra_arg == 1 || - extra_arg == 2 || - extra_arg == 3) - pregpriv->rx_stbc = extra_arg; - } - break; - case 0x13: /* set ampdu_enable */ - { - struct registry_priv *pregpriv = &padapter->registrypriv; - /* 0: disable, 0x1:enable (but wifi_spec should be 0), 0x2: force enable (don't care wifi_spec) */ - if (extra_arg >= 0 && extra_arg < 3) - pregpriv->ampdu_enable = extra_arg; - } - break; - case 0x14: /* get wifi_spec */ - break; - case 0x23: - padapter->bNotifyChannelChange = extra_arg; - break; - case 0x24: - padapter->bShowGetP2PState = extra_arg; - break; - case 0xdd:/* registers dump, 0 for mac reg, 1 for bb reg, 2 for rf reg */ - if (extra_arg == 0) - mac_reg_dump(padapter); - else if (extra_arg == 1) - bb_reg_dump(padapter); - else if (extra_arg == 2) - rf_reg_dump(padapter); - break; - case 0xee:/* turn on/off dynamic funcs */ - if (extra_arg != 0xf) { - /* extra_arg = 0 - disable all dynamic func - * extra_arg = 1 - disable DIG - * extra_arg = 6 - turn on all dynamic func - */ - rtw_set_dynamic_functions(padapter, extra_arg); - } - break; - case 0xfd: - rtw_write8(padapter, 0xc50, arg); - rtw_write8(padapter, 0xc58, arg); - break; - case 0xfe: - break; - case 0xff: - break; - } - break; - default: - break; - } - return ret; -} - -static int rtw_wx_set_priv(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *awrq, - char *extra) -{ - int ret = 0; - int len = 0; - char *ext; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct iw_point *dwrq = (struct iw_point *)awrq; - - if (dwrq->length == 0) - return -EFAULT; - - len = dwrq->length; - ext = vmalloc(len); - if (!ext) - return -ENOMEM; - - if (copy_from_user(ext, dwrq->pointer, len)) { - vfree(ext); - return -EFAULT; - } - - /* added for wps2.0 @20110524 */ - if (dwrq->flags == 0x8766 && len > 8) { - u32 cp_sz; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - u8 *probereq_wpsie = ext; - int probereq_wpsie_len = len; - u8 wps_oui[4] = {0x0, 0x50, 0xf2, 0x04}; - - if ((_VENDOR_SPECIFIC_IE_ == probereq_wpsie[0]) && - (!memcmp(&probereq_wpsie[2], wps_oui, 4))) { - cp_sz = min(probereq_wpsie_len, MAX_WPS_IE_LEN); - - pmlmepriv->wps_probe_req_ie_len = 0; - kfree(pmlmepriv->wps_probe_req_ie); - pmlmepriv->wps_probe_req_ie = NULL; - - pmlmepriv->wps_probe_req_ie = kmemdup(probereq_wpsie, cp_sz, GFP_KERNEL); - if (!pmlmepriv->wps_probe_req_ie) { - ret = -EINVAL; - goto FREE_EXT; - } - pmlmepriv->wps_probe_req_ie_len = cp_sz; - } - goto FREE_EXT; - } - - if (len >= WEXT_CSCAN_HEADER_SIZE && - !memcmp(ext, WEXT_CSCAN_HEADER, WEXT_CSCAN_HEADER_SIZE)) { - ret = rtw_wx_set_scan(dev, info, awrq, ext); - goto FREE_EXT; - } - -FREE_EXT: - - vfree(ext); - - return ret; -} - -static int rtw_pm_set(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - int ret = 0; - unsigned mode = 0; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - - if (!memcmp(extra, "lps =", 4)) { - sscanf(extra + 4, "%u", &mode); - ret = rtw_pm_set_lps(padapter, mode); - } else if (!memcmp(extra, "ips =", 4)) { - sscanf(extra + 4, "%u", &mode); - ret = rtw_pm_set_ips(padapter, mode); - } else { - ret = -EINVAL; - } - - return ret; -} - -static iw_handler rtw_handlers[] = { - IW_HANDLER(SIOCGIWNAME, rtw_wx_get_name), - IW_HANDLER(SIOCGIWFREQ, rtw_wx_get_freq), - IW_HANDLER(SIOCSIWMODE, rtw_wx_set_mode), - IW_HANDLER(SIOCGIWMODE, rtw_wx_get_mode), - IW_HANDLER(SIOCGIWSENS, rtw_wx_get_sens), - IW_HANDLER(SIOCGIWRANGE, rtw_wx_get_range), - IW_HANDLER(SIOCSIWPRIV, rtw_wx_set_priv), - IW_HANDLER(SIOCSIWAP, rtw_wx_set_wap), - IW_HANDLER(SIOCGIWAP, rtw_wx_get_wap), - IW_HANDLER(SIOCSIWMLME, rtw_wx_set_mlme), - IW_HANDLER(SIOCSIWSCAN, rtw_wx_set_scan), - IW_HANDLER(SIOCGIWSCAN, rtw_wx_get_scan), - IW_HANDLER(SIOCSIWESSID, rtw_wx_set_essid), - IW_HANDLER(SIOCGIWESSID, rtw_wx_get_essid), - IW_HANDLER(SIOCGIWNICKN, rtw_wx_get_nick), - IW_HANDLER(SIOCSIWRATE, rtw_wx_set_rate), - IW_HANDLER(SIOCGIWRATE, rtw_wx_get_rate), - IW_HANDLER(SIOCSIWRTS, rtw_wx_set_rts), - IW_HANDLER(SIOCGIWRTS, rtw_wx_get_rts), - IW_HANDLER(SIOCSIWFRAG, rtw_wx_set_frag), - IW_HANDLER(SIOCGIWFRAG, rtw_wx_get_frag), - IW_HANDLER(SIOCGIWRETRY, rtw_wx_get_retry), - IW_HANDLER(SIOCSIWENCODE, rtw_wx_set_enc), - IW_HANDLER(SIOCGIWENCODE, rtw_wx_get_enc), - IW_HANDLER(SIOCGIWPOWER, rtw_wx_get_power), - IW_HANDLER(SIOCSIWGENIE, rtw_wx_set_gen_ie), - IW_HANDLER(SIOCSIWAUTH, rtw_wx_set_auth), - IW_HANDLER(SIOCSIWENCODEEXT, rtw_wx_set_enc_ext), - IW_HANDLER(SIOCSIWPMKSA, rtw_wx_set_pmkid), -}; - -static const struct iw_priv_args rtw_private_args[] = { - { - SIOCIWFIRSTPRIV + 0x0, - IW_PRIV_TYPE_CHAR | 0x7FF, 0, "write" - }, - { - SIOCIWFIRSTPRIV + 0x1, - IW_PRIV_TYPE_CHAR | 0x7FF, - IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, "read" - }, - { - SIOCIWFIRSTPRIV + 0x2, 0, 0, "driver_ext" - }, - { - SIOCIWFIRSTPRIV + 0x4, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "apinfo" - }, - { - SIOCIWFIRSTPRIV + 0x5, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "setpid" - }, - { - SIOCIWFIRSTPRIV + 0x6, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_start" - }, - { - SIOCIWFIRSTPRIV + 0xA, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "channel_plan" - }, - - { - SIOCIWFIRSTPRIV + 0xB, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "dbg" - }, - { - SIOCIWFIRSTPRIV + 0xC, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0, "rfw" - }, - { - SIOCIWFIRSTPRIV + 0xD, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, "rfr" - }, - { - SIOCIWFIRSTPRIV + 0x10, - IW_PRIV_TYPE_CHAR | P2P_PRIVATE_IOCTL_SET_LEN, 0, "p2p_set" - }, - { - SIOCIWFIRSTPRIV + 0x11, - IW_PRIV_TYPE_CHAR | P2P_PRIVATE_IOCTL_SET_LEN, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | P2P_PRIVATE_IOCTL_SET_LEN, "p2p_get" - }, - { - SIOCIWFIRSTPRIV + 0x12, - IW_PRIV_TYPE_CHAR | P2P_PRIVATE_IOCTL_SET_LEN, IW_PRIV_TYPE_CHAR | IFNAMSIZ, "p2p_get2" - }, - { - SIOCIWFIRSTPRIV + 0x16, - IW_PRIV_TYPE_CHAR | 64, 0, "pm_set" - }, - - {SIOCIWFIRSTPRIV + 0x18, IW_PRIV_TYPE_CHAR | IFNAMSIZ, 0, "rereg_nd_name"}, -}; - -static iw_handler rtw_private_handler[] = { - NULL, /* 0x00 */ - NULL, /* 0x01 */ - NULL, /* 0x02 */ -NULL, /* 0x03 */ -/* for MM DTV platform */ - rtw_get_ap_info, /* 0x04 */ - - rtw_set_pid, /* 0x05 */ - rtw_wps_start, /* 0x06 */ - - NULL, /* 0x07 */ - NULL, /* 0x08 */ - NULL, /* 0x09 */ - -/* Set Channel depend on the country code */ - rtw_wx_set_channel_plan, /* 0x0A */ - - rtw_dbg_port, /* 0x0B */ - rtw_wx_write_rf, /* 0x0C */ - rtw_wx_read_rf, /* 0x0D */ - NULL, /* 0x0E */ - NULL, /* 0x0F */ - - rtw_p2p_set, /* 0x10 */ - NULL, /* 0x11 */ - rtw_p2p_get2, /* 0x12 */ - - NULL, /* 0x13 */ - NULL, /* 0x14 */ - NULL, /* 0x15 */ - - rtw_pm_set, /* 0x16 */ - NULL, /* 0x17 */ - rtw_rereg_nd_name, /* 0x18 */ -}; - -static struct iw_statistics *rtw_get_wireless_stats(struct net_device *dev) -{ - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct iw_statistics *piwstats = &padapter->iwstats; - int tmp_noise = 0; - int tmp; - - if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED)) { - piwstats->qual.qual = 0; - piwstats->qual.level = 0; - piwstats->qual.noise = 0; - } else { - tmp_noise = padapter->recvpriv.noise; - - piwstats->qual.level = padapter->signal_strength; - tmp = 219 + 3 * padapter->signal_strength; - tmp = min(100, tmp); - tmp = max(0, tmp); - piwstats->qual.qual = tmp; - piwstats->qual.noise = tmp_noise; - } - piwstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; - return &padapter->iwstats; -} - -struct iw_handler_def rtw_handlers_def = { - .standard = rtw_handlers, - .num_standard = ARRAY_SIZE(rtw_handlers), - .private = rtw_private_handler, - .private_args = (struct iw_priv_args *)rtw_private_args, - .num_private = ARRAY_SIZE(rtw_private_handler), - .num_private_args = ARRAY_SIZE(rtw_private_args), - .get_wireless_stats = rtw_get_wireless_stats, -}; diff --git a/drivers/staging/r8188eu/os_dep/os_intfs.c b/drivers/staging/r8188eu/os_dep/os_intfs.c deleted file mode 100644 index dc419fd1ffa5..000000000000 --- a/drivers/staging/r8188eu/os_dep/os_intfs.c +++ /dev/null @@ -1,807 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#define _OS_INTFS_C_ - -#include "../include/osdep_service.h" -#include "../include/drv_types.h" -#include "../include/hal_intf.h" -#include "../include/rtw_ioctl.h" -#include "../include/usb_osintf.h" -#include "../include/rtw_br_ext.h" -#include "../include/rtw_led.h" -#include "../include/rtl8188e_dm.h" - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Realtek Wireless Lan Driver"); -MODULE_AUTHOR("Realtek Semiconductor Corp."); -MODULE_FIRMWARE(FW_RTL8188EU); - -#define CONFIG_BR_EXT_BRNAME "br0" -#define RTW_NOTCH_FILTER 0 /* 0:Disable, 1:Enable, */ - -/* module param defaults */ -static int rtw_rfintfs = HWPI; -static int rtw_lbkmode;/* RTL8712_AIR_TRX; */ -static int rtw_network_mode = Ndis802_11IBSS;/* Ndis802_11Infrastructure; infra, ad-hoc, auto */ -static int rtw_channel = 1;/* ad-hoc support requirement */ -static int rtw_wireless_mode = WIRELESS_11BG_24N; -static int rtw_vrtl_carrier_sense = AUTO_VCS; -static int rtw_vcs_type = RTS_CTS;/* */ -static int rtw_rts_thresh = 2347;/* */ -static int rtw_frag_thresh = 2346;/* */ -static int rtw_preamble = PREAMBLE_LONG;/* long, short, auto */ -static int rtw_scan_mode = 1;/* active, passive */ -static int rtw_adhoc_tx_pwr = 1; -static int rtw_soft_ap; -static int rtw_power_mgnt = 1; -static int rtw_ips_mode = IPS_NORMAL; - -static int rtw_smart_ps = 2; - -module_param(rtw_ips_mode, int, 0644); -MODULE_PARM_DESC(rtw_ips_mode, "The default IPS mode"); - -static int rtw_radio_enable = 1; -static int rtw_long_retry_lmt = 7; -static int rtw_short_retry_lmt = 7; -static int rtw_busy_thresh = 40; -static int rtw_ack_policy = NORMAL_ACK; - -static int rtw_software_encrypt; -static int rtw_software_decrypt; - -static int rtw_acm_method;/* 0:By SW 1:By HW. */ - -static int rtw_wmm_enable = 1;/* default is set to enable the wmm. */ -static int rtw_uapsd_enable; -static int rtw_uapsd_max_sp = NO_LIMIT; -static int rtw_uapsd_acbk_en; -static int rtw_uapsd_acbe_en; -static int rtw_uapsd_acvi_en; -static int rtw_uapsd_acvo_en; - -static int rtw_led_enable = 1; - -static int rtw_ht_enable = 1; -static int rtw_cbw40_enable = 3; /* 0 :disable, bit(0): enable 2.4g, bit(1): enable 5g */ -static int rtw_ampdu_enable = 1;/* for enable tx_ampdu */ -static int rtw_rx_stbc = 1;/* 0: disable, bit(0):enable 2.4g, bit(1):enable 5g, default is set to enable 2.4GHZ for IOT issue with bufflao's AP at 5GHZ */ -static int rtw_ampdu_amsdu;/* 0: disabled, 1:enabled, 2:auto */ - -static int rtw_lowrate_two_xmit = 1;/* Use 2 path Tx to transmit MCS0~7 and legacy mode */ - -static int rtw_low_power; -static int rtw_wifi_spec; -static int rtw_channel_plan = RT_CHANNEL_DOMAIN_MAX; -static int rtw_AcceptAddbaReq = true;/* 0:Reject AP's Add BA req, 1:Accept AP's Add BA req. */ - -static int rtw_antdiv_cfg = 2; /* 0:OFF , 1:ON, 2:decide by Efuse config */ -static int rtw_antdiv_type; /* 0:decide by efuse 1: for 88EE, 1Tx and 1RxCG are diversity.(2 Ant with SPDT), 2: for 88EE, 1Tx and 2Rx are diversity.(2 Ant, Tx and RxCG are both on aux port, RxCS is on main port), 3: for 88EE, 1Tx and 1RxCG are fixed.(1Ant, Tx and RxCG are both on aux port) */ - - -static int rtw_hwpdn_mode = 2;/* 0:disable, 1:enable, 2: by EFUSE config */ - -static int rtw_hwpwrp_detect; /* HW power ping detect 0:disable , 1:enable */ - -static int rtw_hw_wps_pbc = 1; - -int rtw_mc2u_disable; - -static int rtw_80211d; - -static char *ifname = "wlan%d"; -module_param(ifname, charp, 0644); -MODULE_PARM_DESC(ifname, "The default name to allocate for first interface"); - -static char *if2name = "wlan%d"; -module_param(if2name, charp, 0644); -MODULE_PARM_DESC(if2name, "The default name to allocate for second interface"); - -char *rtw_initmac; /* temp mac address if users want to use instead of the mac address in Efuse */ - -module_param(rtw_initmac, charp, 0644); -module_param(rtw_channel_plan, int, 0644); -module_param(rtw_rfintfs, int, 0644); -module_param(rtw_lbkmode, int, 0644); -module_param(rtw_network_mode, int, 0644); -module_param(rtw_channel, int, 0644); -module_param(rtw_wmm_enable, int, 0644); -module_param(rtw_vrtl_carrier_sense, int, 0644); -module_param(rtw_vcs_type, int, 0644); -module_param(rtw_busy_thresh, int, 0644); -module_param(rtw_led_enable, int, 0644); -module_param(rtw_ht_enable, int, 0644); -module_param(rtw_cbw40_enable, int, 0644); -module_param(rtw_ampdu_enable, int, 0644); -module_param(rtw_rx_stbc, int, 0644); -module_param(rtw_ampdu_amsdu, int, 0644); -module_param(rtw_lowrate_two_xmit, int, 0644); -module_param(rtw_power_mgnt, int, 0644); -module_param(rtw_smart_ps, int, 0644); -module_param(rtw_low_power, int, 0644); -module_param(rtw_wifi_spec, int, 0644); -module_param(rtw_antdiv_cfg, int, 0644); -module_param(rtw_antdiv_type, int, 0644); -module_param(rtw_hwpdn_mode, int, 0644); -module_param(rtw_hwpwrp_detect, int, 0644); -module_param(rtw_hw_wps_pbc, int, 0644); - -static uint rtw_max_roaming_times = 2; -module_param(rtw_max_roaming_times, uint, 0644); -MODULE_PARM_DESC(rtw_max_roaming_times, "The max roaming times to try"); - -static int rtw_fw_iol = 1;/* 0:Disable, 1:enable, 2:by usb speed */ -module_param(rtw_fw_iol, int, 0644); -MODULE_PARM_DESC(rtw_fw_iol, "FW IOL"); - -module_param(rtw_mc2u_disable, int, 0644); - -module_param(rtw_80211d, int, 0644); -MODULE_PARM_DESC(rtw_80211d, "Enable 802.11d mechanism"); - -static uint rtw_notch_filter = RTW_NOTCH_FILTER; -module_param(rtw_notch_filter, uint, 0644); -MODULE_PARM_DESC(rtw_notch_filter, "0:Disable, 1:Enable, 2:Enable only for P2P"); - -static uint loadparam(struct adapter *padapter) -{ - struct registry_priv *registry_par = &padapter->registrypriv; - - registry_par->rfintfs = (u8)rtw_rfintfs; - registry_par->lbkmode = (u8)rtw_lbkmode; - registry_par->network_mode = (u8)rtw_network_mode; - - memcpy(registry_par->ssid.Ssid, "ANY", 3); - registry_par->ssid.SsidLength = 3; - - registry_par->channel = (u8)rtw_channel; - registry_par->wireless_mode = (u8)rtw_wireless_mode; - registry_par->vrtl_carrier_sense = (u8)rtw_vrtl_carrier_sense; - registry_par->vcs_type = (u8)rtw_vcs_type; - registry_par->rts_thresh = (u16)rtw_rts_thresh; - registry_par->frag_thresh = (u16)rtw_frag_thresh; - registry_par->preamble = (u8)rtw_preamble; - registry_par->scan_mode = (u8)rtw_scan_mode; - registry_par->adhoc_tx_pwr = (u8)rtw_adhoc_tx_pwr; - registry_par->soft_ap = (u8)rtw_soft_ap; - registry_par->smart_ps = (u8)rtw_smart_ps; - registry_par->power_mgnt = (u8)rtw_power_mgnt; - registry_par->ips_mode = (u8)rtw_ips_mode; - registry_par->radio_enable = (u8)rtw_radio_enable; - registry_par->long_retry_lmt = (u8)rtw_long_retry_lmt; - registry_par->short_retry_lmt = (u8)rtw_short_retry_lmt; - registry_par->busy_thresh = (u16)rtw_busy_thresh; - registry_par->ack_policy = (u8)rtw_ack_policy; - registry_par->software_encrypt = (u8)rtw_software_encrypt; - registry_par->software_decrypt = (u8)rtw_software_decrypt; - registry_par->acm_method = (u8)rtw_acm_method; - - /* UAPSD */ - registry_par->wmm_enable = (u8)rtw_wmm_enable; - registry_par->uapsd_enable = (u8)rtw_uapsd_enable; - registry_par->uapsd_max_sp = (u8)rtw_uapsd_max_sp; - registry_par->uapsd_acbk_en = (u8)rtw_uapsd_acbk_en; - registry_par->uapsd_acbe_en = (u8)rtw_uapsd_acbe_en; - registry_par->uapsd_acvi_en = (u8)rtw_uapsd_acvi_en; - registry_par->uapsd_acvo_en = (u8)rtw_uapsd_acvo_en; - - registry_par->led_enable = (u8)rtw_led_enable; - - registry_par->ht_enable = (u8)rtw_ht_enable; - registry_par->cbw40_enable = (u8)rtw_cbw40_enable; - registry_par->ampdu_enable = (u8)rtw_ampdu_enable; - registry_par->rx_stbc = (u8)rtw_rx_stbc; - registry_par->ampdu_amsdu = (u8)rtw_ampdu_amsdu; - registry_par->lowrate_two_xmit = (u8)rtw_lowrate_two_xmit; - registry_par->low_power = (u8)rtw_low_power; - registry_par->wifi_spec = (u8)rtw_wifi_spec; - registry_par->channel_plan = (u8)rtw_channel_plan; - registry_par->bAcceptAddbaReq = (u8)rtw_AcceptAddbaReq; - registry_par->antdiv_cfg = (u8)rtw_antdiv_cfg; - registry_par->antdiv_type = (u8)rtw_antdiv_type; - registry_par->hwpdn_mode = (u8)rtw_hwpdn_mode;/* 0:disable, 1:enable, 2:by EFUSE config */ - registry_par->hwpwrp_detect = (u8)rtw_hwpwrp_detect;/* 0:disable, 1:enable */ - registry_par->hw_wps_pbc = (u8)rtw_hw_wps_pbc; - - registry_par->max_roaming_times = (u8)rtw_max_roaming_times; - - registry_par->fw_iol = rtw_fw_iol; - - registry_par->enable80211d = (u8)rtw_80211d; - snprintf(registry_par->ifname, 16, "%s", ifname); - snprintf(registry_par->if2name, 16, "%s", if2name); - registry_par->notch_filter = (u8)rtw_notch_filter; - - return _SUCCESS; -} - -static int rtw_net_set_mac_address(struct net_device *pnetdev, void *p) -{ - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(pnetdev); - struct sockaddr *addr = p; - - if (!padapter->bup) - memcpy(padapter->eeprompriv.mac_addr, addr->sa_data, ETH_ALEN); - - return 0; -} - -static struct net_device_stats *rtw_net_get_stats(struct net_device *pnetdev) -{ - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(pnetdev); - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct recv_priv *precvpriv = &padapter->recvpriv; - - padapter->stats.tx_packets = pxmitpriv->tx_pkts;/* pxmitpriv->tx_pkts++; */ - padapter->stats.rx_packets = precvpriv->rx_pkts;/* precvpriv->rx_pkts++; */ - padapter->stats.tx_dropped = pxmitpriv->tx_drop; - padapter->stats.rx_dropped = precvpriv->rx_drop; - padapter->stats.tx_bytes = pxmitpriv->tx_bytes; - padapter->stats.rx_bytes = precvpriv->rx_bytes; - return &padapter->stats; -} - -/* - * AC to queue mapping - * - * AC_VO -> queue 0 - * AC_VI -> queue 1 - * AC_BE -> queue 2 - * AC_BK -> queue 3 - */ -static const u16 rtw_1d_to_queue[8] = { 2, 3, 3, 2, 1, 1, 0, 0 }; - -/* Given a data frame determine the 802.1p/1d tag to use. */ -static unsigned int rtw_classify8021d(struct sk_buff *skb) -{ - unsigned int dscp; - - /* skb->priority values from 256->263 are magic values to - * directly indicate a specific 802.1d priority. This is used - * to allow 802.1d priority to be passed directly in from VLAN - * tags, etc. - */ - if (skb->priority >= 256 && skb->priority <= 263) - return skb->priority - 256; - - switch (skb->protocol) { - case htons(ETH_P_IP): - dscp = ip_hdr(skb)->tos & 0xfc; - break; - default: - return 0; - } - - return dscp >> 5; -} - -static u16 rtw_select_queue(struct net_device *dev, struct sk_buff *skb, struct net_device *sb_dev) -{ - struct adapter *padapter = rtw_netdev_priv(dev); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - skb->priority = rtw_classify8021d(skb); - - if (pmlmepriv->acm_mask != 0) - skb->priority = qos_acm(pmlmepriv->acm_mask, skb->priority); - - return rtw_1d_to_queue[skb->priority]; -} - -u16 rtw_recv_select_queue(struct sk_buff *skb) -{ - struct iphdr *piphdr; - unsigned int dscp; - __be16 eth_type; - u32 priority; - u8 *pdata = skb->data; - - memcpy(ð_type, pdata + (ETH_ALEN << 1), 2); - - switch (eth_type) { - case htons(ETH_P_IP): - piphdr = (struct iphdr *)(pdata + ETH_HLEN); - dscp = piphdr->tos & 0xfc; - priority = dscp >> 5; - break; - default: - priority = 0; - } - - return rtw_1d_to_queue[priority]; -} - -static const struct net_device_ops rtw_netdev_ops = { - .ndo_open = netdev_open, - .ndo_stop = netdev_close, - .ndo_start_xmit = rtw_xmit_entry, - .ndo_select_queue = rtw_select_queue, - .ndo_set_mac_address = rtw_net_set_mac_address, - .ndo_get_stats = rtw_net_get_stats, -}; - -int rtw_init_netdev_name(struct net_device *pnetdev, const char *ifname) -{ - int err; - - err = dev_alloc_name(pnetdev, ifname); - if (err < 0) - return err; - - netif_carrier_off(pnetdev); - return 0; -} - -static const struct device_type wlan_type = { - .name = "wlan", -}; - -struct net_device *rtw_init_netdev(struct adapter *old_padapter) -{ - struct adapter *padapter; - struct net_device *pnetdev; - - if (old_padapter) - pnetdev = rtw_alloc_etherdev_with_old_priv(sizeof(struct adapter), (void *)old_padapter); - else - pnetdev = rtw_alloc_etherdev(sizeof(struct adapter)); - - if (!pnetdev) - return NULL; - - pnetdev->dev.type = &wlan_type; - padapter = rtw_netdev_priv(pnetdev); - padapter->pnetdev = pnetdev; - pnetdev->netdev_ops = &rtw_netdev_ops; - pnetdev->watchdog_timeo = HZ * 3; /* 3 second timeout */ - pnetdev->wireless_handlers = (struct iw_handler_def *)&rtw_handlers_def; - - /* step 2. */ - loadparam(padapter); - - return pnetdev; -} - -int rtw_start_drv_threads(struct adapter *padapter) -{ - padapter->cmdThread = kthread_run(rtw_cmd_thread, padapter, "RTW_CMD_THREAD"); - if (IS_ERR(padapter->cmdThread)) - return PTR_ERR(padapter->cmdThread); - - /* wait for rtw_cmd_thread() to start running */ - wait_for_completion(&padapter->cmdpriv.start_cmd_thread); - - return 0; -} - -void rtw_stop_drv_threads(struct adapter *padapter) -{ - /* Below is to termindate rtw_cmd_thread & event_thread... */ - complete(&padapter->cmdpriv.enqueue_cmd); - if (padapter->cmdThread) - /* wait for rtw_cmd_thread() to stop running */ - wait_for_completion(&padapter->cmdpriv.stop_cmd_thread); -} - -static void rtw_init_default_value(struct adapter *padapter) -{ - struct registry_priv *pregistrypriv = &padapter->registrypriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - - /* xmit_priv */ - pxmitpriv->frag_len = pregistrypriv->frag_thresh; - - /* mlme_priv */ - pmlmepriv->scan_interval = SCAN_INTERVAL;/* 30*2 sec = 60sec */ - pmlmepriv->scan_mode = SCAN_ACTIVE; - - /* ht_priv */ - pmlmepriv->htpriv.ampdu_enable = false;/* set to disabled */ - - /* security_priv */ - psecuritypriv->binstallGrpkey = false; - psecuritypriv->sw_encrypt = pregistrypriv->software_encrypt; - psecuritypriv->sw_decrypt = pregistrypriv->software_decrypt; - psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */ - psecuritypriv->dot11PrivacyAlgrthm = _NO_PRIVACY_; - psecuritypriv->dot11PrivacyKeyIndex = 0; - psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_; - psecuritypriv->dot118021XGrpKeyid = 1; - psecuritypriv->ndisauthtype = Ndis802_11AuthModeOpen; - psecuritypriv->ndisencryptstatus = Ndis802_11WEPDisabled; - - /* registry_priv */ - rtw_init_registrypriv_dev_network(padapter); - rtw_update_registrypriv_dev_network(padapter); - - /* hal_priv */ - rtl8188eu_init_default_value(padapter); - - /* misc. */ - padapter->bReadPortCancel = false; - padapter->bWritePortCancel = false; - padapter->bRxRSSIDisplay = 0; - padapter->bNotifyChannelChange = 0; - padapter->bShowGetP2PState = 1; -} - -void rtw_reset_drv_sw(struct adapter *padapter) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - /* hal_priv */ - rtl8188eu_init_default_value(padapter); - padapter->bReadPortCancel = false; - padapter->bWritePortCancel = false; - padapter->bRxRSSIDisplay = 0; - pmlmepriv->scan_interval = SCAN_INTERVAL;/* 30*2 sec = 60sec */ - - padapter->xmitpriv.tx_pkts = 0; - padapter->recvpriv.rx_pkts = 0; - - pmlmepriv->LinkDetectInfo.bBusyTraffic = false; - - _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING); - - /* mlmeextpriv */ - padapter->mlmeextpriv.sitesurvey_res.state = SCAN_DISABLE; - - rtw_set_signal_stat_timer(&padapter->recvpriv); -} - -u8 rtw_init_drv_sw(struct adapter *padapter) -{ - if (rtw_init_cmd_priv(&padapter->cmdpriv)) { - dev_err(dvobj_to_dev(padapter->dvobj), "rtw_init_cmd_priv failed\n"); - return _FAIL; - } - - padapter->cmdpriv.padapter = padapter; - - if (rtw_init_evt_priv(&padapter->evtpriv)) { - dev_err(dvobj_to_dev(padapter->dvobj), "rtw_init_evt_priv failed\n"); - goto free_cmd_priv; - } - - if (rtw_init_mlme_priv(padapter)) { - dev_err(dvobj_to_dev(padapter->dvobj), "rtw_init_mlme_priv failed\n"); - goto free_evt_priv; - } - - rtw_init_wifidirect_timers(padapter); - init_wifidirect_info(padapter, P2P_ROLE_DISABLE); - reset_global_wifidirect_info(padapter); - - init_mlme_ext_priv(padapter); - - if (_rtw_init_xmit_priv(&padapter->xmitpriv, padapter)) { - dev_err(dvobj_to_dev(padapter->dvobj), "_rtw_init_xmit_priv failed\n"); - goto free_mlme_ext; - } - - if (_rtw_init_recv_priv(&padapter->recvpriv, padapter)) { - dev_err(dvobj_to_dev(padapter->dvobj), "_rtw_init_recv_priv failed\n"); - goto free_xmit_priv; - } - - if (_rtw_init_sta_priv(&padapter->stapriv)) { - dev_err(dvobj_to_dev(padapter->dvobj), "_rtw_init_sta_priv failed\n"); - goto free_recv_priv; - } - - padapter->stapriv.padapter = padapter; - - rtw_init_bcmc_stainfo(padapter); - - rtw_init_pwrctrl_priv(padapter); - - rtw_init_default_value(padapter); - - rtl8188e_init_dm_priv(padapter); - rtl8188eu_InitSwLeds(padapter); - - spin_lock_init(&padapter->br_ext_lock); - - return _SUCCESS; - -free_recv_priv: - _rtw_free_recv_priv(&padapter->recvpriv); - -free_xmit_priv: - _rtw_free_xmit_priv(&padapter->xmitpriv); - -free_mlme_ext: - free_mlme_ext_priv(&padapter->mlmeextpriv); - - rtw_free_mlme_priv(&padapter->mlmepriv); - -free_evt_priv: - rtw_free_evt_priv(&padapter->evtpriv); - -free_cmd_priv: - rtw_free_cmd_priv(&padapter->cmdpriv); - - return _FAIL; -} - -void rtw_cancel_all_timer(struct adapter *padapter) -{ - _cancel_timer_ex(&padapter->mlmepriv.assoc_timer); - - _cancel_timer_ex(&padapter->mlmepriv.scan_to_timer); - - _cancel_timer_ex(&padapter->mlmepriv.dynamic_chk_timer); - - /* cancel sw led timer */ - rtl8188eu_DeInitSwLeds(padapter); - - _cancel_timer_ex(&padapter->pwrctrlpriv.pwr_state_check_timer); - - _cancel_timer_ex(&padapter->recvpriv.signal_stat_timer); -} - -void rtw_free_drv_sw(struct adapter *padapter) -{ - /* we can call rtw_p2p_enable here, but: */ - /* 1. rtw_p2p_enable may have IO operation */ - /* 2. rtw_p2p_enable is bundled with wext interface */ - { - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) { - _cancel_timer_ex(&pwdinfo->find_phase_timer); - _cancel_timer_ex(&pwdinfo->restore_p2p_state_timer); - _cancel_timer_ex(&pwdinfo->pre_tx_scan_timer); - rtw_p2p_set_state(pwdinfo, P2P_STATE_NONE); - } - } - - free_mlme_ext_priv(&padapter->mlmeextpriv); - - rtw_free_cmd_priv(&padapter->cmdpriv); - - rtw_free_evt_priv(&padapter->evtpriv); - - rtw_free_mlme_priv(&padapter->mlmepriv); - _rtw_free_xmit_priv(&padapter->xmitpriv); - - _rtw_free_sta_priv(&padapter->stapriv); /* will free bcmc_stainfo here */ - - _rtw_free_recv_priv(&padapter->recvpriv); - - /* free the old_pnetdev */ - if (padapter->rereg_nd_name_priv.old_pnetdev) { - free_netdev(padapter->rereg_nd_name_priv.old_pnetdev); - padapter->rereg_nd_name_priv.old_pnetdev = NULL; - } - - /* clear pbuddystruct adapter to avoid access wrong pointer. */ - if (padapter->pbuddy_adapter) - padapter->pbuddy_adapter->pbuddy_adapter = NULL; -} - -void netdev_br_init(struct net_device *netdev) -{ - struct adapter *adapter = (struct adapter *)rtw_netdev_priv(netdev); - - rcu_read_lock(); - - if (rcu_dereference(adapter->pnetdev->rx_handler_data)) { - struct net_device *br_netdev; - struct net *devnet = NULL; - - devnet = dev_net(netdev); - br_netdev = dev_get_by_name(devnet, CONFIG_BR_EXT_BRNAME); - if (br_netdev) { - memcpy(adapter->br_mac, br_netdev->dev_addr, ETH_ALEN); - dev_put(br_netdev); - } else { - pr_info("%s()-%d: dev_get_by_name(%s) failed!", - __func__, __LINE__, CONFIG_BR_EXT_BRNAME); - } - } - adapter->ethBrExtInfo.addPPPoETag = 1; - - rcu_read_unlock(); -} - -static int _netdev_open(struct net_device *pnetdev) -{ - uint status; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(pnetdev); - - if (!padapter->bup) { - padapter->bDriverStopped = false; - padapter->bSurpriseRemoved = false; - - status = rtw_hal_init(padapter); - if (status == _FAIL) - goto netdev_open_error; - - netdev_dbg(pnetdev, "MAC Address = %pM\n", pnetdev->dev_addr); - - if (rtw_start_drv_threads(padapter)) { - pr_info("Initialize driver software resource Failed!\n"); - goto netdev_open_error; - } - - if (init_hw_mlme_ext(padapter) == _FAIL) { - pr_info("can't init mlme_ext_priv\n"); - goto netdev_open_error; - } - if (rtl8188eu_inirp_init(padapter)) - goto netdev_open_error; - - rtw_led_control(padapter, LED_CTL_NO_LINK); - - padapter->bup = true; - } - padapter->net_closed = false; - - _set_timer(&padapter->mlmepriv.dynamic_chk_timer, 2000); - - padapter->pwrctrlpriv.bips_processing = false; - rtw_set_pwr_state_check_timer(&padapter->pwrctrlpriv); - - if (!rtw_netif_queue_stopped(pnetdev)) - netif_tx_start_all_queues(pnetdev); - else - netif_tx_wake_all_queues(pnetdev); - - netdev_br_init(pnetdev); - - return 0; - -netdev_open_error: - padapter->bup = false; - netif_carrier_off(pnetdev); - netif_tx_stop_all_queues(pnetdev); - return -1; -} - -int netdev_open(struct net_device *pnetdev) -{ - int ret; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(pnetdev); - - mutex_lock(padapter->hw_init_mutex); - ret = _netdev_open(pnetdev); - mutex_unlock(padapter->hw_init_mutex); - return ret; -} - -static int ips_netdrv_open(struct adapter *padapter) -{ - int status = _SUCCESS; - padapter->net_closed = false; - - padapter->bDriverStopped = false; - padapter->bSurpriseRemoved = false; - - status = rtw_hal_init(padapter); - if (status == _FAIL) - goto netdev_open_error; - - if (rtl8188eu_inirp_init(padapter)) - goto netdev_open_error; - - rtw_set_pwr_state_check_timer(&padapter->pwrctrlpriv); - _set_timer(&padapter->mlmepriv.dynamic_chk_timer, 5000); - - return _SUCCESS; - -netdev_open_error: - return _FAIL; -} - -int rtw_ips_pwr_up(struct adapter *padapter) -{ - int result; - rtw_reset_drv_sw(padapter); - - result = ips_netdrv_open(padapter); - - rtw_led_control(padapter, LED_CTL_NO_LINK); - - return result; -} - -void rtw_ips_pwr_down(struct adapter *padapter) -{ - padapter->net_closed = true; - - rtw_led_control(padapter, LED_CTL_POWER_OFF); - - rtw_ips_dev_unload(padapter); -} - -static void rtw_fifo_cleanup(struct adapter *adapter) -{ - struct pwrctrl_priv *pwrpriv = &adapter->pwrctrlpriv; - u8 trycnt = 100; - int res; - u32 reg; - - /* pause tx */ - rtw_write8(adapter, REG_TXPAUSE, 0xff); - - /* keep sn */ - /* FIXME: return an error to caller */ - res = rtw_read16(adapter, REG_NQOS_SEQ, &adapter->xmitpriv.nqos_ssn); - if (res) - return; - - if (!pwrpriv->bkeepfwalive) { - /* RX DMA stop */ - res = rtw_read32(adapter, REG_RXPKT_NUM, ®); - if (res) - return; - - rtw_write32(adapter, REG_RXPKT_NUM, - (reg | RW_RELEASE_EN)); - do { - res = rtw_read32(adapter, REG_RXPKT_NUM, ®); - if (res) - continue; - - if (!(reg & RXDMA_IDLE)) - break; - } while (trycnt--); - - /* RQPN Load 0 */ - rtw_write16(adapter, REG_RQPN_NPQ, 0x0); - rtw_write32(adapter, REG_RQPN, 0x80000000); - mdelay(10); - } -} - -void rtw_ips_dev_unload(struct adapter *padapter) -{ - rtw_fifo_cleanup(padapter); - - rtw_read_port_cancel(padapter); - rtw_write_port_cancel(padapter); - - /* s5. */ - if (!padapter->bSurpriseRemoved) - rtw_hal_deinit(padapter); -} - -int netdev_close(struct net_device *pnetdev) -{ - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(pnetdev); - struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); - - padapter->net_closed = true; - - if (padapter->pwrctrlpriv.rf_pwrstate == rf_on) { - /* s1. */ - if (pnetdev) { - if (!rtw_netif_queue_stopped(pnetdev)) - netif_tx_stop_all_queues(pnetdev); - } - - /* s2. */ - LeaveAllPowerSaveMode(padapter); - rtw_disassoc_cmd(padapter, 500, false); - /* s2-2. indicate disconnect to os */ - rtw_indicate_disconnect(padapter); - /* s2-3. */ - rtw_free_assoc_resources(padapter, 1); - /* s2-4. */ - rtw_free_network_queue(padapter, true); - /* Close LED */ - rtw_led_control(padapter, LED_CTL_POWER_OFF); - } - - nat25_db_cleanup(padapter); - - rtw_p2p_enable(padapter, P2P_ROLE_DISABLE); - - kfree(dvobj->firmware.data); - dvobj->firmware.data = NULL; - - return 0; -} diff --git a/drivers/staging/r8188eu/os_dep/osdep_service.c b/drivers/staging/r8188eu/os_dep/osdep_service.c deleted file mode 100644 index 88271f956b52..000000000000 --- a/drivers/staging/r8188eu/os_dep/osdep_service.c +++ /dev/null @@ -1,227 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2007 - 2012 Realtek Corporation. */ - -#define _OSDEP_SERVICE_C_ - -#include "../include/osdep_service.h" -#include "../include/drv_types.h" -#include "../include/rtw_ioctl_set.h" - -/* -* Translate the OS dependent @param error_code to OS independent RTW_STATUS_CODE -* @return: one of RTW_STATUS_CODE -*/ -inline int RTW_STATUS_CODE(int error_code) -{ - if (error_code >= 0) - return _SUCCESS; - return _FAIL; -} - -void *rtw_malloc2d(int h, int w, int size) -{ - int j; - - void **a = kzalloc(h * sizeof(void *) + h * w * size, GFP_KERNEL); - if (!a) - return NULL; - - for (j = 0; j < h; j++) - a[j] = ((char *)(a + h)) + j * w * size; - - return a; -} - -/* -For the following list_xxx operations, -caller must guarantee the atomic context. -Otherwise, there will be racing condition. -*/ -/* -Caller must check if the list is empty before calling rtw_list_delete -*/ - -static const struct device_type wlan_type = { - .name = "wlan", -}; - -struct net_device *rtw_alloc_etherdev_with_old_priv(int sizeof_priv, - void *old_priv) -{ - struct net_device *pnetdev; - struct rtw_netdev_priv_indicator *pnpi; - - pnetdev = alloc_etherdev_mq(sizeof(struct rtw_netdev_priv_indicator), 4); - if (!pnetdev) - return NULL; - - pnetdev->dev.type = &wlan_type; - pnpi = netdev_priv(pnetdev); - pnpi->priv = old_priv; - pnpi->sizeof_priv = sizeof_priv; - - return pnetdev; -} - -struct net_device *rtw_alloc_etherdev(int sizeof_priv) -{ - struct net_device *pnetdev; - struct rtw_netdev_priv_indicator *pnpi; - - pnetdev = alloc_etherdev_mq(sizeof(struct rtw_netdev_priv_indicator), 4); - if (!pnetdev) - return NULL; - - pnpi = netdev_priv(pnetdev); - - pnpi->priv = vzalloc(sizeof_priv); - if (!pnpi->priv) { - free_netdev(pnetdev); - return NULL; - } - - pnpi->sizeof_priv = sizeof_priv; - - return pnetdev; -} - -void rtw_free_netdev(struct net_device *netdev) -{ - struct rtw_netdev_priv_indicator *pnpi; - - pnpi = netdev_priv(netdev); - - vfree(pnpi->priv); - free_netdev(netdev); -} - -int rtw_change_ifname(struct adapter *padapter, const char *ifname) -{ - struct net_device *pnetdev; - struct net_device *cur_pnetdev; - struct rereg_nd_name_data *rereg_priv; - int ret; - - if (!padapter) - goto error; - - cur_pnetdev = padapter->pnetdev; - rereg_priv = &padapter->rereg_nd_name_priv; - - /* free the old_pnetdev */ - if (rereg_priv->old_pnetdev) { - free_netdev(rereg_priv->old_pnetdev); - rereg_priv->old_pnetdev = NULL; - } - - if (!rtnl_is_locked()) - unregister_netdev(cur_pnetdev); - else - unregister_netdevice(cur_pnetdev); - - rereg_priv->old_pnetdev = cur_pnetdev; - - pnetdev = rtw_init_netdev(padapter); - if (!pnetdev) { - ret = -1; - goto error; - } - - SET_NETDEV_DEV(pnetdev, dvobj_to_dev(adapter_to_dvobj(padapter))); - - rtw_init_netdev_name(pnetdev, ifname); - - eth_hw_addr_set(pnetdev, padapter->eeprompriv.mac_addr); - - if (!rtnl_is_locked()) - ret = register_netdev(pnetdev); - else - ret = register_netdevice(pnetdev); - if (ret != 0) - goto error; - - return 0; -error: - return -1; -} - -void rtw_buf_update(u8 **buf, u32 *buf_len, u8 *src, u32 src_len) -{ - u32 dup_len = 0; - u8 *ori = NULL; - u8 *dup = NULL; - - if (!buf || !buf_len) - return; - - if (!src || !src_len) - goto keep_ori; - - /* duplicate src */ - dup = kmalloc(src_len, GFP_ATOMIC); - if (dup) { - dup_len = src_len; - memcpy(dup, src, dup_len); - } - -keep_ori: - ori = *buf; - - /* replace buf with dup */ - *buf_len = 0; - *buf = dup; - *buf_len = dup_len; - - /* free ori */ - kfree(ori); -} - -/** - * rtw_cbuf_empty - test if cbuf is empty - * @cbuf: pointer of struct rtw_cbuf - * - * Returns: true if cbuf is empty - */ -inline bool rtw_cbuf_empty(struct rtw_cbuf *cbuf) -{ - return cbuf->write == cbuf->read; -} - -/** - * rtw_cbuf_pop - pop a pointer from cbuf - * @cbuf: pointer of struct rtw_cbuf - * - * Lock free operation, be careful of the use scheme - * Returns: pointer popped out - */ -void *rtw_cbuf_pop(struct rtw_cbuf *cbuf) -{ - void *buf; - if (rtw_cbuf_empty(cbuf)) - return NULL; - - buf = cbuf->bufs[cbuf->read]; - cbuf->read = (cbuf->read + 1) % cbuf->size; - - return buf; -} - -/** - * rtw_cbuf_alloc - allocate a rtw_cbuf with given size and do initialization - * @size: size of pointer - * - * Returns: pointer of srtuct rtw_cbuf, NULL for allocation failure - */ -struct rtw_cbuf *rtw_cbuf_alloc(u32 size) -{ - struct rtw_cbuf *cbuf; - - cbuf = kmalloc(struct_size(cbuf, bufs, size), GFP_KERNEL); - - if (cbuf) { - cbuf->write = 0; - cbuf->read = 0; - cbuf->size = size; - } - return cbuf; -} diff --git a/drivers/staging/r8188eu/os_dep/usb_intf.c b/drivers/staging/r8188eu/os_dep/usb_intf.c deleted file mode 100644 index 74a16d1757ce..000000000000 --- a/drivers/staging/r8188eu/os_dep/usb_intf.c +++ /dev/null @@ -1,445 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2007 - 2011 Realtek Corporation. */ - -#include -#include "../include/osdep_service.h" -#include "../include/drv_types.h" -#include "../include/hal_intf.h" -#include "../include/osdep_intf.h" -#include "../include/usb_ops.h" -#include "../include/usb_osintf.h" -#include "../include/rtw_ioctl.h" -#include "../include/rtl8188e_hal.h" - -int ui_pid[3] = {0, 0, 0}; - -static int rtw_suspend(struct usb_interface *intf, pm_message_t message); -static int rtw_resume(struct usb_interface *intf); - -static int rtw_drv_init(struct usb_interface *pusb_intf, const struct usb_device_id *pdid); -static void rtw_dev_remove(struct usb_interface *pusb_intf); - -#define USB_VENDER_ID_REALTEK 0x0bda - -/* DID_USB_v916_20130116 */ -static struct usb_device_id rtw_usb_id_tbl[] = { - /*=== Realtek demoboard ===*/ - {USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8179)}, /* 8188EUS */ - {USB_DEVICE(USB_VENDER_ID_REALTEK, 0x0179)}, /* 8188ETV */ - {USB_DEVICE(USB_VENDER_ID_REALTEK, 0xffef)}, /* Rosewill USB-N150 Nano */ - /*=== Customer ID ===*/ - /****** 8188EUS ********/ - {USB_DEVICE(0x07B8, 0x8179)}, /* Abocom - Abocom */ - {USB_DEVICE(0x0DF6, 0x0076)}, /* Sitecom N150 v2 */ - {USB_DEVICE(0x2001, 0x330F)}, /* DLink DWA-125 REV D1 */ - {USB_DEVICE(0x2001, 0x3310)}, /* Dlink DWA-123 REV D1 */ - {USB_DEVICE(0x2001, 0x3311)}, /* DLink GO-USB-N150 REV B1 */ - {USB_DEVICE(0x2001, 0x331B)}, /* D-Link DWA-121 rev B1 */ - {USB_DEVICE(0x056E, 0x4008)}, /* Elecom WDC-150SU2M */ - {USB_DEVICE(0x2357, 0x010c)}, /* TP-Link TL-WN722N v2 */ - {USB_DEVICE(0x2357, 0x0111)}, /* TP-Link TL-WN727N v5.21 */ - {USB_DEVICE(0x2C4E, 0x0102)}, /* MERCUSYS MW150US v2 */ - {USB_DEVICE(0x0B05, 0x18F0)}, /* ASUS USB-N10 Nano B1 */ - {USB_DEVICE(0x7392, 0xb811)}, /* Edimax EW-7811Un V2 */ - {} /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE(usb, rtw_usb_id_tbl); - -struct rtw_usb_drv { - struct usb_driver usbdrv; - int drv_registered; - struct mutex hw_init_mutex; -}; - -static struct rtw_usb_drv rtl8188e_usb_drv = { - .usbdrv.name = KBUILD_MODNAME, - .usbdrv.probe = rtw_drv_init, - .usbdrv.disconnect = rtw_dev_remove, - .usbdrv.id_table = rtw_usb_id_tbl, - .usbdrv.suspend = rtw_suspend, - .usbdrv.resume = rtw_resume, - .usbdrv.reset_resume = rtw_resume, -}; - -static struct rtw_usb_drv *usb_drv = &rtl8188e_usb_drv; - -static struct dvobj_priv *usb_dvobj_init(struct usb_interface *usb_intf) -{ - int i; - u8 rt_num_in_pipes = 0; - struct dvobj_priv *pdvobjpriv; - struct usb_host_config *phost_conf; - struct usb_config_descriptor *pconf_desc; - struct usb_host_interface *phost_iface; - struct usb_interface_descriptor *piface_desc; - struct usb_endpoint_descriptor *pendp_desc; - struct usb_device *pusbd; - - pdvobjpriv = kzalloc(sizeof(*pdvobjpriv), GFP_KERNEL); - if (!pdvobjpriv) - goto err; - - pdvobjpriv->pusbintf = usb_intf; - pusbd = interface_to_usbdev(usb_intf); - pdvobjpriv->pusbdev = pusbd; - usb_set_intfdata(usb_intf, pdvobjpriv); - - pdvobjpriv->RtNumOutPipes = 0; - - phost_conf = pusbd->actconfig; - pconf_desc = &phost_conf->desc; - - phost_iface = &usb_intf->altsetting[0]; - piface_desc = &phost_iface->desc; - - pdvobjpriv->NumInterfaces = pconf_desc->bNumInterfaces; - pdvobjpriv->InterfaceNumber = piface_desc->bInterfaceNumber; - - for (i = 0; i < piface_desc->bNumEndpoints; i++) { - int ep_num; - pendp_desc = &phost_iface->endpoint[i].desc; - - ep_num = usb_endpoint_num(pendp_desc); - - if (usb_endpoint_is_bulk_in(pendp_desc)) { - pdvobjpriv->RtInPipe = ep_num; - rt_num_in_pipes++; - } else if (usb_endpoint_is_bulk_out(pendp_desc)) { - pdvobjpriv->RtOutPipe[pdvobjpriv->RtNumOutPipes] = - ep_num; - pdvobjpriv->RtNumOutPipes++; - } - } - - if (rt_num_in_pipes != 1) - goto err; - - /* 3 misc */ - rtw_reset_continual_urb_error(pdvobjpriv); - - usb_get_dev(pusbd); - return pdvobjpriv; - -err: - kfree(pdvobjpriv); - return NULL; -} - -static void usb_dvobj_deinit(struct usb_interface *usb_intf) -{ - struct dvobj_priv *dvobj = usb_get_intfdata(usb_intf); - - usb_set_intfdata(usb_intf, NULL); - if (dvobj) { - /* Modify condition for 92DU DMDP 2010.11.18, by Thomas */ - if ((dvobj->NumInterfaces != 2 && - dvobj->NumInterfaces != 3) || - (dvobj->InterfaceNumber == 1)) { - if (interface_to_usbdev(usb_intf)->state != - USB_STATE_NOTATTACHED) - /* If we didn't unplug usb dongle and - * remove/insert module, driver fails - * on sitesurvey for the first time when - * device is up . Reset usb port for sitesurvey - * fail issue. */ - usb_reset_device(interface_to_usbdev(usb_intf)); - } - kfree(dvobj); - } - - usb_put_dev(interface_to_usbdev(usb_intf)); - -} - -static void rtw_dev_unload(struct adapter *padapter) -{ - if (padapter->bup) { - padapter->bDriverStopped = true; - if (padapter->xmitpriv.ack_tx) - rtw_ack_tx_done(&padapter->xmitpriv, RTW_SCTX_DONE_DRV_STOP); - /* s3. */ - rtw_read_port_cancel(padapter); - rtw_write_port_cancel(padapter); - - /* s4. */ - rtw_stop_drv_threads(padapter); - - /* s5. */ - if (!padapter->bSurpriseRemoved) { - rtw_hal_deinit(padapter); - padapter->bSurpriseRemoved = true; - } - - padapter->bup = false; - } -} - -static int rtw_suspend(struct usb_interface *pusb_intf, pm_message_t message) -{ - struct dvobj_priv *dvobj = usb_get_intfdata(pusb_intf); - struct adapter *padapter = dvobj->if1; - struct net_device *pnetdev = padapter->pnetdev; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - - if ((!padapter->bup) || (padapter->bDriverStopped) || - (padapter->bSurpriseRemoved)) - goto exit; - - pwrpriv->bInSuspend = true; - rtw_cancel_all_timer(padapter); - LeaveAllPowerSaveMode(padapter); - - mutex_lock(&pwrpriv->lock); - /* s1. */ - if (pnetdev) { - netif_carrier_off(pnetdev); - netif_tx_stop_all_queues(pnetdev); - } - - /* s2. */ - rtw_disassoc_cmd(padapter, 0, false); - - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) && - check_fwstate(pmlmepriv, _FW_LINKED)) - pmlmepriv->to_roaming = 1; - /* s2-2. indicate disconnect to os */ - rtw_indicate_disconnect(padapter); - /* s2-3. */ - rtw_free_assoc_resources(padapter, 1); - /* s2-4. */ - rtw_free_network_queue(padapter, true); - - rtw_dev_unload(padapter); - mutex_unlock(&pwrpriv->lock); - - if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) - rtw_indicate_scan_done(padapter); - - if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) - rtw_indicate_disconnect(padapter); - -exit: - return 0; -} - -static int rtw_resume(struct usb_interface *pusb_intf) -{ - struct dvobj_priv *dvobj = usb_get_intfdata(pusb_intf); - struct adapter *padapter = dvobj->if1; - struct net_device *pnetdev; - struct pwrctrl_priv *pwrpriv = NULL; - int ret = -1; - - pnetdev = padapter->pnetdev; - pwrpriv = &padapter->pwrctrlpriv; - - mutex_lock(&pwrpriv->lock); - rtw_reset_drv_sw(padapter); - if (pwrpriv) - pwrpriv->bkeepfwalive = false; - - if (netdev_open(pnetdev) != 0) { - mutex_unlock(&pwrpriv->lock); - goto exit; - } - - netif_device_attach(pnetdev); - netif_carrier_on(pnetdev); - - mutex_unlock(&pwrpriv->lock); - - if (padapter->pid[1] != 0) - rtw_signal_process(padapter->pid[1], SIGUSR2); - - rtw_roaming(padapter, NULL); - - ret = 0; -exit: - if (pwrpriv) - pwrpriv->bInSuspend = false; - - return ret; -} - -/* - * drv_init() - a device potentially for us - * - * notes: drv_init() is called when the bus driver has located - * a card for us to support. - * We accept the new device by returning 0. - */ - -static int rtw_usb_if1_init(struct dvobj_priv *dvobj, struct usb_interface *pusb_intf) -{ - struct adapter *padapter = NULL; - struct net_device *pnetdev = NULL; - int ret; - - padapter = vzalloc(sizeof(*padapter)); - if (!padapter) - return -ENOMEM; - - padapter->dvobj = dvobj; - dvobj->if1 = padapter; - - padapter->bDriverStopped = true; - - padapter->hw_init_mutex = &usb_drv->hw_init_mutex; - - rtw_handle_dualmac(padapter, 1); - - pnetdev = rtw_init_netdev(padapter); - if (!pnetdev) { - ret = -ENODEV; - goto handle_dualmac; - } - SET_NETDEV_DEV(pnetdev, dvobj_to_dev(dvobj)); - padapter = rtw_netdev_priv(pnetdev); - - /* step read_chip_version */ - rtl8188e_read_chip_version(padapter); - - /* step usb endpoint mapping */ - ret = rtl8188eu_interface_configure(padapter); - if (ret) - goto handle_dualmac; - - /* step read efuse/eeprom data and get mac_addr */ - ret = ReadAdapterInfo8188EU(padapter); - if (ret) - goto handle_dualmac; - - /* step 5. */ - if (rtw_init_drv_sw(padapter) == _FAIL) { - ret = -ENODEV; - goto handle_dualmac; - } - -#ifdef CONFIG_PM - if (padapter->pwrctrlpriv.bSupportRemoteWakeup) { - dvobj->pusbdev->do_remote_wakeup = 1; - pusb_intf->needs_remote_wakeup = 1; - device_init_wakeup(&pusb_intf->dev, 1); - } -#endif - - /* 2012-07-11 Move here to prevent the 8723AS-VAU BT auto - * suspend influence */ - usb_autopm_get_interface(pusb_intf); - - /* alloc dev name after read efuse. */ - ret = rtw_init_netdev_name(pnetdev, padapter->registrypriv.ifname); - if (ret) - goto free_drv_sw; - rtw_macaddr_cfg(padapter->eeprompriv.mac_addr); - rtw_init_wifidirect_addrs(padapter, padapter->eeprompriv.mac_addr, - padapter->eeprompriv.mac_addr); - eth_hw_addr_set(pnetdev, padapter->eeprompriv.mac_addr); - - /* step 6. Tell the network stack we exist */ - ret = register_netdev(pnetdev); - if (ret) - goto free_drv_sw; - - return 0; - -free_drv_sw: - rtw_cancel_all_timer(padapter); - rtw_free_drv_sw(padapter); -handle_dualmac: - rtw_handle_dualmac(padapter, 0); - if (pnetdev) - rtw_free_netdev(pnetdev); - else - vfree(padapter); - - return ret; -} - -static void rtw_usb_if1_deinit(struct adapter *if1) -{ - struct net_device *pnetdev = if1->pnetdev; - struct mlme_priv *pmlmepriv = &if1->mlmepriv; - - if (check_fwstate(pmlmepriv, _FW_LINKED)) - rtw_disassoc_cmd(if1, 0, false); - - free_mlme_ap_info(if1); - - if (pnetdev) { - /* will call netdev_close() */ - unregister_netdev(pnetdev); - } - rtw_cancel_all_timer(if1); - - rtw_dev_unload(if1); - rtw_handle_dualmac(if1, 0); - rtw_free_drv_sw(if1); - if (pnetdev) - rtw_free_netdev(pnetdev); -} - -static int rtw_drv_init(struct usb_interface *pusb_intf, const struct usb_device_id *pdid) -{ - struct dvobj_priv *dvobj; - int ret; - - /* Initialize dvobj_priv */ - dvobj = usb_dvobj_init(pusb_intf); - if (!dvobj) - return -ENODEV; - - ret = rtw_usb_if1_init(dvobj, pusb_intf); - if (ret) { - usb_dvobj_deinit(pusb_intf); - return ret; - } - - if (ui_pid[1] != 0) - rtw_signal_process(ui_pid[1], SIGUSR2); - - return 0; -} - -/* - * dev_remove() - our device is being removed -*/ -/* rmmod module & unplug(SurpriseRemoved) will call r871xu_dev_remove() => how to recognize both */ -static void rtw_dev_remove(struct usb_interface *pusb_intf) -{ - struct dvobj_priv *dvobj = usb_get_intfdata(pusb_intf); - struct adapter *padapter = dvobj->if1; - - if (usb_drv->drv_registered) - padapter->bSurpriseRemoved = true; - - rtw_pm_set_ips(padapter, IPS_NONE); - rtw_pm_set_lps(padapter, PS_MODE_ACTIVE); - - LeaveAllPowerSaveMode(padapter); - - rtw_usb_if1_deinit(padapter); - - usb_dvobj_deinit(pusb_intf); -} - -static int __init rtw_drv_entry(void) -{ - mutex_init(&usb_drv->hw_init_mutex); - - usb_drv->drv_registered = true; - return usb_register(&usb_drv->usbdrv); -} - -static void __exit rtw_drv_halt(void) -{ - usb_drv->drv_registered = false; - usb_deregister(&usb_drv->usbdrv); - - mutex_destroy(&usb_drv->hw_init_mutex); -} - -module_init(rtw_drv_entry); -module_exit(rtw_drv_halt); diff --git a/drivers/staging/r8188eu/os_dep/usb_ops_linux.c b/drivers/staging/r8188eu/os_dep/usb_ops_linux.c deleted file mode 100644 index ca09f7ed7e4d..000000000000 --- a/drivers/staging/r8188eu/os_dep/usb_ops_linux.c +++ /dev/null @@ -1,136 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2007 - 2012 Realtek Corporation. */ - -#define _USB_OPS_LINUX_C_ - -#include "../include/drv_types.h" -#include "../include/rtl8188e_recv.h" - -static unsigned int ffaddr2pipehdl(struct dvobj_priv *pdvobj, u32 addr) -{ - unsigned int pipe = 0, ep_num = 0; - struct usb_device *pusbd = pdvobj->pusbdev; - - if (addr < HW_QUEUE_ENTRY) { - ep_num = pdvobj->Queue2Pipe[addr]; - pipe = usb_sndbulkpipe(pusbd, ep_num); - } - - return pipe; -} - -void rtw_read_port_cancel(struct adapter *padapter) -{ - int i; - struct recv_buf *precvbuf = (struct recv_buf *)padapter->recvpriv.precv_buf; - - padapter->bReadPortCancel = true; - - for (i = 0; i < NR_RECVBUFF; i++) { - precvbuf->reuse = true; - usb_kill_urb(precvbuf->purb); - precvbuf++; - } -} - -static void usb_write_port_complete(struct urb *purb) -{ - struct xmit_buf *pxmitbuf = (struct xmit_buf *)purb->context; - struct adapter *padapter = pxmitbuf->padapter; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - if (pxmitbuf->high_queue) - rtw_chk_hi_queue_cmd(padapter); - - switch (purb->status) { - case 0: - case -EINPROGRESS: - case -ENOENT: - case -ECONNRESET: - case -EPIPE: - case -EPROTO: - break; - case -ESHUTDOWN: - padapter->bDriverStopped = true; - break; - default: - padapter->bSurpriseRemoved = true; - break; - } - - rtw_sctx_done_err(&pxmitbuf->sctx, - purb->status ? RTW_SCTX_DONE_WRITE_PORT_ERR : RTW_SCTX_DONE_SUCCESS); - rtw_free_xmitbuf(pxmitpriv, pxmitbuf); - tasklet_hi_schedule(&pxmitpriv->xmit_tasklet); -} - -u32 rtw_write_port(struct adapter *padapter, u32 addr, u32 cnt, u8 *wmem) -{ - unsigned long irqL; - unsigned int pipe; - int status; - u32 ret = _FAIL; - struct urb *purb = NULL; - struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter); - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct xmit_buf *pxmitbuf = (struct xmit_buf *)wmem; - struct xmit_frame *pxmitframe = (struct xmit_frame *)pxmitbuf->priv_data; - struct usb_device *pusbd = pdvobj->pusbdev; - - if (padapter->bDriverStopped || padapter->bSurpriseRemoved) { - rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_TX_DENY); - goto exit; - } - - spin_lock_irqsave(&pxmitpriv->lock, irqL); - pxmitbuf->high_queue = (addr == HIGH_QUEUE_INX); - spin_unlock_irqrestore(&pxmitpriv->lock, irqL); - - purb = pxmitbuf->pxmit_urb; - - /* translate DMA FIFO addr to pipehandle */ - pipe = ffaddr2pipehdl(pdvobj, addr); - - usb_fill_bulk_urb(purb, pusbd, pipe, - pxmitframe->buf_addr, /* pxmitbuf->pbuf */ - cnt, - usb_write_port_complete, - pxmitbuf);/* context is pxmitbuf */ - - status = usb_submit_urb(purb, GFP_ATOMIC); - if (status) { - rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_WRITE_PORT_ERR); - if (status == -ENODEV) - padapter->bDriverStopped = true; - goto exit; - } - - ret = _SUCCESS; - -/* We add the URB_ZERO_PACKET flag to urb so that the host will send the zero packet automatically. */ - -exit: - if (ret != _SUCCESS) - rtw_free_xmitbuf(pxmitpriv, pxmitbuf); - - return ret; -} - -void rtw_write_port_cancel(struct adapter *padapter) -{ - int i; - struct xmit_buf *pxmitbuf = (struct xmit_buf *)padapter->xmitpriv.pxmitbuf; - - padapter->bWritePortCancel = true; - - for (i = 0; i < NR_XMITBUFF; i++) { - usb_kill_urb(pxmitbuf->pxmit_urb); - pxmitbuf++; - } - - pxmitbuf = (struct xmit_buf *)padapter->xmitpriv.pxmit_extbuf; - for (i = 0; i < NR_XMIT_EXTBUFF; i++) { - usb_kill_urb(pxmitbuf->pxmit_urb); - pxmitbuf++; - } -} From c3a4aec055ec275c9f860e88d37e97248927d898 Mon Sep 17 00:00:00 2001 From: Jiapeng Chong Date: Tue, 7 Mar 2023 16:49:18 +0800 Subject: [PATCH 278/778] splice: Remove redundant assignment to ret The variable ret belongs to redundant assignment and can be deleted. fs/splice.c:940:2: warning: Value stored to 'ret' is never read. Reported-by: Abaci Robot Link: https://bugzilla.openanolis.cn/show_bug.cgi?id=4406 Signed-off-by: Jiapeng Chong Reviewed-by: Chaitanya Kulkarni Signed-off-by: Christian Brauner (Microsoft) --- fs/splice.c | 1 - 1 file changed, 1 deletion(-) diff --git a/fs/splice.c b/fs/splice.c index 2e76dbb81a8f..2c3dec2b6dfa 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -937,7 +937,6 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd, /* * Do the splice. */ - ret = 0; bytes = 0; len = sd->total_len; flags = sd->flags; From dc592190a5543c559010e09e8130a1af3f9068d3 Mon Sep 17 00:00:00 2001 From: Jiapeng Chong Date: Wed, 8 Mar 2023 15:13:16 +0800 Subject: [PATCH 279/778] fs/locks: Remove redundant assignment to cmd Variable 'cmd' set but not used. fs/locks.c:2428:3: warning: Value stored to 'cmd' is never read. Reported-by: Abaci Robot Link: https://bugzilla.openanolis.cn/show_bug.cgi?id=4439 Signed-off-by: Jiapeng Chong Reviewed-by: Chaitanya Kulkarni Signed-off-by: Christian Brauner (Microsoft) --- fs/locks.c | 1 - 1 file changed, 1 deletion(-) diff --git a/fs/locks.c b/fs/locks.c index 66b4eef09db5..d82c4cacdfb9 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -2425,7 +2425,6 @@ int fcntl_getlk64(struct file *filp, unsigned int cmd, struct flock64 *flock) if (flock->l_pid != 0) goto out; - cmd = F_GETLK64; fl->fl_flags |= FL_OFDLCK; fl->fl_owner = filp; } From 8987986b07f5dded3f81b159f5bb146f2d1a21ed Mon Sep 17 00:00:00 2001 From: Lucas Tanure Date: Thu, 9 Mar 2023 14:00:51 +0000 Subject: [PATCH 280/778] ASoC: cs35l41: Steam Deck Shared boost properties quirk Add support for Steam Deck bios old properties. If a Steam deck didn't upgrade the BIOS, the driver should be able to handle the previous properties for shared boost types. Signed-off-by: Lucas Tanure Acked-by: Charles Keepax Link: https://lore.kernel.org/r/20230309140051.945329-1-lucas.tanure@collabora.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l41.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/cs35l41.c b/sound/soc/codecs/cs35l41.c index 1624510d09c0..9ec01a5f09ca 100644 --- a/sound/soc/codecs/cs35l41.c +++ b/sound/soc/codecs/cs35l41.c @@ -1022,9 +1022,21 @@ static int cs35l41_handle_pdata(struct device *dev, struct cs35l41_hw_cfg *hw_cf unsigned int val; int ret; - ret = device_property_read_u32(dev, "cirrus,boost-type", &val); - if (ret >= 0) - hw_cfg->bst_type = val; + /* Some ACPI systems received the Shared Boost feature before the upstream driver, + * leaving those systems with deprecated _DSD properties. + * To correctly configure those systems add shared-boost-active and shared-boost-passive + * properties mapped to the correct value in boost-type. + * These two are not DT properties and should not be used in new systems designs. + */ + if (device_property_read_bool(dev, "cirrus,shared-boost-active")) { + hw_cfg->bst_type = CS35L41_SHD_BOOST_ACTV; + } else if (device_property_read_bool(dev, "cirrus,shared-boost-passive")) { + hw_cfg->bst_type = CS35L41_SHD_BOOST_PASS; + } else { + ret = device_property_read_u32(dev, "cirrus,boost-type", &val); + if (ret >= 0) + hw_cfg->bst_type = val; + } ret = device_property_read_u32(dev, "cirrus,boost-peak-milliamp", &val); if (ret >= 0) From a279adedbb5206ccadb6b2817838cbb1c834133d Mon Sep 17 00:00:00 2001 From: Yangtao Li Date: Fri, 3 Mar 2023 14:37:31 +0800 Subject: [PATCH 281/778] erofs: mark z_erofs_lzma_init/erofs_pcpubuf_init w/ __init They are used during the erofs module init phase. Let's mark it as __init like any other function. Signed-off-by: Yangtao Li Reviewed-by: Yue Hu Reviewed-by: Gao Xiang Reviewed-by: Chao Yu Link: https://lore.kernel.org/r/20230303063731.66760-1-frank.li@vivo.com Signed-off-by: Gao Xiang --- fs/erofs/decompressor_lzma.c | 2 +- fs/erofs/internal.h | 4 ++-- fs/erofs/pcpubuf.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/erofs/decompressor_lzma.c b/fs/erofs/decompressor_lzma.c index 091fd5adf818..307b37f0b9f5 100644 --- a/fs/erofs/decompressor_lzma.c +++ b/fs/erofs/decompressor_lzma.c @@ -47,7 +47,7 @@ void z_erofs_lzma_exit(void) } } -int z_erofs_lzma_init(void) +int __init z_erofs_lzma_init(void) { unsigned int i; diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h index 3f3561d37d1b..1db018f8c2e8 100644 --- a/fs/erofs/internal.h +++ b/fs/erofs/internal.h @@ -486,7 +486,7 @@ static inline void *erofs_vm_map_ram(struct page **pages, unsigned int count) void *erofs_get_pcpubuf(unsigned int requiredpages); void erofs_put_pcpubuf(void *ptr); int erofs_pcpubuf_growsize(unsigned int nrpages); -void erofs_pcpubuf_init(void); +void __init erofs_pcpubuf_init(void); void erofs_pcpubuf_exit(void); int erofs_register_sysfs(struct super_block *sb); @@ -545,7 +545,7 @@ static inline int z_erofs_fill_inode(struct inode *inode) { return -EOPNOTSUPP; #endif /* !CONFIG_EROFS_FS_ZIP */ #ifdef CONFIG_EROFS_FS_ZIP_LZMA -int z_erofs_lzma_init(void); +int __init z_erofs_lzma_init(void); void z_erofs_lzma_exit(void); int z_erofs_load_lzma_config(struct super_block *sb, struct erofs_super_block *dsb, diff --git a/fs/erofs/pcpubuf.c b/fs/erofs/pcpubuf.c index a2efd833d1b6..c7a4b1d77069 100644 --- a/fs/erofs/pcpubuf.c +++ b/fs/erofs/pcpubuf.c @@ -114,7 +114,7 @@ out: return ret; } -void erofs_pcpubuf_init(void) +void __init erofs_pcpubuf_init(void) { int cpu; From 8f121dfb15f7b4ab345992ce96003eb63fd608f4 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Sun, 5 Mar 2023 21:44:55 +0800 Subject: [PATCH 282/778] erofs: fix wrong kunmap when using LZMA on HIGHMEM platforms As the call trace shown, the root cause is kunmap incorrect pages: BUG: kernel NULL pointer dereference, address: 00000000 CPU: 1 PID: 40 Comm: kworker/u5:0 Not tainted 6.2.0-rc5 #4 Workqueue: erofs_worker z_erofs_decompressqueue_work EIP: z_erofs_lzma_decompress+0x34b/0x8ac z_erofs_decompress+0x12/0x14 z_erofs_decompress_queue+0x7e7/0xb1c z_erofs_decompressqueue_work+0x32/0x60 process_one_work+0x24b/0x4d8 ? process_one_work+0x1a4/0x4d8 worker_thread+0x14c/0x3fc kthread+0xe6/0x10c ? rescuer_thread+0x358/0x358 ? kthread_complete_and_exit+0x18/0x18 ret_from_fork+0x1c/0x28 ---[ end trace 0000000000000000 ]--- The bug is trivial and should be fixed now. It has no impact on !HIGHMEM platforms. Fixes: 622ceaddb764 ("erofs: lzma compression support") Cc: # 5.16+ Reviewed-by: Yue Hu Reviewed-by: Chao Yu Signed-off-by: Gao Xiang Link: https://lore.kernel.org/r/20230305134455.88236-1-hsiangkao@linux.alibaba.com --- fs/erofs/decompressor_lzma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/erofs/decompressor_lzma.c b/fs/erofs/decompressor_lzma.c index 307b37f0b9f5..d38e19c11270 100644 --- a/fs/erofs/decompressor_lzma.c +++ b/fs/erofs/decompressor_lzma.c @@ -278,7 +278,7 @@ again: } } if (no < nrpages_out && strm->buf.out) - kunmap(rq->in[no]); + kunmap(rq->out[no]); if (ni < nrpages_in) kunmap(rq->in[ni]); /* 4. push back LZMA stream context to the global list */ From 647dd2c3f0e16b71a1a77897d038164d48eea154 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Thu, 9 Mar 2023 13:31:47 +0800 Subject: [PATCH 283/778] erofs: Revert "erofs: fix kvcalloc() misuse with __GFP_NOFAIL" Let's revert commit 12724ba38992 ("erofs: fix kvcalloc() misuse with __GFP_NOFAIL") since kvmalloc() already supports __GFP_NOFAIL in commit a421ef303008 ("mm: allow !GFP_KERNEL allocations for kvmalloc"). So the original fix was wrong. Actually there was some issue as [1] discussed, so before that mm fix is landed, the warn could still happen but applying this commit first will cause less. [1] https://lore.kernel.org/r/20230305053035.1911-1-hsiangkao@linux.alibaba.com Fixes: 12724ba38992 ("erofs: fix kvcalloc() misuse with __GFP_NOFAIL") Reviewed-by: Chao Yu Link: https://lore.kernel.org/r/20230309053148.9223-1-hsiangkao@linux.alibaba.com Signed-off-by: Gao Xiang --- fs/erofs/zdata.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/fs/erofs/zdata.c b/fs/erofs/zdata.c index 3247d2422bea..f1708c77a991 100644 --- a/fs/erofs/zdata.c +++ b/fs/erofs/zdata.c @@ -1312,12 +1312,12 @@ static int z_erofs_decompress_pcluster(struct z_erofs_decompress_backend *be, if (!be->decompressed_pages) be->decompressed_pages = - kcalloc(be->nr_pages, sizeof(struct page *), - GFP_KERNEL | __GFP_NOFAIL); + kvcalloc(be->nr_pages, sizeof(struct page *), + GFP_KERNEL | __GFP_NOFAIL); if (!be->compressed_pages) be->compressed_pages = - kcalloc(pclusterpages, sizeof(struct page *), - GFP_KERNEL | __GFP_NOFAIL); + kvcalloc(pclusterpages, sizeof(struct page *), + GFP_KERNEL | __GFP_NOFAIL); z_erofs_parse_out_bvecs(be); err2 = z_erofs_parse_in_bvecs(be, &overlapped); @@ -1365,7 +1365,7 @@ out: } if (be->compressed_pages < be->onstack_pages || be->compressed_pages >= be->onstack_pages + Z_EROFS_ONSTACK_PAGES) - kfree(be->compressed_pages); + kvfree(be->compressed_pages); z_erofs_fill_other_copies(be, err); for (i = 0; i < be->nr_pages; ++i) { @@ -1384,7 +1384,7 @@ out: } if (be->decompressed_pages != be->onstack_pages) - kfree(be->decompressed_pages); + kvfree(be->decompressed_pages); pcl->length = 0; pcl->partial = true; From 9ff471800b74f5f952c7e75a0355f1d30ee2b046 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Thu, 9 Mar 2023 13:31:48 +0800 Subject: [PATCH 284/778] erofs: get rid of a useless DBG_BUGON `err` could be -EINTR and it should not be the case. Actually such DBG_BUGON is useless. Reviewed-by: Chao Yu Link: https://lore.kernel.org/r/20230309053148.9223-2-hsiangkao@linux.alibaba.com Signed-off-by: Gao Xiang --- fs/erofs/zmap.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/fs/erofs/zmap.c b/fs/erofs/zmap.c index 8bf6d30518b6..655da4d739cb 100644 --- a/fs/erofs/zmap.c +++ b/fs/erofs/zmap.c @@ -757,9 +757,6 @@ int z_erofs_map_blocks_iter(struct inode *inode, struct erofs_map_blocks *map, err = z_erofs_do_map_blocks(inode, map, flags); out: trace_z_erofs_map_blocks_iter_exit(inode, map, flags, err); - - /* aggressively BUG_ON iff CONFIG_EROFS_FS_DEBUG is on */ - DBG_BUGON(err < 0 && err != -ENOMEM); return err; } From 3993f4f456309580445bb515fbc609d995b6a3ae Mon Sep 17 00:00:00 2001 From: Yue Hu Date: Mon, 6 Mar 2023 15:55:27 +0800 Subject: [PATCH 285/778] erofs: use wrapper i_blocksize() in erofs_file_read_iter() linux/fs.h has a wrapper for this operation. Signed-off-by: Yue Hu Reviewed-by: Gao Xiang Reviewed-by: Chao Yu Link: https://lore.kernel.org/r/20230306075527.1338-1-zbestahu@gmail.com Signed-off-by: Gao Xiang --- fs/erofs/data.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/erofs/data.c b/fs/erofs/data.c index e16545849ea7..c08c0f578bc6 100644 --- a/fs/erofs/data.c +++ b/fs/erofs/data.c @@ -376,7 +376,7 @@ static ssize_t erofs_file_read_iter(struct kiocb *iocb, struct iov_iter *to) if (bdev) blksize_mask = bdev_logical_block_size(bdev) - 1; else - blksize_mask = (1 << inode->i_blkbits) - 1; + blksize_mask = i_blocksize(inode) - 1; if ((iocb->ki_pos | iov_iter_count(to) | iov_iter_alignment(to)) & blksize_mask) From 03b3d6be73e81ddb7c2930d942cdd17f4cfd5ba5 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 8 Mar 2023 09:26:13 -0700 Subject: [PATCH 286/778] io_uring/uring_cmd: ensure that device supports IOPOLL It's possible for a file type to support uring commands, but not pollable ones. Hence before issuing one of those, we should check that it is supported and error out upfront if it isn't. Cc: stable@vger.kernel.org Fixes: 5756a3a7e713 ("io_uring: add iopoll infrastructure for io_uring_cmd") Link: https://github.com/axboe/liburing/issues/816 Reviewed-by: Kanchan Joshi Signed-off-by: Jens Axboe --- io_uring/uring_cmd.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/io_uring/uring_cmd.c b/io_uring/uring_cmd.c index 446a189b78b0..2e4c483075d3 100644 --- a/io_uring/uring_cmd.c +++ b/io_uring/uring_cmd.c @@ -108,7 +108,7 @@ int io_uring_cmd(struct io_kiocb *req, unsigned int issue_flags) struct file *file = req->file; int ret; - if (!req->file->f_op->uring_cmd) + if (!file->f_op->uring_cmd) return -EOPNOTSUPP; ret = security_uring_cmd(ioucmd); @@ -120,6 +120,8 @@ int io_uring_cmd(struct io_kiocb *req, unsigned int issue_flags) if (ctx->flags & IORING_SETUP_CQE32) issue_flags |= IO_URING_F_CQE32; if (ctx->flags & IORING_SETUP_IOPOLL) { + if (!file->f_op->uring_cmd_iopoll) + return -EOPNOTSUPP; issue_flags |= IO_URING_F_IOPOLL; req->iopoll_completed = 0; WRITE_ONCE(ioucmd->cookie, NULL); From fa780334a8c392d959ae05eb19f2410b3a1e6cb0 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 9 Mar 2023 09:51:13 -0700 Subject: [PATCH 287/778] =?UTF-8?q?io=5Furing:=20silence=20variable=20?= =?UTF-8?q?=E2=80=98prev=E2=80=99=20set=20but=20not=20used=20warning?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If io_uring.o is built with W=1, it triggers a warning: io_uring/io_uring.c: In function ‘__io_submit_flush_completions’: io_uring/io_uring.c:1502:40: warning: variable ‘prev’ set but not used [-Wunused-but-set-variable] 1502 | struct io_wq_work_node *node, *prev; | ^~~~ which is due to the wq_list_for_each() iterator always keeping a 'prev' variable. Most users need this to remove an entry from a list, for example, but __io_submit_flush_completions() never does that. Add a basic helper that doesn't track prev instead, and use that in that function. Reported-by: Vincenzo Palazzo Reviewed-by: Vincenzo Palazzo Signed-off-by: Jens Axboe --- io_uring/io_uring.c | 4 ++-- io_uring/slist.h | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c index fd1cc35a1c00..722624b6d0dc 100644 --- a/io_uring/io_uring.c +++ b/io_uring/io_uring.c @@ -1499,14 +1499,14 @@ void io_free_batch_list(struct io_ring_ctx *ctx, struct io_wq_work_node *node) static void __io_submit_flush_completions(struct io_ring_ctx *ctx) __must_hold(&ctx->uring_lock) { - struct io_wq_work_node *node, *prev; struct io_submit_state *state = &ctx->submit_state; + struct io_wq_work_node *node; __io_cq_lock(ctx); /* must come first to preserve CQE ordering in failure cases */ if (state->cqes_count) __io_flush_post_cqes(ctx); - wq_list_for_each(node, prev, &state->compl_reqs) { + __wq_list_for_each(node, &state->compl_reqs) { struct io_kiocb *req = container_of(node, struct io_kiocb, comp_list); diff --git a/io_uring/slist.h b/io_uring/slist.h index 7c198a40d5f1..0eb194817242 100644 --- a/io_uring/slist.h +++ b/io_uring/slist.h @@ -3,6 +3,9 @@ #include +#define __wq_list_for_each(pos, head) \ + for (pos = (head)->first; pos; pos = (pos)->next) + #define wq_list_for_each(pos, prv, head) \ for (pos = (head)->first, prv = NULL; pos; prv = pos, pos = (pos)->next) @@ -113,4 +116,4 @@ static inline struct io_wq_work *wq_next_work(struct io_wq_work *work) return container_of(work->list.next, struct io_wq_work, list); } -#endif // INTERNAL_IO_SLIST_H \ No newline at end of file +#endif // INTERNAL_IO_SLIST_H From 573b22ccb7ce9ab7f0539a2e11a9d3609a8783f5 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 6 Mar 2023 01:20:30 +0000 Subject: [PATCH 288/778] sh: sanitize the flags on sigreturn We fetch %SR value from sigframe; it might have been modified by signal handler, so we can't trust it with any bits that are not modifiable in user mode. Signed-off-by: Al Viro Cc: Rich Felker Signed-off-by: Linus Torvalds --- arch/sh/include/asm/processor_32.h | 1 + arch/sh/kernel/signal_32.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/arch/sh/include/asm/processor_32.h b/arch/sh/include/asm/processor_32.h index 27aebf1e75a2..3ef7adf739c8 100644 --- a/arch/sh/include/asm/processor_32.h +++ b/arch/sh/include/asm/processor_32.h @@ -50,6 +50,7 @@ #define SR_FD 0x00008000 #define SR_MD 0x40000000 +#define SR_USER_MASK 0x00000303 // M, Q, S, T bits /* * DSP structure and data */ diff --git a/arch/sh/kernel/signal_32.c b/arch/sh/kernel/signal_32.c index 90f495d35db2..a6bfc6f37491 100644 --- a/arch/sh/kernel/signal_32.c +++ b/arch/sh/kernel/signal_32.c @@ -115,6 +115,7 @@ static int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *r0_p) { unsigned int err = 0; + unsigned int sr = regs->sr & ~SR_USER_MASK; #define COPY(x) err |= __get_user(regs->x, &sc->sc_##x) COPY(regs[1]); @@ -130,6 +131,8 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *r0_p COPY(sr); COPY(pc); #undef COPY + regs->sr = (regs->sr & SR_USER_MASK) | sr; + #ifdef CONFIG_SH_FPU if (boot_cpu_data.flags & CPU_HAS_FPU) { int owned_fp; From b2bda460b1b744a3835ce9d291360b6185e7e305 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 10 Mar 2023 05:24:43 +1000 Subject: [PATCH 289/778] mailmap: add mailmap entries for Faith. Reviewed-by: Faith Ekstrand Signed-off-by: Dave Airlie --- .mailmap | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.mailmap b/.mailmap index 5367faaf7831..4ff64c33a152 100644 --- a/.mailmap +++ b/.mailmap @@ -136,6 +136,9 @@ Erik Kaneda Eugen Hristev Evgeniy Polyakov Ezequiel Garcia +Faith Ekstrand +Faith Ekstrand +Faith Ekstrand Felipe W Damasio Felix Kuhling Felix Moeller From 55e7dddcaf4a55d2f097463cdf5709c3278c6fa9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Sun, 26 Feb 2023 23:26:46 +0100 Subject: [PATCH 290/778] misc: ad525x_dpot-i2c: Convert to i2c's .probe_new() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit .probe_new() doesn't get the i2c_device_id * parameter, so determine that explicitly in the probe function. Acked-by: Greg Kroah-Hartman Link: https://lore.kernel.org/lkml/20221118224540.619276-483-uwe@kleine-koenig.org Signed-off-by: Uwe Kleine-König Signed-off-by: Wolfram Sang --- drivers/misc/ad525x_dpot-i2c.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/misc/ad525x_dpot-i2c.c b/drivers/misc/ad525x_dpot-i2c.c index 28ffb4377d98..3856d5c04c5f 100644 --- a/drivers/misc/ad525x_dpot-i2c.c +++ b/drivers/misc/ad525x_dpot-i2c.c @@ -50,9 +50,9 @@ static const struct ad_dpot_bus_ops bops = { .write_r8d16 = write_r8d16, }; -static int ad_dpot_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int ad_dpot_i2c_probe(struct i2c_client *client) { + const struct i2c_device_id *id = i2c_client_get_device_id(client); struct ad_dpot_bus_data bdata = { .client = client, .bops = &bops, @@ -106,7 +106,7 @@ static struct i2c_driver ad_dpot_i2c_driver = { .driver = { .name = "ad_dpot", }, - .probe = ad_dpot_i2c_probe, + .probe_new = ad_dpot_i2c_probe, .remove = ad_dpot_i2c_remove, .id_table = ad_dpot_id, }; From 0b79d5d1e5982bc3b0da9cd3b40ce972a72f2541 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Sun, 26 Feb 2023 23:26:47 +0100 Subject: [PATCH 291/778] mtd: maps: pismo: Convert to i2c's .probe_new() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The probe function doesn't make use of the i2c_device_id * parameter so it can be trivially converted. Acked-by: Richard Weinberger Link: https://lore.kernel.org/lkml/20221118224540.619276-497-uwe@kleine-koenig.org Signed-off-by: Uwe Kleine-König Signed-off-by: Wolfram Sang --- drivers/mtd/maps/pismo.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/maps/pismo.c b/drivers/mtd/maps/pismo.c index 5fcefcd0baca..3e0fff3f129e 100644 --- a/drivers/mtd/maps/pismo.c +++ b/drivers/mtd/maps/pismo.c @@ -206,8 +206,7 @@ static void pismo_remove(struct i2c_client *client) kfree(pismo); } -static int pismo_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int pismo_probe(struct i2c_client *client) { struct pismo_pdata *pdata = client->dev.platform_data; struct pismo_eeprom eeprom; @@ -260,7 +259,7 @@ static struct i2c_driver pismo_driver = { .driver = { .name = "pismo", }, - .probe = pismo_probe, + .probe_new = pismo_probe, .remove = pismo_remove, .id_table = pismo_id, }; From 01d93875dafdaaf90bfc782074cae5b4605f3907 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Sun, 26 Feb 2023 23:26:48 +0100 Subject: [PATCH 292/778] serial: sc16is7xx: Convert to i2c's .probe_new() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit .probe_new() doesn't get the i2c_device_id * parameter, so determine that explicitly in the probe function. Reviewed-by: Greg Kroah-Hartman Link: https://lore.kernel.org/lkml/20221118224540.619276-572-uwe@kleine-koenig.org Signed-off-by: Uwe Kleine-König Signed-off-by: Wolfram Sang --- drivers/tty/serial/sc16is7xx.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c index 29c94be09159..abad091baeea 100644 --- a/drivers/tty/serial/sc16is7xx.c +++ b/drivers/tty/serial/sc16is7xx.c @@ -1666,9 +1666,9 @@ MODULE_ALIAS("spi:sc16is7xx"); #endif #ifdef CONFIG_SERIAL_SC16IS7XX_I2C -static int sc16is7xx_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) +static int sc16is7xx_i2c_probe(struct i2c_client *i2c) { + const struct i2c_device_id *id = i2c_client_get_device_id(i2c); const struct sc16is7xx_devtype *devtype; struct regmap *regmap; @@ -1709,7 +1709,7 @@ static struct i2c_driver sc16is7xx_i2c_uart_driver = { .name = SC16IS7XX_NAME, .of_match_table = sc16is7xx_dt_ids, }, - .probe = sc16is7xx_i2c_probe, + .probe_new = sc16is7xx_i2c_probe, .remove = sc16is7xx_i2c_remove, .id_table = sc16is7xx_i2c_id_table, }; From e60289897e90801e951a3e172789967c9e2afb7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Sun, 26 Feb 2023 23:26:49 +0100 Subject: [PATCH 293/778] w1: ds2482: Convert to i2c's .probe_new() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The probe function doesn't make use of the i2c_device_id * parameter so it can be trivially converted. Link: https://lore.kernel.org/lkml/20221118224540.619276-596-uwe@kleine-koenig.org Signed-off-by: Uwe Kleine-König Signed-off-by: Wolfram Sang --- drivers/w1/masters/ds2482.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/w1/masters/ds2482.c b/drivers/w1/masters/ds2482.c index 62c44616d8a9..3d8b51316bef 100644 --- a/drivers/w1/masters/ds2482.c +++ b/drivers/w1/masters/ds2482.c @@ -442,8 +442,7 @@ static u8 ds2482_w1_set_pullup(void *data, int delay) } -static int ds2482_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int ds2482_probe(struct i2c_client *client) { struct ds2482_data *data; int err = -ENODEV; @@ -553,7 +552,7 @@ static struct i2c_driver ds2482_driver = { .driver = { .name = "ds2482", }, - .probe = ds2482_probe, + .probe_new = ds2482_probe, .remove = ds2482_remove, .id_table = ds2482_id, }; From 79e070c5ee7a3faeb9ab8e1fa270b846a4fa2e56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Sun, 26 Feb 2023 23:26:50 +0100 Subject: [PATCH 294/778] media: i2c: ov5695: convert to i2c's .probe_new() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The probe function doesn't make use of the i2c_device_id * parameter so it can be trivially converted. Reviewed-by: Kieran Bingham Acked-by: Hans Verkuil Link: https://lore.kernel.org/lkml/20221121102705.16092-1-u.kleine-koenig@pengutronix.de Signed-off-by: Uwe Kleine-König Signed-off-by: Wolfram Sang --- drivers/media/i2c/ov5695.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/media/i2c/ov5695.c b/drivers/media/i2c/ov5695.c index 61906fc54e37..b287c28920a6 100644 --- a/drivers/media/i2c/ov5695.c +++ b/drivers/media/i2c/ov5695.c @@ -1267,8 +1267,7 @@ static int ov5695_configure_regulators(struct ov5695 *ov5695) ov5695->supplies); } -static int ov5695_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int ov5695_probe(struct i2c_client *client) { struct device *dev = &client->dev; struct ov5695 *ov5695; @@ -1393,7 +1392,7 @@ static struct i2c_driver ov5695_i2c_driver = { .pm = &ov5695_pm_ops, .of_match_table = of_match_ptr(ov5695_of_match), }, - .probe = &ov5695_probe, + .probe_new = &ov5695_probe, .remove = &ov5695_remove, }; From 7eafbd40901c2b6f884c022c10bec5c8ec5c6a24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Sun, 26 Feb 2023 23:26:51 +0100 Subject: [PATCH 295/778] media: i2c: ov2685: convert to i2c's .probe_new() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The probe function doesn't make use of the i2c_device_id * parameter so it can be trivially converted. Reviewed-by: Kieran Bingham Acked-by: Hans Verkuil Link: https://lore.kernel.org/lkml/20221121102838.16448-1-u.kleine-koenig@pengutronix.de Signed-off-by: Uwe Kleine-König Signed-off-by: Wolfram Sang --- drivers/media/i2c/ov2685.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/media/i2c/ov2685.c b/drivers/media/i2c/ov2685.c index a3b524f15d89..1c80b121e7d6 100644 --- a/drivers/media/i2c/ov2685.c +++ b/drivers/media/i2c/ov2685.c @@ -707,8 +707,7 @@ static int ov2685_configure_regulators(struct ov2685 *ov2685) ov2685->supplies); } -static int ov2685_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int ov2685_probe(struct i2c_client *client) { struct device *dev = &client->dev; struct ov2685 *ov2685; @@ -830,7 +829,7 @@ static struct i2c_driver ov2685_i2c_driver = { .pm = &ov2685_pm_ops, .of_match_table = of_match_ptr(ov2685_of_match), }, - .probe = &ov2685_probe, + .probe_new = &ov2685_probe, .remove = &ov2685_remove, }; From 03c835f498b540087244a6757e87dfe7ef10999b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Sun, 26 Feb 2023 23:26:52 +0100 Subject: [PATCH 296/778] i2c: Switch .probe() to not take an id parameter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit b8a1a4cd5a98 ("i2c: Provide a temporary .probe_new() call-back type") introduced a new probe callback to convert i2c init routines to not take an i2c_device_id parameter. Now that all in-tree drivers are converted to the temporary .probe_new() callback, .probe() can be modified to match the desired prototype. Now that .probe() and .probe_new() have the same semantic, they can be defined as members of an anonymous union to save some memory and simplify the core code a bit. Signed-off-by: Uwe Kleine-König Signed-off-by: Wolfram Sang --- drivers/i2c/i2c-core-base.c | 11 ++--------- include/linux/i2c.h | 18 +++++++++++------- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index cb5fa971d67e..63253e2b2c1f 100644 --- a/drivers/i2c/i2c-core-base.c +++ b/drivers/i2c/i2c-core-base.c @@ -561,15 +561,8 @@ static int i2c_device_probe(struct device *dev) goto err_detach_pm_domain; } - /* - * When there are no more users of probe(), - * rename probe_new to probe. - */ - if (driver->probe_new) - status = driver->probe_new(client); - else if (driver->probe) - status = driver->probe(client, - i2c_match_id(driver->id_table, client)); + if (driver->probe) + status = driver->probe(client); else status = -EINVAL; diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 500404d85141..5ba89663ea86 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -236,8 +236,8 @@ enum i2c_driver_flags { /** * struct i2c_driver - represent an I2C device driver * @class: What kind of i2c device we instantiate (for detect) - * @probe: Callback for device binding - soon to be deprecated - * @probe_new: New callback for device binding + * @probe: Callback for device binding + * @probe_new: Transitional callback for device binding - do not use * @remove: Callback for device unbinding * @shutdown: Callback for device shutdown * @alert: Alert callback, for example for the SMBus alert protocol @@ -272,14 +272,18 @@ enum i2c_driver_flags { struct i2c_driver { unsigned int class; + union { /* Standard driver model interfaces */ - int (*probe)(struct i2c_client *client, const struct i2c_device_id *id); + int (*probe)(struct i2c_client *client); + /* + * Legacy callback that was part of a conversion of .probe(). + * Today it has the same semantic as .probe(). Don't use for new + * code. + */ + int (*probe_new)(struct i2c_client *client); + }; void (*remove)(struct i2c_client *client); - /* New driver model interface to aid the seamless removal of the - * current probe()'s, more commonly unused than used second parameter. - */ - int (*probe_new)(struct i2c_client *client); /* driver model interfaces that don't relate to enumeration */ void (*shutdown)(struct i2c_client *client); From 2f2afad9d35ff762028de7497dac60aa32be9f0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Sun, 26 Feb 2023 23:26:53 +0100 Subject: [PATCH 297/778] i2c: mux: Convert all drivers to new .probe() callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that .probe() was changed not to get the id parameter, drivers can be converted back to that with the eventual goal to drop .probe_new(). Implement that for the i2c mux drivers. Acked-by: Guenter Roeck Acked-by: Peter Rosin Signed-off-by: Uwe Kleine-König Signed-off-by: Wolfram Sang --- drivers/i2c/muxes/i2c-mux-ltc4306.c | 2 +- drivers/i2c/muxes/i2c-mux-pca9541.c | 2 +- drivers/i2c/muxes/i2c-mux-pca954x.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/i2c/muxes/i2c-mux-ltc4306.c b/drivers/i2c/muxes/i2c-mux-ltc4306.c index 70835825083f..5a03031519be 100644 --- a/drivers/i2c/muxes/i2c-mux-ltc4306.c +++ b/drivers/i2c/muxes/i2c-mux-ltc4306.c @@ -306,7 +306,7 @@ static struct i2c_driver ltc4306_driver = { .name = "ltc4306", .of_match_table = of_match_ptr(ltc4306_of_match), }, - .probe_new = ltc4306_probe, + .probe = ltc4306_probe, .remove = ltc4306_remove, .id_table = ltc4306_id, }; diff --git a/drivers/i2c/muxes/i2c-mux-pca9541.c b/drivers/i2c/muxes/i2c-mux-pca9541.c index 09d1d9e67e31..ce0fb69249a8 100644 --- a/drivers/i2c/muxes/i2c-mux-pca9541.c +++ b/drivers/i2c/muxes/i2c-mux-pca9541.c @@ -336,7 +336,7 @@ static struct i2c_driver pca9541_driver = { .name = "pca9541", .of_match_table = of_match_ptr(pca9541_of_match), }, - .probe_new = pca9541_probe, + .probe = pca9541_probe, .remove = pca9541_remove, .id_table = pca9541_id, }; diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c index 3639e6d7304c..0ccee2ae5720 100644 --- a/drivers/i2c/muxes/i2c-mux-pca954x.c +++ b/drivers/i2c/muxes/i2c-mux-pca954x.c @@ -554,7 +554,7 @@ static struct i2c_driver pca954x_driver = { .pm = &pca954x_pm, .of_match_table = pca954x_of_match, }, - .probe_new = pca954x_probe, + .probe = pca954x_probe, .remove = pca954x_remove, .id_table = pca954x_id, }; From 834a9dc46db796f662615a18b8a38dde73f3b804 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Sun, 26 Feb 2023 23:26:54 +0100 Subject: [PATCH 298/778] i2c: Convert drivers to new .probe() callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that .probe() was changed not to get the id parameter, drivers can be converted back to that with the eventual goal to drop .probe_new(). Implement that for the i2c drivers that are part of the i2c core. Signed-off-by: Uwe Kleine-König Signed-off-by: Wolfram Sang --- drivers/i2c/i2c-core-base.c | 2 +- drivers/i2c/i2c-slave-eeprom.c | 2 +- drivers/i2c/i2c-slave-testunit.c | 2 +- drivers/i2c/i2c-smbus.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index 63253e2b2c1f..ae3af738b03f 100644 --- a/drivers/i2c/i2c-core-base.c +++ b/drivers/i2c/i2c-core-base.c @@ -1050,7 +1050,7 @@ static int dummy_probe(struct i2c_client *client) static struct i2c_driver dummy_driver = { .driver.name = "dummy", - .probe_new = dummy_probe, + .probe = dummy_probe, .id_table = dummy_id, }; diff --git a/drivers/i2c/i2c-slave-eeprom.c b/drivers/i2c/i2c-slave-eeprom.c index 5f25f23c4ff8..5946c0d0aef9 100644 --- a/drivers/i2c/i2c-slave-eeprom.c +++ b/drivers/i2c/i2c-slave-eeprom.c @@ -207,7 +207,7 @@ static struct i2c_driver i2c_slave_eeprom_driver = { .driver = { .name = "i2c-slave-eeprom", }, - .probe_new = i2c_slave_eeprom_probe, + .probe = i2c_slave_eeprom_probe, .remove = i2c_slave_eeprom_remove, .id_table = i2c_slave_eeprom_id, }; diff --git a/drivers/i2c/i2c-slave-testunit.c b/drivers/i2c/i2c-slave-testunit.c index 75ee7ebdb614..a49642bbae4b 100644 --- a/drivers/i2c/i2c-slave-testunit.c +++ b/drivers/i2c/i2c-slave-testunit.c @@ -171,7 +171,7 @@ static struct i2c_driver i2c_slave_testunit_driver = { .driver = { .name = "i2c-slave-testunit", }, - .probe_new = i2c_slave_testunit_probe, + .probe = i2c_slave_testunit_probe, .remove = i2c_slave_testunit_remove, .id_table = i2c_slave_testunit_id, }; diff --git a/drivers/i2c/i2c-smbus.c b/drivers/i2c/i2c-smbus.c index cd19546d31fc..138c3f5e0093 100644 --- a/drivers/i2c/i2c-smbus.c +++ b/drivers/i2c/i2c-smbus.c @@ -169,7 +169,7 @@ static struct i2c_driver smbalert_driver = { .driver = { .name = "smbus_alert", }, - .probe_new = smbalert_probe, + .probe = smbalert_probe, .remove = smbalert_remove, .id_table = smbalert_ids, }; From 9e5f81f9a6e78ba411117146ecf324d0145ae89a Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 9 Mar 2023 08:45:46 +0100 Subject: [PATCH 299/778] i2c: dev: Fix bus callback return values The i2cdev_{at,de}tach_adapter() callbacks are used for two purposes: 1. As notifier callbacks, when (un)registering I2C adapters created or destroyed after i2c_dev_init(), 2. As bus iterator callbacks, for registering already existing adapters from i2c_dev_init(), and for cleanup. Unfortunately both use cases expect different return values: the former expects NOTIFY_* return codes, while the latter expects zero or error codes, and aborts in case of error. Hence in case 2, as soon as i2cdev_{at,de}tach_adapter() returns (non-zero) NOTIFY_OK, the bus iterator aborts. This causes (a) only the first already existing adapter to be registered, leading to missing /dev/i2c-* entries, and (b) a failure to unregister all but the first I2C adapter during cleanup. Fix this by introducing separate callbacks for the bus iterator, wrapping the notifier functions, and always returning succes. Any errors inside these callback functions are unlikely to happen, and are fatal anyway. Fixes: cddf70d0bce71c2a ("i2c: dev: fix notifier return values") Signed-off-by: Geert Uytterhoeven Reviewed-by: Bartosz Golaszewski Signed-off-by: Wolfram Sang --- drivers/i2c/i2c-dev.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index 107623c4cc14..95a0b63ac560 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c @@ -646,7 +646,7 @@ static void i2cdev_dev_release(struct device *dev) kfree(i2c_dev); } -static int i2cdev_attach_adapter(struct device *dev, void *dummy) +static int i2cdev_attach_adapter(struct device *dev) { struct i2c_adapter *adap; struct i2c_dev *i2c_dev; @@ -685,7 +685,7 @@ err_put_i2c_dev: return NOTIFY_DONE; } -static int i2cdev_detach_adapter(struct device *dev, void *dummy) +static int i2cdev_detach_adapter(struct device *dev) { struct i2c_adapter *adap; struct i2c_dev *i2c_dev; @@ -711,9 +711,9 @@ static int i2cdev_notifier_call(struct notifier_block *nb, unsigned long action, switch (action) { case BUS_NOTIFY_ADD_DEVICE: - return i2cdev_attach_adapter(dev, NULL); + return i2cdev_attach_adapter(dev); case BUS_NOTIFY_DEL_DEVICE: - return i2cdev_detach_adapter(dev, NULL); + return i2cdev_detach_adapter(dev); } return NOTIFY_DONE; @@ -725,6 +725,18 @@ static struct notifier_block i2cdev_notifier = { /* ------------------------------------------------------------------------- */ +static int __init i2c_dev_attach_adapter(struct device *dev, void *dummy) +{ + i2cdev_attach_adapter(dev); + return 0; +} + +static int __exit i2c_dev_detach_adapter(struct device *dev, void *dummy) +{ + i2cdev_detach_adapter(dev); + return 0; +} + /* * module load/unload record keeping */ @@ -752,7 +764,7 @@ static int __init i2c_dev_init(void) goto out_unreg_class; /* Bind to already existing adapters right away */ - i2c_for_each_dev(NULL, i2cdev_attach_adapter); + i2c_for_each_dev(NULL, i2c_dev_attach_adapter); return 0; @@ -768,7 +780,7 @@ out: static void __exit i2c_dev_exit(void) { bus_unregister_notifier(&i2c_bus_type, &i2cdev_notifier); - i2c_for_each_dev(NULL, i2cdev_detach_adapter); + i2c_for_each_dev(NULL, i2c_dev_detach_adapter); class_destroy(i2c_dev_class); unregister_chrdev_region(MKDEV(I2C_MAJOR, 0), I2C_MINORS); } From 42d0c4bdf753063b6eec55415003184d3ca24f6e Mon Sep 17 00:00:00 2001 From: Seth Forshee Date: Thu, 9 Mar 2023 14:39:09 -0600 Subject: [PATCH 300/778] filelocks: use mount idmapping for setlease permission check A user should be allowed to take out a lease via an idmapped mount if the fsuid matches the mapped uid of the inode. generic_setlease() is checking the unmapped inode uid, causing these operations to be denied. Fix this by comparing against the mapped inode uid instead of the unmapped uid. Fixes: 9caccd41541a ("fs: introduce MOUNT_ATTR_IDMAP") Cc: stable@vger.kernel.org Signed-off-by: Seth Forshee (DigitalOcean) Signed-off-by: Christian Brauner (Microsoft) --- fs/locks.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/locks.c b/fs/locks.c index d82c4cacdfb9..df8b26a42524 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -1863,9 +1863,10 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp, void **priv) { struct inode *inode = file_inode(filp); + vfsuid_t vfsuid = i_uid_into_vfsuid(file_mnt_idmap(filp), inode); int error; - if ((!uid_eq(current_fsuid(), inode->i_uid)) && !capable(CAP_LEASE)) + if ((!vfsuid_eq_kuid(vfsuid, current_fsuid())) && !capable(CAP_LEASE)) return -EACCES; if (!S_ISREG(inode->i_mode)) return -EINVAL; From 76950340cf03b149412fe0d5f0810e52ac1df8cb Mon Sep 17 00:00:00 2001 From: Alexandre Ghiti Date: Wed, 8 Mar 2023 10:16:39 +0100 Subject: [PATCH 301/778] riscv: Use READ_ONCE_NOCHECK in imprecise unwinding stack mode When CONFIG_FRAME_POINTER is unset, the stack unwinding function walk_stackframe randomly reads the stack and then, when KASAN is enabled, it can lead to the following backtrace: [ 0.000000] ================================================================== [ 0.000000] BUG: KASAN: stack-out-of-bounds in walk_stackframe+0xa6/0x11a [ 0.000000] Read of size 8 at addr ffffffff81807c40 by task swapper/0 [ 0.000000] [ 0.000000] CPU: 0 PID: 0 Comm: swapper Not tainted 6.2.0-12919-g24203e6db61f #43 [ 0.000000] Hardware name: riscv-virtio,qemu (DT) [ 0.000000] Call Trace: [ 0.000000] [] walk_stackframe+0x0/0x11a [ 0.000000] [] init_param_lock+0x26/0x2a [ 0.000000] [] walk_stackframe+0xa2/0x11a [ 0.000000] [] dump_stack_lvl+0x22/0x36 [ 0.000000] [] print_report+0x198/0x4a8 [ 0.000000] [] init_param_lock+0x26/0x2a [ 0.000000] [] walk_stackframe+0xa2/0x11a [ 0.000000] [] kasan_report+0x9a/0xc8 [ 0.000000] [] walk_stackframe+0xa2/0x11a [ 0.000000] [] walk_stackframe+0xa2/0x11a [ 0.000000] [] desc_make_final+0x80/0x84 [ 0.000000] [] stack_trace_save+0x88/0xa6 [ 0.000000] [] filter_irq_stacks+0x72/0x76 [ 0.000000] [] devkmsg_read+0x32a/0x32e [ 0.000000] [] kasan_save_stack+0x28/0x52 [ 0.000000] [] desc_make_final+0x7c/0x84 [ 0.000000] [] stack_trace_save+0x84/0xa6 [ 0.000000] [] kasan_set_track+0x12/0x20 [ 0.000000] [] __kasan_slab_alloc+0x58/0x5e [ 0.000000] [] __kmem_cache_create+0x21e/0x39a [ 0.000000] [] create_boot_cache+0x70/0x9c [ 0.000000] [] kmem_cache_init+0x6c/0x11e [ 0.000000] [] mm_init+0xd8/0xfe [ 0.000000] [] start_kernel+0x190/0x3ca [ 0.000000] [ 0.000000] The buggy address belongs to stack of task swapper/0 [ 0.000000] and is located at offset 0 in frame: [ 0.000000] stack_trace_save+0x0/0xa6 [ 0.000000] [ 0.000000] This frame has 1 object: [ 0.000000] [32, 56) 'c' [ 0.000000] [ 0.000000] The buggy address belongs to the physical page: [ 0.000000] page:(____ptrval____) refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x81a07 [ 0.000000] flags: 0x1000(reserved|zone=0) [ 0.000000] raw: 0000000000001000 ff600003f1e3d150 ff600003f1e3d150 0000000000000000 [ 0.000000] raw: 0000000000000000 0000000000000000 00000001ffffffff [ 0.000000] page dumped because: kasan: bad access detected [ 0.000000] [ 0.000000] Memory state around the buggy address: [ 0.000000] ffffffff81807b00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [ 0.000000] ffffffff81807b80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [ 0.000000] >ffffffff81807c00: 00 00 00 00 00 00 00 00 f1 f1 f1 f1 00 00 00 f3 [ 0.000000] ^ [ 0.000000] ffffffff81807c80: f3 f3 f3 f3 00 00 00 00 00 00 00 00 00 00 00 00 [ 0.000000] ffffffff81807d00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [ 0.000000] ================================================================== Fix that by using READ_ONCE_NOCHECK when reading the stack in imprecise mode. Fixes: 5d8544e2d007 ("RISC-V: Generic library routines and assembly") Reported-by: Chathura Rajapaksha Link: https://lore.kernel.org/all/CAD7mqryDQCYyJ1gAmtMm8SASMWAQ4i103ptTb0f6Oda=tPY2=A@mail.gmail.com/ Suggested-by: Dmitry Vyukov Signed-off-by: Alexandre Ghiti Link: https://lore.kernel.org/r/20230308091639.602024-1-alexghiti@rivosinc.com Signed-off-by: Palmer Dabbelt --- arch/riscv/kernel/stacktrace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/riscv/kernel/stacktrace.c b/arch/riscv/kernel/stacktrace.c index f9a5a7c90ff0..64a9c093aef9 100644 --- a/arch/riscv/kernel/stacktrace.c +++ b/arch/riscv/kernel/stacktrace.c @@ -101,7 +101,7 @@ void notrace walk_stackframe(struct task_struct *task, while (!kstack_end(ksp)) { if (__kernel_text_address(pc) && unlikely(!fn(arg, pc))) break; - pc = (*ksp++) - 0x4; + pc = READ_ONCE_NOCHECK(*ksp++) - 0x4; } } From 2a8db5ec4a28a0fce822d10224db9471a44b6925 Mon Sep 17 00:00:00 2001 From: Conor Dooley Date: Fri, 3 Mar 2023 14:37:55 +0000 Subject: [PATCH 302/778] RISC-V: Don't check text_mutex during stop_machine We're currently using stop_machine() to update ftrace & kprobes, which means that the thread that takes text_mutex during may not be the same as the thread that eventually patches the code. This isn't actually a race because the lock is still held (preventing any other concurrent accesses) and there is only one thread running during stop_machine(), but it does trigger a lockdep failure. This patch just elides the lockdep check during stop_machine. Fixes: c15ac4fd60d5 ("riscv/ftrace: Add dynamic function tracer support") Suggested-by: Steven Rostedt Reported-by: Changbin Du Signed-off-by: Palmer Dabbelt Signed-off-by: Conor Dooley Link: https://lore.kernel.org/r/20230303143754.4005217-1-conor.dooley@microchip.com Signed-off-by: Palmer Dabbelt --- arch/riscv/include/asm/ftrace.h | 2 +- arch/riscv/include/asm/patch.h | 2 ++ arch/riscv/kernel/ftrace.c | 13 +++++++++++-- arch/riscv/kernel/patch.c | 28 +++++++++++++++++++++++++--- 4 files changed, 39 insertions(+), 6 deletions(-) diff --git a/arch/riscv/include/asm/ftrace.h b/arch/riscv/include/asm/ftrace.h index 9e73922e1e2e..d47d87c2d7e3 100644 --- a/arch/riscv/include/asm/ftrace.h +++ b/arch/riscv/include/asm/ftrace.h @@ -109,6 +109,6 @@ int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec); #define ftrace_init_nop ftrace_init_nop #endif -#endif +#endif /* CONFIG_DYNAMIC_FTRACE */ #endif /* _ASM_RISCV_FTRACE_H */ diff --git a/arch/riscv/include/asm/patch.h b/arch/riscv/include/asm/patch.h index f433121774c0..63c98833d510 100644 --- a/arch/riscv/include/asm/patch.h +++ b/arch/riscv/include/asm/patch.h @@ -9,4 +9,6 @@ int patch_text_nosync(void *addr, const void *insns, size_t len); int patch_text(void *addr, u32 *insns, int ninsns); +extern int riscv_patch_in_stop_machine; + #endif /* _ASM_RISCV_PATCH_H */ diff --git a/arch/riscv/kernel/ftrace.c b/arch/riscv/kernel/ftrace.c index 5bff37af4770..03a6434a8cdd 100644 --- a/arch/riscv/kernel/ftrace.c +++ b/arch/riscv/kernel/ftrace.c @@ -15,10 +15,19 @@ void ftrace_arch_code_modify_prepare(void) __acquires(&text_mutex) { mutex_lock(&text_mutex); + + /* + * The code sequences we use for ftrace can't be patched while the + * kernel is running, so we need to use stop_machine() to modify them + * for now. This doesn't play nice with text_mutex, we use this flag + * to elide the check. + */ + riscv_patch_in_stop_machine = true; } void ftrace_arch_code_modify_post_process(void) __releases(&text_mutex) { + riscv_patch_in_stop_machine = false; mutex_unlock(&text_mutex); } @@ -107,9 +116,9 @@ int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec) { int out; - ftrace_arch_code_modify_prepare(); + mutex_lock(&text_mutex); out = ftrace_make_nop(mod, rec, MCOUNT_ADDR); - ftrace_arch_code_modify_post_process(); + mutex_unlock(&text_mutex); return out; } diff --git a/arch/riscv/kernel/patch.c b/arch/riscv/kernel/patch.c index 8086d1a281cd..575e71d6c8ae 100644 --- a/arch/riscv/kernel/patch.c +++ b/arch/riscv/kernel/patch.c @@ -11,6 +11,7 @@ #include #include #include +#include #include struct patch_insn { @@ -20,6 +21,8 @@ struct patch_insn { atomic_t cpu_count; }; +int riscv_patch_in_stop_machine = false; + #ifdef CONFIG_MMU /* * The fix_to_virt(, idx) needs a const value (not a dynamic variable of @@ -60,8 +63,15 @@ static int patch_insn_write(void *addr, const void *insn, size_t len) * Before reaching here, it was expected to lock the text_mutex * already, so we don't need to give another lock here and could * ensure that it was safe between each cores. + * + * We're currently using stop_machine() for ftrace & kprobes, and while + * that ensures text_mutex is held before installing the mappings it + * does not ensure text_mutex is held by the calling thread. That's + * safe but triggers a lockdep failure, so just elide it for that + * specific case. */ - lockdep_assert_held(&text_mutex); + if (!riscv_patch_in_stop_machine) + lockdep_assert_held(&text_mutex); if (across_pages) patch_map(addr + len, FIX_TEXT_POKE1); @@ -125,6 +135,7 @@ NOKPROBE_SYMBOL(patch_text_cb); int patch_text(void *addr, u32 *insns, int ninsns) { + int ret; struct patch_insn patch = { .addr = addr, .insns = insns, @@ -132,7 +143,18 @@ int patch_text(void *addr, u32 *insns, int ninsns) .cpu_count = ATOMIC_INIT(0), }; - return stop_machine_cpuslocked(patch_text_cb, - &patch, cpu_online_mask); + /* + * kprobes takes text_mutex, before calling patch_text(), but as we call + * calls stop_machine(), the lockdep assertion in patch_insn_write() + * gets confused by the context in which the lock is taken. + * Instead, ensure the lock is held before calling stop_machine(), and + * set riscv_patch_in_stop_machine to skip the check in + * patch_insn_write(). + */ + lockdep_assert_held(&text_mutex); + riscv_patch_in_stop_machine = true; + ret = stop_machine_cpuslocked(patch_text_cb, &patch, cpu_online_mask); + riscv_patch_in_stop_machine = false; + return ret; } NOKPROBE_SYMBOL(patch_text); From 93bb18d2a873d2fa9625c8ea927723660a868b95 Mon Sep 17 00:00:00 2001 From: lyndonli Date: Thu, 2 Mar 2023 14:18:12 +0800 Subject: [PATCH 303/778] drm/amdgpu: Fix call trace warning and hang when removing amdgpu device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On GPUs with RAS enabled, below call trace and hang are observed when shutting down device. v2: use DRM device unplugged flag instead of shutdown flag as the check to prevent memory wipe in shutdown stage. [ +0.000000] RIP: 0010:amdgpu_vram_mgr_fini+0x18d/0x1c0 [amdgpu] [ +0.000001] PKRU: 55555554 [ +0.000001] Call Trace: [ +0.000001] [ +0.000002] amdgpu_ttm_fini+0x140/0x1c0 [amdgpu] [ +0.000183] amdgpu_bo_fini+0x27/0xa0 [amdgpu] [ +0.000184] gmc_v11_0_sw_fini+0x2b/0x40 [amdgpu] [ +0.000163] amdgpu_device_fini_sw+0xb6/0x510 [amdgpu] [ +0.000152] amdgpu_driver_release_kms+0x16/0x30 [amdgpu] [ +0.000090] drm_dev_release+0x28/0x50 [drm] [ +0.000016] devm_drm_dev_init_release+0x38/0x60 [drm] [ +0.000011] devm_action_release+0x15/0x20 [ +0.000003] release_nodes+0x40/0xc0 [ +0.000001] devres_release_all+0x9e/0xe0 [ +0.000001] device_unbind_cleanup+0x12/0x80 [ +0.000003] device_release_driver_internal+0xff/0x160 [ +0.000001] driver_detach+0x4a/0x90 [ +0.000001] bus_remove_driver+0x6c/0xf0 [ +0.000001] driver_unregister+0x31/0x50 [ +0.000001] pci_unregister_driver+0x40/0x90 [ +0.000003] amdgpu_exit+0x15/0x120 [amdgpu] Signed-off-by: lyndonli Reviewed-by: Guchun Chen Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index e3e1ed4314dd..6c7d672412b2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -1315,7 +1315,7 @@ void amdgpu_bo_release_notify(struct ttm_buffer_object *bo) if (!bo->resource || bo->resource->mem_type != TTM_PL_VRAM || !(abo->flags & AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE) || - adev->in_suspend || adev->shutdown) + adev->in_suspend || drm_dev_is_unplugged(adev_to_drm(adev))) return; if (WARN_ON_ONCE(!dma_resv_trylock(bo->base.resv))) From 1717cc5f2962a4652c76ed3858b499ccae6c277c Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Wed, 1 Mar 2023 09:36:06 -0600 Subject: [PATCH 304/778] drm/amd: Fix initialization mistake for NBIO 7.3.0 The same strapping initialization issue that happened on NBIO 7.5.1 appears to be happening on NBIO 7.3.0. Apply the same fix to 7.3.0 as well. Note: This workaround relies upon the integrated GPU being enabled in BIOS. If the integrated GPU is disabled in BIOS a different workaround will be required. Reported-by: Thomas Glanzmann Cc: Basavaraj Natikar Link: https://lore.kernel.org/linux-usb/Y%2Fz9GdHjPyF2rNG3@glanzmann.de/T/#u Signed-off-by: Mario Limonciello Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/nbio_v7_2.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v7_2.c b/drivers/gpu/drm/amd/amdgpu/nbio_v7_2.c index 4b0d563c6522..4ef1fa4603c8 100644 --- a/drivers/gpu/drm/amd/amdgpu/nbio_v7_2.c +++ b/drivers/gpu/drm/amd/amdgpu/nbio_v7_2.c @@ -382,11 +382,6 @@ static void nbio_v7_2_init_registers(struct amdgpu_device *adev) if (def != data) WREG32_PCIE_PORT(SOC15_REG_OFFSET(NBIO, 0, regBIF1_PCIE_MST_CTRL_3), data); break; - case IP_VERSION(7, 5, 1): - data = RREG32_SOC15(NBIO, 0, regRCC_DEV2_EPF0_STRAP2); - data &= ~RCC_DEV2_EPF0_STRAP2__STRAP_NO_SOFT_RESET_DEV2_F0_MASK; - WREG32_SOC15(NBIO, 0, regRCC_DEV2_EPF0_STRAP2, data); - fallthrough; default: def = data = RREG32_PCIE_PORT(SOC15_REG_OFFSET(NBIO, 0, regPCIE_CONFIG_CNTL)); data = REG_SET_FIELD(data, PCIE_CONFIG_CNTL, @@ -399,6 +394,15 @@ static void nbio_v7_2_init_registers(struct amdgpu_device *adev) break; } + switch (adev->ip_versions[NBIO_HWIP][0]) { + case IP_VERSION(7, 3, 0): + case IP_VERSION(7, 5, 1): + data = RREG32_SOC15(NBIO, 0, regRCC_DEV2_EPF0_STRAP2); + data &= ~RCC_DEV2_EPF0_STRAP2__STRAP_NO_SOFT_RESET_DEV2_F0_MASK; + WREG32_SOC15(NBIO, 0, regRCC_DEV2_EPF0_STRAP2, data); + break; + } + if (amdgpu_sriov_vf(adev)) adev->rmmio_remap.reg_offset = SOC15_REG_OFFSET(NBIO, 0, regBIF_BX_PF0_HDP_MEM_COHERENCY_FLUSH_CNTL) << 2; From 20534dbcc7b7bfb447279cdcfb0d88ee3b779a18 Mon Sep 17 00:00:00 2001 From: Shashank Sharma Date: Mon, 27 Feb 2023 15:42:28 +0100 Subject: [PATCH 305/778] drm/amdgpu: fix return value check in kfd This patch fixes a return value check in kfd doorbell handling. This function should return 0(error) only when the ida_simple_get returns < 0(error), return > 0 is a success case. Cc: Felix Kuehling Cc: Alex Deucher Fixes: 16f0013157bf ("drm/amdkfd: Allocate doorbells only when needed") Acked-by: Christian Koenig Reviewed-by: Felix Kuehling Signed-off-by: Shashank Sharma Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c b/drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c index cbef2e147da5..38c9e1ca6691 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c @@ -280,7 +280,7 @@ phys_addr_t kfd_get_process_doorbells(struct kfd_process_device *pdd) if (!pdd->doorbell_index) { int r = kfd_alloc_process_doorbells(pdd->dev, &pdd->doorbell_index); - if (r) + if (r < 0) return 0; } From 8879ec6dfdcdcca7718eeb4a584805eb205288bf Mon Sep 17 00:00:00 2001 From: lyndonli Date: Fri, 3 Mar 2023 14:55:05 +0800 Subject: [PATCH 306/778] drm/amdgpu: Fix the warning info when removing amdgpu device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Actually, the drm_dev_enter in psp_cmd_submit_buf does not protect anything. If DRM device is unplugged, it will always check the condition in WARN_ON. So drop drm_dev_enter and drm_dev_exit in psp_cmd_submit_buf. When removing amdgpu, the calling order is as follows: amdgpu_pci_remove drm_dev_unplug amdgpu_driver_unload_kms amdgpu_device_fini_hw amdgpu_device_ip_fini_early psp_hw_fini psp_ras_terminate psp_ta_unloadye psp_cmd_submit_buf [ 4507.740388] Call Trace: [ 4507.740389] [ 4507.740391] psp_ta_unload+0x44/0x70 [amdgpu] [ 4507.740485] psp_ras_terminate+0x4d/0x70 [amdgpu] [ 4507.740575] psp_hw_fini+0x28/0xa0 [amdgpu] [ 4507.740662] amdgpu_device_fini_hw+0x328/0x442 [amdgpu] [ 4507.740791] amdgpu_driver_unload_kms+0x51/0x60 [amdgpu] [ 4507.740875] amdgpu_pci_remove+0x5a/0x140 [amdgpu] [ 4507.740962] ? _raw_spin_unlock_irqrestore+0x27/0x43 [ 4507.740965] ? __pm_runtime_resume+0x60/0x90 [ 4507.740968] pci_device_remove+0x39/0xb0 [ 4507.740971] device_remove+0x46/0x70 [ 4507.740972] device_release_driver_internal+0xd1/0x160 [ 4507.740974] driver_detach+0x4a/0x90 [ 4507.740975] bus_remove_driver+0x6c/0xf0 [ 4507.740976] driver_unregister+0x31/0x50 [ 4507.740977] pci_unregister_driver+0x40/0x90 [ 4507.740978] amdgpu_exit+0x15/0x120 [amdgpu] v2: fix commit message style issue Signed-off-by: lyndonli Reviewed-by: Guchun Chen Acked-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index 28fe6d941054..3f5d13035aff 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -602,27 +602,14 @@ psp_cmd_submit_buf(struct psp_context *psp, struct psp_gfx_cmd_resp *cmd, uint64_t fence_mc_addr) { int ret; - int index, idx; + int index; int timeout = 20000; bool ras_intr = false; bool skip_unsupport = false; - bool dev_entered; if (psp->adev->no_hw_access) return 0; - dev_entered = drm_dev_enter(adev_to_drm(psp->adev), &idx); - /* - * We allow sending PSP messages LOAD_ASD and UNLOAD_TA without acquiring - * a lock in drm_dev_enter during driver unload because we must call - * drm_dev_unplug as the beginning of unload driver sequence . It is very - * crucial that userspace can't access device instances anymore. - */ - if (!dev_entered) - WARN_ON(psp->cmd_buf_mem->cmd_id != GFX_CMD_ID_LOAD_ASD && - psp->cmd_buf_mem->cmd_id != GFX_CMD_ID_UNLOAD_TA && - psp->cmd_buf_mem->cmd_id != GFX_CMD_ID_INVOKE_CMD); - memset(psp->cmd_buf_mem, 0, PSP_CMD_BUFFER_SIZE); memcpy(psp->cmd_buf_mem, cmd, sizeof(struct psp_gfx_cmd_resp)); @@ -686,8 +673,6 @@ psp_cmd_submit_buf(struct psp_context *psp, } exit: - if (dev_entered) - drm_dev_exit(idx); return ret; } From 0dcdf8498eae2727bb33cef3576991dc841d4343 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 6 Mar 2023 10:34:20 -0500 Subject: [PATCH 307/778] drm/amdgpu: fix error checking in amdgpu_read_mm_registers for soc15 Properly skip non-existent registers as well. Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/2442 Reviewed-by: Hawking Zhang Reviewed-by: Evan Quan Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdgpu/soc15.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c index 7cd17dda32ce..2eddd7f6cd41 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc15.c +++ b/drivers/gpu/drm/amd/amdgpu/soc15.c @@ -439,8 +439,9 @@ static int soc15_read_register(struct amdgpu_device *adev, u32 se_num, *value = 0; for (i = 0; i < ARRAY_SIZE(soc15_allowed_read_registers); i++) { en = &soc15_allowed_read_registers[i]; - if (adev->reg_offset[en->hwip][en->inst] && - reg_offset != (adev->reg_offset[en->hwip][en->inst][en->seg] + if (!adev->reg_offset[en->hwip][en->inst]) + continue; + else if (reg_offset != (adev->reg_offset[en->hwip][en->inst][en->seg] + en->reg_offset)) continue; From 2915e43a033a778816fa4bc621f033576796521e Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 6 Mar 2023 10:35:34 -0500 Subject: [PATCH 308/778] drm/amdgpu: fix error checking in amdgpu_read_mm_registers for soc21 Properly skip non-existent registers as well. Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/2442 Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdgpu/soc21.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/soc21.c b/drivers/gpu/drm/amd/amdgpu/soc21.c index 620f7409825d..9df2236007ab 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc21.c +++ b/drivers/gpu/drm/amd/amdgpu/soc21.c @@ -291,9 +291,10 @@ static int soc21_read_register(struct amdgpu_device *adev, u32 se_num, *value = 0; for (i = 0; i < ARRAY_SIZE(soc21_allowed_read_registers); i++) { en = &soc21_allowed_read_registers[i]; - if (adev->reg_offset[en->hwip][en->inst] && - reg_offset != (adev->reg_offset[en->hwip][en->inst][en->seg] - + en->reg_offset)) + if (!adev->reg_offset[en->hwip][en->inst]) + continue; + else if (reg_offset != (adev->reg_offset[en->hwip][en->inst][en->seg] + + en->reg_offset)) continue; *value = soc21_get_register_value(adev, From b42fee5e0b44344cfe4c38e61341ee250362c83f Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 7 Mar 2023 08:59:13 -0500 Subject: [PATCH 309/778] drm/amdgpu: fix error checking in amdgpu_read_mm_registers for nv Properly skip non-existent registers as well. Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/2442 Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdgpu/nv.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/nv.c b/drivers/gpu/drm/amd/amdgpu/nv.c index d972025f0d20..855d390c41de 100644 --- a/drivers/gpu/drm/amd/amdgpu/nv.c +++ b/drivers/gpu/drm/amd/amdgpu/nv.c @@ -444,9 +444,10 @@ static int nv_read_register(struct amdgpu_device *adev, u32 se_num, *value = 0; for (i = 0; i < ARRAY_SIZE(nv_allowed_read_registers); i++) { en = &nv_allowed_read_registers[i]; - if (adev->reg_offset[en->hwip][en->inst] && - reg_offset != (adev->reg_offset[en->hwip][en->inst][en->seg] - + en->reg_offset)) + if (!adev->reg_offset[en->hwip][en->inst]) + continue; + else if (reg_offset != (adev->reg_offset[en->hwip][en->inst][en->seg] + + en->reg_offset)) continue; *value = nv_get_register_value(adev, From 6ce2ea07c5ff0a8188eab0e5cd1f0e4899b36835 Mon Sep 17 00:00:00 2001 From: Veerabadhran Gopalakrishnan Date: Wed, 8 Mar 2023 19:33:53 +0530 Subject: [PATCH 310/778] drm/amdgpu/soc21: Add video cap query support for VCN_4_0_4 Added the video capability query support for VCN version 4_0_4 Signed-off-by: Veerabadhran Gopalakrishnan Reviewed-by: Leo Liu Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org # 6.1.x --- drivers/gpu/drm/amd/amdgpu/soc21.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/amdgpu/soc21.c b/drivers/gpu/drm/amd/amdgpu/soc21.c index 9df2236007ab..061793d390cc 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc21.c +++ b/drivers/gpu/drm/amd/amdgpu/soc21.c @@ -111,6 +111,7 @@ static int soc21_query_video_codecs(struct amdgpu_device *adev, bool encode, switch (adev->ip_versions[UVD_HWIP][0]) { case IP_VERSION(4, 0, 0): case IP_VERSION(4, 0, 2): + case IP_VERSION(4, 0, 4): if (adev->vcn.harvest_config & AMDGPU_VCN_HARVEST_VCN0) { if (encode) *codecs = &vcn_4_0_0_video_codecs_encode_vcn1; From 609d54441493c99f21c1823dfd66fa7f4c512ff4 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Mon, 6 Mar 2023 13:54:50 -0500 Subject: [PATCH 311/778] fs: prevent out-of-bounds array speculation when closing a file descriptor Google-Bug-Id: 114199369 Signed-off-by: Theodore Ts'o Signed-off-by: Al Viro --- fs/file.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/file.c b/fs/file.c index c942c89ca4cd..7893ea161d77 100644 --- a/fs/file.c +++ b/fs/file.c @@ -642,6 +642,7 @@ static struct file *pick_file(struct files_struct *files, unsigned fd) if (fd >= fdt->max_fds) return NULL; + fd = array_index_nospec(fd, fdt->max_fds); file = fdt->fd[fd]; if (file) { rcu_assign_pointer(fdt->fd[fd], NULL); From 75034eb5e4c267d4ab93085b5d6fa3dab2535b34 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 10 Mar 2023 15:34:54 +0200 Subject: [PATCH 312/778] ASoC: SOF: Intel: MTL: Don't access EM2 This reverts commit 2b5a30cafb2ef ("ASoC: SOF: Intel: MTL: Enable DMI L1"). It came to our attention that the access to the EM2 register is restricted to the DSP side on MTL compared to prior platforms. Writing to it from the host side has no effect (negative or positive), it is better to remove the code to not cause confusion and wrong impression. Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230310133454.15362-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/mtl.c | 3 --- sound/soc/sof/intel/mtl.h | 2 -- 2 files changed, 5 deletions(-) diff --git a/sound/soc/sof/intel/mtl.c b/sound/soc/sof/intel/mtl.c index 8f0ed1cbf3b5..58959c24cb71 100644 --- a/sound/soc/sof/intel/mtl.c +++ b/sound/soc/sof/intel/mtl.c @@ -280,9 +280,6 @@ static int mtl_dsp_post_fw_run(struct snd_sof_dev *sdev) } hda_sdw_int_enable(sdev, true); - - /* enable DMI L1 */ - snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, MTL_EM2, MTL_EM2_L1SEN, MTL_EM2_L1SEN); return 0; } diff --git a/sound/soc/sof/intel/mtl.h b/sound/soc/sof/intel/mtl.h index ddc05304a9d5..26418fb08807 100644 --- a/sound/soc/sof/intel/mtl.h +++ b/sound/soc/sof/intel/mtl.h @@ -28,8 +28,6 @@ #define MTL_HFINTIPPTR_PTR_MASK GENMASK(20, 0) #define MTL_HDA_VS_D0I3C 0x1D4A -#define MTL_EM2 0x1c44 -#define MTL_EM2_L1SEN BIT(13) #define MTL_DSP2CXCAP_PRIMARY_CORE 0x178D00 #define MTL_DSP2CXCTL_PRIMARY_CORE 0x178D04 From 1dcdce5919115a471bf4921a57f20050c545a236 Mon Sep 17 00:00:00 2001 From: Ye Bin Date: Tue, 7 Mar 2023 09:52:52 +0800 Subject: [PATCH 313/778] ext4: move where set the MAY_INLINE_DATA flag is set The only caller of ext4_find_inline_data_nolock() that needs setting of EXT4_STATE_MAY_INLINE_DATA flag is ext4_iget_extra_inode(). In ext4_write_inline_data_end() we just need to update inode->i_inline_off. Since we are going to add one more caller that does not need to set EXT4_STATE_MAY_INLINE_DATA, just move setting of EXT4_STATE_MAY_INLINE_DATA out to ext4_iget_extra_inode(). Signed-off-by: Ye Bin Cc: stable@kernel.org Reviewed-by: Jan Kara Link: https://lore.kernel.org/r/20230307015253.2232062-2-yebin@huaweicloud.com Signed-off-by: Theodore Ts'o --- fs/ext4/inline.c | 1 - fs/ext4/inode.c | 7 ++++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c index 2b42ececa46d..1602d74b5eeb 100644 --- a/fs/ext4/inline.c +++ b/fs/ext4/inline.c @@ -159,7 +159,6 @@ int ext4_find_inline_data_nolock(struct inode *inode) (void *)ext4_raw_inode(&is.iloc)); EXT4_I(inode)->i_inline_size = EXT4_MIN_INLINE_DATA_SIZE + le32_to_cpu(is.s.here->e_value_size); - ext4_set_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA); } out: brelse(is.iloc.bh); diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index b65dadfe3b45..530e420ae0e8 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -4797,8 +4797,13 @@ static inline int ext4_iget_extra_inode(struct inode *inode, if (EXT4_INODE_HAS_XATTR_SPACE(inode) && *magic == cpu_to_le32(EXT4_XATTR_MAGIC)) { + int err; + ext4_set_inode_state(inode, EXT4_STATE_XATTR); - return ext4_find_inline_data_nolock(inode); + err = ext4_find_inline_data_nolock(inode); + if (!err && ext4_has_inline_data(inode)) + ext4_set_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA); + return err; } else EXT4_I(inode)->i_inline_off = 0; return 0; From 2b96b4a5d9443ca4cad58b0040be455803c05a42 Mon Sep 17 00:00:00 2001 From: Ye Bin Date: Tue, 7 Mar 2023 09:52:53 +0800 Subject: [PATCH 314/778] ext4: fix WARNING in ext4_update_inline_data Syzbot found the following issue: EXT4-fs (loop0): mounted filesystem 00000000-0000-0000-0000-000000000000 without journal. Quota mode: none. fscrypt: AES-256-CTS-CBC using implementation "cts-cbc-aes-aesni" fscrypt: AES-256-XTS using implementation "xts-aes-aesni" ------------[ cut here ]------------ WARNING: CPU: 0 PID: 5071 at mm/page_alloc.c:5525 __alloc_pages+0x30a/0x560 mm/page_alloc.c:5525 Modules linked in: CPU: 1 PID: 5071 Comm: syz-executor263 Not tainted 6.2.0-rc1-syzkaller #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/26/2022 RIP: 0010:__alloc_pages+0x30a/0x560 mm/page_alloc.c:5525 RSP: 0018:ffffc90003c2f1c0 EFLAGS: 00010246 RAX: ffffc90003c2f220 RBX: 0000000000000014 RCX: 0000000000000000 RDX: 0000000000000028 RSI: 0000000000000000 RDI: ffffc90003c2f248 RBP: ffffc90003c2f2d8 R08: dffffc0000000000 R09: ffffc90003c2f220 R10: fffff52000785e49 R11: 1ffff92000785e44 R12: 0000000000040d40 R13: 1ffff92000785e40 R14: dffffc0000000000 R15: 1ffff92000785e3c FS: 0000555556c0d300(0000) GS:ffff8880b9800000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f95d5e04138 CR3: 00000000793aa000 CR4: 00000000003506f0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: __alloc_pages_node include/linux/gfp.h:237 [inline] alloc_pages_node include/linux/gfp.h:260 [inline] __kmalloc_large_node+0x95/0x1e0 mm/slab_common.c:1113 __do_kmalloc_node mm/slab_common.c:956 [inline] __kmalloc+0xfe/0x190 mm/slab_common.c:981 kmalloc include/linux/slab.h:584 [inline] kzalloc include/linux/slab.h:720 [inline] ext4_update_inline_data+0x236/0x6b0 fs/ext4/inline.c:346 ext4_update_inline_dir fs/ext4/inline.c:1115 [inline] ext4_try_add_inline_entry+0x328/0x990 fs/ext4/inline.c:1307 ext4_add_entry+0x5a4/0xeb0 fs/ext4/namei.c:2385 ext4_add_nondir+0x96/0x260 fs/ext4/namei.c:2772 ext4_create+0x36c/0x560 fs/ext4/namei.c:2817 lookup_open fs/namei.c:3413 [inline] open_last_lookups fs/namei.c:3481 [inline] path_openat+0x12ac/0x2dd0 fs/namei.c:3711 do_filp_open+0x264/0x4f0 fs/namei.c:3741 do_sys_openat2+0x124/0x4e0 fs/open.c:1310 do_sys_open fs/open.c:1326 [inline] __do_sys_openat fs/open.c:1342 [inline] __se_sys_openat fs/open.c:1337 [inline] __x64_sys_openat+0x243/0x290 fs/open.c:1337 do_syscall_x64 arch/x86/entry/common.c:50 [inline] do_syscall_64+0x3d/0xb0 arch/x86/entry/common.c:80 entry_SYSCALL_64_after_hwframe+0x63/0xcd Above issue happens as follows: ext4_iget ext4_find_inline_data_nolock ->i_inline_off=164 i_inline_size=60 ext4_try_add_inline_entry __ext4_mark_inode_dirty ext4_expand_extra_isize_ea ->i_extra_isize=32 s_want_extra_isize=44 ext4_xattr_shift_entries ->after shift i_inline_off is incorrect, actually is change to 176 ext4_try_add_inline_entry ext4_update_inline_dir get_max_inline_xattr_value_size if (EXT4_I(inode)->i_inline_off) entry = (struct ext4_xattr_entry *)((void *)raw_inode + EXT4_I(inode)->i_inline_off); free += EXT4_XATTR_SIZE(le32_to_cpu(entry->e_value_size)); ->As entry is incorrect, then 'free' may be negative ext4_update_inline_data value = kzalloc(len, GFP_NOFS); -> len is unsigned int, maybe very large, then trigger warning when 'kzalloc()' To resolve the above issue we need to update 'i_inline_off' after 'ext4_xattr_shift_entries()'. We do not need to set EXT4_STATE_MAY_INLINE_DATA flag here, since ext4_mark_inode_dirty() already sets this flag if needed. Setting EXT4_STATE_MAY_INLINE_DATA when it is needed may trigger a BUG_ON in ext4_writepages(). Reported-by: syzbot+d30838395804afc2fa6f@syzkaller.appspotmail.com Cc: stable@kernel.org Signed-off-by: Ye Bin Reviewed-by: Jan Kara Link: https://lore.kernel.org/r/20230307015253.2232062-3-yebin@huaweicloud.com Signed-off-by: Theodore Ts'o --- fs/ext4/xattr.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index 863c15388848..2a006e4db467 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c @@ -2851,6 +2851,9 @@ shift: (void *)header, total_ino); EXT4_I(inode)->i_extra_isize = new_extra_isize; + if (ext4_has_inline_data(inode)) + error = ext4_find_inline_data_nolock(inode); + cleanup: if (error && (mnt_count != le16_to_cpu(sbi->s_es->s_mnt_count))) { ext4_warning(inode->i_sb, "Unable to expand inode %lu. Delete some EAs or run e2fsck.", From 62913ae96de747091c4dacd06d158e7729c1a76d Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Tue, 7 Mar 2023 23:15:49 -0500 Subject: [PATCH 315/778] ext4, jbd2: add an optimized bmap for the journal inode The generic bmap() function exported by the VFS takes locks and does checks that are not necessary for the journal inode. So allow the file system to set a journal-optimized bmap function in journal->j_bmap. Reported-by: syzbot+9543479984ae9e576000@syzkaller.appspotmail.com Link: https://syzkaller.appspot.com/bug?id=e4aaa78795e490421c79f76ec3679006c8ff4cf0 Signed-off-by: Theodore Ts'o --- fs/ext4/super.c | 23 +++++++++++++++++++++++ fs/jbd2/journal.c | 9 ++++++--- include/linux/jbd2.h | 8 ++++++++ 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 2192b4111442..46b7345d2b6a 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -5742,6 +5742,28 @@ static struct inode *ext4_get_journal_inode(struct super_block *sb, return journal_inode; } +static int ext4_journal_bmap(journal_t *journal, sector_t *block) +{ + struct ext4_map_blocks map; + int ret; + + if (journal->j_inode == NULL) + return 0; + + map.m_lblk = *block; + map.m_len = 1; + ret = ext4_map_blocks(NULL, journal->j_inode, &map, 0); + if (ret <= 0) { + ext4_msg(journal->j_inode->i_sb, KERN_CRIT, + "journal bmap failed: block %llu ret %d\n", + *block, ret); + jbd2_journal_abort(journal, ret ? ret : -EIO); + return ret; + } + *block = map.m_pblk; + return 0; +} + static journal_t *ext4_get_journal(struct super_block *sb, unsigned int journal_inum) { @@ -5762,6 +5784,7 @@ static journal_t *ext4_get_journal(struct super_block *sb, return NULL; } journal->j_private = sb; + journal->j_bmap = ext4_journal_bmap; ext4_init_journal_params(sb, journal); return journal; } diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index 2696f43e7239..c84f588fdcd0 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c @@ -970,10 +970,13 @@ int jbd2_journal_bmap(journal_t *journal, unsigned long blocknr, { int err = 0; unsigned long long ret; - sector_t block = 0; + sector_t block = blocknr; - if (journal->j_inode) { - block = blocknr; + if (journal->j_bmap) { + err = journal->j_bmap(journal, &block); + if (err == 0) + *retp = block; + } else if (journal->j_inode) { ret = bmap(journal->j_inode, &block); if (ret || !block) { diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h index 2170e0cc279d..6ffa34c51a11 100644 --- a/include/linux/jbd2.h +++ b/include/linux/jbd2.h @@ -1308,6 +1308,14 @@ struct journal_s struct buffer_head *bh, enum passtype pass, int off, tid_t expected_commit_id); + + /** + * @j_bmap: + * + * Bmap function that should be used instead of the generic + * VFS bmap function. + */ + int (*j_bmap)(struct journal_s *journal, sector_t *block); }; #define jbd2_might_wait_for_commit(j) \ From eee00237fa5ec8f704f7323b54e48cc34e2d9168 Mon Sep 17 00:00:00 2001 From: Ye Bin Date: Tue, 7 Mar 2023 14:17:02 +0800 Subject: [PATCH 316/778] ext4: commit super block if fs record error when journal record without error Now, 'es->s_state' maybe covered by recover journal. And journal errno maybe not recorded in journal sb as IO error. ext4_update_super() only update error information when 'sbi->s_add_error_count' large than zero. Then 'EXT4_ERROR_FS' flag maybe lost. To solve above issue just recover 'es->s_state' error flag after journal replay like error info. Signed-off-by: Ye Bin Reviewed-by: Baokun Li Reviewed-by: Jan Kara Link: https://lore.kernel.org/r/20230307061703.245965-2-yebin@huaweicloud.com --- fs/ext4/super.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 46b7345d2b6a..effe5e5bab71 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -5959,6 +5959,7 @@ static int ext4_load_journal(struct super_block *sb, err = jbd2_journal_wipe(journal, !really_read_only); if (!err) { char *save = kmalloc(EXT4_S_ERR_LEN, GFP_KERNEL); + if (save) memcpy(save, ((char *) es) + EXT4_S_ERR_START, EXT4_S_ERR_LEN); @@ -5967,6 +5968,14 @@ static int ext4_load_journal(struct super_block *sb, memcpy(((char *) es) + EXT4_S_ERR_START, save, EXT4_S_ERR_LEN); kfree(save); + es->s_state |= cpu_to_le16(EXT4_SB(sb)->s_mount_state & + EXT4_ERROR_FS); + /* Write out restored error information to the superblock */ + if (!bdev_read_only(sb->s_bdev)) { + int err2; + err2 = ext4_commit_super(sb); + err = err ? : err2; + } } if (err) { From f57886ca1606ba74cc4ec4eb5cbf073934ffa559 Mon Sep 17 00:00:00 2001 From: Ye Bin Date: Tue, 7 Mar 2023 14:17:03 +0800 Subject: [PATCH 317/778] ext4: make sure fs error flag setted before clear journal error Now, jounral error number maybe cleared even though ext4_commit_super() failed. This may lead to error flag miss, then fsck will miss to check file system deeply. Signed-off-by: Ye Bin Reviewed-by: Jan Kara Link: https://lore.kernel.org/r/20230307061703.245965-3-yebin@huaweicloud.com --- fs/ext4/super.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/fs/ext4/super.c b/fs/ext4/super.c index effe5e5bab71..a7495f4ef3e1 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -6205,11 +6205,13 @@ static int ext4_clear_journal_err(struct super_block *sb, errstr = ext4_decode_error(sb, j_errno, nbuf); ext4_warning(sb, "Filesystem error recorded " "from previous mount: %s", errstr); - ext4_warning(sb, "Marking fs in need of filesystem check."); EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS; es->s_state |= cpu_to_le16(EXT4_ERROR_FS); - ext4_commit_super(sb); + j_errno = ext4_commit_super(sb); + if (j_errno) + return j_errno; + ext4_warning(sb, "Marked fs in need of filesystem check."); jbd2_journal_clear_err(journal); jbd2_journal_update_sb_errno(journal); From f5361da1e60d54ec81346aee8e3d8baf1be0b762 Mon Sep 17 00:00:00 2001 From: Zhihao Cheng Date: Wed, 8 Mar 2023 11:26:43 +0800 Subject: [PATCH 318/778] ext4: zero i_disksize when initializing the bootloader inode If the boot loader inode has never been used before, the EXT4_IOC_SWAP_BOOT inode will initialize it, including setting the i_size to 0. However, if the "never before used" boot loader has a non-zero i_size, then i_disksize will be non-zero, and the inconsistency between i_size and i_disksize can trigger a kernel warning: WARNING: CPU: 0 PID: 2580 at fs/ext4/file.c:319 CPU: 0 PID: 2580 Comm: bb Not tainted 6.3.0-rc1-00004-g703695902cfa RIP: 0010:ext4_file_write_iter+0xbc7/0xd10 Call Trace: vfs_write+0x3b1/0x5c0 ksys_write+0x77/0x160 __x64_sys_write+0x22/0x30 do_syscall_64+0x39/0x80 Reproducer: 1. create corrupted image and mount it: mke2fs -t ext4 /tmp/foo.img 200 debugfs -wR "sif <5> size 25700" /tmp/foo.img mount -t ext4 /tmp/foo.img /mnt cd /mnt echo 123 > file 2. Run the reproducer program: posix_memalign(&buf, 1024, 1024) fd = open("file", O_RDWR | O_DIRECT); ioctl(fd, EXT4_IOC_SWAP_BOOT); write(fd, buf, 1024); Fix this by setting i_disksize as well as i_size to zero when initiaizing the boot loader inode. Link: https://bugzilla.kernel.org/show_bug.cgi?id=217159 Cc: stable@kernel.org Signed-off-by: Zhihao Cheng Link: https://lore.kernel.org/r/20230308032643.641113-1-chengzhihao1@huawei.com Signed-off-by: Theodore Ts'o --- fs/ext4/ioctl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index 2e8c34036313..cc17205f7f49 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c @@ -431,6 +431,7 @@ static long swap_inode_boot_loader(struct super_block *sb, ei_bl->i_flags = 0; inode_set_iversion(inode_bl, 1); i_size_write(inode_bl, 0); + EXT4_I(inode_bl)->i_disksize = inode_bl->i_size; inode_bl->i_mode = S_IFREG; if (ext4_has_feature_extents(sb)) { ext4_set_inode_flag(inode_bl, EXT4_INODE_EXTENTS); From 1e108e60a44a924e3666fa2a10b53f6c31522856 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 10 Mar 2023 08:47:31 -0600 Subject: [PATCH 319/778] ASoC: Use of_property_present() for testing DT property presence It is preferred to use typed property access functions (i.e. of_property_read_ functions) rather than low-level of_get_property/of_find_property functions for reading properties. As part of this, convert of_get_property/of_find_property calls to the recently added of_property_present() helper when we just want to test for presence of a property and nothing more. Signed-off-by: Rob Herring Link: https://lore.kernel.org/r/20230310144732.1546328-1-robh@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/lpass-macro-common.c | 2 +- sound/soc/generic/audio-graph-card.c | 2 +- sound/soc/generic/audio-graph-card2.c | 2 +- sound/soc/mxs/mxs-sgtl5000.c | 2 +- sound/soc/samsung/i2s.c | 2 +- sound/soc/sh/fsi.c | 2 +- sound/soc/stm/stm32_i2s.c | 2 +- sound/soc/stm/stm32_sai_sub.c | 4 ++-- sound/soc/tegra/tegra_asoc_machine.c | 2 +- 9 files changed, 10 insertions(+), 10 deletions(-) diff --git a/sound/soc/codecs/lpass-macro-common.c b/sound/soc/codecs/lpass-macro-common.c index 1b9082d237c1..f54baaad54d4 100644 --- a/sound/soc/codecs/lpass-macro-common.c +++ b/sound/soc/codecs/lpass-macro-common.c @@ -16,7 +16,7 @@ struct lpass_macro *lpass_macro_pds_init(struct device *dev) struct lpass_macro *l_pds; int ret; - if (!of_find_property(dev->of_node, "power-domains", NULL)) + if (!of_property_present(dev->of_node, "power-domains")) return NULL; l_pds = devm_kzalloc(dev, sizeof(*l_pds), GFP_KERNEL); diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index 5daa824a4ffc..d788f5f23a8a 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -78,7 +78,7 @@ static int graph_get_dai_id(struct device_node *ep) * only of_graph_parse_endpoint(). * We need to check "reg" property */ - if (of_get_property(ep, "reg", NULL)) + if (of_property_present(ep, "reg")) return info.id; node = of_get_parent(ep); diff --git a/sound/soc/generic/audio-graph-card2.c b/sound/soc/generic/audio-graph-card2.c index 06609a526b78..259544f64df9 100644 --- a/sound/soc/generic/audio-graph-card2.c +++ b/sound/soc/generic/audio-graph-card2.c @@ -376,7 +376,7 @@ static int graph_get_dai_id(struct device_node *ep) * only of_graph_parse_endpoint(). * We need to check "reg" property */ - if (of_get_property(ep, "reg", NULL)) + if (of_property_present(ep, "reg")) return info.id; node = of_get_parent(ep); diff --git a/sound/soc/mxs/mxs-sgtl5000.c b/sound/soc/mxs/mxs-sgtl5000.c index 746f40938675..a55e7256a4c3 100644 --- a/sound/soc/mxs/mxs-sgtl5000.c +++ b/sound/soc/mxs/mxs-sgtl5000.c @@ -150,7 +150,7 @@ static int mxs_sgtl5000_probe(struct platform_device *pdev) card->dev = &pdev->dev; - if (of_find_property(np, "audio-routing", NULL)) { + if (of_property_present(np, "audio-routing")) { card->dapm_widgets = mxs_sgtl5000_dapm_widgets; card->num_dapm_widgets = ARRAY_SIZE(mxs_sgtl5000_dapm_widgets); diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index 6f96032090de..083e278aa021 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -1289,7 +1289,7 @@ static int i2s_register_clock_provider(struct samsung_i2s_priv *priv) int ret, i; /* Register the clock provider only if it's expected in the DTB */ - if (!of_find_property(dev->of_node, "#clock-cells", NULL)) + if (!of_property_present(dev->of_node, "#clock-cells")) return 0; /* Get the RCLKSRC mux clock parent clock names */ diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index f3edc2e3d9d7..9f3f1af6349f 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c @@ -1855,7 +1855,7 @@ static void fsi_of_parse(char *name, for (i = 0; i < ARRAY_SIZE(of_parse_property); i++) { sprintf(prop, "%s,%s", name, of_parse_property[i].name); - if (of_get_property(np, prop, NULL)) + if (of_property_present(np, prop)) flags |= of_parse_property[i].val; } info->flags = flags; diff --git a/sound/soc/stm/stm32_i2s.c b/sound/soc/stm/stm32_i2s.c index f3dd9f8e621c..9dad85ecb93f 100644 --- a/sound/soc/stm/stm32_i2s.c +++ b/sound/soc/stm/stm32_i2s.c @@ -1066,7 +1066,7 @@ static int stm32_i2s_parse_dt(struct platform_device *pdev, "Could not get x11k parent clock\n"); /* Register mclk provider if requested */ - if (of_find_property(np, "#clock-cells", NULL)) { + if (of_property_present(np, "#clock-cells")) { ret = stm32_i2s_add_mclk_provider(i2s); if (ret < 0) return ret; diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c index eb31b49e6597..8ba4206f751d 100644 --- a/sound/soc/stm/stm32_sai_sub.c +++ b/sound/soc/stm/stm32_sai_sub.c @@ -1394,7 +1394,7 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev, /* Get spdif iec60958 property */ sai->spdif = false; - if (of_get_property(np, "st,iec60958", NULL)) { + if (of_property_present(np, "st,iec60958")) { if (!STM_SAI_HAS_SPDIF(sai) || sai->dir == SNDRV_PCM_STREAM_CAPTURE) { dev_err(&pdev->dev, "S/PDIF IEC60958 not supported\n"); @@ -1480,7 +1480,7 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev, return 0; /* Register mclk provider if requested */ - if (of_find_property(np, "#clock-cells", NULL)) { + if (of_property_present(np, "#clock-cells")) { ret = stm32_sai_add_mclk_provider(sai); if (ret < 0) return ret; diff --git a/sound/soc/tegra/tegra_asoc_machine.c b/sound/soc/tegra/tegra_asoc_machine.c index 78faa8bcae27..2dc1f44c5a8b 100644 --- a/sound/soc/tegra/tegra_asoc_machine.c +++ b/sound/soc/tegra/tegra_asoc_machine.c @@ -502,7 +502,7 @@ int tegra_asoc_machine_probe(struct platform_device *pdev) * If clock parents are not set in DT, configure here to use clk_out_1 * as mclk and extern1 as parent for Tegra30 and higher. */ - if (!of_find_property(dev->of_node, "assigned-clock-parents", NULL) && + if (!of_property_present(dev->of_node, "assigned-clock-parents") && !of_machine_is_compatible("nvidia,tegra20")) { struct clk *clk_out_1, *clk_extern1; From 2d2998b84330899bf88a0414f3356869be4a69eb Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 10 Mar 2023 08:47:32 -0600 Subject: [PATCH 320/778] ASoC: Use of_property_read_bool() for boolean properties It is preferred to use typed property access functions (i.e. of_property_read_ functions) rather than low-level of_get_property/of_find_property functions for reading properties. Convert reading boolean properties to to of_property_read_bool(). Signed-off-by: Rob Herring Link: https://lore.kernel.org/r/20230310144733.1546413-1-robh@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/sta32x.c | 39 +++++++++++------------ sound/soc/codecs/sta350.c | 63 +++++++++++++++++--------------------- sound/soc/codecs/tas5086.c | 2 +- sound/soc/fsl/fsl_sai.c | 12 ++++---- sound/soc/fsl/fsl_ssi.c | 2 +- sound/soc/fsl/imx-card.c | 2 +- sound/soc/sh/rcar/ssi.c | 4 +-- 7 files changed, 57 insertions(+), 67 deletions(-) diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c index 8c86b578eba8..29af9595dac1 100644 --- a/sound/soc/codecs/sta32x.c +++ b/sound/soc/codecs/sta32x.c @@ -1054,35 +1054,32 @@ static int sta32x_probe_dt(struct device *dev, struct sta32x_priv *sta32x) of_property_read_u8(np, "st,ch3-output-mapping", &pdata->ch3_output_mapping); - if (of_get_property(np, "st,fault-detect-recovery", NULL)) - pdata->fault_detect_recovery = 1; - if (of_get_property(np, "st,thermal-warning-recovery", NULL)) - pdata->thermal_warning_recovery = 1; - if (of_get_property(np, "st,thermal-warning-adjustment", NULL)) - pdata->thermal_warning_adjustment = 1; - if (of_get_property(np, "st,needs_esd_watchdog", NULL)) - pdata->needs_esd_watchdog = 1; + pdata->fault_detect_recovery = + of_property_read_bool(np, "st,fault-detect-recovery"); + pdata->thermal_warning_recovery = + of_property_read_bool(np, "st,thermal-warning-recovery"); + pdata->thermal_warning_adjustment = + of_property_read_bool(np, "st,thermal-warning-adjustment"); + pdata->needs_esd_watchdog = + of_property_read_bool(np, "st,needs_esd_watchdog"); tmp = 140; of_property_read_u16(np, "st,drop-compensation-ns", &tmp); pdata->drop_compensation_ns = clamp_t(u16, tmp, 0, 300) / 20; /* CONFE */ - if (of_get_property(np, "st,max-power-use-mpcc", NULL)) - pdata->max_power_use_mpcc = 1; - - if (of_get_property(np, "st,max-power-correction", NULL)) - pdata->max_power_correction = 1; - - if (of_get_property(np, "st,am-reduction-mode", NULL)) - pdata->am_reduction_mode = 1; - - if (of_get_property(np, "st,odd-pwm-speed-mode", NULL)) - pdata->odd_pwm_speed_mode = 1; + pdata->max_power_use_mpcc = + of_property_read_bool(np, "st,max-power-use-mpcc"); + pdata->max_power_correction = + of_property_read_bool(np, "st,max-power-correction"); + pdata->am_reduction_mode = + of_property_read_bool(np, "st,am-reduction-mode"); + pdata->odd_pwm_speed_mode = + of_property_read_bool(np, "st,odd-pwm-speed-mode"); /* CONFF */ - if (of_get_property(np, "st,invalid-input-detect-mute", NULL)) - pdata->invalid_input_detect_mute = 1; + pdata->invalid_input_detect_mute = + of_property_read_bool(np, "st,invalid-input-detect-mute"); sta32x->pdata = pdata; diff --git a/sound/soc/codecs/sta350.c b/sound/soc/codecs/sta350.c index 9ed13aeb3cbd..b033a5fcd6c0 100644 --- a/sound/soc/codecs/sta350.c +++ b/sound/soc/codecs/sta350.c @@ -1106,12 +1106,12 @@ static int sta350_probe_dt(struct device *dev, struct sta350_priv *sta350) of_property_read_u8(np, "st,ch3-output-mapping", &pdata->ch3_output_mapping); - if (of_get_property(np, "st,thermal-warning-recovery", NULL)) - pdata->thermal_warning_recovery = 1; - if (of_get_property(np, "st,thermal-warning-adjustment", NULL)) - pdata->thermal_warning_adjustment = 1; - if (of_get_property(np, "st,fault-detect-recovery", NULL)) - pdata->fault_detect_recovery = 1; + pdata->thermal_warning_recovery = + of_property_read_bool(np, "st,thermal-warning-recovery"); + pdata->thermal_warning_adjustment = + of_property_read_bool(np, "st,thermal-warning-adjustment"); + pdata->fault_detect_recovery = + of_property_read_bool(np, "st,fault-detect-recovery"); pdata->ffx_power_output_mode = STA350_FFX_PM_VARIABLE_DROP_COMP; if (!of_property_read_string(np, "st,ffx-power-output-mode", @@ -1133,41 +1133,34 @@ static int sta350_probe_dt(struct device *dev, struct sta350_priv *sta350) of_property_read_u16(np, "st,drop-compensation-ns", &tmp); pdata->drop_compensation_ns = clamp_t(u16, tmp, 0, 300) / 20; - if (of_get_property(np, "st,overcurrent-warning-adjustment", NULL)) - pdata->oc_warning_adjustment = 1; + pdata->oc_warning_adjustment = + of_property_read_bool(np, "st,overcurrent-warning-adjustment"); /* CONFE */ - if (of_get_property(np, "st,max-power-use-mpcc", NULL)) - pdata->max_power_use_mpcc = 1; - - if (of_get_property(np, "st,max-power-correction", NULL)) - pdata->max_power_correction = 1; - - if (of_get_property(np, "st,am-reduction-mode", NULL)) - pdata->am_reduction_mode = 1; - - if (of_get_property(np, "st,odd-pwm-speed-mode", NULL)) - pdata->odd_pwm_speed_mode = 1; - - if (of_get_property(np, "st,distortion-compensation", NULL)) - pdata->distortion_compensation = 1; + pdata->max_power_use_mpcc = + of_property_read_bool(np, "st,max-power-use-mpcc"); + pdata->max_power_correction = + of_property_read_bool(np, "st,max-power-correction"); + pdata->am_reduction_mode = + of_property_read_bool(np, "st,am-reduction-mode"); + pdata->odd_pwm_speed_mode = + of_property_read_bool(np, "st,odd-pwm-speed-mode"); + pdata->distortion_compensation = + of_property_read_bool(np, "st,distortion-compensation"); /* CONFF */ - if (of_get_property(np, "st,invalid-input-detect-mute", NULL)) - pdata->invalid_input_detect_mute = 1; + pdata->invalid_input_detect_mute = + of_property_read_bool(np, "st,invalid-input-detect-mute"); /* MISC */ - if (of_get_property(np, "st,activate-mute-output", NULL)) - pdata->activate_mute_output = 1; - - if (of_get_property(np, "st,bridge-immediate-off", NULL)) - pdata->bridge_immediate_off = 1; - - if (of_get_property(np, "st,noise-shape-dc-cut", NULL)) - pdata->noise_shape_dc_cut = 1; - - if (of_get_property(np, "st,powerdown-master-volume", NULL)) - pdata->powerdown_master_vol = 1; + pdata->activate_mute_output = + of_property_read_bool(np, "st,activate-mute-output"); + pdata->bridge_immediate_off = + of_property_read_bool(np, "st,bridge-immediate-off"); + pdata->noise_shape_dc_cut = + of_property_read_bool(np, "st,noise-shape-dc-cut"); + pdata->powerdown_master_vol = + of_property_read_bool(np, "st,powerdown-master-volume"); if (!of_property_read_u8(np, "st,powerdown-delay-divider", &tmp8)) { if (is_power_of_2(tmp8) && tmp8 >= 1 && tmp8 <= 128) diff --git a/sound/soc/codecs/tas5086.c b/sound/soc/codecs/tas5086.c index 22143cc5afa7..f9e7122894bd 100644 --- a/sound/soc/codecs/tas5086.c +++ b/sound/soc/codecs/tas5086.c @@ -840,7 +840,7 @@ static int tas5086_probe(struct snd_soc_component *component) snprintf(name, sizeof(name), "ti,mid-z-channel-%d", i + 1); - if (of_get_property(of_node, name, NULL) != NULL) + if (of_property_read_bool(of_node, name)) priv->pwm_start_mid_z |= 1 << i; } } diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index 1b197478b3d9..4e6b75f1ddd0 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -1380,18 +1380,18 @@ static int fsl_sai_probe(struct platform_device *pdev) sai->cpu_dai_drv.symmetric_channels = 1; sai->cpu_dai_drv.symmetric_sample_bits = 1; - if (of_find_property(np, "fsl,sai-synchronous-rx", NULL) && - of_find_property(np, "fsl,sai-asynchronous", NULL)) { + if (of_property_read_bool(np, "fsl,sai-synchronous-rx") && + of_property_read_bool(np, "fsl,sai-asynchronous")) { /* error out if both synchronous and asynchronous are present */ dev_err(dev, "invalid binding for synchronous mode\n"); return -EINVAL; } - if (of_find_property(np, "fsl,sai-synchronous-rx", NULL)) { + if (of_property_read_bool(np, "fsl,sai-synchronous-rx")) { /* Sync Rx with Tx */ sai->synchronous[RX] = false; sai->synchronous[TX] = true; - } else if (of_find_property(np, "fsl,sai-asynchronous", NULL)) { + } else if (of_property_read_bool(np, "fsl,sai-asynchronous")) { /* Discard all settings for asynchronous mode */ sai->synchronous[RX] = false; sai->synchronous[TX] = false; @@ -1400,7 +1400,7 @@ static int fsl_sai_probe(struct platform_device *pdev) sai->cpu_dai_drv.symmetric_sample_bits = 0; } - if (of_find_property(np, "fsl,sai-mclk-direction-output", NULL) && + if (of_property_read_bool(np, "fsl,sai-mclk-direction-output") && of_device_is_compatible(np, "fsl,imx6ul-sai")) { gpr = syscon_regmap_lookup_by_compatible("fsl,imx6ul-iomuxc-gpr"); if (IS_ERR(gpr)) { @@ -1443,7 +1443,7 @@ static int fsl_sai_probe(struct platform_device *pdev) dev_warn(dev, "Error reading SAI version: %d\n", ret); /* Select MCLK direction */ - if (of_find_property(np, "fsl,sai-mclk-direction-output", NULL) && + if (of_property_read_bool(np, "fsl,sai-mclk-direction-output") && sai->soc_data->max_register >= FSL_SAI_MCTL) { regmap_update_bits(sai->regmap, FSL_SAI_MCTL, FSL_SAI_MCTL_MCLK_EN, FSL_SAI_MCTL_MCLK_EN); diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 46a53551b955..6af00b62a60f 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -1447,7 +1447,7 @@ static int fsl_ssi_probe_from_dt(struct fsl_ssi *ssi) return -EINVAL; } strcpy(ssi->card_name, "ac97-codec"); - } else if (!of_find_property(np, "fsl,ssi-asynchronous", NULL)) { + } else if (!of_property_read_bool(np, "fsl,ssi-asynchronous")) { /* * In synchronous mode, STCK and STFS ports are used by RX * as well. So the software should limit the sample rates, diff --git a/sound/soc/fsl/imx-card.c b/sound/soc/fsl/imx-card.c index 3f128ced4180..64a4d7e9db60 100644 --- a/sound/soc/fsl/imx-card.c +++ b/sound/soc/fsl/imx-card.c @@ -563,7 +563,7 @@ static int imx_card_parse_of(struct imx_card_data *data) link_data->cpu_sysclk_id = FSL_SAI_CLK_MAST1; /* sai may support mclk/bclk = 1 */ - if (of_find_property(np, "fsl,mclk-equal-bclk", NULL)) { + if (of_property_read_bool(np, "fsl,mclk-equal-bclk")) { link_data->one2one_ratio = true; } else { int i; diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 8ddee5b03ece..690ac0d6ef41 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -1211,10 +1211,10 @@ int rsnd_ssi_probe(struct rsnd_priv *priv) goto rsnd_ssi_probe_done; } - if (of_get_property(np, "shared-pin", NULL)) + if (of_property_read_bool(np, "shared-pin")) rsnd_flags_set(ssi, RSND_SSI_CLK_PIN_SHARE); - if (of_get_property(np, "no-busif", NULL)) + if (of_property_read_bool(np, "no-busif")) rsnd_flags_set(ssi, RSND_SSI_NO_BUSIF); ssi->irq = irq_of_parse_and_map(np, 0); From e25c54d17914b0df4f902d1f25cd52f54e20cfbf Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Sat, 11 Mar 2023 10:29:29 +0100 Subject: [PATCH 321/778] ubi: block: Fix missing blk_mq_end_request Switching to BLK_MQ_F_BLOCKING wrongly removed the call to blk_mq_end_request(). Add it back to have our IOs finished Fixes: 91cc8fbcc8c7 ("ubi: block: set BLK_MQ_F_BLOCKING") Analyzed-by: Linus Torvalds Reported-by: Daniel Palmer Link: https://lore.kernel.org/linux-mtd/CAHk-=wi29bbBNh3RqJKu3PxzpjDN5D5K17gEVtXrb7-6bfrnMQ@mail.gmail.com/ Signed-off-by: Richard Weinberger Reviewed-by: Christoph Hellwig Tested-by: Daniel Palmer Signed-off-by: Linus Torvalds --- drivers/mtd/ubi/block.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/ubi/block.c b/drivers/mtd/ubi/block.c index 1de87062c67b..3711d7f74600 100644 --- a/drivers/mtd/ubi/block.c +++ b/drivers/mtd/ubi/block.c @@ -221,7 +221,10 @@ static blk_status_t ubiblock_read(struct request *req) rq_for_each_segment(bvec, req, iter) flush_dcache_page(bvec.bv_page); - return errno_to_blk_status(ret); + + blk_mq_end_request(req, errno_to_blk_status(ret)); + + return BLK_STS_OK; } static int ubiblock_open(struct block_device *bdev, fmode_t mode) From e7304080e0e50d979ce9eaf694ad8283e2e539ea Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 12 Mar 2023 08:52:03 -0700 Subject: [PATCH 322/778] cpumask: relax sanity checking constraints The cpumask_check() was unnecessarily tight, and causes problems for the users of cpumask_next(). We have a number of users that take the previous return value of one of the bit scanning functions and subtract one to keep it in "range". But since the scanning functions end up returning up to 'small_cpumask_bits' instead of the tighter 'nr_cpumask_bits', the range really needs to be using that widened form. [ This "previous-1" behavior is also the reason we have all those comments about /* -1 is a legal arg here. */ and separate checks for that being ok. So we could have just made "small_cpumask_bits-1" be a similar special "don't check this" value. Tetsuo Handa even suggested a patch that only does that for cpumask_next(), since that seems to be the only actual case that triggers, but that all makes it even _more_ magical and special. So just relax the check ] One example of this kind of pattern being the 'c_start()' function in arch/x86/kernel/cpu/proc.c, but also duplicated in various forms on other architectures. Reported-by: syzbot+96cae094d90877641f32@syzkaller.appspotmail.com Link: https://syzkaller.appspot.com/bug?extid=96cae094d90877641f32 Reported-by: Tetsuo Handa Link: https://lore.kernel.org/lkml/c1f4cc16-feea-b83c-82cf-1a1f007b7eb9@I-love.SAKURA.ne.jp/ Fixes: 596ff4a09b89 ("cpumask: re-introduce constant-sized cpumask optimizations") Signed-off-by: Linus Torvalds --- include/linux/cpumask.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h index 63d637d18e79..d4901ca8883c 100644 --- a/include/linux/cpumask.h +++ b/include/linux/cpumask.h @@ -147,7 +147,7 @@ static __always_inline void cpu_max_bits_warn(unsigned int cpu, unsigned int bit /* verify cpu argument to cpumask_* operators */ static __always_inline unsigned int cpumask_check(unsigned int cpu) { - cpu_max_bits_warn(cpu, nr_cpumask_bits); + cpu_max_bits_warn(cpu, small_cpumask_bits); return cpu; } From 80a6c216b16d7f5c584d2148c2e4345ea4eb06ce Mon Sep 17 00:00:00 2001 From: Morten Linderud Date: Wed, 15 Feb 2023 10:25:52 +0100 Subject: [PATCH 323/778] tpm/eventlog: Don't abort tpm_read_log on faulty ACPI address tpm_read_log_acpi() should return -ENODEV when no eventlog from the ACPI table is found. If the firmware vendor includes an invalid log address we are unable to map from the ACPI memory and tpm_read_log() returns -EIO which would abort discovery of the eventlog. Change the return value from -EIO to -ENODEV when acpi_os_map_iomem() fails to map the event log. The following hardware was used to test this issue: Framework Laptop (Pre-production) BIOS: INSYDE Corp, Revision: 3.2 TPM Device: NTC, Firmware Revision: 7.2 Dump of the faulty ACPI TPM2 table: [000h 0000 4] Signature : "TPM2" [Trusted Platform Module hardware interface Table] [004h 0004 4] Table Length : 0000004C [008h 0008 1] Revision : 04 [009h 0009 1] Checksum : 2B [00Ah 0010 6] Oem ID : "INSYDE" [010h 0016 8] Oem Table ID : "TGL-ULT" [018h 0024 4] Oem Revision : 00000002 [01Ch 0028 4] Asl Compiler ID : "ACPI" [020h 0032 4] Asl Compiler Revision : 00040000 [024h 0036 2] Platform Class : 0000 [026h 0038 2] Reserved : 0000 [028h 0040 8] Control Address : 0000000000000000 [030h 0048 4] Start Method : 06 [Memory Mapped I/O] [034h 0052 12] Method Parameters : 00 00 00 00 00 00 00 00 00 00 00 00 [040h 0064 4] Minimum Log Length : 00010000 [044h 0068 8] Log Address : 000000004053D000 Fixes: 0cf577a03f21 ("tpm: Fix handling of missing event log") Tested-by: Erkki Eilonen Signed-off-by: Morten Linderud Reviewed-by: Jarkko Sakkinen Signed-off-by: Jarkko Sakkinen --- drivers/char/tpm/eventlog/acpi.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/char/tpm/eventlog/acpi.c b/drivers/char/tpm/eventlog/acpi.c index 40360e599bc3..bd757d836c5c 100644 --- a/drivers/char/tpm/eventlog/acpi.c +++ b/drivers/char/tpm/eventlog/acpi.c @@ -144,8 +144,12 @@ int tpm_read_log_acpi(struct tpm_chip *chip) ret = -EIO; virt = acpi_os_map_iomem(start, len); - if (!virt) + if (!virt) { + dev_warn(&chip->dev, "%s: Failed to map ACPI memory\n", __func__); + /* try EFI log next */ + ret = -ENODEV; goto err; + } memcpy_fromio(log->bios_event_log, virt, len); From f1324bbc4011ed8aef3f4552210fc429bcd616da Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Mon, 27 Feb 2023 20:44:39 -0600 Subject: [PATCH 324/778] tpm: disable hwrng for fTPM on some AMD designs AMD has issued an advisory indicating that having fTPM enabled in BIOS can cause "stuttering" in the OS. This issue has been fixed in newer versions of the fTPM firmware, but it's up to system designers to decide whether to distribute it. This issue has existed for a while, but is more prevalent starting with kernel 6.1 because commit b006c439d58db ("hwrng: core - start hwrng kthread also for untrusted sources") started to use the fTPM for hwrng by default. However, all uses of /dev/hwrng result in unacceptable stuttering. So, simply disable registration of the defective hwrng when detecting these faulty fTPM versions. As this is caused by faulty firmware, it is plausible that such a problem could also be reproduced by other TPM interactions, but this hasn't been shown by any user's testing or reports. It is hypothesized to be triggered more frequently by the use of the RNG because userspace software will fetch random numbers regularly. Intentionally continue to register other TPM functionality so that users that rely upon PCR measurements or any storage of data will still have access to it. If it's found later that another TPM functionality is exacerbating this problem a module parameter it can be turned off entirely and a module parameter can be introduced to allow users who rely upon fTPM functionality to turn it on even though this problem is present. Link: https://www.amd.com/en/support/kb/faq/pa-410 Link: https://bugzilla.kernel.org/show_bug.cgi?id=216989 Link: https://lore.kernel.org/all/20230209153120.261904-1-Jason@zx2c4.com/ Fixes: b006c439d58d ("hwrng: core - start hwrng kthread also for untrusted sources") Cc: stable@vger.kernel.org Cc: Jarkko Sakkinen Cc: Thorsten Leemhuis Cc: James Bottomley Tested-by: reach622@mailcuk.com Tested-by: Bell <1138267643@qq.com> Co-developed-by: Jason A. Donenfeld Signed-off-by: Jason A. Donenfeld Signed-off-by: Mario Limonciello Reviewed-by: Jarkko Sakkinen Signed-off-by: Jarkko Sakkinen --- drivers/char/tpm/tpm-chip.c | 60 +++++++++++++++++++++++++++++- drivers/char/tpm/tpm.h | 73 +++++++++++++++++++++++++++++++++++++ 2 files changed, 132 insertions(+), 1 deletion(-) diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c index b99f55f2d4fd..0601e6e5e326 100644 --- a/drivers/char/tpm/tpm-chip.c +++ b/drivers/char/tpm/tpm-chip.c @@ -511,6 +511,63 @@ static int tpm_add_legacy_sysfs(struct tpm_chip *chip) return 0; } +/* + * Some AMD fTPM versions may cause stutter + * https://www.amd.com/en/support/kb/faq/pa-410 + * + * Fixes are available in two series of fTPM firmware: + * 6.x.y.z series: 6.0.18.6 + + * 3.x.y.z series: 3.57.y.5 + + */ +static bool tpm_amd_is_rng_defective(struct tpm_chip *chip) +{ + u32 val1, val2; + u64 version; + int ret; + + if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) + return false; + + ret = tpm_request_locality(chip); + if (ret) + return false; + + ret = tpm2_get_tpm_pt(chip, TPM2_PT_MANUFACTURER, &val1, NULL); + if (ret) + goto release; + if (val1 != 0x414D4400U /* AMD */) { + ret = -ENODEV; + goto release; + } + ret = tpm2_get_tpm_pt(chip, TPM2_PT_FIRMWARE_VERSION_1, &val1, NULL); + if (ret) + goto release; + ret = tpm2_get_tpm_pt(chip, TPM2_PT_FIRMWARE_VERSION_2, &val2, NULL); + +release: + tpm_relinquish_locality(chip); + + if (ret) + return false; + + version = ((u64)val1 << 32) | val2; + if ((version >> 48) == 6) { + if (version >= 0x0006000000180006ULL) + return false; + } else if ((version >> 48) == 3) { + if (version >= 0x0003005700000005ULL) + return false; + } else { + return false; + } + + dev_warn(&chip->dev, + "AMD fTPM version 0x%llx causes system stutter; hwrng disabled\n", + version); + + return true; +} + static int tpm_hwrng_read(struct hwrng *rng, void *data, size_t max, bool wait) { struct tpm_chip *chip = container_of(rng, struct tpm_chip, hwrng); @@ -520,7 +577,8 @@ static int tpm_hwrng_read(struct hwrng *rng, void *data, size_t max, bool wait) static int tpm_add_hwrng(struct tpm_chip *chip) { - if (!IS_ENABLED(CONFIG_HW_RANDOM_TPM) || tpm_is_firmware_upgrade(chip)) + if (!IS_ENABLED(CONFIG_HW_RANDOM_TPM) || tpm_is_firmware_upgrade(chip) || + tpm_amd_is_rng_defective(chip)) return 0; snprintf(chip->hwrng_name, sizeof(chip->hwrng_name), diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 24ee4e1cc452..830014a26609 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -150,6 +150,79 @@ enum tpm_sub_capabilities { TPM_CAP_PROP_TIS_DURATION = 0x120, }; +enum tpm2_pt_props { + TPM2_PT_NONE = 0x00000000, + TPM2_PT_GROUP = 0x00000100, + TPM2_PT_FIXED = TPM2_PT_GROUP * 1, + TPM2_PT_FAMILY_INDICATOR = TPM2_PT_FIXED + 0, + TPM2_PT_LEVEL = TPM2_PT_FIXED + 1, + TPM2_PT_REVISION = TPM2_PT_FIXED + 2, + TPM2_PT_DAY_OF_YEAR = TPM2_PT_FIXED + 3, + TPM2_PT_YEAR = TPM2_PT_FIXED + 4, + TPM2_PT_MANUFACTURER = TPM2_PT_FIXED + 5, + TPM2_PT_VENDOR_STRING_1 = TPM2_PT_FIXED + 6, + TPM2_PT_VENDOR_STRING_2 = TPM2_PT_FIXED + 7, + TPM2_PT_VENDOR_STRING_3 = TPM2_PT_FIXED + 8, + TPM2_PT_VENDOR_STRING_4 = TPM2_PT_FIXED + 9, + TPM2_PT_VENDOR_TPM_TYPE = TPM2_PT_FIXED + 10, + TPM2_PT_FIRMWARE_VERSION_1 = TPM2_PT_FIXED + 11, + TPM2_PT_FIRMWARE_VERSION_2 = TPM2_PT_FIXED + 12, + TPM2_PT_INPUT_BUFFER = TPM2_PT_FIXED + 13, + TPM2_PT_HR_TRANSIENT_MIN = TPM2_PT_FIXED + 14, + TPM2_PT_HR_PERSISTENT_MIN = TPM2_PT_FIXED + 15, + TPM2_PT_HR_LOADED_MIN = TPM2_PT_FIXED + 16, + TPM2_PT_ACTIVE_SESSIONS_MAX = TPM2_PT_FIXED + 17, + TPM2_PT_PCR_COUNT = TPM2_PT_FIXED + 18, + TPM2_PT_PCR_SELECT_MIN = TPM2_PT_FIXED + 19, + TPM2_PT_CONTEXT_GAP_MAX = TPM2_PT_FIXED + 20, + TPM2_PT_NV_COUNTERS_MAX = TPM2_PT_FIXED + 22, + TPM2_PT_NV_INDEX_MAX = TPM2_PT_FIXED + 23, + TPM2_PT_MEMORY = TPM2_PT_FIXED + 24, + TPM2_PT_CLOCK_UPDATE = TPM2_PT_FIXED + 25, + TPM2_PT_CONTEXT_HASH = TPM2_PT_FIXED + 26, + TPM2_PT_CONTEXT_SYM = TPM2_PT_FIXED + 27, + TPM2_PT_CONTEXT_SYM_SIZE = TPM2_PT_FIXED + 28, + TPM2_PT_ORDERLY_COUNT = TPM2_PT_FIXED + 29, + TPM2_PT_MAX_COMMAND_SIZE = TPM2_PT_FIXED + 30, + TPM2_PT_MAX_RESPONSE_SIZE = TPM2_PT_FIXED + 31, + TPM2_PT_MAX_DIGEST = TPM2_PT_FIXED + 32, + TPM2_PT_MAX_OBJECT_CONTEXT = TPM2_PT_FIXED + 33, + TPM2_PT_MAX_SESSION_CONTEXT = TPM2_PT_FIXED + 34, + TPM2_PT_PS_FAMILY_INDICATOR = TPM2_PT_FIXED + 35, + TPM2_PT_PS_LEVEL = TPM2_PT_FIXED + 36, + TPM2_PT_PS_REVISION = TPM2_PT_FIXED + 37, + TPM2_PT_PS_DAY_OF_YEAR = TPM2_PT_FIXED + 38, + TPM2_PT_PS_YEAR = TPM2_PT_FIXED + 39, + TPM2_PT_SPLIT_MAX = TPM2_PT_FIXED + 40, + TPM2_PT_TOTAL_COMMANDS = TPM2_PT_FIXED + 41, + TPM2_PT_LIBRARY_COMMANDS = TPM2_PT_FIXED + 42, + TPM2_PT_VENDOR_COMMANDS = TPM2_PT_FIXED + 43, + TPM2_PT_NV_BUFFER_MAX = TPM2_PT_FIXED + 44, + TPM2_PT_MODES = TPM2_PT_FIXED + 45, + TPM2_PT_MAX_CAP_BUFFER = TPM2_PT_FIXED + 46, + TPM2_PT_VAR = TPM2_PT_GROUP * 2, + TPM2_PT_PERMANENT = TPM2_PT_VAR + 0, + TPM2_PT_STARTUP_CLEAR = TPM2_PT_VAR + 1, + TPM2_PT_HR_NV_INDEX = TPM2_PT_VAR + 2, + TPM2_PT_HR_LOADED = TPM2_PT_VAR + 3, + TPM2_PT_HR_LOADED_AVAIL = TPM2_PT_VAR + 4, + TPM2_PT_HR_ACTIVE = TPM2_PT_VAR + 5, + TPM2_PT_HR_ACTIVE_AVAIL = TPM2_PT_VAR + 6, + TPM2_PT_HR_TRANSIENT_AVAIL = TPM2_PT_VAR + 7, + TPM2_PT_HR_PERSISTENT = TPM2_PT_VAR + 8, + TPM2_PT_HR_PERSISTENT_AVAIL = TPM2_PT_VAR + 9, + TPM2_PT_NV_COUNTERS = TPM2_PT_VAR + 10, + TPM2_PT_NV_COUNTERS_AVAIL = TPM2_PT_VAR + 11, + TPM2_PT_ALGORITHM_SET = TPM2_PT_VAR + 12, + TPM2_PT_LOADED_CURVES = TPM2_PT_VAR + 13, + TPM2_PT_LOCKOUT_COUNTER = TPM2_PT_VAR + 14, + TPM2_PT_MAX_AUTH_FAIL = TPM2_PT_VAR + 15, + TPM2_PT_LOCKOUT_INTERVAL = TPM2_PT_VAR + 16, + TPM2_PT_LOCKOUT_RECOVERY = TPM2_PT_VAR + 17, + TPM2_PT_NV_WRITE_RECOVERY = TPM2_PT_VAR + 18, + TPM2_PT_AUDIT_COUNTER_0 = TPM2_PT_VAR + 19, + TPM2_PT_AUDIT_COUNTER_1 = TPM2_PT_VAR + 20, +}; /* 128 bytes is an arbitrary cap. This could be as large as TPM_BUFSIZE - 18 * bytes, but 128 is still a relatively large number of random bytes and From 79d1ed5ca7db67d48e870c979f0e0f6b0947944a Mon Sep 17 00:00:00 2001 From: Hector Martin Date: Sat, 11 Mar 2023 23:19:14 +0900 Subject: [PATCH 325/778] wifi: cfg80211: Partial revert "wifi: cfg80211: Fix use after free for wext" This reverts part of commit 015b8cc5e7c4 ("wifi: cfg80211: Fix use after free for wext") This commit broke WPA offload by unconditionally clearing the crypto modes for non-WEP connections. Drop that part of the patch. Signed-off-by: Hector Martin Reported-by: Ilya Reported-and-tested-by: Janne Grunau Reviewed-by: Eric Curtin Fixes: 015b8cc5e7c4 ("wifi: cfg80211: Fix use after free for wext") Cc: stable@kernel.org Link: https://lore.kernel.org/linux-wireless/ZAx0TWRBlGfv7pNl@kroah.com/T/#m11e6e0915ab8fa19ce8bc9695ab288c0fe018edf Signed-off-by: Linus Torvalds --- net/wireless/sme.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/net/wireless/sme.c b/net/wireless/sme.c index 28ce13840a88..7bdeb8eea92d 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c @@ -1500,8 +1500,6 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev, connect->key = NULL; connect->key_len = 0; connect->key_idx = 0; - connect->crypto.cipher_group = 0; - connect->crypto.n_ciphers_pairwise = 0; } wdev->connect_keys = connkeys; From eeac8ede17557680855031c6f305ece2378af326 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 12 Mar 2023 16:36:44 -0700 Subject: [PATCH 326/778] Linux 6.3-rc2 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index d7bd0eb9b346..c933ceb4f21d 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ VERSION = 6 PATCHLEVEL = 3 SUBLEVEL = 0 -EXTRAVERSION = -rc1 +EXTRAVERSION = -rc2 NAME = Hurr durr I'ma ninja sloth # *DOCUMENTATION* From 3eac8de3f51b3567c4ba6139736b59027da56285 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 13 Mar 2023 13:03:38 +0200 Subject: [PATCH 327/778] ASoC: SOF: ipc3-control: Rename snd_sof_refresh_control() Rename the snd_sof_refresh_control() to sof_ipc3_refresh_control() to follow the function naming convention for IPC specific code. Signed-off-by: Peter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20230313110344.16644-2-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc3-control.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sound/soc/sof/ipc3-control.c b/sound/soc/sof/ipc3-control.c index 217ac5501a98..4e9d04124145 100644 --- a/sound/soc/sof/ipc3-control.c +++ b/sound/soc/sof/ipc3-control.c @@ -104,7 +104,7 @@ unlock: return ret; } -static void snd_sof_refresh_control(struct snd_sof_control *scontrol) +static void sof_ipc3_refresh_control(struct snd_sof_control *scontrol) { struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; struct snd_soc_component *scomp = scontrol->scomp; @@ -138,7 +138,7 @@ static int sof_ipc3_volume_get(struct snd_sof_control *scontrol, unsigned int channels = scontrol->num_channels; unsigned int i; - snd_sof_refresh_control(scontrol); + sof_ipc3_refresh_control(scontrol); /* read back each channel */ for (i = 0; i < channels; i++) @@ -189,7 +189,7 @@ static int sof_ipc3_switch_get(struct snd_sof_control *scontrol, unsigned int channels = scontrol->num_channels; unsigned int i; - snd_sof_refresh_control(scontrol); + sof_ipc3_refresh_control(scontrol); /* read back each channel */ for (i = 0; i < channels; i++) @@ -237,7 +237,7 @@ static int sof_ipc3_enum_get(struct snd_sof_control *scontrol, unsigned int channels = scontrol->num_channels; unsigned int i; - snd_sof_refresh_control(scontrol); + sof_ipc3_refresh_control(scontrol); /* read back each channel */ for (i = 0; i < channels; i++) @@ -286,7 +286,7 @@ static int sof_ipc3_bytes_get(struct snd_sof_control *scontrol, struct sof_abi_hdr *data = cdata->data; size_t size; - snd_sof_refresh_control(scontrol); + sof_ipc3_refresh_control(scontrol); if (scontrol->max_size > sizeof(ucontrol->value.bytes.data)) { dev_err_ratelimited(scomp->dev, "data max %zu exceeds ucontrol data array size\n", @@ -352,7 +352,7 @@ static int sof_ipc3_bytes_ext_get(struct snd_sof_control *scontrol, struct snd_ctl_tlv header; size_t data_size; - snd_sof_refresh_control(scontrol); + sof_ipc3_refresh_control(scontrol); /* * Decrement the limit by ext bytes header size to From 76fc628aebdb452e3c620d9ff5c5e9448d316754 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 13 Mar 2023 13:03:39 +0200 Subject: [PATCH 328/778] ASoC: SOF: ipc3-control: Merge functions to handle bytes_ext get variants The code for bytes_ext_get and bytes_ext_volatile_get is identical with the only difference is that in case of volatile_get we refresh the data from the DSP before returning it to user space. Convert the callbacks to a simple wrapper for the same function. Signed-off-by: Peter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20230313110344.16644-3-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc3-control.c | 80 +++++++++++------------------------- 1 file changed, 23 insertions(+), 57 deletions(-) diff --git a/sound/soc/sof/ipc3-control.c b/sound/soc/sof/ipc3-control.c index 4e9d04124145..ad040e7bb850 100644 --- a/sound/soc/sof/ipc3-control.c +++ b/sound/soc/sof/ipc3-control.c @@ -343,55 +343,6 @@ static int sof_ipc3_bytes_put(struct snd_sof_control *scontrol, return 0; } -static int sof_ipc3_bytes_ext_get(struct snd_sof_control *scontrol, - const unsigned int __user *binary_data, unsigned int size) -{ - struct snd_ctl_tlv __user *tlvd = (struct snd_ctl_tlv __user *)binary_data; - struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; - struct snd_soc_component *scomp = scontrol->scomp; - struct snd_ctl_tlv header; - size_t data_size; - - sof_ipc3_refresh_control(scontrol); - - /* - * Decrement the limit by ext bytes header size to - * ensure the user space buffer is not exceeded. - */ - if (size < sizeof(struct snd_ctl_tlv)) - return -ENOSPC; - - size -= sizeof(struct snd_ctl_tlv); - - /* set the ABI header values */ - cdata->data->magic = SOF_ABI_MAGIC; - cdata->data->abi = SOF_ABI_VERSION; - - /* check data size doesn't exceed max coming from topology */ - if (cdata->data->size > scontrol->max_size - sizeof(struct sof_abi_hdr)) { - dev_err_ratelimited(scomp->dev, "User data size %d exceeds max size %zu\n", - cdata->data->size, - scontrol->max_size - sizeof(struct sof_abi_hdr)); - return -EINVAL; - } - - data_size = cdata->data->size + sizeof(struct sof_abi_hdr); - - /* make sure we don't exceed size provided by user space for data */ - if (data_size > size) - return -ENOSPC; - - header.numid = cdata->cmd; - header.length = data_size; - if (copy_to_user(tlvd, &header, sizeof(struct snd_ctl_tlv))) - return -EFAULT; - - if (copy_to_user(tlvd->tlv, cdata->data, data_size)) - return -EFAULT; - - return 0; -} - static int sof_ipc3_bytes_ext_put(struct snd_sof_control *scontrol, const unsigned int __user *binary_data, unsigned int size) @@ -457,16 +408,15 @@ static int sof_ipc3_bytes_ext_put(struct snd_sof_control *scontrol, return 0; } -static int sof_ipc3_bytes_ext_volatile_get(struct snd_sof_control *scontrol, - const unsigned int __user *binary_data, - unsigned int size) +static int _sof_ipc3_bytes_ext_get(struct snd_sof_control *scontrol, + const unsigned int __user *binary_data, + unsigned int size, bool from_dsp) { struct snd_ctl_tlv __user *tlvd = (struct snd_ctl_tlv __user *)binary_data; struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; struct snd_soc_component *scomp = scontrol->scomp; struct snd_ctl_tlv header; size_t data_size; - int ret; /* * Decrement the limit by ext bytes header size to @@ -482,9 +432,12 @@ static int sof_ipc3_bytes_ext_volatile_get(struct snd_sof_control *scontrol, cdata->data->abi = SOF_ABI_VERSION; /* get all the component data from DSP */ - ret = sof_ipc3_set_get_kcontrol_data(scontrol, false, true); - if (ret < 0) - return ret; + if (from_dsp) { + int ret = sof_ipc3_set_get_kcontrol_data(scontrol, false, true); + + if (ret < 0) + return ret; + } /* check data size doesn't exceed max coming from topology */ if (cdata->data->size > scontrol->max_size - sizeof(struct sof_abi_hdr)) { @@ -508,7 +461,20 @@ static int sof_ipc3_bytes_ext_volatile_get(struct snd_sof_control *scontrol, if (copy_to_user(tlvd->tlv, cdata->data, data_size)) return -EFAULT; - return ret; + return 0; +} + +static int sof_ipc3_bytes_ext_get(struct snd_sof_control *scontrol, + const unsigned int __user *binary_data, unsigned int size) +{ + return _sof_ipc3_bytes_ext_get(scontrol, binary_data, size, false); +} + +static int sof_ipc3_bytes_ext_volatile_get(struct snd_sof_control *scontrol, + const unsigned int __user *binary_data, + unsigned int size) +{ + return _sof_ipc3_bytes_ext_get(scontrol, binary_data, size, true); } static void snd_sof_update_control(struct snd_sof_control *scontrol, From 2e4ef6f4798c1d2951dd7bb3ae5f0d41ec3d31e8 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 13 Mar 2023 13:03:40 +0200 Subject: [PATCH 329/778] ASoC: SOF: uapi: header: Convert sof_abi_hdr comments to kernel style Replace the comments for sof_abi_hdr to kernel style. Signed-off-by: Peter Ujfalusi Reviewed-by: Ranjani Sridharan Reviewed-by: Jaska Uimonen Reviewed-by: Kai Vehmanen Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20230313110344.16644-4-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- include/uapi/sound/sof/header.h | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/include/uapi/sound/sof/header.h b/include/uapi/sound/sof/header.h index e9bba93a5399..e53b62b9e2c5 100644 --- a/include/uapi/sound/sof/header.h +++ b/include/uapi/sound/sof/header.h @@ -11,19 +11,25 @@ #include -/* - * Header for all non IPC ABI data. +/** + * struct sof_abi_hdr - Header for all non IPC ABI data. + * @magic: Magic number for validation: 0x00464F53 ('S', 'O', 'F', '\0') + * @type: Component specific type + * @size: The size in bytes of the data, excluding this struct + * @abi: SOF ABI version + * @reserved: Reserved for future use + * @data: Component data - opaque to core * * Identifies data type, size and ABI. * Used by any bespoke component data structures or binary blobs. */ struct sof_abi_hdr { - __u32 magic; /**< 'S', 'O', 'F', '\0' */ - __u32 type; /**< component specific type */ - __u32 size; /**< size in bytes of data excl. this struct */ - __u32 abi; /**< SOF ABI version */ - __u32 reserved[4]; /**< reserved for future use */ - __u32 data[]; /**< Component data - opaque to core */ + __u32 magic; + __u32 type; + __u32 size; + __u32 abi; + __u32 reserved[4]; + __u32 data[]; } __packed; #define SOF_MANIFEST_DATA_TYPE_NHLT 1 From ea4a4e82f625ae451175a2a74779776b006d25a1 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 13 Mar 2023 13:03:41 +0200 Subject: [PATCH 330/778] ASoC: SOF: uapi: header: Update sof_abi_hdr doc for IPC4 use With IPC4 the sof_abit_hdr is only used between user space (and in topology) and kernel. The same abi header is used with small differencies like different magic number and the type field have slightly different name, but similar function in IPC4 (param_id). Update the kernel documentation to highlight the differences. Signed-off-by: Peter Ujfalusi Reviewed-by: Bard Liao Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Jaska Uimonen Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20230313110344.16644-5-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- include/uapi/sound/sof/abi.h | 2 ++ include/uapi/sound/sof/header.h | 11 ++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/include/uapi/sound/sof/abi.h b/include/uapi/sound/sof/abi.h index 3566630ca965..45c657c3919e 100644 --- a/include/uapi/sound/sof/abi.h +++ b/include/uapi/sound/sof/abi.h @@ -60,5 +60,7 @@ /* SOF ABI magic number "SOF\0". */ #define SOF_ABI_MAGIC 0x00464F53 +/* SOF IPC4 ABI magic number "SOF4". */ +#define SOF_IPC4_ABI_MAGIC 0x34464F53 #endif diff --git a/include/uapi/sound/sof/header.h b/include/uapi/sound/sof/header.h index e53b62b9e2c5..cb3c1ace69e3 100644 --- a/include/uapi/sound/sof/header.h +++ b/include/uapi/sound/sof/header.h @@ -13,10 +13,15 @@ /** * struct sof_abi_hdr - Header for all non IPC ABI data. - * @magic: Magic number for validation: 0x00464F53 ('S', 'O', 'F', '\0') - * @type: Component specific type + * @magic: Magic number for validation + * for IPC3 data: 0x00464F53 ('S', 'O', 'F', '\0') + * for IPC4 data: 0x34464F53 ('S', 'O', 'F', '4') + * @type: module specific parameter + * for IPC3: Component specific type + * for IPC4: parameter ID (param_id) of the data * @size: The size in bytes of the data, excluding this struct - * @abi: SOF ABI version + * @abi: SOF ABI version. The version is valid in scope of the 'magic', IPC3 and + * IPC4 ABI version numbers have no relationship. * @reserved: Reserved for future use * @data: Component data - opaque to core * From dc47ef4f8f6426cd625eb4057e174541e7c23ccd Mon Sep 17 00:00:00 2001 From: Libin Yang Date: Mon, 13 Mar 2023 13:03:42 +0200 Subject: [PATCH 331/778] ASoC: SOF: ipc4-control: set_volume_data only applies to VOLSW family MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make sure sof_ipc4_set_volume_data() is only called for the SND_SOC_TPLG_CTL_VOLSW, SND_SOC_TPLG_CTL_VOLSW_SX and SND_SOC_TPLG_CTL_VOLSW_XR_SX info_type. Signed-off-by: Libin Yang Reviewed-by: Péter Ujfalusi Reviewed-by: Bard Liao Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230313110344.16644-6-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-control.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/sound/soc/sof/ipc4-control.c b/sound/soc/sof/ipc4-control.c index 67bd2233fd9a..c978325db416 100644 --- a/sound/soc/sof/ipc4-control.c +++ b/sound/soc/sof/ipc4-control.c @@ -186,15 +186,25 @@ static int sof_ipc4_widget_kcontrol_setup(struct snd_sof_dev *sdev, struct snd_s struct snd_sof_control *scontrol; int ret; - list_for_each_entry(scontrol, &sdev->kcontrol_list, list) + list_for_each_entry(scontrol, &sdev->kcontrol_list, list) { if (scontrol->comp_id == swidget->comp_id) { - ret = sof_ipc4_set_volume_data(sdev, swidget, scontrol, false); - if (ret < 0) { - dev_err(sdev->dev, "%s: kcontrol %d set up failed for widget %s\n", - __func__, scontrol->comp_id, swidget->widget->name); - return ret; + switch (scontrol->info_type) { + case SND_SOC_TPLG_CTL_VOLSW: + case SND_SOC_TPLG_CTL_VOLSW_SX: + case SND_SOC_TPLG_CTL_VOLSW_XR_SX: + ret = sof_ipc4_set_volume_data(sdev, swidget, + scontrol, false); + if (ret < 0) { + dev_err(sdev->dev, "kcontrol %d set up failed for widget %s\n", + scontrol->comp_id, swidget->widget->name); + return ret; + } + break; + default: + break; } } + } return 0; } From a382082ff74b036944cbc5b6ad29b65f633acd3a Mon Sep 17 00:00:00 2001 From: Libin Yang Date: Mon, 13 Mar 2023 13:03:43 +0200 Subject: [PATCH 332/778] ASoC: SOF: ipc4-topology: Add support for TPLG_CTL_BYTES MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add byte type support for IPC4. The bytes controls are used to transfer configuration blobs to/from firmware via large_config messages. Signed-off-by: Libin Yang Reviewed-by: Péter Ujfalusi Reviewed-by: Bard Liao Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230313110344.16644-7-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 67 +++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index cb75f685e722..d7ce95b9fa0f 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -1502,6 +1502,71 @@ static int sof_ipc4_control_load_volume(struct snd_sof_dev *sdev, struct snd_sof return 0; } +static int sof_ipc4_control_load_bytes(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol) +{ + struct sof_ipc4_control_data *control_data; + struct sof_ipc4_msg *msg; + int ret; + + if (scontrol->max_size < (sizeof(*control_data) + sizeof(struct sof_abi_hdr))) { + dev_err(sdev->dev, "insufficient size for a bytes control %s: %zu.\n", + scontrol->name, scontrol->max_size); + return -EINVAL; + } + + if (scontrol->priv_size > scontrol->max_size - sizeof(*control_data)) { + dev_err(sdev->dev, "scontrol %s bytes data size %zu exceeds max %zu.\n", + scontrol->name, scontrol->priv_size, + scontrol->max_size - sizeof(*control_data)); + return -EINVAL; + } + + scontrol->size = sizeof(struct sof_ipc4_control_data) + scontrol->priv_size; + + scontrol->ipc_control_data = kzalloc(scontrol->max_size, GFP_KERNEL); + if (!scontrol->ipc_control_data) + return -ENOMEM; + + control_data = scontrol->ipc_control_data; + control_data->index = scontrol->index; + if (scontrol->priv_size > 0) { + memcpy(control_data->data, scontrol->priv, scontrol->priv_size); + kfree(scontrol->priv); + scontrol->priv = NULL; + + if (control_data->data->magic != SOF_IPC4_ABI_MAGIC) { + dev_err(sdev->dev, "Wrong ABI magic (%#x) for control: %s\n", + control_data->data->magic, scontrol->name); + ret = -EINVAL; + goto err; + } + + /* TODO: check the ABI version */ + + if (control_data->data->size + sizeof(struct sof_abi_hdr) != + scontrol->priv_size) { + dev_err(sdev->dev, "Control %s conflict in bytes %zu vs. priv size %zu.\n", + scontrol->name, + control_data->data->size + sizeof(struct sof_abi_hdr), + scontrol->priv_size); + ret = -EINVAL; + goto err; + } + } + + msg = &control_data->msg; + msg->primary = SOF_IPC4_MSG_TYPE_SET(SOF_IPC4_MOD_LARGE_CONFIG_SET); + msg->primary |= SOF_IPC4_MSG_DIR(SOF_IPC4_MSG_REQUEST); + msg->primary |= SOF_IPC4_MSG_TARGET(SOF_IPC4_MODULE_MSG); + + return 0; + +err: + kfree(scontrol->ipc_control_data); + scontrol->ipc_control_data = NULL; + return ret; +} + static int sof_ipc4_control_setup(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol) { switch (scontrol->info_type) { @@ -1509,6 +1574,8 @@ static int sof_ipc4_control_setup(struct snd_sof_dev *sdev, struct snd_sof_contr case SND_SOC_TPLG_CTL_VOLSW_SX: case SND_SOC_TPLG_CTL_VOLSW_XR_SX: return sof_ipc4_control_load_volume(sdev, scontrol); + case SND_SOC_TPLG_CTL_BYTES: + return sof_ipc4_control_load_bytes(sdev, scontrol); default: break; } From a062c8899fede2ab5660a817e9b602d3fa280a99 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 13 Mar 2023 13:03:44 +0200 Subject: [PATCH 333/778] ASoC: SOF: ipc4-control: Add support for bytes control get and put Add support for bytes control by implementing bytes_get/put and bytes_ext_get/put and blobs with either module init instance or large config type. For module init instance type the put will only update the stored configuration blob and it is going to be taken into use next time the module is (re-)initialized. Large config type of blobs are sent to the firmware whenever the DSP is powered up. Signed-off-by: Peter Ujfalusi Reviewed-by: Ranjani Sridharan Reviewed-by: Jaska Uimonen Reviewed-by: Kai Vehmanen Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20230313110344.16644-8-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-control.c | 248 ++++++++++++++++++++++++++++++++++- 1 file changed, 241 insertions(+), 7 deletions(-) diff --git a/sound/soc/sof/ipc4-control.c b/sound/soc/sof/ipc4-control.c index c978325db416..38c2531e2f09 100644 --- a/sound/soc/sof/ipc4-control.c +++ b/sound/soc/sof/ipc4-control.c @@ -180,11 +180,237 @@ static int sof_ipc4_volume_get(struct snd_sof_control *scontrol, return 0; } +static int sof_ipc4_set_get_bytes_data(struct snd_sof_dev *sdev, + struct snd_sof_control *scontrol, + bool set, bool lock) +{ + struct sof_ipc4_control_data *cdata = scontrol->ipc_control_data; + struct sof_abi_hdr *data = cdata->data; + struct sof_ipc4_msg *msg = &cdata->msg; + int ret = 0; + + /* Send the new data to the firmware only if it is powered up */ + if (set && !pm_runtime_active(sdev->dev)) + return 0; + + msg->extension = SOF_IPC4_MOD_EXT_MSG_PARAM_ID(data->type); + + msg->data_ptr = data->data; + msg->data_size = data->size; + + ret = sof_ipc4_set_get_kcontrol_data(scontrol, set, lock); + if (ret < 0) + dev_err(sdev->dev, "Failed to %s for %s\n", + set ? "set bytes update" : "get bytes", + scontrol->name); + + msg->data_ptr = NULL; + msg->data_size = 0; + + return ret; +} + +static int sof_ipc4_bytes_put(struct snd_sof_control *scontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct sof_ipc4_control_data *cdata = scontrol->ipc_control_data; + struct snd_soc_component *scomp = scontrol->scomp; + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); + struct sof_abi_hdr *data = cdata->data; + size_t size; + + if (scontrol->max_size > sizeof(ucontrol->value.bytes.data)) { + dev_err_ratelimited(scomp->dev, + "data max %zu exceeds ucontrol data array size\n", + scontrol->max_size); + return -EINVAL; + } + + /* scontrol->max_size has been verified to be >= sizeof(struct sof_abi_hdr) */ + if (data->size > scontrol->max_size - sizeof(*data)) { + dev_err_ratelimited(scomp->dev, + "data size too big %u bytes max is %zu\n", + data->size, scontrol->max_size - sizeof(*data)); + return -EINVAL; + } + + size = data->size + sizeof(*data); + + /* copy from kcontrol */ + memcpy(data, ucontrol->value.bytes.data, size); + + sof_ipc4_set_get_bytes_data(sdev, scontrol, true, true); + + return 0; +} + +static int sof_ipc4_bytes_get(struct snd_sof_control *scontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct sof_ipc4_control_data *cdata = scontrol->ipc_control_data; + struct snd_soc_component *scomp = scontrol->scomp; + struct sof_abi_hdr *data = cdata->data; + size_t size; + + if (scontrol->max_size > sizeof(ucontrol->value.bytes.data)) { + dev_err_ratelimited(scomp->dev, "data max %zu exceeds ucontrol data array size\n", + scontrol->max_size); + return -EINVAL; + } + + if (data->size > scontrol->max_size - sizeof(*data)) { + dev_err_ratelimited(scomp->dev, + "%u bytes of control data is invalid, max is %zu\n", + data->size, scontrol->max_size - sizeof(*data)); + return -EINVAL; + } + + size = data->size + sizeof(*data); + + /* copy back to kcontrol */ + memcpy(ucontrol->value.bytes.data, data, size); + + return 0; +} + +static int sof_ipc4_bytes_ext_put(struct snd_sof_control *scontrol, + const unsigned int __user *binary_data, + unsigned int size) +{ + struct snd_ctl_tlv __user *tlvd = (struct snd_ctl_tlv __user *)binary_data; + struct sof_ipc4_control_data *cdata = scontrol->ipc_control_data; + struct snd_soc_component *scomp = scontrol->scomp; + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); + struct sof_abi_hdr *data = cdata->data; + struct sof_abi_hdr abi_hdr; + struct snd_ctl_tlv header; + + /* + * The beginning of bytes data contains a header from where + * the length (as bytes) is needed to know the correct copy + * length of data from tlvd->tlv. + */ + if (copy_from_user(&header, tlvd, sizeof(struct snd_ctl_tlv))) + return -EFAULT; + + /* make sure TLV info is consistent */ + if (header.length + sizeof(struct snd_ctl_tlv) > size) { + dev_err_ratelimited(scomp->dev, + "Inconsistent TLV, data %d + header %zu > %d\n", + header.length, sizeof(struct snd_ctl_tlv), size); + return -EINVAL; + } + + /* be->max is coming from topology */ + if (header.length > scontrol->max_size) { + dev_err_ratelimited(scomp->dev, + "Bytes data size %d exceeds max %zu\n", + header.length, scontrol->max_size); + return -EINVAL; + } + + /* Verify the ABI header first */ + if (copy_from_user(&abi_hdr, tlvd->tlv, sizeof(abi_hdr))) + return -EFAULT; + + if (abi_hdr.magic != SOF_IPC4_ABI_MAGIC) { + dev_err_ratelimited(scomp->dev, "Wrong ABI magic 0x%08x\n", + abi_hdr.magic); + return -EINVAL; + } + + if (abi_hdr.size > scontrol->max_size - sizeof(abi_hdr)) { + dev_err_ratelimited(scomp->dev, + "%u bytes of control data is invalid, max is %zu\n", + abi_hdr.size, scontrol->max_size - sizeof(abi_hdr)); + return -EINVAL; + } + + /* Copy the whole binary data which includes the ABI header and the payload */ + if (copy_from_user(data, tlvd->tlv, header.length)) + return -EFAULT; + + sof_ipc4_set_get_bytes_data(sdev, scontrol, true, true); + + return 0; +} + +static int _sof_ipc4_bytes_ext_get(struct snd_sof_control *scontrol, + const unsigned int __user *binary_data, + unsigned int size, bool from_dsp) +{ + struct snd_ctl_tlv __user *tlvd = (struct snd_ctl_tlv __user *)binary_data; + struct sof_ipc4_control_data *cdata = scontrol->ipc_control_data; + struct snd_soc_component *scomp = scontrol->scomp; + struct sof_abi_hdr *data = cdata->data; + struct snd_ctl_tlv header; + size_t data_size; + + /* + * Decrement the limit by ext bytes header size to ensure the user space + * buffer is not exceeded. + */ + if (size < sizeof(struct snd_ctl_tlv)) + return -ENOSPC; + + size -= sizeof(struct snd_ctl_tlv); + + /* get all the component data from DSP */ + if (from_dsp) { + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); + int ret = sof_ipc4_set_get_bytes_data(sdev, scontrol, false, true); + + if (ret < 0) + return ret; + + /* Set the ABI magic (if the control is not initialized) */ + data->magic = SOF_IPC4_ABI_MAGIC; + } + + if (data->size > scontrol->max_size - sizeof(*data)) { + dev_err_ratelimited(scomp->dev, + "%u bytes of control data is invalid, max is %zu\n", + data->size, scontrol->max_size - sizeof(*data)); + return -EINVAL; + } + + data_size = data->size + sizeof(struct sof_abi_hdr); + + /* make sure we don't exceed size provided by user space for data */ + if (data_size > size) + return -ENOSPC; + + header.numid = scontrol->comp_id; + header.length = data_size; + + if (copy_to_user(tlvd, &header, sizeof(struct snd_ctl_tlv))) + return -EFAULT; + + if (copy_to_user(tlvd->tlv, data, data_size)) + return -EFAULT; + + return 0; +} + +static int sof_ipc4_bytes_ext_get(struct snd_sof_control *scontrol, + const unsigned int __user *binary_data, + unsigned int size) +{ + return _sof_ipc4_bytes_ext_get(scontrol, binary_data, size, false); +} + +static int sof_ipc4_bytes_ext_volatile_get(struct snd_sof_control *scontrol, + const unsigned int __user *binary_data, + unsigned int size) +{ + return _sof_ipc4_bytes_ext_get(scontrol, binary_data, size, true); +} + /* set up all controls for the widget */ static int sof_ipc4_widget_kcontrol_setup(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) { struct snd_sof_control *scontrol; - int ret; + int ret = 0; list_for_each_entry(scontrol, &sdev->kcontrol_list, list) { if (scontrol->comp_id == swidget->comp_id) { @@ -194,11 +420,10 @@ static int sof_ipc4_widget_kcontrol_setup(struct snd_sof_dev *sdev, struct snd_s case SND_SOC_TPLG_CTL_VOLSW_XR_SX: ret = sof_ipc4_set_volume_data(sdev, swidget, scontrol, false); - if (ret < 0) { - dev_err(sdev->dev, "kcontrol %d set up failed for widget %s\n", - scontrol->comp_id, swidget->widget->name); - return ret; - } + break; + case SND_SOC_TPLG_CTL_BYTES: + ret = sof_ipc4_set_get_bytes_data(sdev, scontrol, + true, false); break; default: break; @@ -206,7 +431,11 @@ static int sof_ipc4_widget_kcontrol_setup(struct snd_sof_dev *sdev, struct snd_s } } - return 0; + if (ret < 0) + dev_err(sdev->dev, "kcontrol %d set up failed for widget %s\n", + scontrol->comp_id, swidget->widget->name); + + return ret; } static int @@ -234,6 +463,11 @@ sof_ipc4_set_up_volume_table(struct snd_sof_control *scontrol, int tlv[SOF_TLV_I const struct sof_ipc_tplg_control_ops tplg_ipc4_control_ops = { .volume_put = sof_ipc4_volume_put, .volume_get = sof_ipc4_volume_get, + .bytes_put = sof_ipc4_bytes_put, + .bytes_get = sof_ipc4_bytes_get, + .bytes_ext_put = sof_ipc4_bytes_ext_put, + .bytes_ext_get = sof_ipc4_bytes_ext_get, + .bytes_ext_volatile_get = sof_ipc4_bytes_ext_volatile_get, .widget_kcontrol_setup = sof_ipc4_widget_kcontrol_setup, .set_up_volume_table = sof_ipc4_set_up_volume_table, }; From 3f738e4a126c9ee082d814edeb7416697f9e2b37 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Mon, 13 Mar 2023 14:48:46 +0200 Subject: [PATCH 334/778] ASoC: SOF: rename a couple of tokens MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename SOF_TKN_CAVS_AUDIO_FORMAT_IN_VALID and SOF_TKN_CAVS_AUDIO_FORMAT_OUT_VALID as SOF_TKN_CAVS_AUDIO_FORMAT_IN_VALID_BIT_DEPTH and SOF_TKN_CAVS_AUDIO_FORMAT_OUT_VALID_BIT_DEPTH respectively. These are currently not used. Signed-off-by: Ranjani Sridharan Reviewed-by: Rander Wang Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230313124856.8140-2-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- include/uapi/sound/sof/tokens.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/uapi/sound/sof/tokens.h b/include/uapi/sound/sof/tokens.h index bacaf8a6317e..a1ef6b5c0d45 100644 --- a/include/uapi/sound/sof/tokens.h +++ b/include/uapi/sound/sof/tokens.h @@ -173,7 +173,7 @@ /* CAVS AUDIO FORMAT */ #define SOF_TKN_CAVS_AUDIO_FORMAT_IN_RATE 1900 #define SOF_TKN_CAVS_AUDIO_FORMAT_IN_BIT_DEPTH 1901 -#define SOF_TKN_CAVS_AUDIO_FORMAT_IN_VALID_BIT 1902 +#define SOF_TKN_CAVS_AUDIO_FORMAT_IN_VALID_BIT_DEPTH 1902 #define SOF_TKN_CAVS_AUDIO_FORMAT_IN_CHANNELS 1903 #define SOF_TKN_CAVS_AUDIO_FORMAT_IN_CH_MAP 1904 #define SOF_TKN_CAVS_AUDIO_FORMAT_IN_CH_CFG 1905 @@ -183,7 +183,7 @@ /* intentional token numbering discontinuity, reserved for future use */ #define SOF_TKN_CAVS_AUDIO_FORMAT_OUT_RATE 1930 #define SOF_TKN_CAVS_AUDIO_FORMAT_OUT_BIT_DEPTH 1931 -#define SOF_TKN_CAVS_AUDIO_FORMAT_OUT_VALID_BIT 1932 +#define SOF_TKN_CAVS_AUDIO_FORMAT_OUT_VALID_BIT_DEPTH 1932 #define SOF_TKN_CAVS_AUDIO_FORMAT_OUT_CHANNELS 1933 #define SOF_TKN_CAVS_AUDIO_FORMAT_OUT_CH_MAP 1934 #define SOF_TKN_CAVS_AUDIO_FORMAT_OUT_CH_CFG 1935 From bb79f2a608245cd92b3183d77aec6902e51de950 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Mon, 13 Mar 2023 14:48:47 +0200 Subject: [PATCH 335/778] ASoC: SOF: Use input/output pin consistently MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently we use input/output and sink/source pins interchangeably. Remove the references to sink/source pins and replace with input/output pins everywhere for consistency and clarity. Signed-off-by: Ranjani Sridharan Reviewed-by: Rander Wang Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230313124856.8140-3-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- include/uapi/sound/sof/tokens.h | 12 ++--- sound/soc/sof/ipc4-topology.c | 48 ++++++++++---------- sound/soc/sof/sof-audio.h | 32 ++++++------- sound/soc/sof/topology.c | 80 ++++++++++++++++----------------- 4 files changed, 86 insertions(+), 86 deletions(-) diff --git a/include/uapi/sound/sof/tokens.h b/include/uapi/sound/sof/tokens.h index a1ef6b5c0d45..0b5110427132 100644 --- a/include/uapi/sound/sof/tokens.h +++ b/include/uapi/sound/sof/tokens.h @@ -88,14 +88,14 @@ #define SOF_TKN_COMP_CPC 406 #define SOF_TKN_COMP_IS_PAGES 409 #define SOF_TKN_COMP_NUM_AUDIO_FORMATS 410 -#define SOF_TKN_COMP_NUM_SINK_PINS 411 -#define SOF_TKN_COMP_NUM_SOURCE_PINS 412 +#define SOF_TKN_COMP_NUM_INPUT_PINS 411 +#define SOF_TKN_COMP_NUM_OUTPUT_PINS 412 /* - * The token for sink/source pin binding, it specifies the widget - * name that the sink/source pin is connected from/to. + * The token for input/output pin binding, it specifies the widget + * name that the input/output pin is connected from/to. */ -#define SOF_TKN_COMP_SINK_PIN_BINDING_WNAME 413 -#define SOF_TKN_COMP_SRC_PIN_BINDING_WNAME 414 +#define SOF_TKN_COMP_INPUT_PIN_BINDING_WNAME 413 +#define SOF_TKN_COMP_OUTPUT_PIN_BINDING_WNAME 414 /* SSP */ diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index 0bb16ed38e48..a501eb9befa8 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -1698,17 +1698,17 @@ static int sof_ipc4_get_queue_id(struct snd_sof_widget *src_widget, u32 num_pins; int i; - if (pin_type == SOF_PIN_TYPE_SOURCE) { + if (pin_type == SOF_PIN_TYPE_OUTPUT) { current_swidget = src_widget; - pin_binding = src_widget->src_pin_binding; - queue_ida = &src_widget->src_queue_ida; - num_pins = src_widget->num_source_pins; + pin_binding = src_widget->output_pin_binding; + queue_ida = &src_widget->output_queue_ida; + num_pins = src_widget->num_output_pins; buddy_name = sink_widget->widget->name; } else { current_swidget = sink_widget; - pin_binding = sink_widget->sink_pin_binding; - queue_ida = &sink_widget->sink_queue_ida; - num_pins = sink_widget->num_sink_pins; + pin_binding = sink_widget->input_pin_binding; + queue_ida = &sink_widget->input_queue_ida; + num_pins = sink_widget->num_input_pins; buddy_name = src_widget->widget->name; } @@ -1716,12 +1716,12 @@ static int sof_ipc4_get_queue_id(struct snd_sof_widget *src_widget, if (num_pins < 1) { dev_err(scomp->dev, "invalid %s num_pins: %d for queue allocation for %s\n", - (pin_type == SOF_PIN_TYPE_SOURCE ? "source" : "sink"), + (pin_type == SOF_PIN_TYPE_OUTPUT ? "output" : "input"), num_pins, current_swidget->widget->name); return -EINVAL; } - /* If there is only one sink/source pin, queue id must be 0 */ + /* If there is only one input/output pin, queue id must be 0 */ if (num_pins == 1) return 0; @@ -1736,7 +1736,7 @@ static int sof_ipc4_get_queue_id(struct snd_sof_widget *src_widget, * mixed use pin binding array and ida for queue ID allocation. */ dev_err(scomp->dev, "no %s queue id found from pin binding array for %s\n", - (pin_type == SOF_PIN_TYPE_SOURCE ? "source" : "sink"), + (pin_type == SOF_PIN_TYPE_OUTPUT ? "output" : "input"), current_swidget->widget->name); return -EINVAL; } @@ -1752,14 +1752,14 @@ static void sof_ipc4_put_queue_id(struct snd_sof_widget *swidget, int queue_id, char **pin_binding; int num_pins; - if (pin_type == SOF_PIN_TYPE_SOURCE) { - pin_binding = swidget->src_pin_binding; - queue_ida = &swidget->src_queue_ida; - num_pins = swidget->num_source_pins; + if (pin_type == SOF_PIN_TYPE_OUTPUT) { + pin_binding = swidget->output_pin_binding; + queue_ida = &swidget->output_queue_ida; + num_pins = swidget->num_output_pins; } else { - pin_binding = swidget->sink_pin_binding; - queue_ida = &swidget->sink_queue_ida; - num_pins = swidget->num_sink_pins; + pin_binding = swidget->input_pin_binding; + queue_ida = &swidget->input_queue_ida; + num_pins = swidget->num_input_pins; } /* Nothing to free if queue ID is not allocated with ida. */ @@ -1829,7 +1829,7 @@ static int sof_ipc4_route_setup(struct snd_sof_dev *sdev, struct snd_sof_route * int ret; sroute->src_queue_id = sof_ipc4_get_queue_id(src_widget, sink_widget, - SOF_PIN_TYPE_SOURCE); + SOF_PIN_TYPE_OUTPUT); if (sroute->src_queue_id < 0) { dev_err(sdev->dev, "failed to get queue ID for source widget: %s\n", src_widget->widget->name); @@ -1837,12 +1837,12 @@ static int sof_ipc4_route_setup(struct snd_sof_dev *sdev, struct snd_sof_route * } sroute->dst_queue_id = sof_ipc4_get_queue_id(src_widget, sink_widget, - SOF_PIN_TYPE_SINK); + SOF_PIN_TYPE_INPUT); if (sroute->dst_queue_id < 0) { dev_err(sdev->dev, "failed to get queue ID for sink widget: %s\n", sink_widget->widget->name); sof_ipc4_put_queue_id(src_widget, sroute->src_queue_id, - SOF_PIN_TYPE_SOURCE); + SOF_PIN_TYPE_OUTPUT); return sroute->dst_queue_id; } @@ -1886,8 +1886,8 @@ static int sof_ipc4_route_setup(struct snd_sof_dev *sdev, struct snd_sof_route * return ret; out: - sof_ipc4_put_queue_id(src_widget, sroute->src_queue_id, SOF_PIN_TYPE_SOURCE); - sof_ipc4_put_queue_id(sink_widget, sroute->dst_queue_id, SOF_PIN_TYPE_SINK); + sof_ipc4_put_queue_id(src_widget, sroute->src_queue_id, SOF_PIN_TYPE_OUTPUT); + sof_ipc4_put_queue_id(sink_widget, sroute->dst_queue_id, SOF_PIN_TYPE_INPUT); return ret; } @@ -1932,8 +1932,8 @@ static int sof_ipc4_route_free(struct snd_sof_dev *sdev, struct snd_sof_route *s src_widget->widget->name, sroute->src_queue_id, sink_widget->widget->name, sroute->dst_queue_id); out: - sof_ipc4_put_queue_id(sink_widget, sroute->dst_queue_id, SOF_PIN_TYPE_SINK); - sof_ipc4_put_queue_id(src_widget, sroute->src_queue_id, SOF_PIN_TYPE_SOURCE); + sof_ipc4_put_queue_id(sink_widget, sroute->dst_queue_id, SOF_PIN_TYPE_INPUT); + sof_ipc4_put_queue_id(src_widget, sroute->src_queue_id, SOF_PIN_TYPE_OUTPUT); return ret; } diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h index 239b82f37976..a1c4d3f34153 100644 --- a/sound/soc/sof/sof-audio.h +++ b/sound/soc/sof/sof-audio.h @@ -30,9 +30,9 @@ */ #define SOF_WIDGET_MAX_NUM_PINS 8 -/* The type of a widget pin is either sink or source */ -#define SOF_PIN_TYPE_SINK 0 -#define SOF_PIN_TYPE_SOURCE 1 +/* Widget pin type */ +#define SOF_PIN_TYPE_INPUT 0 +#define SOF_PIN_TYPE_OUTPUT 1 /* max number of FE PCMs before BEs */ #define SOF_BE_PCM_BASE 16 @@ -433,31 +433,31 @@ struct snd_sof_widget { struct snd_sof_tuple *tuples; /* - * The allowed range for num_sink/source_pins is [0, SOF_WIDGET_MAX_NUM_PINS]. - * Widgets may have zero sink or source pins, for example the tone widget has - * zero sink pins. + * The allowed range for num_input/output_pins is [0, SOF_WIDGET_MAX_NUM_PINS]. + * Widgets may have zero input or output pins, for example the tone widget has + * zero input pins. */ - u32 num_sink_pins; - u32 num_source_pins; + u32 num_input_pins; + u32 num_output_pins; /* - * The sink/source pin binding array, it takes the form of + * The input/output pin binding array, it takes the form of * [widget_name_connected_to_pin0, widget_name_connected_to_pin1, ...], * with the index as the queue ID. * * The array is used for special pin binding. Note that even if there - * is only one sink/source pin requires special pin binding, pin binding - * should be defined for all sink/source pins in topology, for pin(s) that + * is only one input/output pin requires special pin binding, pin binding + * should be defined for all input/output pins in topology, for pin(s) that * are not used, give the value "NotConnected". * * If pin binding is not defined in topology, nothing to parse in the kernel, - * sink_pin_binding and src_pin_binding shall be NULL. + * input_pin_binding and output_pin_binding shall be NULL. */ - char **sink_pin_binding; - char **src_pin_binding; + char **input_pin_binding; + char **output_pin_binding; - struct ida src_queue_ida; - struct ida sink_queue_ida; + struct ida output_queue_ida; + struct ida input_queue_ida; void *private; /* core does not touch this */ }; diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 9f3a038fe21a..9f84b4c362c3 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -416,19 +416,19 @@ static const struct sof_topology_token led_tokens[] = { }; static const struct sof_topology_token comp_pin_tokens[] = { - {SOF_TKN_COMP_NUM_SINK_PINS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, - offsetof(struct snd_sof_widget, num_sink_pins)}, - {SOF_TKN_COMP_NUM_SOURCE_PINS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, - offsetof(struct snd_sof_widget, num_source_pins)}, + {SOF_TKN_COMP_NUM_INPUT_PINS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, + offsetof(struct snd_sof_widget, num_input_pins)}, + {SOF_TKN_COMP_NUM_OUTPUT_PINS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, + offsetof(struct snd_sof_widget, num_output_pins)}, }; -static const struct sof_topology_token comp_sink_pin_binding_tokens[] = { - {SOF_TKN_COMP_SINK_PIN_BINDING_WNAME, SND_SOC_TPLG_TUPLE_TYPE_STRING, +static const struct sof_topology_token comp_input_pin_binding_tokens[] = { + {SOF_TKN_COMP_INPUT_PIN_BINDING_WNAME, SND_SOC_TPLG_TUPLE_TYPE_STRING, get_token_string, 0}, }; -static const struct sof_topology_token comp_src_pin_binding_tokens[] = { - {SOF_TKN_COMP_SRC_PIN_BINDING_WNAME, SND_SOC_TPLG_TUPLE_TYPE_STRING, +static const struct sof_topology_token comp_output_pin_binding_tokens[] = { + {SOF_TKN_COMP_OUTPUT_PIN_BINDING_WNAME, SND_SOC_TPLG_TUPLE_TYPE_STRING, get_token_string, 0}, }; @@ -1286,12 +1286,12 @@ static void sof_free_pin_binding(struct snd_sof_widget *swidget, u32 num_pins; int i; - if (pin_type == SOF_PIN_TYPE_SINK) { - pin_binding = swidget->sink_pin_binding; - num_pins = swidget->num_sink_pins; + if (pin_type == SOF_PIN_TYPE_INPUT) { + pin_binding = swidget->input_pin_binding; + num_pins = swidget->num_input_pins; } else { - pin_binding = swidget->src_pin_binding; - num_pins = swidget->num_source_pins; + pin_binding = swidget->output_pin_binding; + num_pins = swidget->num_output_pins; } if (pin_binding) { @@ -1313,14 +1313,14 @@ static int sof_parse_pin_binding(struct snd_sof_widget *swidget, int ret; int i; - if (pin_type == SOF_PIN_TYPE_SINK) { - num_pins = swidget->num_sink_pins; - pin_binding_token = comp_sink_pin_binding_tokens; - token_count = ARRAY_SIZE(comp_sink_pin_binding_tokens); + if (pin_type == SOF_PIN_TYPE_INPUT) { + num_pins = swidget->num_input_pins; + pin_binding_token = comp_input_pin_binding_tokens; + token_count = ARRAY_SIZE(comp_input_pin_binding_tokens); } else { - num_pins = swidget->num_source_pins; - pin_binding_token = comp_src_pin_binding_tokens; - token_count = ARRAY_SIZE(comp_src_pin_binding_tokens); + num_pins = swidget->num_output_pins; + pin_binding_token = comp_output_pin_binding_tokens; + token_count = ARRAY_SIZE(comp_output_pin_binding_tokens); } memset(pin_binding, 0, SOF_WIDGET_MAX_NUM_PINS * sizeof(char *)); @@ -1337,10 +1337,10 @@ static int sof_parse_pin_binding(struct snd_sof_widget *swidget, ret = -ENOMEM; goto err; } - if (pin_type == SOF_PIN_TYPE_SINK) - swidget->sink_pin_binding = pb; + if (pin_type == SOF_PIN_TYPE_INPUT) + swidget->input_pin_binding = pb; else - swidget->src_pin_binding = pb; + swidget->output_pin_binding = pb; } return 0; @@ -1379,8 +1379,8 @@ static int sof_widget_ready(struct snd_soc_component *scomp, int index, swidget->private = NULL; mutex_init(&swidget->setup_mutex); - ida_init(&swidget->src_queue_ida); - ida_init(&swidget->sink_queue_ida); + ida_init(&swidget->output_queue_ida); + ida_init(&swidget->input_queue_ida); ret = sof_parse_tokens(scomp, swidget, comp_pin_tokens, ARRAY_SIZE(comp_pin_tokens), priv->array, @@ -1391,29 +1391,29 @@ static int sof_widget_ready(struct snd_soc_component *scomp, int index, goto widget_free; } - if (swidget->num_sink_pins > SOF_WIDGET_MAX_NUM_PINS || - swidget->num_source_pins > SOF_WIDGET_MAX_NUM_PINS) { - dev_err(scomp->dev, "invalid pins for %s: [sink: %d, src: %d]\n", - swidget->widget->name, swidget->num_sink_pins, swidget->num_source_pins); + if (swidget->num_input_pins > SOF_WIDGET_MAX_NUM_PINS || + swidget->num_output_pins > SOF_WIDGET_MAX_NUM_PINS) { + dev_err(scomp->dev, "invalid pins for %s: [input: %d, output: %d]\n", + swidget->widget->name, swidget->num_input_pins, swidget->num_output_pins); ret = -EINVAL; goto widget_free; } - if (swidget->num_sink_pins > 1) { - ret = sof_parse_pin_binding(swidget, priv, SOF_PIN_TYPE_SINK); + if (swidget->num_input_pins > 1) { + ret = sof_parse_pin_binding(swidget, priv, SOF_PIN_TYPE_INPUT); /* on parsing error, pin binding is not allocated, nothing to free. */ if (ret < 0) { - dev_err(scomp->dev, "failed to parse sink pin binding for %s\n", + dev_err(scomp->dev, "failed to parse input pin binding for %s\n", w->name); goto widget_free; } } - if (swidget->num_source_pins > 1) { - ret = sof_parse_pin_binding(swidget, priv, SOF_PIN_TYPE_SOURCE); + if (swidget->num_output_pins > 1) { + ret = sof_parse_pin_binding(swidget, priv, SOF_PIN_TYPE_OUTPUT); /* on parsing error, pin binding is not allocated, nothing to free. */ if (ret < 0) { - dev_err(scomp->dev, "failed to parse source pin binding for %s\n", + dev_err(scomp->dev, "failed to parse output pin binding for %s\n", w->name); goto widget_free; } @@ -1422,7 +1422,7 @@ static int sof_widget_ready(struct snd_soc_component *scomp, int index, dev_dbg(scomp->dev, "tplg: widget %d (%s) is ready [type: %d, pipe: %d, pins: %d / %d, stream: %s]\n", swidget->comp_id, w->name, swidget->id, index, - swidget->num_sink_pins, swidget->num_source_pins, + swidget->num_input_pins, swidget->num_output_pins, strnlen(w->sname, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) > 0 ? w->sname : "none"); widget_ops = tplg_ops ? tplg_ops->widget : NULL; @@ -1643,11 +1643,11 @@ out: if (widget_ops && widget_ops[swidget->id].ipc_free) widget_ops[swidget->id].ipc_free(swidget); - ida_destroy(&swidget->src_queue_ida); - ida_destroy(&swidget->sink_queue_ida); + ida_destroy(&swidget->output_queue_ida); + ida_destroy(&swidget->input_queue_ida); - sof_free_pin_binding(swidget, SOF_PIN_TYPE_SINK); - sof_free_pin_binding(swidget, SOF_PIN_TYPE_SOURCE); + sof_free_pin_binding(swidget, SOF_PIN_TYPE_INPUT); + sof_free_pin_binding(swidget, SOF_PIN_TYPE_OUTPUT); kfree(swidget->tuples); From e63a73f94fef0cf592aa7bb55f907007d747af4f Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Mon, 13 Mar 2023 14:48:48 +0200 Subject: [PATCH 336/778] ASoC: SOF: ipc4-topology: Add a new field in struct sof_ipc4_available_audio_format MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a new field, input_audio_fmts, in struct sof_ipc4_available_audio_format and parse all the available input audio formats into this new field and not into the base_config field. This is preparation to remove the base_config array from the struct sof_ipc4_available_audio_format. This simplifies the sof_ipc4_init_audio_fmt() function as the reference audio format for matching with input params has the same size. Signed-off-by: Ranjani Sridharan Reviewed-by: Rander Wang Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230313124856.8140-4-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-pcm.c | 2 +- sound/soc/sof/ipc4-topology.c | 119 ++++++++++++++++++---------------- sound/soc/sof/ipc4-topology.h | 2 + 3 files changed, 65 insertions(+), 58 deletions(-) diff --git a/sound/soc/sof/ipc4-pcm.c b/sound/soc/sof/ipc4-pcm.c index 68258767aace..a679c08d9bb1 100644 --- a/sound/soc/sof/ipc4-pcm.c +++ b/sound/soc/sof/ipc4-pcm.c @@ -389,7 +389,7 @@ static int sof_ipc4_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, snd_mask_none(fmt); snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S32_LE); - rate->min = ipc4_copier->available_fmt.base_config->audio_fmt.sampling_frequency; + rate->min = ipc4_copier->available_fmt.input_audio_fmts->sampling_frequency; rate->max = rate->min; switch (ipc4_copier->dai_type) { diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index a501eb9befa8..d56e0f12b5d0 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -180,7 +180,7 @@ static int sof_ipc4_get_audio_fmt(struct snd_soc_component *scomp, bool has_out_format) { struct sof_ipc4_base_module_cfg *base_config; - struct sof_ipc4_audio_format *out_format; + struct sof_ipc4_audio_format *out_format, *in_format; int audio_fmt_num = 0; int ret, i; @@ -206,7 +206,7 @@ static int sof_ipc4_get_audio_fmt(struct snd_soc_component *scomp, swidget->num_tuples, sizeof(*base_config), 1); if (ret) { dev_err(scomp->dev, "parse comp tokens failed %d\n", ret); - goto err_in; + goto err; } } @@ -217,7 +217,7 @@ static int sof_ipc4_get_audio_fmt(struct snd_soc_component *scomp, available_fmt->audio_fmt_num); if (ret) { dev_err(scomp->dev, "parse buffer size tokens failed %d\n", ret); - goto err_in; + goto err; } for (i = 0; i < available_fmt->audio_fmt_num; i++) @@ -225,9 +225,17 @@ static int sof_ipc4_get_audio_fmt(struct snd_soc_component *scomp, base_config[i].ibs, base_config[i].obs, base_config[i].cpc, base_config[i].is_pages); - ret = sof_update_ipc_object(scomp, &base_config->audio_fmt, + in_format = kcalloc(available_fmt->audio_fmt_num, + sizeof(struct sof_ipc4_audio_format), GFP_KERNEL); + if (!in_format) { + kfree(base_config); + ret = -ENOMEM; + goto err; + } + + ret = sof_update_ipc_object(scomp, available_fmt->input_audio_fmts, SOF_IN_AUDIO_FORMAT_TOKENS, swidget->tuples, - swidget->num_tuples, sizeof(*base_config), + swidget->num_tuples, sizeof(struct sof_ipc4_audio_format), available_fmt->audio_fmt_num); if (ret) { dev_err(scomp->dev, "parse base_config audio_fmt tokens failed %d\n", ret); @@ -235,12 +243,10 @@ static int sof_ipc4_get_audio_fmt(struct snd_soc_component *scomp, } dev_dbg(scomp->dev, "Get input audio formats for %s\n", swidget->widget->name); - sof_ipc4_dbg_audio_format(scomp->dev, &base_config->audio_fmt, - sizeof(*base_config), + sof_ipc4_dbg_audio_format(scomp->dev, available_fmt->input_audio_fmts, + sizeof(struct sof_ipc4_audio_format), available_fmt->audio_fmt_num); - available_fmt->base_config = base_config; - if (!has_out_format) return 0; @@ -260,18 +266,22 @@ static int sof_ipc4_get_audio_fmt(struct snd_soc_component *scomp, goto err_out; } - available_fmt->out_audio_fmt = out_format; dev_dbg(scomp->dev, "Get output audio formats for %s\n", swidget->widget->name); sof_ipc4_dbg_audio_format(scomp->dev, out_format, sizeof(*out_format), available_fmt->audio_fmt_num); + available_fmt->base_config = base_config; + available_fmt->out_audio_fmt = out_format; + available_fmt->input_audio_fmts = in_format; + return 0; err_out: kfree(out_format); err_in: + kfree(in_format); +err: kfree(base_config); - return ret; } @@ -283,6 +293,8 @@ static void sof_ipc4_free_audio_fmt(struct sof_ipc4_available_audio_format *avai available_fmt->base_config = NULL; kfree(available_fmt->out_audio_fmt); available_fmt->out_audio_fmt = NULL; + kfree(available_fmt->input_audio_fmts); + available_fmt->input_audio_fmts = NULL; } static void sof_ipc4_widget_free_comp_pipeline(struct snd_sof_widget *swidget) @@ -904,17 +916,16 @@ static int sof_ipc4_init_audio_fmt(struct snd_sof_dev *sdev, struct sof_ipc4_base_module_cfg *base_config, struct sof_ipc4_audio_format *out_format, struct snd_pcm_hw_params *params, - struct sof_ipc4_available_audio_format *available_fmt, - size_t object_offset) + struct sof_ipc4_available_audio_format *available_fmt) { - void *ptr = available_fmt->ref_audio_fmt; + struct sof_ipc4_audio_format *fmt = available_fmt->ref_audio_fmt; u32 valid_bits; u32 channels; u32 rate; int sample_valid_bits; int i; - if (!ptr) { + if (!fmt) { dev_err(sdev->dev, "no reference formats for %s\n", swidget->widget->name); return -EINVAL; } @@ -943,25 +954,14 @@ static int sof_ipc4_init_audio_fmt(struct snd_sof_dev *sdev, * Search supported audio formats to match rate, channels ,and * sample_valid_bytes from runtime params */ - for (i = 0; i < available_fmt->audio_fmt_num; i++, ptr = (u8 *)ptr + object_offset) { - struct sof_ipc4_audio_format *fmt = ptr; - + for (i = 0; i < available_fmt->audio_fmt_num; i++, fmt++) { rate = fmt->sampling_frequency; channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(fmt->fmt_cfg); valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt->fmt_cfg); if (params_rate(params) == rate && params_channels(params) == channels && sample_valid_bits == valid_bits) { - dev_dbg(sdev->dev, "matching audio format index for %uHz, %ubit, %u channels: %d\n", + dev_dbg(sdev->dev, "matched audio format index for %uHz, %ubit, %u channels: %d\n", rate, valid_bits, channels, i); - - /* copy ibs/obs and input format */ - memcpy(base_config, &available_fmt->base_config[i], - sizeof(struct sof_ipc4_base_module_cfg)); - - /* copy output format */ - if (out_format) - memcpy(out_format, &available_fmt->out_audio_fmt[i], - sizeof(struct sof_ipc4_audio_format)); break; } } @@ -972,10 +972,25 @@ static int sof_ipc4_init_audio_fmt(struct snd_sof_dev *sdev, return -EINVAL; } + /* copy input format */ + memcpy(&base_config->audio_fmt, &available_fmt->input_audio_fmts[i], sizeof(*fmt)); + + /* set base_cfg ibs/obs */ + base_config->ibs = available_fmt->base_config[i].ibs; + base_config->obs = available_fmt->base_config[i].obs; + dev_dbg(sdev->dev, "Init input audio formats for %s\n", swidget->widget->name); sof_ipc4_dbg_audio_format(sdev->dev, &base_config->audio_fmt, sizeof(*base_config), 1); if (out_format) { + /* + * Current topology defines pin 0 input and output formats only in pairs. + * This assumes that the pin 0 formats are defined before all other pins. + * So pick the output audio format with the same index as the chosen + * input format. This logic will need to be updated when the format definitions + * in topology change. + */ + memcpy(out_format, &available_fmt->out_audio_fmt[i], sizeof(*fmt)); dev_dbg(sdev->dev, "Init output audio formats for %s\n", swidget->widget->name); sof_ipc4_dbg_audio_format(sdev->dev, out_format, sizeof(*out_format), 1); @@ -1147,7 +1162,6 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, struct snd_sof_dai *dai; struct snd_mask *fmt; int out_sample_valid_bits; - size_t ref_audio_fmt_size; void **ipc_config_data; int *ipc_config_size; u32 **data; @@ -1171,17 +1185,14 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, available_fmt = &ipc4_copier->available_fmt; /* - * base_config->audio_fmt and out_audio_fmt represent the input and output audio - * formats. Use the input format as the reference to match pcm params for playback - * and the output format as reference for capture. + * Use the input_audio_fmts to match pcm params for playback and the out_audio_fmt + * for capture. */ - if (dir == SNDRV_PCM_STREAM_PLAYBACK) { - available_fmt->ref_audio_fmt = &available_fmt->base_config->audio_fmt; - ref_audio_fmt_size = sizeof(struct sof_ipc4_base_module_cfg); - } else { + if (dir == SNDRV_PCM_STREAM_PLAYBACK) + available_fmt->ref_audio_fmt = available_fmt->input_audio_fmts; + else available_fmt->ref_audio_fmt = available_fmt->out_audio_fmt; - ref_audio_fmt_size = sizeof(struct sof_ipc4_audio_format); - } + copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK; copier_data->gtw_cfg.node_id |= SOF_IPC4_NODE_INDEX(platform_params->stream_tag - 1); @@ -1201,7 +1212,6 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, available_fmt = &ipc4_copier->available_fmt; if (dir == SNDRV_PCM_STREAM_CAPTURE) { available_fmt->ref_audio_fmt = available_fmt->out_audio_fmt; - ref_audio_fmt_size = sizeof(struct sof_ipc4_audio_format); /* * modify the input params for the dai copier as it only supports @@ -1211,8 +1221,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, snd_mask_none(fmt); snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S32_LE); } else { - available_fmt->ref_audio_fmt = &available_fmt->base_config->audio_fmt; - ref_audio_fmt_size = sizeof(struct sof_ipc4_base_module_cfg); + available_fmt->ref_audio_fmt = available_fmt->input_audio_fmts; } ref_params = pipeline_params; @@ -1232,12 +1241,8 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, copier_data = &ipc4_copier->data; available_fmt = &ipc4_copier->available_fmt; - /* - * base_config->audio_fmt represent the input audio formats. Use - * the input format as the reference to match pcm params - */ - available_fmt->ref_audio_fmt = &available_fmt->base_config->audio_fmt; - ref_audio_fmt_size = sizeof(struct sof_ipc4_base_module_cfg); + /* Use the input formats as the reference to match pcm params */ + available_fmt->ref_audio_fmt = available_fmt->input_audio_fmts; ref_params = pipeline_params; break; @@ -1251,7 +1256,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, /* set input and output audio formats */ ret = sof_ipc4_init_audio_fmt(sdev, swidget, &copier_data->base_config, &copier_data->out_format, ref_params, - available_fmt, ref_audio_fmt_size); + available_fmt); if (ret < 0) return ret; @@ -1400,14 +1405,14 @@ static int sof_ipc4_prepare_gain_module(struct snd_sof_widget *swidget, struct snd_soc_component *scomp = swidget->scomp; struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); struct sof_ipc4_gain *gain = swidget->private; + struct sof_ipc4_available_audio_format *available_fmt = &gain->available_fmt; int ret; - gain->available_fmt.ref_audio_fmt = &gain->available_fmt.base_config->audio_fmt; + available_fmt->ref_audio_fmt = available_fmt->input_audio_fmts; /* output format is not required to be sent to the FW for gain */ ret = sof_ipc4_init_audio_fmt(sdev, swidget, &gain->base_config, - NULL, pipeline_params, &gain->available_fmt, - sizeof(gain->base_config)); + NULL, pipeline_params, available_fmt); if (ret < 0) return ret; @@ -1425,15 +1430,15 @@ static int sof_ipc4_prepare_mixer_module(struct snd_sof_widget *swidget, struct snd_soc_component *scomp = swidget->scomp; struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); struct sof_ipc4_mixer *mixer = swidget->private; + struct sof_ipc4_available_audio_format *available_fmt = &mixer->available_fmt; int ret; /* only 32bit is supported by mixer */ - mixer->available_fmt.ref_audio_fmt = &mixer->available_fmt.base_config->audio_fmt; + available_fmt->ref_audio_fmt = available_fmt->input_audio_fmts; /* output format is not required to be sent to the FW for mixer */ ret = sof_ipc4_init_audio_fmt(sdev, swidget, &mixer->base_config, - NULL, pipeline_params, &mixer->available_fmt, - sizeof(mixer->base_config)); + NULL, pipeline_params, available_fmt); if (ret < 0) return ret; @@ -1451,15 +1456,15 @@ static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget, struct snd_soc_component *scomp = swidget->scomp; struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); struct sof_ipc4_src *src = swidget->private; + struct sof_ipc4_available_audio_format *available_fmt = &src->available_fmt; struct snd_interval *rate; int ret; - src->available_fmt.ref_audio_fmt = &src->available_fmt.base_config->audio_fmt; + available_fmt->ref_audio_fmt = available_fmt->input_audio_fmts; /* output format is not required to be sent to the FW for SRC */ ret = sof_ipc4_init_audio_fmt(sdev, swidget, &src->base_config, - NULL, pipeline_params, &src->available_fmt, - sizeof(src->base_config)); + NULL, pipeline_params, available_fmt); if (ret < 0) return ret; diff --git a/sound/soc/sof/ipc4-topology.h b/sound/soc/sof/ipc4-topology.h index 22900b572766..addc5b55cc10 100644 --- a/sound/soc/sof/ipc4-topology.h +++ b/sound/soc/sof/ipc4-topology.h @@ -146,6 +146,7 @@ struct ipc4_pipeline_set_state_data { * struct sof_ipc4_available_audio_format - Available audio formats * @base_config: Available base config * @out_audio_fmt: Available output audio format + * @input_audio_fmts: Available input audio formats * @ref_audio_fmt: Reference audio format to match runtime audio format * @dma_buffer_size: Available Gateway DMA buffer size (in bytes) * @audio_fmt_num: Number of available audio formats @@ -153,6 +154,7 @@ struct ipc4_pipeline_set_state_data { struct sof_ipc4_available_audio_format { struct sof_ipc4_base_module_cfg *base_config; struct sof_ipc4_audio_format *out_audio_fmt; + struct sof_ipc4_audio_format *input_audio_fmts; struct sof_ipc4_audio_format *ref_audio_fmt; u32 *dma_buffer_size; int audio_fmt_num; From 594c1bb9ff7365b90cb4d325deb8c38ddda90557 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Mon, 13 Mar 2023 14:48:49 +0200 Subject: [PATCH 337/778] ASoC: SOF: ipc4-topology: Do not parse the DMA_BUFFER_SIZE token MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Do not parse the SOF_TKN_CAVS_AUDIO_FORMAT_DMA_BUFFER_SIZE token as the dma_buffer_size can be derived from the input/output buffer size and the type of widget during copier prepare. For the deep buffer case, introduce a new token that will be used to get the deep buffer DMA size for the host copier from topology. Signed-off-by: Ranjani Sridharan Reviewed-by: Rander Wang Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230313124856.8140-5-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- include/uapi/sound/sof/tokens.h | 1 + sound/soc/sof/ipc4-topology.c | 112 ++++++++++++++------------------ sound/soc/sof/ipc4-topology.h | 5 +- sound/soc/sof/sof-audio.h | 2 +- sound/soc/sof/topology.c | 1 - 5 files changed, 52 insertions(+), 69 deletions(-) diff --git a/include/uapi/sound/sof/tokens.h b/include/uapi/sound/sof/tokens.h index 0b5110427132..9e91e2640dd4 100644 --- a/include/uapi/sound/sof/tokens.h +++ b/include/uapi/sound/sof/tokens.h @@ -197,6 +197,7 @@ /* COPIER */ #define SOF_TKN_INTEL_COPIER_NODE_TYPE 1980 +#define SOF_TKN_INTEL_COPIER_DEEP_BUFFER_DMA_MS 1981 /* ACP I2S */ #define SOF_TKN_AMD_ACPI2S_RATE 1700 diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index d56e0f12b5d0..50cd4fe3141c 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -78,8 +78,8 @@ static const struct sof_topology_token ipc4_out_audio_format_tokens[] = { offsetof(struct sof_ipc4_audio_format, fmt_cfg)}, }; -static const struct sof_topology_token ipc4_copier_gateway_cfg_tokens[] = { - {SOF_TKN_CAVS_AUDIO_FORMAT_DMA_BUFFER_SIZE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 0}, +static const struct sof_topology_token ipc4_copier_deep_buffer_tokens[] = { + {SOF_TKN_INTEL_COPIER_DEEP_BUFFER_DMA_MS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 0}, }; static const struct sof_topology_token ipc4_copier_tokens[] = { @@ -138,8 +138,8 @@ static const struct sof_token_info ipc4_token_list[SOF_TOKEN_COUNT] = { [SOF_AUDIO_FORMAT_BUFFER_SIZE_TOKENS] = {"IPC4 Audio format buffer size tokens", ipc4_audio_format_buffer_size_tokens, ARRAY_SIZE(ipc4_audio_format_buffer_size_tokens)}, - [SOF_COPIER_GATEWAY_CFG_TOKENS] = {"IPC4 Copier gateway config tokens", - ipc4_copier_gateway_cfg_tokens, ARRAY_SIZE(ipc4_copier_gateway_cfg_tokens)}, + [SOF_COPIER_DEEP_BUFFER_TOKENS] = {"IPC4 Copier deep buffer tokens", + ipc4_copier_deep_buffer_tokens, ARRAY_SIZE(ipc4_copier_deep_buffer_tokens)}, [SOF_COPIER_TOKENS] = {"IPC4 Copier tokens", ipc4_copier_tokens, ARRAY_SIZE(ipc4_copier_tokens)}, [SOF_AUDIO_FMT_NUM_TOKENS] = {"IPC4 Audio format number tokens", @@ -348,7 +348,7 @@ static int sof_ipc4_widget_setup_pcm(struct snd_sof_widget *swidget) struct snd_soc_component *scomp = swidget->scomp; struct sof_ipc4_copier *ipc4_copier; int node_type = 0; - int ret, i; + int ret; ipc4_copier = kzalloc(sizeof(*ipc4_copier), GFP_KERNEL); if (!ipc4_copier) @@ -363,13 +363,6 @@ static int sof_ipc4_widget_setup_pcm(struct snd_sof_widget *swidget) if (ret) goto free_copier; - available_fmt->dma_buffer_size = kcalloc(available_fmt->audio_fmt_num, sizeof(u32), - GFP_KERNEL); - if (!available_fmt->dma_buffer_size) { - ret = -ENOMEM; - goto free_available_fmt; - } - /* * This callback is used by host copier and module-to-module copier, * and only host copier needs to set gtw_cfg. @@ -377,21 +370,6 @@ static int sof_ipc4_widget_setup_pcm(struct snd_sof_widget *swidget) if (!WIDGET_IS_AIF(swidget->id)) goto skip_gtw_cfg; - ret = sof_update_ipc_object(scomp, available_fmt->dma_buffer_size, - SOF_COPIER_GATEWAY_CFG_TOKENS, swidget->tuples, - swidget->num_tuples, sizeof(u32), - available_fmt->audio_fmt_num); - if (ret) { - dev_err(scomp->dev, "Failed to parse dma buffer size in audio format for %s\n", - swidget->widget->name); - goto err; - } - - dev_dbg(scomp->dev, "dma buffer size:\n"); - for (i = 0; i < available_fmt->audio_fmt_num; i++) - dev_dbg(scomp->dev, "%d: %u\n", i, - available_fmt->dma_buffer_size[i]); - ret = sof_update_ipc_object(scomp, &node_type, SOF_COPIER_TOKENS, swidget->tuples, swidget->num_tuples, sizeof(node_type), 1); @@ -399,7 +377,7 @@ static int sof_ipc4_widget_setup_pcm(struct snd_sof_widget *swidget) if (ret) { dev_err(scomp->dev, "parse host copier node type token failed %d\n", ret); - goto err; + goto free_available_fmt; } dev_dbg(scomp->dev, "host copier '%s' node_type %u\n", swidget->widget->name, node_type); @@ -407,7 +385,7 @@ skip_gtw_cfg: ipc4_copier->gtw_attr = kzalloc(sizeof(*ipc4_copier->gtw_attr), GFP_KERNEL); if (!ipc4_copier->gtw_attr) { ret = -ENOMEM; - goto err; + goto free_available_fmt; } ipc4_copier->copier_config = (uint32_t *)ipc4_copier->gtw_attr; @@ -438,8 +416,6 @@ skip_gtw_cfg: free_gtw_attr: kfree(ipc4_copier->gtw_attr); -err: - kfree(available_fmt->dma_buffer_size); free_available_fmt: sof_ipc4_free_audio_fmt(available_fmt); free_copier: @@ -457,7 +433,6 @@ static void sof_ipc4_widget_free_comp_pcm(struct snd_sof_widget *swidget) return; available_fmt = &ipc4_copier->available_fmt; - kfree(available_fmt->dma_buffer_size); kfree(available_fmt->base_config); kfree(available_fmt->out_audio_fmt); kfree(ipc4_copier->gtw_attr); @@ -472,7 +447,7 @@ static int sof_ipc4_widget_setup_comp_dai(struct snd_sof_widget *swidget) struct snd_sof_dai *dai = swidget->private; struct sof_ipc4_copier *ipc4_copier; int node_type = 0; - int ret, i; + int ret; ipc4_copier = kzalloc(sizeof(*ipc4_copier), GFP_KERNEL); if (!ipc4_copier) @@ -486,33 +461,12 @@ static int sof_ipc4_widget_setup_comp_dai(struct snd_sof_widget *swidget) if (ret) goto free_copier; - available_fmt->dma_buffer_size = kcalloc(available_fmt->audio_fmt_num, sizeof(u32), - GFP_KERNEL); - if (!available_fmt->dma_buffer_size) { - ret = -ENOMEM; - goto free_available_fmt; - } - - ret = sof_update_ipc_object(scomp, available_fmt->dma_buffer_size, - SOF_COPIER_GATEWAY_CFG_TOKENS, swidget->tuples, - swidget->num_tuples, sizeof(u32), - available_fmt->audio_fmt_num); - if (ret) { - dev_err(scomp->dev, "Failed to parse dma buffer size in audio format for %s\n", - swidget->widget->name); - goto err; - } - - for (i = 0; i < available_fmt->audio_fmt_num; i++) - dev_dbg(scomp->dev, "%d: dma buffer size: %u\n", i, - available_fmt->dma_buffer_size[i]); - ret = sof_update_ipc_object(scomp, &node_type, SOF_COPIER_TOKENS, swidget->tuples, swidget->num_tuples, sizeof(node_type), 1); if (ret) { dev_err(scomp->dev, "parse dai node type failed %d\n", ret); - goto err; + goto free_available_fmt; } ret = sof_update_ipc_object(scomp, ipc4_copier, @@ -520,7 +474,7 @@ static int sof_ipc4_widget_setup_comp_dai(struct snd_sof_widget *swidget) swidget->num_tuples, sizeof(u32), 1); if (ret) { dev_err(scomp->dev, "parse dai copier node token failed %d\n", ret); - goto err; + goto free_available_fmt; } dev_dbg(scomp->dev, "dai %s node_type %u dai_type %u dai_index %d\n", swidget->widget->name, @@ -554,7 +508,7 @@ static int sof_ipc4_widget_setup_comp_dai(struct snd_sof_widget *swidget) blob = kzalloc(sizeof(*blob), GFP_KERNEL); if (!blob) { ret = -ENOMEM; - goto err; + goto free_available_fmt; } list_for_each_entry(w, &sdev->widget_list, list) { @@ -583,7 +537,7 @@ static int sof_ipc4_widget_setup_comp_dai(struct snd_sof_widget *swidget) ipc4_copier->gtw_attr = kzalloc(sizeof(*ipc4_copier->gtw_attr), GFP_KERNEL); if (!ipc4_copier->gtw_attr) { ret = -ENOMEM; - goto err; + goto free_available_fmt; } ipc4_copier->copier_config = (uint32_t *)ipc4_copier->gtw_attr; @@ -604,8 +558,6 @@ static int sof_ipc4_widget_setup_comp_dai(struct snd_sof_widget *swidget) free_copier_config: kfree(ipc4_copier->copier_config); -err: - kfree(available_fmt->dma_buffer_size); free_available_fmt: sof_ipc4_free_audio_fmt(available_fmt); free_copier: @@ -633,7 +585,6 @@ static void sof_ipc4_widget_free_comp_dai(struct snd_sof_widget *swidget) ipc4_copier = dai->private; available_fmt = &ipc4_copier->available_fmt; - kfree(available_fmt->dma_buffer_size); kfree(available_fmt->base_config); kfree(available_fmt->out_audio_fmt); if (ipc4_copier->dai_type != SOF_DAI_INTEL_SSP && @@ -1166,6 +1117,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, int *ipc_config_size; u32 **data; int ipc_size, ret; + u32 deep_buffer_dma_ms = 0; dev_dbg(sdev->dev, "copier %s, type %d", swidget->widget->name, swidget->id); @@ -1177,6 +1129,16 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, struct snd_sof_widget *pipe_widget; struct sof_ipc4_pipeline *pipeline; + /* parse the deep buffer dma size */ + ret = sof_update_ipc_object(scomp, &deep_buffer_dma_ms, + SOF_COPIER_DEEP_BUFFER_TOKENS, swidget->tuples, + swidget->num_tuples, sizeof(u32), 1); + if (ret) { + dev_err(scomp->dev, "Failed to parse deep buffer dma size for %s\n", + swidget->widget->name); + return ret; + } + pipe_widget = swidget->spipe->pipe_widget; pipeline = pipe_widget->private; ipc4_copier = (struct sof_ipc4_copier *)swidget->private; @@ -1367,8 +1329,29 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, return -EINVAL; } - /* set the gateway dma_buffer_size using the matched ID returned above */ - copier_data->gtw_cfg.dma_buffer_size = available_fmt->dma_buffer_size[ret]; + /* + * Set the gateway dma_buffer_size to 2ms buffer size to meet the FW expectation. In the + * deep buffer case, set the dma_buffer_size depending on the deep_buffer_dma_ms set + * in topology. + */ + switch (swidget->id) { + case snd_soc_dapm_dai_in: + copier_data->gtw_cfg.dma_buffer_size = + SOF_IPC4_MIN_DMA_BUFFER_SIZE * copier_data->base_config.ibs; + break; + case snd_soc_dapm_aif_in: + copier_data->gtw_cfg.dma_buffer_size = + max((u32)SOF_IPC4_MIN_DMA_BUFFER_SIZE, deep_buffer_dma_ms) * + copier_data->base_config.ibs; + break; + case snd_soc_dapm_dai_out: + case snd_soc_dapm_aif_out: + copier_data->gtw_cfg.dma_buffer_size = + SOF_IPC4_MIN_DMA_BUFFER_SIZE * copier_data->base_config.obs; + break; + default: + break; + } data = &ipc4_copier->copier_config; ipc_config_size = &ipc4_copier->ipc_config_size; @@ -2170,7 +2153,7 @@ static enum sof_tokens common_copier_token_list[] = { SOF_AUDIO_FORMAT_BUFFER_SIZE_TOKENS, SOF_IN_AUDIO_FORMAT_TOKENS, SOF_OUT_AUDIO_FORMAT_TOKENS, - SOF_COPIER_GATEWAY_CFG_TOKENS, + SOF_COPIER_DEEP_BUFFER_TOKENS, SOF_COPIER_TOKENS, SOF_COMP_EXT_TOKENS, }; @@ -2186,7 +2169,6 @@ static enum sof_tokens dai_token_list[] = { SOF_AUDIO_FORMAT_BUFFER_SIZE_TOKENS, SOF_IN_AUDIO_FORMAT_TOKENS, SOF_OUT_AUDIO_FORMAT_TOKENS, - SOF_COPIER_GATEWAY_CFG_TOKENS, SOF_COPIER_TOKENS, SOF_DAI_TOKENS, SOF_COMP_EXT_TOKENS, diff --git a/sound/soc/sof/ipc4-topology.h b/sound/soc/sof/ipc4-topology.h index addc5b55cc10..696d6c39a21b 100644 --- a/sound/soc/sof/ipc4-topology.h +++ b/sound/soc/sof/ipc4-topology.h @@ -55,6 +55,9 @@ #define SOF_IPC4_INVALID_NODE_ID 0xffffffff +/* FW requires minimum 2ms DMA buffer size */ +#define SOF_IPC4_MIN_DMA_BUFFER_SIZE 2 + /* * The base of multi-gateways. Multi-gateways addressing starts from * ALH_MULTI_GTW_BASE and there are ALH_MULTI_GTW_COUNT multi-sources @@ -148,7 +151,6 @@ struct ipc4_pipeline_set_state_data { * @out_audio_fmt: Available output audio format * @input_audio_fmts: Available input audio formats * @ref_audio_fmt: Reference audio format to match runtime audio format - * @dma_buffer_size: Available Gateway DMA buffer size (in bytes) * @audio_fmt_num: Number of available audio formats */ struct sof_ipc4_available_audio_format { @@ -156,7 +158,6 @@ struct sof_ipc4_available_audio_format { struct sof_ipc4_audio_format *out_audio_fmt; struct sof_ipc4_audio_format *input_audio_fmts; struct sof_ipc4_audio_format *ref_audio_fmt; - u32 *dma_buffer_size; int audio_fmt_num; }; diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h index a1c4d3f34153..4504f9efdc50 100644 --- a/sound/soc/sof/sof-audio.h +++ b/sound/soc/sof/sof-audio.h @@ -257,7 +257,7 @@ enum sof_tokens { SOF_IN_AUDIO_FORMAT_TOKENS, SOF_OUT_AUDIO_FORMAT_TOKENS, SOF_AUDIO_FORMAT_BUFFER_SIZE_TOKENS, - SOF_COPIER_GATEWAY_CFG_TOKENS, + SOF_COPIER_DEEP_BUFFER_TOKENS, SOF_COPIER_TOKENS, SOF_AUDIO_FMT_NUM_TOKENS, SOF_COPIER_FORMAT_TOKENS, diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 9f84b4c362c3..2d76ab13b3d1 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -1232,7 +1232,6 @@ static int sof_widget_parse_tokens(struct snd_soc_component *scomp, struct snd_s continue; case SOF_IN_AUDIO_FORMAT_TOKENS: case SOF_OUT_AUDIO_FORMAT_TOKENS: - case SOF_COPIER_GATEWAY_CFG_TOKENS: case SOF_AUDIO_FORMAT_BUFFER_SIZE_TOKENS: num_sets = sof_get_token_value(SOF_TKN_COMP_NUM_AUDIO_FORMATS, swidget->tuples, swidget->num_tuples); From 171d5ccedbb6277a8f9a3eae36e4f465ddc3187f Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Mon, 13 Mar 2023 14:48:50 +0200 Subject: [PATCH 338/778] ASoC: SOF: ipc4-topology: Parse the SOF_COMP_TOKENS only once MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is no need to parse the cpc and is_pages values multiple times. It is enough to parse the 2 tokens directly into the base_config field in each module's init_instance IPC payload. Signed-off-by: Ranjani Sridharan Reviewed-by: Rander Wang Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230313124856.8140-6-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 41 ++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index 50cd4fe3141c..b6933fa1a36d 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -170,6 +170,7 @@ static void sof_ipc4_dbg_audio_format(struct device *dev, * @scomp: pointer to pointer to SOC component * @swidget: pointer to struct snd_sof_widget containing tuples * @available_fmt: pointer to struct sof_ipc4_available_audio_format being filling in + * @module_base_cfg: Pointer to the base_config in the module init IPC payload * @has_out_format: true if available_fmt contains output format * * Return: 0 if successful @@ -177,6 +178,7 @@ static void sof_ipc4_dbg_audio_format(struct device *dev, static int sof_ipc4_get_audio_fmt(struct snd_soc_component *scomp, struct snd_sof_widget *swidget, struct sof_ipc4_available_audio_format *available_fmt, + struct sof_ipc4_base_module_cfg *module_base_cfg, bool has_out_format) { struct sof_ipc4_base_module_cfg *base_config; @@ -199,17 +201,18 @@ static int sof_ipc4_get_audio_fmt(struct snd_soc_component *scomp, if (!base_config) return -ENOMEM; - /* set cpc and is_pages for all base_cfg */ - for (i = 0; i < available_fmt->audio_fmt_num; i++) { - ret = sof_update_ipc_object(scomp, &base_config[i], - SOF_COMP_TOKENS, swidget->tuples, - swidget->num_tuples, sizeof(*base_config), 1); - if (ret) { - dev_err(scomp->dev, "parse comp tokens failed %d\n", ret); - goto err; - } + /* set cpc and is_pages in the module's base_config */ + ret = sof_update_ipc_object(scomp, module_base_cfg, SOF_COMP_TOKENS, swidget->tuples, + swidget->num_tuples, sizeof(*module_base_cfg), 1); + if (ret) { + dev_err(scomp->dev, "parse comp tokens for %s failed, error: %d\n", + swidget->widget->name, ret); + goto err; } + dev_dbg(scomp->dev, "widget %s cpc: %d is_pages: %d\n", + swidget->widget->name, module_base_cfg->cpc, module_base_cfg->is_pages); + /* copy the ibs/obs for each base_cfg */ ret = sof_update_ipc_object(scomp, base_config, SOF_AUDIO_FORMAT_BUFFER_SIZE_TOKENS, swidget->tuples, @@ -221,9 +224,8 @@ static int sof_ipc4_get_audio_fmt(struct snd_soc_component *scomp, } for (i = 0; i < available_fmt->audio_fmt_num; i++) - dev_dbg(scomp->dev, "%d: ibs: %d obs: %d cpc: %d is_pages: %d\n", i, - base_config[i].ibs, base_config[i].obs, - base_config[i].cpc, base_config[i].is_pages); + dev_dbg(scomp->dev, "%d: ibs: %d obs: %d\n", i, + base_config[i].ibs, base_config[i].obs); in_format = kcalloc(available_fmt->audio_fmt_num, sizeof(struct sof_ipc4_audio_format), GFP_KERNEL); @@ -359,7 +361,8 @@ static int sof_ipc4_widget_setup_pcm(struct snd_sof_widget *swidget) dev_dbg(scomp->dev, "Updating IPC structure for %s\n", swidget->widget->name); - ret = sof_ipc4_get_audio_fmt(scomp, swidget, available_fmt, true); + ret = sof_ipc4_get_audio_fmt(scomp, swidget, available_fmt, + &ipc4_copier->data.base_config, true); if (ret) goto free_copier; @@ -457,7 +460,8 @@ static int sof_ipc4_widget_setup_comp_dai(struct snd_sof_widget *swidget) dev_dbg(scomp->dev, "Updating IPC structure for %s\n", swidget->widget->name); - ret = sof_ipc4_get_audio_fmt(scomp, swidget, available_fmt, true); + ret = sof_ipc4_get_audio_fmt(scomp, swidget, available_fmt, + &ipc4_copier->data.base_config, true); if (ret) goto free_copier; @@ -665,7 +669,8 @@ static int sof_ipc4_widget_setup_comp_pga(struct snd_sof_widget *swidget) gain->data.init_val = SOF_IPC4_VOL_ZERO_DB; /* The out_audio_fmt in topology is ignored as it is not required to be sent to the FW */ - ret = sof_ipc4_get_audio_fmt(scomp, swidget, &gain->available_fmt, false); + ret = sof_ipc4_get_audio_fmt(scomp, swidget, &gain->available_fmt, &gain->base_config, + false); if (ret) goto err; @@ -731,7 +736,8 @@ static int sof_ipc4_widget_setup_comp_mixer(struct snd_sof_widget *swidget) swidget->private = mixer; /* The out_audio_fmt in topology is ignored as it is not required to be sent to the FW */ - ret = sof_ipc4_get_audio_fmt(scomp, swidget, &mixer->available_fmt, false); + ret = sof_ipc4_get_audio_fmt(scomp, swidget, &mixer->available_fmt, + &mixer->base_config, false); if (ret) goto err; @@ -762,7 +768,8 @@ static int sof_ipc4_widget_setup_comp_src(struct snd_sof_widget *swidget) swidget->private = src; /* The out_audio_fmt in topology is ignored as it is not required by SRC */ - ret = sof_ipc4_get_audio_fmt(scomp, swidget, &src->available_fmt, false); + ret = sof_ipc4_get_audio_fmt(scomp, swidget, &src->available_fmt, &src->base_config, + false); if (ret) goto err; From 8abc9ab956b5756693710e1e09557e0189f01bef Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Mon, 13 Mar 2023 14:48:51 +0200 Subject: [PATCH 339/778] ASoC: SOF: ipc4-topology: Always parse the output formats in topology MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Parse the output formats available in topology always. Whether the output format is sent in the init instance payload or not is decided when sof_ipc4_init_audio_fmt() is invoked. Signed-off-by: Ranjani Sridharan Reviewed-by: Rander Wang Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230313124856.8140-7-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index b6933fa1a36d..0e1e4fc9224c 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -171,15 +171,13 @@ static void sof_ipc4_dbg_audio_format(struct device *dev, * @swidget: pointer to struct snd_sof_widget containing tuples * @available_fmt: pointer to struct sof_ipc4_available_audio_format being filling in * @module_base_cfg: Pointer to the base_config in the module init IPC payload - * @has_out_format: true if available_fmt contains output format * * Return: 0 if successful */ static int sof_ipc4_get_audio_fmt(struct snd_soc_component *scomp, struct snd_sof_widget *swidget, struct sof_ipc4_available_audio_format *available_fmt, - struct sof_ipc4_base_module_cfg *module_base_cfg, - bool has_out_format) + struct sof_ipc4_base_module_cfg *module_base_cfg) { struct sof_ipc4_base_module_cfg *base_config; struct sof_ipc4_audio_format *out_format, *in_format; @@ -249,9 +247,6 @@ static int sof_ipc4_get_audio_fmt(struct snd_soc_component *scomp, sizeof(struct sof_ipc4_audio_format), available_fmt->audio_fmt_num); - if (!has_out_format) - return 0; - out_format = kcalloc(available_fmt->audio_fmt_num, sizeof(*out_format), GFP_KERNEL); if (!out_format) { ret = -ENOMEM; @@ -362,7 +357,7 @@ static int sof_ipc4_widget_setup_pcm(struct snd_sof_widget *swidget) dev_dbg(scomp->dev, "Updating IPC structure for %s\n", swidget->widget->name); ret = sof_ipc4_get_audio_fmt(scomp, swidget, available_fmt, - &ipc4_copier->data.base_config, true); + &ipc4_copier->data.base_config); if (ret) goto free_copier; @@ -461,7 +456,7 @@ static int sof_ipc4_widget_setup_comp_dai(struct snd_sof_widget *swidget) dev_dbg(scomp->dev, "Updating IPC structure for %s\n", swidget->widget->name); ret = sof_ipc4_get_audio_fmt(scomp, swidget, available_fmt, - &ipc4_copier->data.base_config, true); + &ipc4_copier->data.base_config); if (ret) goto free_copier; @@ -668,9 +663,7 @@ static int sof_ipc4_widget_setup_comp_pga(struct snd_sof_widget *swidget) gain->data.channels = SOF_IPC4_GAIN_ALL_CHANNELS_MASK; gain->data.init_val = SOF_IPC4_VOL_ZERO_DB; - /* The out_audio_fmt in topology is ignored as it is not required to be sent to the FW */ - ret = sof_ipc4_get_audio_fmt(scomp, swidget, &gain->available_fmt, &gain->base_config, - false); + ret = sof_ipc4_get_audio_fmt(scomp, swidget, &gain->available_fmt, &gain->base_config); if (ret) goto err; @@ -735,9 +728,8 @@ static int sof_ipc4_widget_setup_comp_mixer(struct snd_sof_widget *swidget) swidget->private = mixer; - /* The out_audio_fmt in topology is ignored as it is not required to be sent to the FW */ ret = sof_ipc4_get_audio_fmt(scomp, swidget, &mixer->available_fmt, - &mixer->base_config, false); + &mixer->base_config); if (ret) goto err; @@ -767,9 +759,7 @@ static int sof_ipc4_widget_setup_comp_src(struct snd_sof_widget *swidget) swidget->private = src; - /* The out_audio_fmt in topology is ignored as it is not required by SRC */ - ret = sof_ipc4_get_audio_fmt(scomp, swidget, &src->available_fmt, &src->base_config, - false); + ret = sof_ipc4_get_audio_fmt(scomp, swidget, &src->available_fmt, &src->base_config); if (ret) goto err; From 7ab6b1e8302cf7a9bc8808c43b3e751e4148a351 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Mon, 13 Mar 2023 14:48:52 +0200 Subject: [PATCH 340/778] ASoC: SOF: ipc4-topology: Modify the type of available input/output formats MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce a new struct sof_ipc4_pin_format which contains the pin index and the buffer size. Replace the type of available input/output audio formats in struct sof_ipc4_available_audio_format with this new struct type and rename them to input_pin_fmts and output_pin_fmts. Also, add a new token, SOF_TKN_CAVS_AUDIO_FORMAT_PIN_INDEX that will be used to parse the pin index for the audio format from topology. Currently we only set the audio format for Pin 0 in topology, so the default value will be 0 for all audio formats. Finally, parse the pin_index and the input/output buffer sizes along with audio formats into the pin_format arrays in struct sof_ipc4_available_audio_format. This makes the base_config array in struct sof_ipc4_available_audio_format redundant. So remove it. This change will allow the addition of audio formats for the non-zero pins in topology transparent to the topology parser in the kernel. Signed-off-by: Ranjani Sridharan Reviewed-by: Rander Wang Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230313124856.8140-8-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- include/uapi/sound/sof/tokens.h | 1 + sound/soc/sof/ipc4-pcm.c | 2 +- sound/soc/sof/ipc4-topology.c | 181 +++++++++++++------------------- sound/soc/sof/ipc4-topology.h | 27 +++-- sound/soc/sof/sof-audio.h | 1 - sound/soc/sof/topology.c | 1 - 6 files changed, 96 insertions(+), 117 deletions(-) diff --git a/include/uapi/sound/sof/tokens.h b/include/uapi/sound/sof/tokens.h index 9e91e2640dd4..92360601b49c 100644 --- a/include/uapi/sound/sof/tokens.h +++ b/include/uapi/sound/sof/tokens.h @@ -180,6 +180,7 @@ #define SOF_TKN_CAVS_AUDIO_FORMAT_IN_INTERLEAVING_STYLE 1906 #define SOF_TKN_CAVS_AUDIO_FORMAT_IN_FMT_CFG 1907 #define SOF_TKN_CAVS_AUDIO_FORMAT_IN_SAMPLE_TYPE 1908 +#define SOF_TKN_CAVS_AUDIO_FORMAT_PIN_INDEX 1909 /* intentional token numbering discontinuity, reserved for future use */ #define SOF_TKN_CAVS_AUDIO_FORMAT_OUT_RATE 1930 #define SOF_TKN_CAVS_AUDIO_FORMAT_OUT_BIT_DEPTH 1931 diff --git a/sound/soc/sof/ipc4-pcm.c b/sound/soc/sof/ipc4-pcm.c index a679c08d9bb1..701da5ee4e4e 100644 --- a/sound/soc/sof/ipc4-pcm.c +++ b/sound/soc/sof/ipc4-pcm.c @@ -389,7 +389,7 @@ static int sof_ipc4_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, snd_mask_none(fmt); snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S32_LE); - rate->min = ipc4_copier->available_fmt.input_audio_fmts->sampling_frequency; + rate->min = ipc4_copier->available_fmt.input_pin_fmts->audio_fmt.sampling_frequency; rate->max = rate->min; switch (ipc4_copier->dai_type) { diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index 0e1e4fc9224c..c462db95f3b2 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -41,41 +41,44 @@ static const struct sof_topology_token ipc4_comp_tokens[] = { offsetof(struct sof_ipc4_base_module_cfg, is_pages)}, }; -static const struct sof_topology_token ipc4_audio_format_buffer_size_tokens[] = { - {SOF_TKN_CAVS_AUDIO_FORMAT_IBS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, - offsetof(struct sof_ipc4_base_module_cfg, ibs)}, - {SOF_TKN_CAVS_AUDIO_FORMAT_OBS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, - offsetof(struct sof_ipc4_base_module_cfg, obs)}, -}; - static const struct sof_topology_token ipc4_in_audio_format_tokens[] = { {SOF_TKN_CAVS_AUDIO_FORMAT_IN_RATE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, - offsetof(struct sof_ipc4_audio_format, sampling_frequency)}, + offsetof(struct sof_ipc4_pin_format, audio_fmt.sampling_frequency)}, {SOF_TKN_CAVS_AUDIO_FORMAT_IN_BIT_DEPTH, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, - offsetof(struct sof_ipc4_audio_format, bit_depth)}, + offsetof(struct sof_ipc4_pin_format, audio_fmt.bit_depth)}, {SOF_TKN_CAVS_AUDIO_FORMAT_IN_CH_MAP, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, - offsetof(struct sof_ipc4_audio_format, ch_map)}, + offsetof(struct sof_ipc4_pin_format, audio_fmt.ch_map)}, {SOF_TKN_CAVS_AUDIO_FORMAT_IN_CH_CFG, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, - offsetof(struct sof_ipc4_audio_format, ch_cfg)}, + offsetof(struct sof_ipc4_pin_format, audio_fmt.ch_cfg)}, {SOF_TKN_CAVS_AUDIO_FORMAT_IN_INTERLEAVING_STYLE, SND_SOC_TPLG_TUPLE_TYPE_WORD, - get_token_u32, offsetof(struct sof_ipc4_audio_format, interleaving_style)}, + get_token_u32, offsetof(struct sof_ipc4_pin_format, + audio_fmt.interleaving_style)}, {SOF_TKN_CAVS_AUDIO_FORMAT_IN_FMT_CFG, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, - offsetof(struct sof_ipc4_audio_format, fmt_cfg)}, + offsetof(struct sof_ipc4_pin_format, audio_fmt.fmt_cfg)}, + {SOF_TKN_CAVS_AUDIO_FORMAT_PIN_INDEX, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, + offsetof(struct sof_ipc4_pin_format, pin_index)}, + {SOF_TKN_CAVS_AUDIO_FORMAT_IBS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, + offsetof(struct sof_ipc4_pin_format, buffer_size)}, }; static const struct sof_topology_token ipc4_out_audio_format_tokens[] = { {SOF_TKN_CAVS_AUDIO_FORMAT_OUT_RATE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, - offsetof(struct sof_ipc4_audio_format, sampling_frequency)}, + offsetof(struct sof_ipc4_pin_format, audio_fmt.sampling_frequency)}, {SOF_TKN_CAVS_AUDIO_FORMAT_OUT_BIT_DEPTH, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, - offsetof(struct sof_ipc4_audio_format, bit_depth)}, + offsetof(struct sof_ipc4_pin_format, audio_fmt.bit_depth)}, {SOF_TKN_CAVS_AUDIO_FORMAT_OUT_CH_MAP, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, - offsetof(struct sof_ipc4_audio_format, ch_map)}, + offsetof(struct sof_ipc4_pin_format, audio_fmt.ch_map)}, {SOF_TKN_CAVS_AUDIO_FORMAT_OUT_CH_CFG, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, - offsetof(struct sof_ipc4_audio_format, ch_cfg)}, + offsetof(struct sof_ipc4_pin_format, audio_fmt.ch_cfg)}, {SOF_TKN_CAVS_AUDIO_FORMAT_OUT_INTERLEAVING_STYLE, SND_SOC_TPLG_TUPLE_TYPE_WORD, - get_token_u32, offsetof(struct sof_ipc4_audio_format, interleaving_style)}, + get_token_u32, offsetof(struct sof_ipc4_pin_format, + audio_fmt.interleaving_style)}, {SOF_TKN_CAVS_AUDIO_FORMAT_OUT_FMT_CFG, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, - offsetof(struct sof_ipc4_audio_format, fmt_cfg)}, + offsetof(struct sof_ipc4_pin_format, audio_fmt.fmt_cfg)}, + {SOF_TKN_CAVS_AUDIO_FORMAT_PIN_INDEX, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, + offsetof(struct sof_ipc4_pin_format, pin_index)}, + {SOF_TKN_CAVS_AUDIO_FORMAT_OBS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, + offsetof(struct sof_ipc4_pin_format, buffer_size)}, }; static const struct sof_topology_token ipc4_copier_deep_buffer_tokens[] = { @@ -135,9 +138,6 @@ static const struct sof_token_info ipc4_token_list[SOF_TOKEN_COUNT] = { ipc4_in_audio_format_tokens, ARRAY_SIZE(ipc4_in_audio_format_tokens)}, [SOF_OUT_AUDIO_FORMAT_TOKENS] = {"IPC4 Output Audio format tokens", ipc4_out_audio_format_tokens, ARRAY_SIZE(ipc4_out_audio_format_tokens)}, - [SOF_AUDIO_FORMAT_BUFFER_SIZE_TOKENS] = {"IPC4 Audio format buffer size tokens", - ipc4_audio_format_buffer_size_tokens, - ARRAY_SIZE(ipc4_audio_format_buffer_size_tokens)}, [SOF_COPIER_DEEP_BUFFER_TOKENS] = {"IPC4 Copier deep buffer tokens", ipc4_copier_deep_buffer_tokens, ARRAY_SIZE(ipc4_copier_deep_buffer_tokens)}, [SOF_COPIER_TOKENS] = {"IPC4 Copier tokens", ipc4_copier_tokens, @@ -148,20 +148,18 @@ static const struct sof_token_info ipc4_token_list[SOF_TOKEN_COUNT] = { [SOF_SRC_TOKENS] = {"SRC tokens", src_tokens, ARRAY_SIZE(src_tokens)}, }; -static void sof_ipc4_dbg_audio_format(struct device *dev, - struct sof_ipc4_audio_format *format, - size_t object_size, int num_format) +static void sof_ipc4_dbg_audio_format(struct device *dev, struct sof_ipc4_pin_format *pin_fmt, + int num_formats) { - struct sof_ipc4_audio_format *fmt; - void *ptr = format; int i; - for (i = 0; i < num_format; i++, ptr = (u8 *)ptr + object_size) { - fmt = ptr; + for (i = 0; i < num_formats; i++) { + struct sof_ipc4_audio_format *fmt = &pin_fmt[i].audio_fmt; dev_dbg(dev, - " #%d: %uHz, %ubit (ch_map %#x ch_cfg %u interleaving_style %u fmt_cfg %#x)\n", - i, fmt->sampling_frequency, fmt->bit_depth, fmt->ch_map, - fmt->ch_cfg, fmt->interleaving_style, fmt->fmt_cfg); + "Pin index #%d: %uHz, %ubit (ch_map %#x ch_cfg %u interleaving_style %u fmt_cfg %#x) buffer size %d\n", + pin_fmt[i].pin_index, fmt->sampling_frequency, fmt->bit_depth, fmt->ch_map, + fmt->ch_cfg, fmt->interleaving_style, fmt->fmt_cfg, + pin_fmt[i].buffer_size); } } @@ -179,10 +177,9 @@ static int sof_ipc4_get_audio_fmt(struct snd_soc_component *scomp, struct sof_ipc4_available_audio_format *available_fmt, struct sof_ipc4_base_module_cfg *module_base_cfg) { - struct sof_ipc4_base_module_cfg *base_config; - struct sof_ipc4_audio_format *out_format, *in_format; + struct sof_ipc4_pin_format *out_format, *in_format; int audio_fmt_num = 0; - int ret, i; + int ret; ret = sof_update_ipc_object(scomp, &audio_fmt_num, SOF_AUDIO_FMT_NUM_TOKENS, swidget->tuples, @@ -195,47 +192,25 @@ static int sof_ipc4_get_audio_fmt(struct snd_soc_component *scomp, dev_dbg(scomp->dev, "Number of audio formats: %d\n", available_fmt->audio_fmt_num); - base_config = kcalloc(available_fmt->audio_fmt_num, sizeof(*base_config), GFP_KERNEL); - if (!base_config) - return -ENOMEM; - /* set cpc and is_pages in the module's base_config */ ret = sof_update_ipc_object(scomp, module_base_cfg, SOF_COMP_TOKENS, swidget->tuples, swidget->num_tuples, sizeof(*module_base_cfg), 1); if (ret) { dev_err(scomp->dev, "parse comp tokens for %s failed, error: %d\n", swidget->widget->name, ret); - goto err; + return ret; } dev_dbg(scomp->dev, "widget %s cpc: %d is_pages: %d\n", swidget->widget->name, module_base_cfg->cpc, module_base_cfg->is_pages); - /* copy the ibs/obs for each base_cfg */ - ret = sof_update_ipc_object(scomp, base_config, - SOF_AUDIO_FORMAT_BUFFER_SIZE_TOKENS, swidget->tuples, - swidget->num_tuples, sizeof(*base_config), - available_fmt->audio_fmt_num); - if (ret) { - dev_err(scomp->dev, "parse buffer size tokens failed %d\n", ret); - goto err; - } + in_format = kcalloc(available_fmt->audio_fmt_num, sizeof(*in_format), GFP_KERNEL); + if (!in_format) + return -ENOMEM; - for (i = 0; i < available_fmt->audio_fmt_num; i++) - dev_dbg(scomp->dev, "%d: ibs: %d obs: %d\n", i, - base_config[i].ibs, base_config[i].obs); - - in_format = kcalloc(available_fmt->audio_fmt_num, - sizeof(struct sof_ipc4_audio_format), GFP_KERNEL); - if (!in_format) { - kfree(base_config); - ret = -ENOMEM; - goto err; - } - - ret = sof_update_ipc_object(scomp, available_fmt->input_audio_fmts, + ret = sof_update_ipc_object(scomp, in_format, SOF_IN_AUDIO_FORMAT_TOKENS, swidget->tuples, - swidget->num_tuples, sizeof(struct sof_ipc4_audio_format), + swidget->num_tuples, sizeof(*in_format), available_fmt->audio_fmt_num); if (ret) { dev_err(scomp->dev, "parse base_config audio_fmt tokens failed %d\n", ret); @@ -243,8 +218,7 @@ static int sof_ipc4_get_audio_fmt(struct snd_soc_component *scomp, } dev_dbg(scomp->dev, "Get input audio formats for %s\n", swidget->widget->name); - sof_ipc4_dbg_audio_format(scomp->dev, available_fmt->input_audio_fmts, - sizeof(struct sof_ipc4_audio_format), + sof_ipc4_dbg_audio_format(scomp->dev, available_fmt->input_pin_fmts, available_fmt->audio_fmt_num); out_format = kcalloc(available_fmt->audio_fmt_num, sizeof(*out_format), GFP_KERNEL); @@ -264,12 +238,10 @@ static int sof_ipc4_get_audio_fmt(struct snd_soc_component *scomp, } dev_dbg(scomp->dev, "Get output audio formats for %s\n", swidget->widget->name); - sof_ipc4_dbg_audio_format(scomp->dev, out_format, sizeof(*out_format), - available_fmt->audio_fmt_num); + sof_ipc4_dbg_audio_format(scomp->dev, out_format, available_fmt->audio_fmt_num); - available_fmt->base_config = base_config; - available_fmt->out_audio_fmt = out_format; - available_fmt->input_audio_fmts = in_format; + available_fmt->output_pin_fmts = out_format; + available_fmt->input_pin_fmts = in_format; return 0; @@ -277,8 +249,6 @@ err_out: kfree(out_format); err_in: kfree(in_format); -err: - kfree(base_config); return ret; } @@ -286,12 +256,10 @@ err: static void sof_ipc4_free_audio_fmt(struct sof_ipc4_available_audio_format *available_fmt) { - kfree(available_fmt->base_config); - available_fmt->base_config = NULL; - kfree(available_fmt->out_audio_fmt); - available_fmt->out_audio_fmt = NULL; - kfree(available_fmt->input_audio_fmts); - available_fmt->input_audio_fmts = NULL; + kfree(available_fmt->output_pin_fmts); + available_fmt->output_pin_fmts = NULL; + kfree(available_fmt->input_pin_fmts); + available_fmt->input_pin_fmts = NULL; } static void sof_ipc4_widget_free_comp_pipeline(struct snd_sof_widget *swidget) @@ -431,8 +399,7 @@ static void sof_ipc4_widget_free_comp_pcm(struct snd_sof_widget *swidget) return; available_fmt = &ipc4_copier->available_fmt; - kfree(available_fmt->base_config); - kfree(available_fmt->out_audio_fmt); + kfree(available_fmt->output_pin_fmts); kfree(ipc4_copier->gtw_attr); kfree(ipc4_copier); swidget->private = NULL; @@ -584,8 +551,7 @@ static void sof_ipc4_widget_free_comp_dai(struct snd_sof_widget *swidget) ipc4_copier = dai->private; available_fmt = &ipc4_copier->available_fmt; - kfree(available_fmt->base_config); - kfree(available_fmt->out_audio_fmt); + kfree(available_fmt->output_pin_fmts); if (ipc4_copier->dai_type != SOF_DAI_INTEL_SSP && ipc4_copier->dai_type != SOF_DAI_INTEL_DMIC) kfree(ipc4_copier->copier_config); @@ -866,14 +832,14 @@ static int sof_ipc4_init_audio_fmt(struct snd_sof_dev *sdev, struct snd_pcm_hw_params *params, struct sof_ipc4_available_audio_format *available_fmt) { - struct sof_ipc4_audio_format *fmt = available_fmt->ref_audio_fmt; + struct sof_ipc4_pin_format *pin_fmt = available_fmt->ref_audio_fmt; u32 valid_bits; u32 channels; u32 rate; int sample_valid_bits; int i; - if (!fmt) { + if (!pin_fmt) { dev_err(sdev->dev, "no reference formats for %s\n", swidget->widget->name); return -EINVAL; } @@ -902,7 +868,9 @@ static int sof_ipc4_init_audio_fmt(struct snd_sof_dev *sdev, * Search supported audio formats to match rate, channels ,and * sample_valid_bytes from runtime params */ - for (i = 0; i < available_fmt->audio_fmt_num; i++, fmt++) { + for (i = 0; i < available_fmt->audio_fmt_num; i++) { + struct sof_ipc4_audio_format *fmt = &pin_fmt[i].audio_fmt; + rate = fmt->sampling_frequency; channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(fmt->fmt_cfg); valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt->fmt_cfg); @@ -921,15 +889,16 @@ static int sof_ipc4_init_audio_fmt(struct snd_sof_dev *sdev, } /* copy input format */ - memcpy(&base_config->audio_fmt, &available_fmt->input_audio_fmts[i], sizeof(*fmt)); + memcpy(&base_config->audio_fmt, &available_fmt->input_pin_fmts[i].audio_fmt, + sizeof(*out_format)); /* set base_cfg ibs/obs */ - base_config->ibs = available_fmt->base_config[i].ibs; - base_config->obs = available_fmt->base_config[i].obs; + base_config->ibs = available_fmt->input_pin_fmts[i].buffer_size; + base_config->obs = available_fmt->output_pin_fmts[i].buffer_size; dev_dbg(sdev->dev, "Init input audio formats for %s\n", swidget->widget->name); - sof_ipc4_dbg_audio_format(sdev->dev, &base_config->audio_fmt, - sizeof(*base_config), 1); + sof_ipc4_dbg_audio_format(sdev->dev, &available_fmt->input_pin_fmts[i], 1); + if (out_format) { /* * Current topology defines pin 0 input and output formats only in pairs. @@ -938,10 +907,10 @@ static int sof_ipc4_init_audio_fmt(struct snd_sof_dev *sdev, * input format. This logic will need to be updated when the format definitions * in topology change. */ - memcpy(out_format, &available_fmt->out_audio_fmt[i], sizeof(*fmt)); + memcpy(out_format, &available_fmt->output_pin_fmts[i].audio_fmt, + sizeof(*out_format)); dev_dbg(sdev->dev, "Init output audio formats for %s\n", swidget->widget->name); - sof_ipc4_dbg_audio_format(sdev->dev, out_format, - sizeof(*out_format), 1); + sof_ipc4_dbg_audio_format(sdev->dev, &available_fmt->output_pin_fmts[i], 1); } /* Return the index of the matched format */ @@ -1144,13 +1113,13 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, available_fmt = &ipc4_copier->available_fmt; /* - * Use the input_audio_fmts to match pcm params for playback and the out_audio_fmt + * Use the input_pin_fmts to match pcm params for playback and the output_pin_fmts * for capture. */ if (dir == SNDRV_PCM_STREAM_PLAYBACK) - available_fmt->ref_audio_fmt = available_fmt->input_audio_fmts; + available_fmt->ref_audio_fmt = available_fmt->input_pin_fmts; else - available_fmt->ref_audio_fmt = available_fmt->out_audio_fmt; + available_fmt->ref_audio_fmt = available_fmt->output_pin_fmts; copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK; copier_data->gtw_cfg.node_id |= @@ -1170,7 +1139,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, copier_data = &ipc4_copier->data; available_fmt = &ipc4_copier->available_fmt; if (dir == SNDRV_PCM_STREAM_CAPTURE) { - available_fmt->ref_audio_fmt = available_fmt->out_audio_fmt; + available_fmt->ref_audio_fmt = available_fmt->output_pin_fmts; /* * modify the input params for the dai copier as it only supports @@ -1180,7 +1149,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, snd_mask_none(fmt); snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S32_LE); } else { - available_fmt->ref_audio_fmt = available_fmt->input_audio_fmts; + available_fmt->ref_audio_fmt = available_fmt->input_pin_fmts; } ref_params = pipeline_params; @@ -1201,7 +1170,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, available_fmt = &ipc4_copier->available_fmt; /* Use the input formats as the reference to match pcm params */ - available_fmt->ref_audio_fmt = available_fmt->input_audio_fmts; + available_fmt->ref_audio_fmt = available_fmt->input_pin_fmts; ref_params = pipeline_params; break; @@ -1388,7 +1357,7 @@ static int sof_ipc4_prepare_gain_module(struct snd_sof_widget *swidget, struct sof_ipc4_available_audio_format *available_fmt = &gain->available_fmt; int ret; - available_fmt->ref_audio_fmt = available_fmt->input_audio_fmts; + available_fmt->ref_audio_fmt = available_fmt->input_pin_fmts; /* output format is not required to be sent to the FW for gain */ ret = sof_ipc4_init_audio_fmt(sdev, swidget, &gain->base_config, @@ -1414,7 +1383,7 @@ static int sof_ipc4_prepare_mixer_module(struct snd_sof_widget *swidget, int ret; /* only 32bit is supported by mixer */ - available_fmt->ref_audio_fmt = available_fmt->input_audio_fmts; + available_fmt->ref_audio_fmt = available_fmt->input_pin_fmts; /* output format is not required to be sent to the FW for mixer */ ret = sof_ipc4_init_audio_fmt(sdev, swidget, &mixer->base_config, @@ -1440,7 +1409,7 @@ static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget, struct snd_interval *rate; int ret; - available_fmt->ref_audio_fmt = available_fmt->input_audio_fmts; + available_fmt->ref_audio_fmt = available_fmt->input_pin_fmts; /* output format is not required to be sent to the FW for SRC */ ret = sof_ipc4_init_audio_fmt(sdev, swidget, &src->base_config, @@ -2147,7 +2116,6 @@ static int sof_ipc4_link_setup(struct snd_sof_dev *sdev, struct snd_soc_dai_link static enum sof_tokens common_copier_token_list[] = { SOF_COMP_TOKENS, SOF_AUDIO_FMT_NUM_TOKENS, - SOF_AUDIO_FORMAT_BUFFER_SIZE_TOKENS, SOF_IN_AUDIO_FORMAT_TOKENS, SOF_OUT_AUDIO_FORMAT_TOKENS, SOF_COPIER_DEEP_BUFFER_TOKENS, @@ -2163,7 +2131,6 @@ static enum sof_tokens pipeline_token_list[] = { static enum sof_tokens dai_token_list[] = { SOF_COMP_TOKENS, SOF_AUDIO_FMT_NUM_TOKENS, - SOF_AUDIO_FORMAT_BUFFER_SIZE_TOKENS, SOF_IN_AUDIO_FORMAT_TOKENS, SOF_OUT_AUDIO_FORMAT_TOKENS, SOF_COPIER_TOKENS, @@ -2175,8 +2142,8 @@ static enum sof_tokens pga_token_list[] = { SOF_COMP_TOKENS, SOF_GAIN_TOKENS, SOF_AUDIO_FMT_NUM_TOKENS, - SOF_AUDIO_FORMAT_BUFFER_SIZE_TOKENS, SOF_IN_AUDIO_FORMAT_TOKENS, + SOF_OUT_AUDIO_FORMAT_TOKENS, SOF_COMP_EXT_TOKENS, }; @@ -2184,7 +2151,7 @@ static enum sof_tokens mixer_token_list[] = { SOF_COMP_TOKENS, SOF_AUDIO_FMT_NUM_TOKENS, SOF_IN_AUDIO_FORMAT_TOKENS, - SOF_AUDIO_FORMAT_BUFFER_SIZE_TOKENS, + SOF_OUT_AUDIO_FORMAT_TOKENS, SOF_COMP_EXT_TOKENS, }; @@ -2193,7 +2160,7 @@ static enum sof_tokens src_token_list[] = { SOF_SRC_TOKENS, SOF_AUDIO_FMT_NUM_TOKENS, SOF_IN_AUDIO_FORMAT_TOKENS, - SOF_AUDIO_FORMAT_BUFFER_SIZE_TOKENS, + SOF_OUT_AUDIO_FORMAT_TOKENS, SOF_COMP_EXT_TOKENS, }; diff --git a/sound/soc/sof/ipc4-topology.h b/sound/soc/sof/ipc4-topology.h index 696d6c39a21b..2d9b1ba549f7 100644 --- a/sound/soc/sof/ipc4-topology.h +++ b/sound/soc/sof/ipc4-topology.h @@ -145,19 +145,32 @@ struct ipc4_pipeline_set_state_data { DECLARE_FLEX_ARRAY(u32, pipeline_ids); } __packed; +/** + * struct sof_ipc4_pin_format - Module pin format + * @pin_index: pin index + * @buffer_size: buffer size in bytes + * @audio_fmt: audio format for the pin + * + * This structure can be used for both output or input pins and the pin_index is relative to the + * pin type i.e output/input pin + */ +struct sof_ipc4_pin_format { + u32 pin_index; + u32 buffer_size; + struct sof_ipc4_audio_format audio_fmt; +}; + /** * struct sof_ipc4_available_audio_format - Available audio formats - * @base_config: Available base config - * @out_audio_fmt: Available output audio format - * @input_audio_fmts: Available input audio formats + * @output_pin_fmts: Available output pin formats + * @input_pin_fmts: Available input pin formats * @ref_audio_fmt: Reference audio format to match runtime audio format * @audio_fmt_num: Number of available audio formats */ struct sof_ipc4_available_audio_format { - struct sof_ipc4_base_module_cfg *base_config; - struct sof_ipc4_audio_format *out_audio_fmt; - struct sof_ipc4_audio_format *input_audio_fmts; - struct sof_ipc4_audio_format *ref_audio_fmt; + struct sof_ipc4_pin_format *output_pin_fmts; + struct sof_ipc4_pin_format *input_pin_fmts; + struct sof_ipc4_pin_format *ref_audio_fmt; int audio_fmt_num; }; diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h index 4504f9efdc50..d220af5f08fb 100644 --- a/sound/soc/sof/sof-audio.h +++ b/sound/soc/sof/sof-audio.h @@ -256,7 +256,6 @@ enum sof_tokens { SOF_COMP_EXT_TOKENS, SOF_IN_AUDIO_FORMAT_TOKENS, SOF_OUT_AUDIO_FORMAT_TOKENS, - SOF_AUDIO_FORMAT_BUFFER_SIZE_TOKENS, SOF_COPIER_DEEP_BUFFER_TOKENS, SOF_COPIER_TOKENS, SOF_AUDIO_FMT_NUM_TOKENS, diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 2d76ab13b3d1..3a091f18731f 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -1232,7 +1232,6 @@ static int sof_widget_parse_tokens(struct snd_soc_component *scomp, struct snd_s continue; case SOF_IN_AUDIO_FORMAT_TOKENS: case SOF_OUT_AUDIO_FORMAT_TOKENS: - case SOF_AUDIO_FORMAT_BUFFER_SIZE_TOKENS: num_sets = sof_get_token_value(SOF_TKN_COMP_NUM_AUDIO_FORMATS, swidget->tuples, swidget->num_tuples); From 9c560549e32bc2951c67106c59587f9f7bf6b70e Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Mon, 13 Mar 2023 14:48:53 +0200 Subject: [PATCH 341/778] ASoC: SOF: ipc4-topology: Modify the signature of sof_ipc4_init_audio_fmt() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only the copier needs to set the output format in its IPC payload. So move the code to set the output format inside sof_ipc4_prepare_copier_module() and modify the signature of sof_ipc4_init_audio_fmt() to remove the out_format argument. Signed-off-by: Ranjani Sridharan Reviewed-by: Rander Wang Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230313124856.8140-9-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 38 ++++++++++++++++------------------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index c462db95f3b2..baa8f4fa6d20 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -828,7 +828,6 @@ static int sof_ipc4_widget_assign_instance_id(struct snd_sof_dev *sdev, static int sof_ipc4_init_audio_fmt(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget, struct sof_ipc4_base_module_cfg *base_config, - struct sof_ipc4_audio_format *out_format, struct snd_pcm_hw_params *params, struct sof_ipc4_available_audio_format *available_fmt) { @@ -890,7 +889,7 @@ static int sof_ipc4_init_audio_fmt(struct snd_sof_dev *sdev, /* copy input format */ memcpy(&base_config->audio_fmt, &available_fmt->input_pin_fmts[i].audio_fmt, - sizeof(*out_format)); + sizeof(struct sof_ipc4_audio_format)); /* set base_cfg ibs/obs */ base_config->ibs = available_fmt->input_pin_fmts[i].buffer_size; @@ -899,20 +898,6 @@ static int sof_ipc4_init_audio_fmt(struct snd_sof_dev *sdev, dev_dbg(sdev->dev, "Init input audio formats for %s\n", swidget->widget->name); sof_ipc4_dbg_audio_format(sdev->dev, &available_fmt->input_pin_fmts[i], 1); - if (out_format) { - /* - * Current topology defines pin 0 input and output formats only in pairs. - * This assumes that the pin 0 formats are defined before all other pins. - * So pick the output audio format with the same index as the chosen - * input format. This logic will need to be updated when the format definitions - * in topology change. - */ - memcpy(out_format, &available_fmt->output_pin_fmts[i].audio_fmt, - sizeof(*out_format)); - dev_dbg(sdev->dev, "Init output audio formats for %s\n", swidget->widget->name); - sof_ipc4_dbg_audio_format(sdev->dev, &available_fmt->output_pin_fmts[i], 1); - } - /* Return the index of the matched format */ return i; } @@ -1182,12 +1167,23 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, } /* set input and output audio formats */ - ret = sof_ipc4_init_audio_fmt(sdev, swidget, &copier_data->base_config, - &copier_data->out_format, ref_params, + ret = sof_ipc4_init_audio_fmt(sdev, swidget, &copier_data->base_config, ref_params, available_fmt); if (ret < 0) return ret; + /* + * Set the output format. Current topology defines pin 0 input and output formats in pairs. + * This assumes that the pin 0 formats are defined before all other pins. + * So pick the output audio format with the same index as the chosen + * input format. This logic will need to be updated when the format definitions + * in topology change. + */ + memcpy(&copier_data->out_format, &available_fmt->output_pin_fmts[ret].audio_fmt, + sizeof(struct sof_ipc4_audio_format)); + dev_dbg(sdev->dev, "Output audio format for %s\n", swidget->widget->name); + sof_ipc4_dbg_audio_format(sdev->dev, &available_fmt->output_pin_fmts[ret], 1); + switch (swidget->id) { case snd_soc_dapm_dai_in: case snd_soc_dapm_dai_out: @@ -1361,7 +1357,7 @@ static int sof_ipc4_prepare_gain_module(struct snd_sof_widget *swidget, /* output format is not required to be sent to the FW for gain */ ret = sof_ipc4_init_audio_fmt(sdev, swidget, &gain->base_config, - NULL, pipeline_params, available_fmt); + pipeline_params, available_fmt); if (ret < 0) return ret; @@ -1387,7 +1383,7 @@ static int sof_ipc4_prepare_mixer_module(struct snd_sof_widget *swidget, /* output format is not required to be sent to the FW for mixer */ ret = sof_ipc4_init_audio_fmt(sdev, swidget, &mixer->base_config, - NULL, pipeline_params, available_fmt); + pipeline_params, available_fmt); if (ret < 0) return ret; @@ -1413,7 +1409,7 @@ static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget, /* output format is not required to be sent to the FW for SRC */ ret = sof_ipc4_init_audio_fmt(sdev, swidget, &src->base_config, - NULL, pipeline_params, available_fmt); + pipeline_params, available_fmt); if (ret < 0) return ret; From f534a94c3d765bcd5bdf10271a265883be2b4030 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Mon, 13 Mar 2023 14:48:54 +0200 Subject: [PATCH 342/778] ASoC: SOF: ipc4-topology: Remove the ref_audio_fmt field MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the field in struct sof_ipc4_available_audio_format and pass the format list to be searched as an argument to sof_ipc4_init_audio_fmt() directly. Signed-off-by: Ranjani Sridharan Reviewed-by: Rander Wang Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230313124856.8140-10-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 42 +++++++++++++++-------------------- sound/soc/sof/ipc4-topology.h | 2 -- 2 files changed, 18 insertions(+), 26 deletions(-) diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index baa8f4fa6d20..3aacc440a5e4 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -829,16 +829,16 @@ static int sof_ipc4_init_audio_fmt(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget, struct sof_ipc4_base_module_cfg *base_config, struct snd_pcm_hw_params *params, - struct sof_ipc4_available_audio_format *available_fmt) + struct sof_ipc4_available_audio_format *available_fmt, + struct sof_ipc4_pin_format *pin_fmts) { - struct sof_ipc4_pin_format *pin_fmt = available_fmt->ref_audio_fmt; u32 valid_bits; u32 channels; u32 rate; int sample_valid_bits; int i; - if (!pin_fmt) { + if (!pin_fmts) { dev_err(sdev->dev, "no reference formats for %s\n", swidget->widget->name); return -EINVAL; } @@ -868,7 +868,7 @@ static int sof_ipc4_init_audio_fmt(struct snd_sof_dev *sdev, * sample_valid_bytes from runtime params */ for (i = 0; i < available_fmt->audio_fmt_num; i++) { - struct sof_ipc4_audio_format *fmt = &pin_fmt[i].audio_fmt; + struct sof_ipc4_audio_format *fmt = &pin_fmts[i].audio_fmt; rate = fmt->sampling_frequency; channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(fmt->fmt_cfg); @@ -1058,6 +1058,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, struct sof_ipc4_available_audio_format *available_fmt; struct snd_soc_component *scomp = swidget->scomp; struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); + struct sof_ipc4_pin_format *format_list_to_search; struct sof_ipc4_copier_data *copier_data; struct snd_pcm_hw_params *ref_params; struct sof_ipc4_copier *ipc4_copier; @@ -1102,9 +1103,9 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, * for capture. */ if (dir == SNDRV_PCM_STREAM_PLAYBACK) - available_fmt->ref_audio_fmt = available_fmt->input_pin_fmts; + format_list_to_search = available_fmt->input_pin_fmts; else - available_fmt->ref_audio_fmt = available_fmt->output_pin_fmts; + format_list_to_search = available_fmt->output_pin_fmts; copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK; copier_data->gtw_cfg.node_id |= @@ -1124,7 +1125,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, copier_data = &ipc4_copier->data; available_fmt = &ipc4_copier->available_fmt; if (dir == SNDRV_PCM_STREAM_CAPTURE) { - available_fmt->ref_audio_fmt = available_fmt->output_pin_fmts; + format_list_to_search = available_fmt->output_pin_fmts; /* * modify the input params for the dai copier as it only supports @@ -1134,7 +1135,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, snd_mask_none(fmt); snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S32_LE); } else { - available_fmt->ref_audio_fmt = available_fmt->input_pin_fmts; + format_list_to_search = available_fmt->input_pin_fmts; } ref_params = pipeline_params; @@ -1154,8 +1155,8 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, copier_data = &ipc4_copier->data; available_fmt = &ipc4_copier->available_fmt; - /* Use the input formats as the reference to match pcm params */ - available_fmt->ref_audio_fmt = available_fmt->input_pin_fmts; + /* Use the input formats to match pcm params */ + format_list_to_search = available_fmt->input_pin_fmts; ref_params = pipeline_params; break; @@ -1168,7 +1169,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, /* set input and output audio formats */ ret = sof_ipc4_init_audio_fmt(sdev, swidget, &copier_data->base_config, ref_params, - available_fmt); + available_fmt, format_list_to_search); if (ret < 0) return ret; @@ -1353,11 +1354,9 @@ static int sof_ipc4_prepare_gain_module(struct snd_sof_widget *swidget, struct sof_ipc4_available_audio_format *available_fmt = &gain->available_fmt; int ret; - available_fmt->ref_audio_fmt = available_fmt->input_pin_fmts; - - /* output format is not required to be sent to the FW for gain */ ret = sof_ipc4_init_audio_fmt(sdev, swidget, &gain->base_config, - pipeline_params, available_fmt); + pipeline_params, available_fmt, + available_fmt->input_pin_fmts); if (ret < 0) return ret; @@ -1378,12 +1377,9 @@ static int sof_ipc4_prepare_mixer_module(struct snd_sof_widget *swidget, struct sof_ipc4_available_audio_format *available_fmt = &mixer->available_fmt; int ret; - /* only 32bit is supported by mixer */ - available_fmt->ref_audio_fmt = available_fmt->input_pin_fmts; - - /* output format is not required to be sent to the FW for mixer */ ret = sof_ipc4_init_audio_fmt(sdev, swidget, &mixer->base_config, - pipeline_params, available_fmt); + pipeline_params, available_fmt, + available_fmt->input_pin_fmts); if (ret < 0) return ret; @@ -1405,11 +1401,9 @@ static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget, struct snd_interval *rate; int ret; - available_fmt->ref_audio_fmt = available_fmt->input_pin_fmts; - - /* output format is not required to be sent to the FW for SRC */ ret = sof_ipc4_init_audio_fmt(sdev, swidget, &src->base_config, - pipeline_params, available_fmt); + pipeline_params, available_fmt, + available_fmt->input_pin_fmts); if (ret < 0) return ret; diff --git a/sound/soc/sof/ipc4-topology.h b/sound/soc/sof/ipc4-topology.h index 2d9b1ba549f7..6359ef8736ae 100644 --- a/sound/soc/sof/ipc4-topology.h +++ b/sound/soc/sof/ipc4-topology.h @@ -164,13 +164,11 @@ struct sof_ipc4_pin_format { * struct sof_ipc4_available_audio_format - Available audio formats * @output_pin_fmts: Available output pin formats * @input_pin_fmts: Available input pin formats - * @ref_audio_fmt: Reference audio format to match runtime audio format * @audio_fmt_num: Number of available audio formats */ struct sof_ipc4_available_audio_format { struct sof_ipc4_pin_format *output_pin_fmts; struct sof_ipc4_pin_format *input_pin_fmts; - struct sof_ipc4_pin_format *ref_audio_fmt; int audio_fmt_num; }; From 4fdef47a44d6ff735902dfe740918f23932225ca Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Mon, 13 Mar 2023 14:48:55 +0200 Subject: [PATCH 343/778] ASoC: SOF: ipc4-topology: Add new tokens for input/output pin format count MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In preparation for handling processing modules with different input/output pin counts, introduce two new tokens for input/output audio format counts. Use these token values to parse all the available audio formats from topology. Signed-off-by: Ranjani Sridharan Reviewed-by: Rander Wang Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230313124856.8140-11-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- include/uapi/sound/sof/tokens.h | 2 + sound/soc/sof/ipc4-topology.c | 145 +++++++++++++++++++------------- sound/soc/sof/ipc4-topology.h | 6 +- sound/soc/sof/topology.c | 42 +++++---- 4 files changed, 117 insertions(+), 78 deletions(-) diff --git a/include/uapi/sound/sof/tokens.h b/include/uapi/sound/sof/tokens.h index 92360601b49c..bd02842124f9 100644 --- a/include/uapi/sound/sof/tokens.h +++ b/include/uapi/sound/sof/tokens.h @@ -96,6 +96,8 @@ */ #define SOF_TKN_COMP_INPUT_PIN_BINDING_WNAME 413 #define SOF_TKN_COMP_OUTPUT_PIN_BINDING_WNAME 414 +#define SOF_TKN_COMP_NUM_INPUT_AUDIO_FORMATS 415 +#define SOF_TKN_COMP_NUM_OUTPUT_AUDIO_FORMATS 416 /* SSP */ diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index 3aacc440a5e4..c91a90dd8a6e 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -90,8 +90,10 @@ static const struct sof_topology_token ipc4_copier_tokens[] = { }; static const struct sof_topology_token ipc4_audio_fmt_num_tokens[] = { - {SOF_TKN_COMP_NUM_AUDIO_FORMATS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, - 0}, + {SOF_TKN_COMP_NUM_INPUT_AUDIO_FORMATS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, + offsetof(struct sof_ipc4_available_audio_format, num_input_formats)}, + {SOF_TKN_COMP_NUM_OUTPUT_AUDIO_FORMATS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, + offsetof(struct sof_ipc4_available_audio_format, num_output_formats)}, }; static const struct sof_topology_token dai_tokens[] = { @@ -178,19 +180,24 @@ static int sof_ipc4_get_audio_fmt(struct snd_soc_component *scomp, struct sof_ipc4_base_module_cfg *module_base_cfg) { struct sof_ipc4_pin_format *out_format, *in_format; - int audio_fmt_num = 0; int ret; - ret = sof_update_ipc_object(scomp, &audio_fmt_num, + ret = sof_update_ipc_object(scomp, available_fmt, SOF_AUDIO_FMT_NUM_TOKENS, swidget->tuples, - swidget->num_tuples, sizeof(audio_fmt_num), 1); - if (ret || audio_fmt_num <= 0) { - dev_err(scomp->dev, "Invalid number of audio formats: %d\n", audio_fmt_num); + swidget->num_tuples, sizeof(available_fmt), 1); + if (ret) { + dev_err(scomp->dev, "Failed to parse audio format token count\n"); + return ret; + } + + if (!available_fmt->num_input_formats && !available_fmt->num_output_formats) { + dev_err(scomp->dev, "No input/output pin formats set in topology\n"); return -EINVAL; } - available_fmt->audio_fmt_num = audio_fmt_num; - dev_dbg(scomp->dev, "Number of audio formats: %d\n", available_fmt->audio_fmt_num); + dev_dbg(scomp->dev, + "Number of input audio formats: %d. Number of output audio formats: %d\n", + available_fmt->num_input_formats, available_fmt->num_output_formats); /* set cpc and is_pages in the module's base_config */ ret = sof_update_ipc_object(scomp, module_base_cfg, SOF_COMP_TOKENS, swidget->tuples, @@ -204,51 +211,57 @@ static int sof_ipc4_get_audio_fmt(struct snd_soc_component *scomp, dev_dbg(scomp->dev, "widget %s cpc: %d is_pages: %d\n", swidget->widget->name, module_base_cfg->cpc, module_base_cfg->is_pages); - in_format = kcalloc(available_fmt->audio_fmt_num, sizeof(*in_format), GFP_KERNEL); - if (!in_format) - return -ENOMEM; + if (available_fmt->num_input_formats) { + in_format = kcalloc(available_fmt->num_input_formats, + sizeof(*in_format), GFP_KERNEL); + if (!in_format) + return -ENOMEM; + available_fmt->input_pin_fmts = in_format; - ret = sof_update_ipc_object(scomp, in_format, - SOF_IN_AUDIO_FORMAT_TOKENS, swidget->tuples, - swidget->num_tuples, sizeof(*in_format), - available_fmt->audio_fmt_num); - if (ret) { - dev_err(scomp->dev, "parse base_config audio_fmt tokens failed %d\n", ret); - goto err_in; + ret = sof_update_ipc_object(scomp, in_format, + SOF_IN_AUDIO_FORMAT_TOKENS, swidget->tuples, + swidget->num_tuples, sizeof(*in_format), + available_fmt->num_input_formats); + if (ret) { + dev_err(scomp->dev, "parse input audio fmt tokens failed %d\n", ret); + goto err_in; + } + + dev_dbg(scomp->dev, "Input audio formats for %s\n", swidget->widget->name); + sof_ipc4_dbg_audio_format(scomp->dev, in_format, + available_fmt->num_input_formats); } - dev_dbg(scomp->dev, "Get input audio formats for %s\n", swidget->widget->name); - sof_ipc4_dbg_audio_format(scomp->dev, available_fmt->input_pin_fmts, - available_fmt->audio_fmt_num); + if (available_fmt->num_output_formats) { + out_format = kcalloc(available_fmt->num_output_formats, sizeof(*out_format), + GFP_KERNEL); + if (!out_format) { + ret = -ENOMEM; + goto err_in; + } - out_format = kcalloc(available_fmt->audio_fmt_num, sizeof(*out_format), GFP_KERNEL); - if (!out_format) { - ret = -ENOMEM; - goto err_in; + ret = sof_update_ipc_object(scomp, out_format, + SOF_OUT_AUDIO_FORMAT_TOKENS, swidget->tuples, + swidget->num_tuples, sizeof(*out_format), + available_fmt->num_output_formats); + if (ret) { + dev_err(scomp->dev, "parse output audio fmt tokens failed\n"); + goto err_out; + } + + available_fmt->output_pin_fmts = out_format; + dev_dbg(scomp->dev, "Output audio formats for %s\n", swidget->widget->name); + sof_ipc4_dbg_audio_format(scomp->dev, out_format, + available_fmt->num_output_formats); } - ret = sof_update_ipc_object(scomp, out_format, - SOF_OUT_AUDIO_FORMAT_TOKENS, swidget->tuples, - swidget->num_tuples, sizeof(*out_format), - available_fmt->audio_fmt_num); - - if (ret) { - dev_err(scomp->dev, "parse output audio_fmt tokens failed\n"); - goto err_out; - } - - dev_dbg(scomp->dev, "Get output audio formats for %s\n", swidget->widget->name); - sof_ipc4_dbg_audio_format(scomp->dev, out_format, available_fmt->audio_fmt_num); - - available_fmt->output_pin_fmts = out_format; - available_fmt->input_pin_fmts = in_format; - return 0; err_out: kfree(out_format); err_in: kfree(in_format); + available_fmt->input_pin_fmts = NULL; return ret; } @@ -830,7 +843,7 @@ static int sof_ipc4_init_audio_fmt(struct snd_sof_dev *sdev, struct sof_ipc4_base_module_cfg *base_config, struct snd_pcm_hw_params *params, struct sof_ipc4_available_audio_format *available_fmt, - struct sof_ipc4_pin_format *pin_fmts) + struct sof_ipc4_pin_format *pin_fmts, u32 pin_fmts_size) { u32 valid_bits; u32 channels; @@ -858,7 +871,7 @@ static int sof_ipc4_init_audio_fmt(struct snd_sof_dev *sdev, return -EINVAL; } - if (!available_fmt->audio_fmt_num) { + if (!pin_fmts_size) { dev_err(sdev->dev, "no formats available for %s\n", swidget->widget->name); return -EINVAL; } @@ -867,7 +880,7 @@ static int sof_ipc4_init_audio_fmt(struct snd_sof_dev *sdev, * Search supported audio formats to match rate, channels ,and * sample_valid_bytes from runtime params */ - for (i = 0; i < available_fmt->audio_fmt_num; i++) { + for (i = 0; i < pin_fmts_size; i++) { struct sof_ipc4_audio_format *fmt = &pin_fmts[i].audio_fmt; rate = fmt->sampling_frequency; @@ -881,22 +894,26 @@ static int sof_ipc4_init_audio_fmt(struct snd_sof_dev *sdev, } } - if (i == available_fmt->audio_fmt_num) { + if (i == pin_fmts_size) { dev_err(sdev->dev, "%s: Unsupported audio format: %uHz, %ubit, %u channels\n", __func__, params_rate(params), sample_valid_bits, params_channels(params)); return -EINVAL; } /* copy input format */ - memcpy(&base_config->audio_fmt, &available_fmt->input_pin_fmts[i].audio_fmt, - sizeof(struct sof_ipc4_audio_format)); + if (available_fmt->num_input_formats && i < available_fmt->num_input_formats) { + memcpy(&base_config->audio_fmt, &available_fmt->input_pin_fmts[i].audio_fmt, + sizeof(struct sof_ipc4_audio_format)); - /* set base_cfg ibs/obs */ - base_config->ibs = available_fmt->input_pin_fmts[i].buffer_size; - base_config->obs = available_fmt->output_pin_fmts[i].buffer_size; + /* set base_cfg ibs/obs */ + base_config->ibs = available_fmt->input_pin_fmts[i].buffer_size; - dev_dbg(sdev->dev, "Init input audio formats for %s\n", swidget->widget->name); - sof_ipc4_dbg_audio_format(sdev->dev, &available_fmt->input_pin_fmts[i], 1); + dev_dbg(sdev->dev, "Init input audio formats for %s\n", swidget->widget->name); + sof_ipc4_dbg_audio_format(sdev->dev, &available_fmt->input_pin_fmts[i], 1); + } + + if (available_fmt->num_output_formats && i < available_fmt->num_output_formats) + base_config->obs = available_fmt->output_pin_fmts[i].buffer_size; /* Return the index of the matched format */ return i; @@ -1070,6 +1087,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, u32 **data; int ipc_size, ret; u32 deep_buffer_dma_ms = 0; + u32 format_list_count; dev_dbg(sdev->dev, "copier %s, type %d", swidget->widget->name, swidget->id); @@ -1102,10 +1120,13 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, * Use the input_pin_fmts to match pcm params for playback and the output_pin_fmts * for capture. */ - if (dir == SNDRV_PCM_STREAM_PLAYBACK) + if (dir == SNDRV_PCM_STREAM_PLAYBACK) { format_list_to_search = available_fmt->input_pin_fmts; - else + format_list_count = available_fmt->num_input_formats; + } else { format_list_to_search = available_fmt->output_pin_fmts; + format_list_count = available_fmt->num_output_formats; + } copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK; copier_data->gtw_cfg.node_id |= @@ -1126,6 +1147,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, available_fmt = &ipc4_copier->available_fmt; if (dir == SNDRV_PCM_STREAM_CAPTURE) { format_list_to_search = available_fmt->output_pin_fmts; + format_list_count = available_fmt->num_output_formats; /* * modify the input params for the dai copier as it only supports @@ -1136,6 +1158,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S32_LE); } else { format_list_to_search = available_fmt->input_pin_fmts; + format_list_count = available_fmt->num_input_formats; } ref_params = pipeline_params; @@ -1157,6 +1180,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, /* Use the input formats to match pcm params */ format_list_to_search = available_fmt->input_pin_fmts; + format_list_count = available_fmt->num_input_formats; ref_params = pipeline_params; break; @@ -1169,7 +1193,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, /* set input and output audio formats */ ret = sof_ipc4_init_audio_fmt(sdev, swidget, &copier_data->base_config, ref_params, - available_fmt, format_list_to_search); + available_fmt, format_list_to_search, format_list_count); if (ret < 0) return ret; @@ -1356,7 +1380,8 @@ static int sof_ipc4_prepare_gain_module(struct snd_sof_widget *swidget, ret = sof_ipc4_init_audio_fmt(sdev, swidget, &gain->base_config, pipeline_params, available_fmt, - available_fmt->input_pin_fmts); + available_fmt->input_pin_fmts, + available_fmt->num_input_formats); if (ret < 0) return ret; @@ -1379,7 +1404,8 @@ static int sof_ipc4_prepare_mixer_module(struct snd_sof_widget *swidget, ret = sof_ipc4_init_audio_fmt(sdev, swidget, &mixer->base_config, pipeline_params, available_fmt, - available_fmt->input_pin_fmts); + available_fmt->input_pin_fmts, + available_fmt->num_input_formats); if (ret < 0) return ret; @@ -1403,7 +1429,8 @@ static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget, ret = sof_ipc4_init_audio_fmt(sdev, swidget, &src->base_config, pipeline_params, available_fmt, - available_fmt->input_pin_fmts); + available_fmt->input_pin_fmts, + available_fmt->num_input_formats); if (ret < 0) return ret; diff --git a/sound/soc/sof/ipc4-topology.h b/sound/soc/sof/ipc4-topology.h index 6359ef8736ae..fad7a628f782 100644 --- a/sound/soc/sof/ipc4-topology.h +++ b/sound/soc/sof/ipc4-topology.h @@ -164,12 +164,14 @@ struct sof_ipc4_pin_format { * struct sof_ipc4_available_audio_format - Available audio formats * @output_pin_fmts: Available output pin formats * @input_pin_fmts: Available input pin formats - * @audio_fmt_num: Number of available audio formats + * @num_input_formats: Number of input pin formats + * @num_output_formats: Number of output pin formats */ struct sof_ipc4_available_audio_format { struct sof_ipc4_pin_format *output_pin_fmts; struct sof_ipc4_pin_format *input_pin_fmts; - int audio_fmt_num; + u32 num_input_formats; + u32 num_output_formats; }; /** diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 3a091f18731f..b642835e14df 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -1231,35 +1231,43 @@ static int sof_widget_parse_tokens(struct snd_soc_component *scomp, struct snd_s continue; case SOF_IN_AUDIO_FORMAT_TOKENS: - case SOF_OUT_AUDIO_FORMAT_TOKENS: - num_sets = sof_get_token_value(SOF_TKN_COMP_NUM_AUDIO_FORMATS, + num_sets = sof_get_token_value(SOF_TKN_COMP_NUM_INPUT_AUDIO_FORMATS, swidget->tuples, swidget->num_tuples); - if (num_sets < 0) { - dev_err(sdev->dev, "Invalid audio format count for %s\n", + dev_err(sdev->dev, "Invalid input audio format count for %s\n", swidget->widget->name); ret = num_sets; goto err; } - - if (num_sets > 1) { - struct snd_sof_tuple *new_tuples; - - num_tuples += token_list[object_token_list[i]].count * num_sets; - new_tuples = krealloc(swidget->tuples, - sizeof(*new_tuples) * num_tuples, GFP_KERNEL); - if (!new_tuples) { - ret = -ENOMEM; - goto err; - } - - swidget->tuples = new_tuples; + break; + case SOF_OUT_AUDIO_FORMAT_TOKENS: + num_sets = sof_get_token_value(SOF_TKN_COMP_NUM_OUTPUT_AUDIO_FORMATS, + swidget->tuples, swidget->num_tuples); + if (num_sets < 0) { + dev_err(sdev->dev, "Invalid output audio format count for %s\n", + swidget->widget->name); + ret = num_sets; + goto err; } break; default: break; } + if (num_sets > 1) { + struct snd_sof_tuple *new_tuples; + + num_tuples += token_list[object_token_list[i]].count * num_sets; + new_tuples = krealloc(swidget->tuples, + sizeof(*new_tuples) * num_tuples, GFP_KERNEL); + if (!new_tuples) { + ret = -ENOMEM; + goto err; + } + + swidget->tuples = new_tuples; + } + /* copy one set of tuples per token ID into swidget->tuples */ ret = sof_copy_tuples(sdev, private->array, le32_to_cpu(private->size), object_token_list[i], num_sets, swidget->tuples, From ad70f2f0e6e38675d7805482d2c625fca5756a2e Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Mon, 13 Mar 2023 14:48:56 +0200 Subject: [PATCH 344/778] ASoC: SOF: ipc4-topology: Search only pin 0 formats MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Base config only contains the input/output audio formats for pin 0. So match only the pin 0 formats during runtime format selection. Signed-off-by: Ranjani Sridharan Reviewed-by: Rander Wang Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230313124856.8140-12-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index c91a90dd8a6e..683182e53a32 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -877,12 +877,15 @@ static int sof_ipc4_init_audio_fmt(struct snd_sof_dev *sdev, } /* - * Search supported audio formats to match rate, channels ,and + * Search supported audio formats with pin index 0 to match rate, channels ,and * sample_valid_bytes from runtime params */ for (i = 0; i < pin_fmts_size; i++) { struct sof_ipc4_audio_format *fmt = &pin_fmts[i].audio_fmt; + if (pin_fmts[i].pin_index) + continue; + rate = fmt->sampling_frequency; channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(fmt->fmt_cfg); valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt->fmt_cfg); From ff728899065922534d80170685fb807194d6487b Mon Sep 17 00:00:00 2001 From: Trevor Wu Date: Tue, 7 Mar 2023 12:09:35 +0800 Subject: [PATCH 345/778] ASoC: mediatek: mt8195: add dai id check before accessing array Coverity shows "afe_priv->dai_priv[dai_id] evaluates to an address that could be at negative offset of an array.". Add dai id check before accessing the array element. This ensures that the offset of an array must be a valid index. Signed-off-by: Trevor Wu Link: https://lore.kernel.org/r/20230307040938.7484-2-trevor.wu@mediatek.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8195/mt8195-dai-adda.c | 17 +- sound/soc/mediatek/mt8195/mt8195-dai-etdm.c | 177 +++++++++++++++++--- sound/soc/mediatek/mt8195/mt8195-dai-pcm.c | 26 ++- 3 files changed, 185 insertions(+), 35 deletions(-) diff --git a/sound/soc/mediatek/mt8195/mt8195-dai-adda.c b/sound/soc/mediatek/mt8195/mt8195-dai-adda.c index f04bd1781356..0dd35255066b 100644 --- a/sound/soc/mediatek/mt8195/mt8195-dai-adda.c +++ b/sound/soc/mediatek/mt8195/mt8195-dai-adda.c @@ -704,13 +704,18 @@ static int mtk_dai_adda_hw_params(struct snd_pcm_substream *substream, { struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); struct mt8195_afe_private *afe_priv = afe->platform_priv; - struct mtk_dai_adda_priv *adda_priv = afe_priv->dai_priv[dai->id]; + struct mtk_dai_adda_priv *adda_priv; unsigned int rate = params_rate(params); - int id = dai->id; - int ret = 0; + int ret; + + if (dai->id != MT8195_AFE_IO_DL_SRC && + dai->id != MT8195_AFE_IO_UL_SRC1 && + dai->id != MT8195_AFE_IO_UL_SRC2) + return -EINVAL; + adda_priv = afe_priv->dai_priv[dai->id]; dev_dbg(afe->dev, "%s(), id %d, stream %d, rate %d\n", - __func__, id, substream->stream, rate); + __func__, dai->id, substream->stream, rate); if (rate > ADDA_HIRES_THRES) adda_priv->hires_required = 1; @@ -718,9 +723,9 @@ static int mtk_dai_adda_hw_params(struct snd_pcm_substream *substream, adda_priv->hires_required = 0; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - ret = mtk_dai_da_configure(afe, rate, id); + ret = mtk_dai_da_configure(afe, rate, dai->id); else - ret = mtk_dai_ad_configure(afe, rate, id); + ret = mtk_dai_ad_configure(afe, rate, dai->id); return ret; } diff --git a/sound/soc/mediatek/mt8195/mt8195-dai-etdm.c b/sound/soc/mediatek/mt8195/mt8195-dai-etdm.c index f2c9a1fdbe0d..eedb9165f911 100644 --- a/sound/soc/mediatek/mt8195/mt8195-dai-etdm.c +++ b/sound/soc/mediatek/mt8195/mt8195-dai-etdm.c @@ -137,6 +137,38 @@ static const struct mtk_dai_etdm_rate mt8195_etdm_rates[] = { { .rate = 352800, .reg_value = 21, }, }; +static bool mt8195_afe_etdm_is_valid(int id) +{ + switch (id) { + case MT8195_AFE_IO_ETDM1_IN: + fallthrough; + case MT8195_AFE_IO_ETDM2_IN: + fallthrough; + case MT8195_AFE_IO_ETDM1_OUT: + fallthrough; + case MT8195_AFE_IO_ETDM2_OUT: + fallthrough; + case MT8195_AFE_IO_DPTX: + fallthrough; + case MT8195_AFE_IO_ETDM3_OUT: + return true; + default: + return false; + } +} + +static bool mt8195_afe_hdmitx_dptx_is_valid(int id) +{ + switch (id) { + case MT8195_AFE_IO_DPTX: + fallthrough; + case MT8195_AFE_IO_ETDM3_OUT: + return true; + default: + return false; + } +} + static int get_etdm_fs_timing(unsigned int rate) { int i; @@ -236,8 +268,12 @@ static int is_cowork_mode(struct snd_soc_dai *dai) { struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); struct mt8195_afe_private *afe_priv = afe->platform_priv; - struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai->id]; + struct mtk_dai_etdm_priv *etdm_data; + if (!mt8195_afe_etdm_is_valid(dai->id)) + return -EINVAL; + + etdm_data = afe_priv->dai_priv[dai->id]; return (etdm_data->cowork_slv_count > 0 || etdm_data->cowork_source_id != COWORK_ETDM_NONE); } @@ -264,8 +300,14 @@ static int get_etdm_cowork_master_id(struct snd_soc_dai *dai) { struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); struct mt8195_afe_private *afe_priv = afe->platform_priv; - struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai->id]; - int dai_id = etdm_data->cowork_source_id; + struct mtk_dai_etdm_priv *etdm_data; + int dai_id; + + if (!mt8195_afe_etdm_is_valid(dai->id)) + return -EINVAL; + + etdm_data = afe_priv->dai_priv[dai->id]; + dai_id = etdm_data->cowork_source_id; if (dai_id == COWORK_ETDM_NONE) dai_id = dai->id; @@ -1276,9 +1318,13 @@ static int mt8195_afe_enable_etdm(struct mtk_base_afe *afe, int dai_id) int ret = 0; struct etdm_con_reg etdm_reg; struct mt8195_afe_private *afe_priv = afe->platform_priv; - struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai_id]; + struct mtk_dai_etdm_priv *etdm_data; unsigned long flags; + if (!mt8195_afe_etdm_is_valid(dai_id)) + return -EINVAL; + + etdm_data = afe_priv->dai_priv[dai_id]; spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags); etdm_data->en_ref_cnt++; if (etdm_data->en_ref_cnt == 1) { @@ -1299,9 +1345,13 @@ static int mt8195_afe_disable_etdm(struct mtk_base_afe *afe, int dai_id) int ret = 0; struct etdm_con_reg etdm_reg; struct mt8195_afe_private *afe_priv = afe->platform_priv; - struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai_id]; + struct mtk_dai_etdm_priv *etdm_data; unsigned long flags; + if (!mt8195_afe_etdm_is_valid(dai_id)) + return -EINVAL; + + etdm_data = afe_priv->dai_priv[dai_id]; spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags); if (etdm_data->en_ref_cnt > 0) { etdm_data->en_ref_cnt--; @@ -1357,12 +1407,16 @@ static int etdm_cowork_slv_sel(int id, int slave_mode) static int mt8195_etdm_sync_mode_configure(struct mtk_base_afe *afe, int dai_id) { struct mt8195_afe_private *afe_priv = afe->platform_priv; - struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai_id]; + struct mtk_dai_etdm_priv *etdm_data; unsigned int reg = 0; unsigned int mask; unsigned int val; int cowork_source_sel; + if (!mt8195_afe_etdm_is_valid(dai_id)) + return -EINVAL; + + etdm_data = afe_priv->dai_priv[dai_id]; if (etdm_data->cowork_source_id == COWORK_ETDM_NONE) return 0; @@ -1532,8 +1586,10 @@ static int mtk_dai_etdm_startup(struct snd_pcm_substream *substream, if (is_cowork_mode(dai)) { mst_dai_id = get_etdm_cowork_master_id(dai); - mtk_dai_etdm_enable_mclk(afe, mst_dai_id); + if (!mt8195_afe_etdm_is_valid(mst_dai_id)) + return -EINVAL; + mtk_dai_etdm_enable_mclk(afe, mst_dai_id); cg_id = mtk_dai_etdm_get_cg_id_by_dai_id(mst_dai_id); if (cg_id >= 0) mt8195_afe_enable_clk(afe, afe_priv->clk[cg_id]); @@ -1571,6 +1627,9 @@ static void mtk_dai_etdm_shutdown(struct snd_pcm_substream *substream, if (is_cowork_mode(dai)) { mst_dai_id = get_etdm_cowork_master_id(dai); + if (!mt8195_afe_etdm_is_valid(mst_dai_id)) + return; + cg_id = mtk_dai_etdm_get_cg_id_by_dai_id(mst_dai_id); if (cg_id >= 0) mt8195_afe_disable_clk(afe, afe_priv->clk[cg_id]); @@ -1631,16 +1690,24 @@ static int mtk_dai_etdm_in_configure(struct mtk_base_afe *afe, int dai_id) { struct mt8195_afe_private *afe_priv = afe->platform_priv; - struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai_id]; + struct mtk_dai_etdm_priv *etdm_data; struct etdm_con_reg etdm_reg; - bool slave_mode = etdm_data->slave_mode; - unsigned int data_mode = etdm_data->data_mode; - unsigned int lrck_width = etdm_data->lrck_width; + bool slave_mode; + unsigned int data_mode; + unsigned int lrck_width; unsigned int val = 0; unsigned int mask = 0; int i; int ret; + if (!mt8195_afe_etdm_is_valid(dai_id)) + return -EINVAL; + + etdm_data = afe_priv->dai_priv[dai_id]; + slave_mode = etdm_data->slave_mode; + data_mode = etdm_data->data_mode; + lrck_width = etdm_data->lrck_width; + dev_dbg(afe->dev, "%s rate %u channels %u, id %d\n", __func__, rate, channels, dai_id); @@ -1748,15 +1815,22 @@ static int mtk_dai_etdm_out_configure(struct mtk_base_afe *afe, int dai_id) { struct mt8195_afe_private *afe_priv = afe->platform_priv; - struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai_id]; + struct mtk_dai_etdm_priv *etdm_data; struct etdm_con_reg etdm_reg; - bool slave_mode = etdm_data->slave_mode; - unsigned int lrck_width = etdm_data->lrck_width; + bool slave_mode; + unsigned int lrck_width; unsigned int val = 0; unsigned int mask = 0; int ret; int fs = 0; + if (!mt8195_afe_etdm_is_valid(dai_id)) + return -EINVAL; + + etdm_data = afe_priv->dai_priv[dai_id]; + slave_mode = etdm_data->slave_mode; + lrck_width = etdm_data->lrck_width; + dev_dbg(afe->dev, "%s rate %u channels %u, id %d\n", __func__, rate, channels, dai_id); @@ -1837,7 +1911,7 @@ static int mtk_dai_etdm_out_configure(struct mtk_base_afe *afe, static int mtk_dai_etdm_mclk_configure(struct mtk_base_afe *afe, int dai_id) { struct mt8195_afe_private *afe_priv = afe->platform_priv; - struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai_id]; + struct mtk_dai_etdm_priv *etdm_data; int clk_id = mtk_dai_etdm_get_clk_id_by_dai_id(dai_id); int clkdiv_id = mtk_dai_etdm_get_clkdiv_id_by_dai_id(dai_id); int apll; @@ -1850,6 +1924,10 @@ static int mtk_dai_etdm_mclk_configure(struct mtk_base_afe *afe, int dai_id) if (clk_id < 0 || clkdiv_id < 0) return 0; + if (!mt8195_afe_etdm_is_valid(dai_id)) + return -EINVAL; + + etdm_data = afe_priv->dai_priv[dai_id]; ret = get_etdm_reg(dai_id, &etdm_reg); if (ret < 0) return ret; @@ -1888,9 +1966,9 @@ static int mtk_dai_etdm_configure(struct mtk_base_afe *afe, int dai_id) { struct mt8195_afe_private *afe_priv = afe->platform_priv; - struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai_id]; + struct mtk_dai_etdm_priv *etdm_data; struct etdm_con_reg etdm_reg; - bool slave_mode = etdm_data->slave_mode; + bool slave_mode; unsigned int etdm_channels; unsigned int val = 0; unsigned int mask = 0; @@ -1898,6 +1976,11 @@ static int mtk_dai_etdm_configure(struct mtk_base_afe *afe, unsigned int wlen = get_etdm_wlen(bit_width); int ret; + if (!mt8195_afe_etdm_is_valid(dai_id)) + return -EINVAL; + + etdm_data = afe_priv->dai_priv[dai_id]; + slave_mode = etdm_data->slave_mode; ret = get_etdm_reg(dai_id, &etdm_reg); if (ret < 0) return ret; @@ -1973,6 +2056,8 @@ static int mtk_dai_etdm_hw_params(struct snd_pcm_substream *substream, if (is_cowork_mode(dai)) { mst_dai_id = get_etdm_cowork_master_id(dai); + if (!mt8195_afe_etdm_is_valid(mst_dai_id)) + return -EINVAL; ret = mtk_dai_etdm_mclk_configure(afe, mst_dai_id); if (ret) @@ -2024,6 +2109,9 @@ static int mtk_dai_etdm_trigger(struct snd_pcm_substream *substream, int cmd, case SNDRV_PCM_TRIGGER_RESUME: if (is_cowork_mode(dai)) { mst_dai_id = get_etdm_cowork_master_id(dai); + if (!mt8195_afe_etdm_is_valid(mst_dai_id)) + return -EINVAL; + mst_etdm_data = afe_priv->dai_priv[mst_dai_id]; //open master first @@ -2040,6 +2128,9 @@ static int mtk_dai_etdm_trigger(struct snd_pcm_substream *substream, int cmd, case SNDRV_PCM_TRIGGER_SUSPEND: if (is_cowork_mode(dai)) { mst_dai_id = get_etdm_cowork_master_id(dai); + if (!mt8195_afe_etdm_is_valid(mst_dai_id)) + return -EINVAL; + mst_etdm_data = afe_priv->dai_priv[mst_dai_id]; for (i = 0; i < mst_etdm_data->cowork_slv_count; i++) { @@ -2061,10 +2152,14 @@ static int mtk_dai_etdm_trigger(struct snd_pcm_substream *substream, int cmd, static int mtk_dai_etdm_cal_mclk(struct mtk_base_afe *afe, int freq, int dai_id) { struct mt8195_afe_private *afe_priv = afe->platform_priv; - struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai_id]; + struct mtk_dai_etdm_priv *etdm_data; int apll; int apll_rate; + if (!mt8195_afe_etdm_is_valid(dai_id)) + return -EINVAL; + + etdm_data = afe_priv->dai_priv[dai_id]; if (freq == 0) { etdm_data->mclk_freq = freq; return 0; @@ -2104,6 +2199,9 @@ static int mtk_dai_etdm_set_sysclk(struct snd_soc_dai *dai, else dai_id = dai->id; + if (!mt8195_afe_etdm_is_valid(dai_id)) + return -EINVAL; + etdm_data = afe_priv->dai_priv[dai_id]; etdm_data->mclk_dir = dir; return mtk_dai_etdm_cal_mclk(afe, freq, dai_id); @@ -2115,8 +2213,12 @@ static int mtk_dai_etdm_set_tdm_slot(struct snd_soc_dai *dai, { struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); struct mt8195_afe_private *afe_priv = afe->platform_priv; - struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai->id]; + struct mtk_dai_etdm_priv *etdm_data; + if (!mt8195_afe_etdm_is_valid(dai->id)) + return -EINVAL; + + etdm_data = afe_priv->dai_priv[dai->id]; dev_dbg(dai->dev, "%s id %d slot_width %d\n", __func__, dai->id, slot_width); @@ -2129,8 +2231,12 @@ static int mtk_dai_etdm_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) { struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); struct mt8195_afe_private *afe_priv = afe->platform_priv; - struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai->id]; + struct mtk_dai_etdm_priv *etdm_data; + if (!mt8195_afe_etdm_is_valid(dai->id)) + return -EINVAL; + + etdm_data = afe_priv->dai_priv[dai->id]; switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: etdm_data->format = MTK_DAI_ETDM_FORMAT_I2S; @@ -2248,13 +2354,18 @@ static int mtk_dai_hdmitx_dptx_hw_params(struct snd_pcm_substream *substream, { struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); struct mt8195_afe_private *afe_priv = afe->platform_priv; - struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai->id]; + struct mtk_dai_etdm_priv *etdm_data; unsigned int rate = params_rate(params); unsigned int channels = params_channels(params); snd_pcm_format_t format = params_format(params); int width = snd_pcm_format_physical_width(format); int ret = 0; + if (!mt8195_afe_hdmitx_dptx_is_valid(dai->id)) + return -EINVAL; + + etdm_data = afe_priv->dai_priv[dai->id]; + /* dptx configure */ if (dai->id == MT8195_AFE_IO_DPTX) { regmap_update_bits(afe->regmap, AFE_DPTX_CON, @@ -2331,7 +2442,12 @@ static int mtk_dai_hdmitx_dptx_set_sysclk(struct snd_soc_dai *dai, { struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); struct mt8195_afe_private *afe_priv = afe->platform_priv; - struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai->id]; + struct mtk_dai_etdm_priv *etdm_data; + + if (!mt8195_afe_hdmitx_dptx_is_valid(dai->id)) + return -EINVAL; + + etdm_data = afe_priv->dai_priv[dai->id]; dev_dbg(dai->dev, "%s id %d freq %u, dir %d\n", __func__, dai->id, freq, dir); @@ -2370,10 +2486,14 @@ static int mtk_dai_etdm_probe(struct snd_soc_dai *dai) { struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); struct mt8195_afe_private *afe_priv = afe->platform_priv; - struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai->id]; + struct mtk_dai_etdm_priv *etdm_data; dev_dbg(dai->dev, "%s id %d\n", __func__, dai->id); + if (!mt8195_afe_etdm_is_valid(dai->id)) + return -EINVAL; + + etdm_data = afe_priv->dai_priv[dai->id]; if (etdm_data->mclk_freq) { dev_dbg(afe->dev, "MCLK always on, rate %d\n", etdm_data->mclk_freq); @@ -2477,6 +2597,11 @@ static void mt8195_etdm_update_sync_info(struct mtk_base_afe *afe) etdm_data = afe_priv->dai_priv[i]; if (etdm_data->cowork_source_id != COWORK_ETDM_NONE) { mst_dai_id = etdm_data->cowork_source_id; + if (!mt8195_afe_etdm_is_valid(mst_dai_id)) { + dev_err(afe->dev, "%s invalid dai id %d\n", + __func__, mst_dai_id); + return; + } mst_data = afe_priv->dai_priv[mst_dai_id]; if (mst_data->cowork_source_id != COWORK_ETDM_NONE) dev_info(afe->dev, "%s [%d] wrong sync source\n" @@ -2513,6 +2638,12 @@ static void mt8195_dai_etdm_parse_of(struct mtk_base_afe *afe) for (i = 0; i < MT8195_AFE_IO_ETDM_NUM; i++) { dai_id = ETDM_TO_DAI_ID(i); + if (!mt8195_afe_etdm_is_valid(dai_id)) { + dev_err(afe->dev, "%s invalid dai id %d\n", + __func__, dai_id); + return; + } + etdm_data = afe_priv->dai_priv[dai_id]; ret = snprintf(prop, sizeof(prop), diff --git a/sound/soc/mediatek/mt8195/mt8195-dai-pcm.c b/sound/soc/mediatek/mt8195/mt8195-dai-pcm.c index 051433689ff5..6d6d79300d51 100644 --- a/sound/soc/mediatek/mt8195/mt8195-dai-pcm.c +++ b/sound/soc/mediatek/mt8195/mt8195-dai-pcm.c @@ -122,17 +122,26 @@ static int mtk_dai_pcm_configure(struct snd_pcm_substream *substream, struct snd_pcm_runtime * const runtime = substream->runtime; struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); struct mt8195_afe_private *afe_priv = afe->platform_priv; - struct mtk_dai_pcmif_priv *pcmif_priv = afe_priv->dai_priv[dai->id]; - unsigned int slave_mode = pcmif_priv->slave_mode; - unsigned int lrck_inv = pcmif_priv->lrck_inv; - unsigned int bck_inv = pcmif_priv->bck_inv; - unsigned int fmt = pcmif_priv->format; + struct mtk_dai_pcmif_priv *pcmif_priv; + unsigned int slave_mode; + unsigned int lrck_inv; + unsigned int bck_inv; + unsigned int fmt; unsigned int bit_width = dai->sample_bits; unsigned int val = 0; unsigned int mask = 0; int fs = 0; int mode = 0; + if (dai->id != MT8195_AFE_IO_PCM) + return -EINVAL; + + pcmif_priv = afe_priv->dai_priv[dai->id]; + slave_mode = pcmif_priv->slave_mode; + lrck_inv = pcmif_priv->lrck_inv; + bck_inv = pcmif_priv->bck_inv; + fmt = pcmif_priv->format; + /* sync freq mode */ fs = mt8195_afe_fs_timing(runtime->rate); if (fs < 0) @@ -230,10 +239,15 @@ static int mtk_dai_pcm_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) { struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); struct mt8195_afe_private *afe_priv = afe->platform_priv; - struct mtk_dai_pcmif_priv *pcmif_priv = afe_priv->dai_priv[dai->id]; + struct mtk_dai_pcmif_priv *pcmif_priv; dev_dbg(dai->dev, "%s fmt 0x%x\n", __func__, fmt); + if (dai->id != MT8195_AFE_IO_PCM) + return -EINVAL; + + pcmif_priv = afe_priv->dai_priv[dai->id]; + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: pcmif_priv->format = MTK_DAI_PCM_FMT_I2S; From 1a3f0116b74ba2f9477c28fcf9d66ac7126455fd Mon Sep 17 00:00:00 2001 From: Trevor Wu Date: Tue, 7 Mar 2023 12:09:36 +0800 Subject: [PATCH 346/778] ASoC: mediatek: mt9195-mt6359: fix UNINIT problem Coverity shows using uninitialized value monitor. When regmap_read returns an error, monitor keeps the value left from earlier computation. To prevent from the unexpected result in the case, assign 0 to monitor. Signed-off-by: Trevor Wu Link: https://lore.kernel.org/r/20230307040938.7484-3-trevor.wu@mediatek.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8195/mt8195-mt6359.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/mediatek/mt8195/mt8195-mt6359.c b/sound/soc/mediatek/mt8195/mt8195-mt6359.c index 4682748d82be..ceca882ecff7 100644 --- a/sound/soc/mediatek/mt8195/mt8195-mt6359.c +++ b/sound/soc/mediatek/mt8195/mt8195-mt6359.c @@ -158,7 +158,7 @@ static int mt8195_mt6359_mtkaif_calibration(struct snd_soc_pcm_runtime *rtd) int mtkaif_phase_cycle[MT8195_MTKAIF_MISO_NUM]; int mtkaif_calibration_num_phase; bool mtkaif_calibration_ok; - unsigned int monitor; + unsigned int monitor = 0; int counter; int phase; int i; From 9760e01b3851dc51d1901876668168328d34a647 Mon Sep 17 00:00:00 2001 From: Trevor Wu Date: Tue, 7 Mar 2023 12:09:37 +0800 Subject: [PATCH 347/778] ASoC: mediatek: mt6358: fix UNINIT problem Coverity shows decaring variable reg without initializer. When regmap_read returns an error, reg keeps the value left from earlier computation. To prevent from the unexpected result in the case, assign 0 to reg. Signed-off-by: Trevor Wu Link: https://lore.kernel.org/r/20230307040938.7484-4-trevor.wu@mediatek.com Signed-off-by: Mark Brown --- sound/soc/codecs/mt6358.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/mt6358.c b/sound/soc/codecs/mt6358.c index b54610b27906..d7b157ddc9a8 100644 --- a/sound/soc/codecs/mt6358.c +++ b/sound/soc/codecs/mt6358.c @@ -429,7 +429,7 @@ static int mt6358_put_volsw(struct snd_kcontrol *kcontrol, struct mt6358_priv *priv = snd_soc_component_get_drvdata(component); struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; - unsigned int reg; + unsigned int reg = 0; int ret; ret = snd_soc_put_volsw(kcontrol, ucontrol); From 3a60fa4c063dacc5eb66660aa23107f3cb8a477e Mon Sep 17 00:00:00 2001 From: Trevor Wu Date: Tue, 7 Mar 2023 12:09:38 +0800 Subject: [PATCH 348/778] ASoC: mediatek: mt6359: fix UNINIT problem Coverity shows decaring variable reg without initializer. When regmap_read returns an error, reg keeps the value left from earlier computation. To prevent from the unexpected result in the case, assign 0 to reg. Signed-off-by: Trevor Wu Link: https://lore.kernel.org/r/20230307040938.7484-5-trevor.wu@mediatek.com Signed-off-by: Mark Brown --- sound/soc/codecs/mt6359.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/mt6359.c b/sound/soc/codecs/mt6359.c index c9a453ce8a2a..cb487e63615c 100644 --- a/sound/soc/codecs/mt6359.c +++ b/sound/soc/codecs/mt6359.c @@ -358,7 +358,7 @@ static int mt6359_put_volsw(struct snd_kcontrol *kcontrol, struct mt6359_priv *priv = snd_soc_component_get_drvdata(component); struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; - unsigned int reg; + unsigned int reg = 0; int index = ucontrol->value.integer.value[0]; int ret; From 8cd3cb17fcf216cb859f86a00fff428fbcecc1d8 Mon Sep 17 00:00:00 2001 From: Chao Song Date: Mon, 13 Mar 2023 12:13:02 +0200 Subject: [PATCH 349/778] ASoC: SOF: sof-audio: add support for setting up loopback routes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit During route setup, playback stream routes are setup by going through sink path, capture stream routes are set up by going through source path. This is not sufficient to handle loopback cases between pipelines configured with different directions, e.g. a sidetone or an amplifier feedback connected to a speaker protection module. So, add the logic to handle such routes between widgets that aren't in the list of DAPM widgets associated with the same PCM. Link: https://github.com/thesofproject/linux/issues/4042 Suggested-by: Bard Liao Signed-off-by: Chao Song Signed-off-by: Ranjani Sridharan Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230313101302.20950-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/sof-audio.c | 61 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c index 6de388a8d0b8..4f12e137ff63 100644 --- a/sound/soc/sof/sof-audio.c +++ b/sound/soc/sof/sof-audio.c @@ -280,9 +280,11 @@ int sof_route_setup(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget *wsourc static int sof_setup_pipeline_connections(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget_list *list, int dir) { + const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); struct snd_soc_dapm_widget *widget; + struct snd_sof_route *sroute; struct snd_soc_dapm_path *p; - int ret; + int ret = 0; int i; /* @@ -325,6 +327,63 @@ static int sof_setup_pipeline_connections(struct snd_sof_dev *sdev, } } + /* + * The above loop handles connections between widgets that belong to the DAPM widget list. + * This is not sufficient to handle loopback cases between pipelines configured with + * different directions, e.g. a sidetone or an amplifier feedback connected to a speaker + * protection module. + */ + list_for_each_entry(sroute, &sdev->route_list, list) { + bool src_widget_in_dapm_list, sink_widget_in_dapm_list; + struct snd_sof_widget *swidget; + + if (sroute->setup) + continue; + + src_widget_in_dapm_list = widget_in_list(list, sroute->src_widget->widget); + sink_widget_in_dapm_list = widget_in_list(list, sroute->sink_widget->widget); + + /* + * if both source and sink are in the DAPM list, the route must already have been + * set up above. And if neither are in the DAPM list, the route shouldn't be + * handled now. + */ + if (src_widget_in_dapm_list == sink_widget_in_dapm_list) + continue; + + /* + * At this point either the source widget or the sink widget is in the DAPM list + * with a route that might need to be set up. Check the use_count of the widget + * that is not in the DAPM list to confirm if it is in use currently before setting + * up the route. + */ + if (src_widget_in_dapm_list) + swidget = sroute->sink_widget; + else + swidget = sroute->src_widget; + + mutex_lock(&swidget->setup_mutex); + if (!swidget->use_count) { + mutex_unlock(&swidget->setup_mutex); + continue; + } + + if (tplg_ops && tplg_ops->route_setup) { + /* + * this route will get freed when either the source widget or the sink + * widget is freed during hw_free + */ + ret = tplg_ops->route_setup(sdev, sroute); + if (!ret) + sroute->setup = true; + } + + mutex_unlock(&swidget->setup_mutex); + + if (ret < 0) + return ret; + } + return 0; } From d7d103d1779c3d0bc4d55f2802930a6b067450c0 Mon Sep 17 00:00:00 2001 From: Tom Rix Date: Thu, 9 Mar 2023 09:09:59 -0500 Subject: [PATCH 350/778] ASoC: SMA1303: set sma_i2c_regmap storage-class-specifier to static smatch reports sound/soc/codecs/sma1303.c:1594:28: warning: symbol 'sma_i2c_regmap' was not declared. Should it be static? sma_i2c_regmap is only used in sma1303, so it should be static Signed-off-by: Tom Rix Link: https://lore.kernel.org/r/20230309140959.2616497-1-trix@redhat.com Signed-off-by: Mark Brown --- sound/soc/codecs/sma1303.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/sma1303.c b/sound/soc/codecs/sma1303.c index fa4b0a60f8a9..b6c132edf3bd 100644 --- a/sound/soc/codecs/sma1303.c +++ b/sound/soc/codecs/sma1303.c @@ -1591,7 +1591,7 @@ static const struct snd_soc_component_driver sma1303_component = { .num_dapm_routes = ARRAY_SIZE(sma1303_audio_map), }; -const struct regmap_config sma_i2c_regmap = { +static const struct regmap_config sma_i2c_regmap = { .reg_bits = 8, .val_bits = 8, From a9048d64fb9605eb68c9912724e4a1346db8ba1a Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 10 Mar 2023 22:43:29 +0100 Subject: [PATCH 351/778] ASoC: codecs: adau1977-spi: Mark OF related data as maybe unused MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver can be compile tested with !CONFIG_OF making certain data unused: sound/soc/codecs/adau1977-spi.c:58:34: error: ‘adau1977_spi_of_match’ defined but not used [-Werror=unused-const-variable=] Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230310214333.274903-6-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/adau1977-spi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/adau1977-spi.c b/sound/soc/codecs/adau1977-spi.c index 8370bec27a9c..207c5c95f35a 100644 --- a/sound/soc/codecs/adau1977-spi.c +++ b/sound/soc/codecs/adau1977-spi.c @@ -55,7 +55,7 @@ static const struct spi_device_id adau1977_spi_ids[] = { }; MODULE_DEVICE_TABLE(spi, adau1977_spi_ids); -static const struct of_device_id adau1977_spi_of_match[] = { +static const struct of_device_id adau1977_spi_of_match[] __maybe_unused = { { .compatible = "adi,adau1977" }, { .compatible = "adi,adau1978" }, { .compatible = "adi,adau1979" }, From 413beba1a336e6068119f31a4441c51a7aeb1b55 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 10 Mar 2023 22:43:30 +0100 Subject: [PATCH 352/778] ASoC: codecs: pcm179x-spi: Mark OF related data as maybe unused MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver can be compile tested with !CONFIG_OF making certain data unused: sound/soc/codecs/pcm179x-spi.c:32:34: error: ‘pcm179x_of_match’ defined but not used [-Werror=unused-const-variable=] Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230310214333.274903-7-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/pcm179x-spi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/pcm179x-spi.c b/sound/soc/codecs/pcm179x-spi.c index ebf63ea90a1c..192fee90c971 100644 --- a/sound/soc/codecs/pcm179x-spi.c +++ b/sound/soc/codecs/pcm179x-spi.c @@ -29,7 +29,7 @@ static int pcm179x_spi_probe(struct spi_device *spi) return pcm179x_common_init(&spi->dev, regmap); } -static const struct of_device_id pcm179x_of_match[] = { +static const struct of_device_id pcm179x_of_match[] __maybe_unused = { { .compatible = "ti,pcm1792a", }, { } }; From 0e8599a35823f05e90513918ff1201f8d210e315 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 10 Mar 2023 22:43:31 +0100 Subject: [PATCH 353/778] ASoC: codecs: rt1019: Mark OF related data as maybe unused MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver can be compile tested with !CONFIG_OF making certain data unused: sound/soc/codecs/rt1019.c:549:34: error: ‘rt1019_of_match’ defined but not used [-Werror=unused-const-variable=] Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230310214333.274903-8-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/rt1019.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/rt1019.c b/sound/soc/codecs/rt1019.c index 49f527c61a7a..dff2596c81eb 100644 --- a/sound/soc/codecs/rt1019.c +++ b/sound/soc/codecs/rt1019.c @@ -546,7 +546,7 @@ static const struct i2c_device_id rt1019_i2c_id[] = { }; MODULE_DEVICE_TABLE(i2c, rt1019_i2c_id); -static const struct of_device_id rt1019_of_match[] = { +static const struct of_device_id rt1019_of_match[] __maybe_unused = { { .compatible = "realtek,rt1019", }, {}, }; From 075a430db402eed0907b80493f1432d47a5120a7 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 10 Mar 2023 22:43:32 +0100 Subject: [PATCH 354/778] ASoC: codecs: src4xxx-i2c: Mark OF related data as maybe unused MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver can be compile tested with !CONFIG_OF making certain data unused: sound/soc/codecs/src4xxx-i2c.c:27:34: error: ‘src4xxx_of_match’ defined but not used [-Werror=unused-const-variable=] Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230310214333.274903-9-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/src4xxx-i2c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/src4xxx-i2c.c b/sound/soc/codecs/src4xxx-i2c.c index 27026030704a..a40fd20df984 100644 --- a/sound/soc/codecs/src4xxx-i2c.c +++ b/sound/soc/codecs/src4xxx-i2c.c @@ -24,7 +24,7 @@ static const struct i2c_device_id src4xxx_i2c_ids[] = { }; MODULE_DEVICE_TABLE(i2c, src4xxx_i2c_ids); -static const struct of_device_id src4xxx_of_match[] = { +static const struct of_device_id src4xxx_of_match[] __maybe_unused = { { .compatible = "ti,src4392", }, { } }; From da1f22825b4fec7e25431fa5238252452f3dce46 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 10 Mar 2023 22:43:33 +0100 Subject: [PATCH 355/778] ASoC: codecs: zl38060: Mark OF related data as maybe unused MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver can be compile tested with !CONFIG_OF making certain data unused: sound/soc/codecs/zl38060.c:611:34: error: ‘zl38_dt_ids’ defined but not used [-Werror=unused-const-variable=] Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230310214333.274903-10-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/zl38060.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/zl38060.c b/sound/soc/codecs/zl38060.c index c3d0a2a7c36f..28c92d90299e 100644 --- a/sound/soc/codecs/zl38060.c +++ b/sound/soc/codecs/zl38060.c @@ -608,7 +608,7 @@ static int zl38_spi_probe(struct spi_device *spi) &zl38_dai, 1); } -static const struct of_device_id zl38_dt_ids[] = { +static const struct of_device_id zl38_dt_ids[] __maybe_unused = { { .compatible = "mscc,zl38060", }, { /* sentinel */ } }; From 12e3b2848bfa8197062b7989eefb7c081d372fb8 Mon Sep 17 00:00:00 2001 From: Ajye Huang Date: Sat, 11 Mar 2023 02:42:01 +0800 Subject: [PATCH 356/778] ASoC: Intel: sof_rt5682: Enable Bluetooth offload on adl_rt1019_rt5682 Enable Bluetooth audio offload for drv_name "adl_rt1019_rt5682" with following board configuration specifically: SSP0 - rt5682 Headset SSP1 - alc1019p speaker amp SSP2 - Bluetooth audio Signed-off-by: Ajye Huang Signed-off-by: Mac Chiang Acked-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20230310184201.1302232-1-ajye_huang@compal.corp-partner.google.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_rt5682.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index 4fe448295a90..2eec32846078 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -1109,7 +1109,9 @@ static const struct platform_device_id board_ids[] = { SOF_SPEAKER_AMP_PRESENT | SOF_RT1019_SPEAKER_AMP_PRESENT | SOF_RT5682_SSP_AMP(1) | - SOF_RT5682_NUM_HDMIDEV(4)), + SOF_RT5682_NUM_HDMIDEV(4) | + SOF_BT_OFFLOAD_SSP(2) | + SOF_SSP_BT_OFFLOAD_PRESENT), }, { .name = "mtl_mx98357_rt5682", From 3c728b1bc5b99c5275ac5c7788ef814c0e51ef54 Mon Sep 17 00:00:00 2001 From: Eugene Huang Date: Tue, 14 Mar 2023 17:05:52 +0800 Subject: [PATCH 357/778] ASOC: Intel: sof_sdw: add quirk for Intel 'Rooks County' NUC M15 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Same quirks as the 'Bishop County' NUC M15, except the rt711 is in the 'JD2 100K' jack detection mode. Link: https://github.com/thesofproject/linux/issues/4088 Signed-off-by: Eugene Huang Reviewed-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20230314090553.498664-2-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index d2ed807abde9..767fa89d0870 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -213,6 +213,17 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { SOF_SDW_PCH_DMIC | RT711_JD1), }, + { + /* NUC15 'Rooks County' LAPRC510 and LAPRC710 skews */ + .callback = sof_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Intel(R) Client Systems"), + DMI_MATCH(DMI_PRODUCT_NAME, "LAPRC"), + }, + .driver_data = (void *)(SOF_SDW_TGL_HDMI | + SOF_SDW_PCH_DMIC | + RT711_JD2_100K), + }, /* TigerLake-SDCA devices */ { .callback = sof_sdw_quirk_cb, From 9c691a42b8926c8966561265cdae3ddc7464d3a2 Mon Sep 17 00:00:00 2001 From: Eugene Huang Date: Tue, 14 Mar 2023 17:05:53 +0800 Subject: [PATCH 358/778] ASoC: Intel: soc-acpi: add table for Intel 'Rooks County' NUC M15 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Same topology as the HP Omen 16-k0005TX, except with the rt1316 amp on link2. Link: https://github.com/thesofproject/linux/issues/4088 Signed-off-by: Eugene Huang Reviewed-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20230314090553.498664-3-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- .../intel/common/soc-acpi-intel-adl-match.c | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/sound/soc/intel/common/soc-acpi-intel-adl-match.c b/sound/soc/intel/common/soc-acpi-intel-adl-match.c index 28dd2046e4ac..d8c80041388a 100644 --- a/sound/soc/intel/common/soc-acpi-intel-adl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-adl-match.c @@ -354,6 +354,20 @@ static const struct snd_soc_acpi_link_adr adl_sdw_rt711_link0_rt1316_link3[] = { {} }; +static const struct snd_soc_acpi_link_adr adl_sdw_rt711_link0_rt1316_link2[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(rt711_sdca_0_adr), + .adr_d = rt711_sdca_0_adr, + }, + { + .mask = BIT(2), + .num_adr = ARRAY_SIZE(rt1316_2_single_adr), + .adr_d = rt1316_2_single_adr, + }, + {} +}; + static const struct snd_soc_acpi_adr_device mx8373_2_adr[] = { { .adr = 0x000223019F837300ull, @@ -624,6 +638,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_sdw_machines[] = { .drv_name = "sof_sdw", .sof_tplg_filename = "sof-adl-rt711-l0-rt1316-l3.tplg", }, + { + .link_mask = 0x5, /* 2 active links required */ + .links = adl_sdw_rt711_link0_rt1316_link2, + .drv_name = "sof_sdw", + .sof_tplg_filename = "sof-adl-rt711-l0-rt1316-l2.tplg", + }, { .link_mask = 0x1, /* link0 required */ .links = adl_rvp, From 083a25b18d6ad9f1f540e629909aa3eaaaf01823 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Thu, 9 Mar 2023 15:13:37 +0800 Subject: [PATCH 359/778] ASoC: soc-pcm: fix hw->formats cleared by soc_pcm_hw_init() for dpcm The hw->formats may be set by snd_dmaengine_pcm_refine_runtime_hwparams() in component's startup()/open(), but soc_pcm_hw_init() will init hw->formats in dpcm_runtime_setup_fe() after component's startup()/open(), which causes the valuable hw->formats to be cleared. So need to store the hw->formats before initialization, then restore it after initialization. Signed-off-by: Shengjiu Wang Link: https://lore.kernel.org/r/1678346017-3660-1-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 5eb056b942ce..7958c9defd49 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1661,10 +1661,14 @@ static void dpcm_runtime_setup_fe(struct snd_pcm_substream *substream) struct snd_pcm_hardware *hw = &runtime->hw; struct snd_soc_dai *dai; int stream = substream->stream; + u64 formats = hw->formats; int i; soc_pcm_hw_init(hw); + if (formats) + hw->formats &= formats; + for_each_rtd_cpu_dais(fe, i, dai) { struct snd_soc_pcm_stream *cpu_stream; From f147ca85d6ecaf65106d1650f3c2e8afacbc833f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=ADcolas=20F=2E=20R=2E=20A=2E=20Prado=20via=20Alsa-dev?= =?UTF-8?q?el?= Date: Mon, 13 Mar 2023 17:29:06 -0400 Subject: [PATCH 360/778] ASoC: mt8192: Remove function name log messages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are some log messages in the mt8192 sound code that print the function name, presumably to aid in tracing. However this can also be achieved by ftrace and without spamming the console, so remove these messages. Signed-off-by: Nícolas F. R. A. Prado Link: https://lore.kernel.org/r/167874298172.26.17917791030607314817@mailman-core.alsa-project.org Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8192/mt8192-afe-clk.c | 4 ---- sound/soc/mediatek/mt8192/mt8192-afe-pcm.c | 4 ---- sound/soc/mediatek/mt8192/mt8192-dai-tdm.c | 2 -- sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c | 2 -- 4 files changed, 12 deletions(-) diff --git a/sound/soc/mediatek/mt8192/mt8192-afe-clk.c b/sound/soc/mediatek/mt8192/mt8192-afe-clk.c index bba5f3056e8f..416aff726253 100644 --- a/sound/soc/mediatek/mt8192/mt8192-afe-clk.c +++ b/sound/soc/mediatek/mt8192/mt8192-afe-clk.c @@ -206,8 +206,6 @@ int mt8192_afe_enable_clock(struct mtk_base_afe *afe) struct mt8192_afe_private *afe_priv = afe->platform_priv; int ret; - dev_info(afe->dev, "%s()\n", __func__); - ret = clk_prepare_enable(afe_priv->clk[CLK_INFRA_SYS_AUDIO]); if (ret) { dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n", @@ -276,8 +274,6 @@ void mt8192_afe_disable_clock(struct mtk_base_afe *afe) { struct mt8192_afe_private *afe_priv = afe->platform_priv; - dev_info(afe->dev, "%s()\n", __func__); - clk_disable_unprepare(afe_priv->clk[CLK_AFE]); mt8192_set_audio_int_bus_parent(afe, CLK_CLK26M); clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIOINTBUS]); diff --git a/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c b/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c index e1e4ca931551..a420b78dde89 100644 --- a/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c +++ b/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c @@ -2055,8 +2055,6 @@ static int mt8192_afe_runtime_suspend(struct device *dev) unsigned int value; int ret; - dev_info(afe->dev, "%s()\n", __func__); - if (!afe->regmap || afe_priv->pm_runtime_bypass_reg_ctl) goto skip_regmap; @@ -2097,8 +2095,6 @@ static int mt8192_afe_runtime_resume(struct device *dev) struct mt8192_afe_private *afe_priv = afe->platform_priv; int ret; - dev_info(afe->dev, "%s()\n", __func__); - ret = mt8192_afe_enable_clock(afe); if (ret) return ret; diff --git a/sound/soc/mediatek/mt8192/mt8192-dai-tdm.c b/sound/soc/mediatek/mt8192/mt8192-dai-tdm.c index f3bebed2428a..bcd2150c2816 100644 --- a/sound/soc/mediatek/mt8192/mt8192-dai-tdm.c +++ b/sound/soc/mediatek/mt8192/mt8192-dai-tdm.c @@ -754,8 +754,6 @@ int mt8192_dai_tdm_register(struct mtk_base_afe *afe) struct mtk_afe_tdm_priv *tdm_priv; struct mtk_base_afe_dai *dai; - dev_info(afe->dev, "%s()\n", __func__); - dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL); if (!dai) return -ENOMEM; diff --git a/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c b/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c index 16660eda577e..87737d054682 100644 --- a/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c +++ b/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c @@ -161,8 +161,6 @@ static int mt8192_mt6359_mtkaif_calibration(struct snd_soc_pcm_runtime *rtd) int counter; int mtkaif_calib_ok; - dev_info(afe->dev, "%s(), start\n", __func__); - pm_runtime_get_sync(afe->dev); mt8192_afe_gpio_request(afe->dev, true, MT8192_DAI_ADDA, 1); mt8192_afe_gpio_request(afe->dev, true, MT8192_DAI_ADDA, 0); From 5f2a53c0687b151c2ecad19995108b40df76ba86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=ADcolas=20F=2E=20R=2E=20A=2E=20Prado?= Date: Mon, 13 Mar 2023 17:29:07 -0400 Subject: [PATCH 361/778] ASoC: mt8192: Move spammy messages to debug level MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are many log messages throughout the mt8192 sound drivers that print to the info level and are triggered very frequently. Move these messages to the debug level to avoid spamming the console. Signed-off-by: Nícolas F. R. A. Prado Reviewed-by: AngeloGioacchino Del Regno Link: https://lore.kernel.org/r/20230313212908.2282961-3-nfraprado@collabora.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8192/mt8192-afe-pcm.c | 2 +- sound/soc/mediatek/mt8192/mt8192-dai-tdm.c | 26 +++++++++---------- .../mt8192/mt8192-mt6359-rt1015-rt5682.c | 10 +++---- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c b/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c index a420b78dde89..333e0ee98c5a 100644 --- a/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c +++ b/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c @@ -369,7 +369,7 @@ static int ul_tinyconn_event(struct snd_soc_dapm_widget *w, unsigned int reg_shift; unsigned int reg_mask_shift; - dev_info(afe->dev, "%s(), event 0x%x\n", __func__, event); + dev_dbg(afe->dev, "%s(), event 0x%x\n", __func__, event); if (strstr(w->name, "UL1")) { reg_shift = VUL1_USE_TINY_SFT; diff --git a/sound/soc/mediatek/mt8192/mt8192-dai-tdm.c b/sound/soc/mediatek/mt8192/mt8192-dai-tdm.c index bcd2150c2816..9ce06821c7d0 100644 --- a/sound/soc/mediatek/mt8192/mt8192-dai-tdm.c +++ b/sound/soc/mediatek/mt8192/mt8192-dai-tdm.c @@ -256,8 +256,8 @@ static int mtk_tdm_en_event(struct snd_soc_dapm_widget *w, return -EINVAL; } - dev_info(cmpnt->dev, "%s(), name %s, event 0x%x\n", - __func__, w->name, event); + dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x\n", + __func__, w->name, event); switch (event) { case SND_SOC_DAPM_PRE_PMU: @@ -288,8 +288,8 @@ static int mtk_tdm_bck_en_event(struct snd_soc_dapm_widget *w, return -EINVAL; } - dev_info(cmpnt->dev, "%s(), name %s, event 0x%x, dai_id %d\n", - __func__, w->name, event, dai_id); + dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x, dai_id %d\n", + __func__, w->name, event, dai_id); switch (event) { case SND_SOC_DAPM_PRE_PMU: @@ -320,8 +320,8 @@ static int mtk_tdm_mck_en_event(struct snd_soc_dapm_widget *w, return -EINVAL; } - dev_info(cmpnt->dev, "%s(), name %s, event 0x%x, dai_id %d\n", - __func__, w->name, event, dai_id); + dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x, dai_id %d\n", + __func__, w->name, event, dai_id); switch (event) { case SND_SOC_DAPM_PRE_PMU: @@ -545,13 +545,13 @@ static int mtk_dai_tdm_hw_params(struct snd_pcm_substream *substream, if (tdm_priv->mclk_rate % tdm_priv->bck_rate != 0) dev_warn(afe->dev, "%s(), bck cannot generate", __func__); - dev_info(afe->dev, "%s(), id %d, rate %d, channels %d, format %d, mclk_rate %d, bck_rate %d\n", - __func__, - tdm_id, rate, channels, format, - tdm_priv->mclk_rate, tdm_priv->bck_rate); + dev_dbg(afe->dev, "%s(), id %d, rate %d, channels %d, format %d, mclk_rate %d, bck_rate %d\n", + __func__, + tdm_id, rate, channels, format, + tdm_priv->mclk_rate, tdm_priv->bck_rate); - dev_info(afe->dev, "%s(), out_channels_per_sdata = %d\n", - __func__, out_channels_per_sdata); + dev_dbg(afe->dev, "%s(), out_channels_per_sdata = %d\n", + __func__, out_channels_per_sdata); /* set tdm */ if (tdm_priv->bck_invert) @@ -644,7 +644,7 @@ static int mtk_dai_tdm_set_sysclk(struct snd_soc_dai *dai, return -EINVAL; } - dev_info(afe->dev, "%s(), freq %d\n", __func__, freq); + dev_dbg(afe->dev, "%s(), freq %d\n", __func__, freq); return mtk_dai_tdm_cal_mclk(afe, tdm_priv, freq); } diff --git a/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c b/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c index 87737d054682..5e163e23a207 100644 --- a/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c +++ b/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c @@ -292,11 +292,11 @@ static int mt8192_mt6359_mtkaif_calibration(struct snd_soc_pcm_runtime *rtd) mt8192_afe_gpio_request(afe->dev, false, MT8192_DAI_ADDA_CH34, 0); pm_runtime_put(afe->dev); - dev_info(afe->dev, "%s(), mtkaif_chosen_phase[0/1/2]:%d/%d/%d\n", - __func__, - afe_priv->mtkaif_chosen_phase[0], - afe_priv->mtkaif_chosen_phase[1], - afe_priv->mtkaif_chosen_phase[2]); + dev_dbg(afe->dev, "%s(), mtkaif_chosen_phase[0/1/2]:%d/%d/%d\n", + __func__, + afe_priv->mtkaif_chosen_phase[0], + afe_priv->mtkaif_chosen_phase[1], + afe_priv->mtkaif_chosen_phase[2]); return 0; } From 5c5a7521e9364a40fe2c1b67ab79991e3e9085df Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 6 Mar 2023 01:43:30 +0000 Subject: [PATCH 362/778] ASoC: soc-dai.c: add missing flag check at snd_soc_pcm_dai_probe() dai->probed is used at snd_soc_pcm_dai_probe/remove(), and used to call real remove() function only when it was probed. int snd_soc_pcm_dai_probe(...) { ... for_each_rtd_dais(rtd, i, dai) { ... if (dai->driver->probe) { (A) int ret = dai->driver->probe(dai); if (ret < 0) return soc_dai_ret(dai, ret); } => dai->probed = 1; } ... } int snd_soc_pcm_dai_remove(...) { ... for_each_rtd_dais(rtd, i, dai) { ... => if (dai->probed && ...) { ... } => dai->probed = 0; } ... } But on probe() case, we need to check dai->probed before calling real probe() function at (A), otherwise real probe() might be called multi times (but real remove() will be called only once). This patch checks it at probe(). Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87wn3u64e6.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-dai.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 0119afbd01fc..02dd64dea179 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -542,6 +542,9 @@ int snd_soc_pcm_dai_probe(struct snd_soc_pcm_runtime *rtd, int order) if (dai->driver->probe_order != order) continue; + if (dai->probed) + continue; + if (dai->driver->probe) { int ret = dai->driver->probe(dai); From 0d3a5178c2994eaf91ad135816a79138055b394a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 6 Mar 2023 01:43:54 +0000 Subject: [PATCH 363/778] ASoC: soc-pcm.c: remove indirect runtime copy substream->runtime will be attached when substream was opened at snd_pcm_attach_substream(). When it uses DPCM, FE substream->runtime is attached, but BE substream->runtime is not. Thus, we are copying FE substream->runtime to BE. But, we are copyig FE substream->runtime to FE dpcm->runtime first (A), and copy it to BE dpcm->runtime (B), and copy it to BE substream->runtime (C). static int dpcm_fe_dai_open(...) { ... (A) fe->dpcm[stream].runtime = fe_substream->runtime; ... } static int dpcm_be_connect(...) { ... (B) be->dpcm[stream].runtime = fe->dpcm[stream].runtime; ... } int dpcm_be_dai_startup(...) { ... (C) be_substream->runtime = be->dpcm[stream].runtime; ... } It is too roundabout and troublesome. OTOH, it is directly copying fe_substream->runtime at dpcm_be_reparent() without using be->dpcm[stream].runtime. static void dpcm_be_reparent(...) { ... for_each_dpcm_fe(be, stream, dpcm) { ... => be_substream->runtime = fe_substream->runtime; break; } } This patch removes indirect copying. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87v8je64dh.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dpcm.h | 1 - sound/soc/soc-compress.c | 7 ------- sound/soc/soc-pcm.c | 10 ++++------ 3 files changed, 4 insertions(+), 14 deletions(-) diff --git a/include/sound/soc-dpcm.h b/include/sound/soc-dpcm.h index 1e7d09556fe3..4d6ac7699833 100644 --- a/include/sound/soc-dpcm.h +++ b/include/sound/soc-dpcm.h @@ -91,7 +91,6 @@ struct snd_soc_dpcm_runtime { struct list_head fe_clients; int users; - struct snd_pcm_runtime *runtime; struct snd_pcm_hw_params hw_params; /* state and update */ diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index e7aa6f360cab..554c329ec87f 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -134,8 +134,6 @@ err_no_lock: static int soc_compr_open_fe(struct snd_compr_stream *cstream) { struct snd_soc_pcm_runtime *fe = cstream->private_data; - struct snd_pcm_substream *fe_substream = - fe->pcm->streams[cstream->direction].substream; struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0); struct snd_soc_dpcm *dpcm; struct snd_soc_dapm_widget_list *list; @@ -143,7 +141,6 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream) int ret; mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); - fe->dpcm[stream].runtime = fe_substream->runtime; ret = dpcm_path_get(fe, stream, &list); if (ret < 0) @@ -153,7 +150,6 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream) /* calculate valid and active FE <-> BE dpcms */ dpcm_process_paths(fe, stream, &list, 1); - fe->dpcm[stream].runtime = fe_substream->runtime; fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; @@ -164,7 +160,6 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream) dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE; dpcm_be_disconnect(fe, stream); - fe->dpcm[stream].runtime = NULL; goto out; } @@ -236,8 +231,6 @@ static int soc_compr_free_fe(struct snd_compr_stream *cstream) mutex_unlock(&fe->card->pcm_mutex); - fe->dpcm[stream].runtime = NULL; - snd_soc_link_compr_shutdown(cstream, 0); snd_soc_compr_components_free(cstream, 0); diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 5eb056b942ce..b7f8a5bcfbc6 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1230,7 +1230,6 @@ static int dpcm_be_connect(struct snd_soc_pcm_runtime *fe, dpcm->be = be; dpcm->fe = fe; - be->dpcm[stream].runtime = fe->dpcm[stream].runtime; dpcm->state = SND_SOC_DPCM_LINK_STATE_NEW; snd_soc_dpcm_stream_lock_irq(fe, stream); list_add(&dpcm->list_be, &fe->dpcm[stream].be_clients); @@ -1465,10 +1464,11 @@ static int dpcm_add_paths(struct snd_soc_pcm_runtime *fe, int stream, struct snd_soc_dapm_widget_list *list = *list_; struct snd_soc_pcm_runtime *be; struct snd_soc_dapm_widget *widget; + struct snd_pcm_substream *fe_substream = snd_soc_dpcm_get_substream(fe, stream); int i, new = 0, err; /* don't connect if FE is not running */ - if (!fe->dpcm[stream].runtime && !fe->fe_compr) + if (!fe_substream->runtime && !fe->fe_compr) return new; /* Create any new FE <--> BE connections */ @@ -1590,6 +1590,7 @@ void dpcm_be_dai_stop(struct snd_soc_pcm_runtime *fe, int stream, int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream) { + struct snd_pcm_substream *fe_substream = snd_soc_dpcm_get_substream(fe, stream); struct snd_soc_pcm_runtime *be; struct snd_soc_dpcm *dpcm; int err, count = 0; @@ -1629,7 +1630,7 @@ int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream) dev_dbg(be->dev, "ASoC: open %s BE %s\n", stream ? "capture" : "playback", be->dai_link->name); - be_substream->runtime = be->dpcm[stream].runtime; + be_substream->runtime = fe_substream->runtime; err = __soc_pcm_open(be, be_substream); if (err < 0) { be->dpcm[stream].users--; @@ -2693,8 +2694,6 @@ static void dpcm_fe_dai_cleanup(struct snd_pcm_substream *fe_substream) dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE; dpcm_be_disconnect(fe, stream); - - fe->dpcm[stream].runtime = NULL; } static int dpcm_fe_dai_close(struct snd_pcm_substream *fe_substream) @@ -2719,7 +2718,6 @@ static int dpcm_fe_dai_open(struct snd_pcm_substream *fe_substream) int stream = fe_substream->stream; snd_soc_dpcm_mutex_lock(fe); - fe->dpcm[stream].runtime = fe_substream->runtime; ret = dpcm_path_get(fe, stream, &list); if (ret < 0) From 6ffa0da5c63f8408101d01075709981005eb66ec Mon Sep 17 00:00:00 2001 From: Herve Codina Date: Tue, 14 Mar 2023 09:21:57 +0100 Subject: [PATCH 364/778] soc: fsl: cpm1: qmc: Fix test dependency The QMC depends on (SOC_FSL && COMPILE_TEST). SOC_FSL does not exist. Fix the dependency using the correct one: FSL_SOC. Signed-off-by: Herve Codina Link: https://lore.kernel.org/r/20230314082157.137176-1-herve.codina@bootlin.com Signed-off-by: Mark Brown --- drivers/soc/fsl/qe/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/fsl/qe/Kconfig b/drivers/soc/fsl/qe/Kconfig index f90cfdf0c763..7268c2fbcbc1 100644 --- a/drivers/soc/fsl/qe/Kconfig +++ b/drivers/soc/fsl/qe/Kconfig @@ -47,7 +47,7 @@ config CPM_TSA config CPM_QMC tristate "CPM QMC support" depends on OF && HAS_IOMEM - depends on CPM1 || (SOC_FSL && COMPILE_TEST) + depends on CPM1 || (FSL_SOC && COMPILE_TEST) depends on CPM_TSA help Freescale CPM QUICC Multichannel Controller From ff750f8e9464e368fc92941553c9c385644ebfc1 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 14 Mar 2023 11:48:59 +0100 Subject: [PATCH 365/778] ASoC: dt-bindings: renesas: rsnd: Update example Miscellaneous updates to make the example match reality: - Correct SSI resource region size, - Complete half-conversion to new-style CPG/MSSR bindings, - Add missing power-domains, resets, and reset-names properties, - Use interrupt binding definitions instead of hardcoded numbers, - Correct interrupt flags, - Drop double blank line. Signed-off-by: Geert Uytterhoeven Acked-by: Krzysztof Kozlowski Acked-by: Kuninori Morimoto Link: https://lore.kernel.org/r/ba4ec999dc152ea1f113253e497c093b8789d414.1678790879.git.geert+renesas@glider.be Signed-off-by: Mark Brown --- .../bindings/sound/renesas,rsnd.yaml | 51 ++++++++++++------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/renesas,rsnd.yaml b/Documentation/devicetree/bindings/sound/renesas,rsnd.yaml index 55e5213b90a1..676dfe7a7f17 100644 --- a/Documentation/devicetree/bindings/sound/renesas,rsnd.yaml +++ b/Documentation/devicetree/bindings/sound/renesas,rsnd.yaml @@ -372,30 +372,33 @@ unevaluatedProperties: false examples: - | + #include + #include + #include rcar_sound: sound@ec500000 { #sound-dai-cells = <1>; compatible = "renesas,rcar_sound-r8a7790", "renesas,rcar_sound-gen2"; reg = <0xec500000 0x1000>, /* SCU */ <0xec5a0000 0x100>, /* ADG */ <0xec540000 0x1000>, /* SSIU */ - <0xec541000 0x1280>, /* SSI */ + <0xec541000 0x280>, /* SSI */ <0xec740000 0x200>; /* Audio DMAC peri peri*/ reg-names = "scu", "adg", "ssiu", "ssi", "audmapp"; - clocks = <&mstp10_clks 1005>, /* SSI-ALL */ - <&mstp10_clks 1006>, <&mstp10_clks 1007>, /* SSI9, SSI8 */ - <&mstp10_clks 1008>, <&mstp10_clks 1009>, /* SSI7, SSI6 */ - <&mstp10_clks 1010>, <&mstp10_clks 1011>, /* SSI5, SSI4 */ - <&mstp10_clks 1012>, <&mstp10_clks 1013>, /* SSI3, SSI2 */ - <&mstp10_clks 1014>, <&mstp10_clks 1015>, /* SSI1, SSI0 */ - <&mstp10_clks 1022>, <&mstp10_clks 1023>, /* SRC9, SRC8 */ - <&mstp10_clks 1024>, <&mstp10_clks 1025>, /* SRC7, SRC6 */ - <&mstp10_clks 1026>, <&mstp10_clks 1027>, /* SRC5, SRC4 */ - <&mstp10_clks 1028>, <&mstp10_clks 1029>, /* SRC3, SRC2 */ - <&mstp10_clks 1030>, <&mstp10_clks 1031>, /* SRC1, SRC0 */ - <&mstp10_clks 1020>, <&mstp10_clks 1021>, /* MIX1, MIX0 */ - <&mstp10_clks 1020>, <&mstp10_clks 1021>, /* CTU1, CTU0 */ - <&mstp10_clks 1019>, <&mstp10_clks 1018>, /* DVC0, DVC1 */ + clocks = <&cpg CPG_MOD 1005>, /* SSI-ALL */ + <&cpg CPG_MOD 1006>, <&cpg CPG_MOD 1007>, /* SSI9, SSI8 */ + <&cpg CPG_MOD 1008>, <&cpg CPG_MOD 1009>, /* SSI7, SSI6 */ + <&cpg CPG_MOD 1010>, <&cpg CPG_MOD 1011>, /* SSI5, SSI4 */ + <&cpg CPG_MOD 1012>, <&cpg CPG_MOD 1013>, /* SSI3, SSI2 */ + <&cpg CPG_MOD 1014>, <&cpg CPG_MOD 1015>, /* SSI1, SSI0 */ + <&cpg CPG_MOD 1022>, <&cpg CPG_MOD 1023>, /* SRC9, SRC8 */ + <&cpg CPG_MOD 1024>, <&cpg CPG_MOD 1025>, /* SRC7, SRC6 */ + <&cpg CPG_MOD 1026>, <&cpg CPG_MOD 1027>, /* SRC5, SRC4 */ + <&cpg CPG_MOD 1028>, <&cpg CPG_MOD 1029>, /* SRC3, SRC2 */ + <&cpg CPG_MOD 1030>, <&cpg CPG_MOD 1031>, /* SRC1, SRC0 */ + <&cpg CPG_MOD 1020>, <&cpg CPG_MOD 1021>, /* MIX1, MIX0 */ + <&cpg CPG_MOD 1020>, <&cpg CPG_MOD 1021>, /* CTU1, CTU0 */ + <&cpg CPG_MOD 1019>, <&cpg CPG_MOD 1018>, /* DVC0, DVC1 */ <&audio_clk_a>, <&audio_clk_b>, /* CLKA, CLKB */ <&audio_clk_c>, <&audio_clk_i>; /* CLKC, CLKI */ @@ -416,6 +419,17 @@ examples: "clk_a", "clk_b", "clk_c", "clk_i"; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; + + resets = <&cpg 1005>, + <&cpg 1006>, <&cpg 1007>, <&cpg 1008>, <&cpg 1009>, + <&cpg 1010>, <&cpg 1011>, <&cpg 1012>, <&cpg 1013>, + <&cpg 1014>, <&cpg 1015>; + reset-names = "ssi-all", + "ssi.9", "ssi.8", "ssi.7", "ssi.6", + "ssi.5", "ssi.4", "ssi.3", "ssi.2", + "ssi.1", "ssi.0"; + rcar_sound,dvc { dvc0: dvc-0 { dmas = <&audma0 0xbc>; @@ -448,7 +462,7 @@ examples: status = "disabled"; }; src1: src-1 { - interrupts = <0 353 0>; + interrupts = ; dmas = <&audma0 0x87>, <&audma1 0x9c>; dma-names = "rx", "tx"; }; @@ -469,12 +483,12 @@ examples: rcar_sound,ssi { ssi0: ssi-0 { - interrupts = <0 370 1>; + interrupts = ; dmas = <&audma0 0x01>, <&audma1 0x02>; dma-names = "rx", "tx"; }; ssi1: ssi-1 { - interrupts = <0 371 1>; + interrupts = ; dmas = <&audma0 0x03>, <&audma1 0x04>; dma-names = "rx", "tx"; }; @@ -516,7 +530,6 @@ examples: }; }; - /* assume audio-graph */ codec { port { From 87771c94025890246a6dfec9773eb62bd41c4c5a Mon Sep 17 00:00:00 2001 From: Vijaya Anand Date: Thu, 16 Mar 2023 04:40:55 +0530 Subject: [PATCH 366/778] ASoC: dt-bindings: adi,adau17x1: Convert to DT schema Convert the binding document for adi,adau17x1 from txt to yaml so one could validate dt-entries correctly and any future additions can go into yaml format. Add address and size cells to example to prevent errors regarding reg format. Signed-off-by: Vijaya Anand Cc: Daniel Baluta Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230315231055.3067-1-sunrockers8@gmail.com Signed-off-by: Mark Brown --- .../bindings/sound/adi,adau17x1.txt | 32 ------------ .../bindings/sound/adi,adau17x1.yaml | 52 +++++++++++++++++++ 2 files changed, 52 insertions(+), 32 deletions(-) delete mode 100644 Documentation/devicetree/bindings/sound/adi,adau17x1.txt create mode 100644 Documentation/devicetree/bindings/sound/adi,adau17x1.yaml diff --git a/Documentation/devicetree/bindings/sound/adi,adau17x1.txt b/Documentation/devicetree/bindings/sound/adi,adau17x1.txt deleted file mode 100644 index 1447dec28125..000000000000 --- a/Documentation/devicetree/bindings/sound/adi,adau17x1.txt +++ /dev/null @@ -1,32 +0,0 @@ -Analog Devices ADAU1361/ADAU1461/ADAU1761/ADAU1961/ADAU1381/ADAU1781 - -Required properties: - - - compatible: Should contain one of the following: - "adi,adau1361" - "adi,adau1461" - "adi,adau1761" - "adi,adau1961" - "adi,adau1381" - "adi,adau1781" - - - reg: The i2c address. Value depends on the state of ADDR0 - and ADDR1, as wired in hardware. - -Optional properties: - - clock-names: If provided must be "mclk". - - clocks: phandle + clock-specifiers for the clock that provides - the audio master clock for the device. - -Examples: -#include - - i2c_bus { - adau1361@38 { - compatible = "adi,adau1761"; - reg = <0x38>; - - clock-names = "mclk"; - clocks = <&audio_clock>; - }; - }; diff --git a/Documentation/devicetree/bindings/sound/adi,adau17x1.yaml b/Documentation/devicetree/bindings/sound/adi,adau17x1.yaml new file mode 100644 index 000000000000..45955f38b6fd --- /dev/null +++ b/Documentation/devicetree/bindings/sound/adi,adau17x1.yaml @@ -0,0 +1,52 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/adi,adau17x1.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: + Analog Devices ADAU1361/ADAU1461/ADAU1761/ADAU1961/ADAU1381/ADAU1781 Codec + +maintainers: + - Lars-Peter Clausen + +properties: + compatible: + enum: + - adi,adau1361 + - adi,adau1381 + - adi,adau1461 + - adi,adau1761 + - adi,adau1781 + - adi,adau1961 + + reg: + maxItems: 1 + description: + The i2c address. Value depends on the state of ADDR0 and ADDR1, + as wired in hardware. + + clock-names: + const: mclk + + clocks: + items: + - description: provides the audio master clock for the device. + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + audio-codec@38 { + compatible = "adi,adau1761"; + reg = <0x38>; + clock-names = "mclk"; + clocks = <&audio_clock>; + }; From 1d8777d21fbb36c4a0e103eb128ca86f9761e61c Mon Sep 17 00:00:00 2001 From: Otabek Nazrullaev Date: Thu, 16 Mar 2023 02:33:30 +0900 Subject: [PATCH 367/778] ASoC: dt-bindings: maxim,max9759: Convert to DT schema. Convert Maxim MAX9759 Speaker Amplifier bindings to DT schema. Add missing gpio header file into examples section Signed-off-by: Otabek Nazrullaev Cc: Daniel Baluta Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230315173404.7215-1-otabeknazrullaev1998@gmail.com Signed-off-by: Mark Brown --- .../bindings/sound/maxim,max9759.txt | 18 -------- .../bindings/sound/maxim,max9759.yaml | 45 +++++++++++++++++++ 2 files changed, 45 insertions(+), 18 deletions(-) delete mode 100644 Documentation/devicetree/bindings/sound/maxim,max9759.txt create mode 100644 Documentation/devicetree/bindings/sound/maxim,max9759.yaml diff --git a/Documentation/devicetree/bindings/sound/maxim,max9759.txt b/Documentation/devicetree/bindings/sound/maxim,max9759.txt deleted file mode 100644 index 737a996374d3..000000000000 --- a/Documentation/devicetree/bindings/sound/maxim,max9759.txt +++ /dev/null @@ -1,18 +0,0 @@ -Maxim MAX9759 Speaker Amplifier -=============================== - -Required properties: -- compatible : "maxim,max9759" -- shutdown-gpios : the gpio connected to the shutdown pin -- mute-gpios : the gpio connected to the mute pin -- gain-gpios : the 2 gpios connected to the g1 and g2 pins - -Example: - -max9759: analog-amplifier { - compatible = "maxim,max9759"; - shutdown-gpios = <&gpio3 20 GPIO_ACTIVE_LOW>; - mute-gpios = <&gpio3 19 GPIO_ACTIVE_LOW>; - gain-gpios = <&gpio3 23 GPIO_ACTIVE_LOW>, - <&gpio3 25 GPIO_ACTIVE_LOW>; -}; diff --git a/Documentation/devicetree/bindings/sound/maxim,max9759.yaml b/Documentation/devicetree/bindings/sound/maxim,max9759.yaml new file mode 100644 index 000000000000..a76ee6a635af --- /dev/null +++ b/Documentation/devicetree/bindings/sound/maxim,max9759.yaml @@ -0,0 +1,45 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/maxim,max9759.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Maxim MAX9759 Speaker Amplifier + +maintainers: + - Otabek Nazrullaev + +properties: + compatible: + const: maxim,max9759 + + shutdown-gpios: + maxItems: 1 + description: the gpio connected to the shutdown pin + + mute-gpios: + maxItems: 1 + description: the gpio connected to the mute pin + + gain-gpios: + maxItems: 2 + description: the 2 gpios connected to the g1 and g2 pins + +required: + - compatible + - shutdown-gpios + - mute-gpios + - gain-gpios + +additionalProperties: false + +examples: + - | + #include + amplifier { + compatible = "maxim,max9759"; + shutdown-gpios = <&gpio3 20 GPIO_ACTIVE_LOW>; + mute-gpios = <&gpio3 19 GPIO_ACTIVE_LOW>; + gain-gpios = <&gpio3 23 GPIO_ACTIVE_LOW>, + <&gpio3 25 GPIO_ACTIVE_LOW>; + }; From 205efd4619b860404ebb5882e5a119eb3b3b3716 Mon Sep 17 00:00:00 2001 From: Ge-org Brohammer Date: Fri, 17 Mar 2023 00:38:51 +0200 Subject: [PATCH 368/778] ASoC: amd: yc: Add DMI entries to support Victus by HP Laptop 16-e1xxx (8A22) This model requires an additional detection quirk to enable the internal microphone. Tried to use git send-email this time. Signed-off-by: Ge-org Brohammer Link: https://lore.kernel.org/r/PAVP195MB2261322C220E95D7F4B2732ADABC9@PAVP195MB2261.EURP195.PROD.OUTLOOK.COM Signed-off-by: Mark Brown --- sound/soc/amd/yc/acp6x-mach.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sound/soc/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c index 4a69ce702360..0acdf0156f07 100644 --- a/sound/soc/amd/yc/acp6x-mach.c +++ b/sound/soc/amd/yc/acp6x-mach.c @@ -269,6 +269,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = { DMI_MATCH(DMI_BOARD_NAME, "8A43"), } }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "HP"), + DMI_MATCH(DMI_BOARD_NAME, "8A22"), + } + }, {} }; From 279e52d6b9f366f9930a0f90ee84e7d0a6a27b26 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Thu, 16 Mar 2023 16:14:57 +0200 Subject: [PATCH 369/778] ASoC: SOF: ipc4-pcm: support multiple configs for BE DAIs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Backend DAIs may support multiple audio formats. Modify pipeline setup to select a suitable configuration based on topology and frontend DAI runtime configuration. For sampling rate, if one of the BE DAI configurations has a sampling rate matching that of FE DAI, configure BE DAI to this rate. For sample format, the current code hardcodes DAI copier sample format to 32bit for both playback and capture pipelines. This is not always desired, so lift the limitation and set the sample format based on topology definitions for the copiers. For capture pipelines, we want to set the BE DAI pipeline format based on topology instead of using the FE DAI format. This covers the common use-case where BE DAI outputs data at a higher sample precision and sample width is reduced later in the pipeline. Instead of hardcoding to 32bit, use the BE DAI copier output format defined in topology. Signed-off-by: Kai Vehmanen Reviewed-by: Péter Ujfalusi Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230316141458.13940-2-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-pcm.c | 66 +++++++++++++++++++++++++++---- sound/soc/sof/ipc4-topology.c | 74 +++++++++++++++++++++++++++++++---- 2 files changed, 125 insertions(+), 15 deletions(-) diff --git a/sound/soc/sof/ipc4-pcm.c b/sound/soc/sof/ipc4-pcm.c index 701da5ee4e4e..4598057b7f28 100644 --- a/sound/soc/sof/ipc4-pcm.c +++ b/sound/soc/sof/ipc4-pcm.c @@ -362,15 +362,68 @@ static void ipc4_ssp_dai_config_pcm_params_match(struct snd_sof_dev *sdev, const } } +/* + * Fixup DAI link parameters for sampling rate based on + * DAI copier configuration. + */ +static int sof_ipc4_pcm_dai_link_fixup_rate(struct snd_sof_dev *sdev, + struct snd_pcm_hw_params *params, + struct sof_ipc4_copier *ipc4_copier) +{ + struct sof_ipc4_pin_format *pin_fmts = ipc4_copier->available_fmt.input_pin_fmts; + struct snd_interval *rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); + int num_input_formats = ipc4_copier->available_fmt.num_input_formats; + unsigned int fe_rate = params_rate(params); + bool fe_be_rate_match = false; + bool single_be_rate = true; + unsigned int be_rate; + int i; + + /* + * Copier does not change sampling rate, so we + * need to only consider the input pin information. + */ + for (i = 0; i < num_input_formats; i++) { + unsigned int val = pin_fmts[i].audio_fmt.sampling_frequency; + + if (i == 0) + be_rate = val; + else if (val != be_rate) + single_be_rate = false; + + if (val == fe_rate) { + fe_be_rate_match = true; + break; + } + } + + /* + * If rate is different than FE rate, topology must + * contain an SRC. But we do require topology to + * define a single rate in the DAI copier config in + * this case (FE rate may be variable). + */ + if (!fe_be_rate_match) { + if (!single_be_rate) { + dev_err(sdev->dev, "Unable to select sampling rate for DAI link\n"); + return -EINVAL; + } + + rate->min = be_rate; + rate->max = rate->min; + } + + return 0; +} + static int sof_ipc4_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) { struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME); struct snd_sof_dai *dai = snd_sof_find_dai(component, rtd->dai_link->name); - struct snd_interval *rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); - struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); struct sof_ipc4_copier *ipc4_copier; + int ret; if (!dai) { dev_err(component->dev, "%s: No DAI found with name %s\n", __func__, @@ -385,12 +438,9 @@ static int sof_ipc4_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, return -EINVAL; } - /* always set BE format to 32-bits for both playback and capture */ - snd_mask_none(fmt); - snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S32_LE); - - rate->min = ipc4_copier->available_fmt.input_pin_fmts->audio_fmt.sampling_frequency; - rate->max = rate->min; + ret = sof_ipc4_pcm_dai_link_fixup_rate(sdev, params, ipc4_copier); + if (ret) + return ret; switch (ipc4_copier->dai_type) { case SOF_DAI_INTEL_SSP: diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index e7b3bdc95dd7..cf438f32b4ed 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -1069,6 +1069,69 @@ static int snd_sof_get_nhlt_endpoint_data(struct snd_sof_dev *sdev, struct snd_s } #endif +static int ipc4_set_fmt_mask(struct snd_mask *fmt, unsigned int bit_depth) +{ + switch (bit_depth) { + case 16: + snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE); + break; + case 24: + snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE); + break; + case 32: + snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S32_LE); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int ipc4_copier_set_capture_fmt(struct snd_sof_dev *sdev, + struct snd_pcm_hw_params *pipeline_params, + struct snd_pcm_hw_params *fe_params, + struct sof_ipc4_available_audio_format *available_fmt) +{ + struct sof_ipc4_audio_format *audio_fmt; + unsigned int sample_valid_bits; + bool multiple_formats = false; + bool fe_format_match = false; + struct snd_mask *fmt; + int i; + + for (i = 0; i < available_fmt->num_output_formats; i++) { + unsigned int val; + + audio_fmt = &available_fmt->output_pin_fmts[i].audio_fmt; + val = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(audio_fmt->fmt_cfg); + + if (i == 0) + sample_valid_bits = val; + else if (sample_valid_bits != val) + multiple_formats = true; + + if (snd_pcm_format_width(params_format(fe_params)) == val) + fe_format_match = true; + } + + fmt = hw_param_mask(pipeline_params, SNDRV_PCM_HW_PARAM_FORMAT); + snd_mask_none(fmt); + + if (multiple_formats) { + if (fe_format_match) { + /* multiple formats defined and one matches FE */ + snd_mask_set_format(fmt, params_format(fe_params)); + return 0; + } + + dev_err(sdev->dev, "Multiple audio formats for single dai_out not supported\n"); + return -EINVAL; + } + + return ipc4_set_fmt_mask(fmt, sample_valid_bits); +} + static int sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, struct snd_pcm_hw_params *fe_params, @@ -1152,13 +1215,10 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, format_list_to_search = available_fmt->output_pin_fmts; format_list_count = available_fmt->num_output_formats; - /* - * modify the input params for the dai copier as it only supports - * 32-bit always - */ - fmt = hw_param_mask(pipeline_params, SNDRV_PCM_HW_PARAM_FORMAT); - snd_mask_none(fmt); - snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S32_LE); + ret = ipc4_copier_set_capture_fmt(sdev, pipeline_params, fe_params, + available_fmt); + if (ret < 0) + return ret; } else { format_list_to_search = available_fmt->input_pin_fmts; format_list_count = available_fmt->num_input_formats; From 37ec7ab49f951ef8c38102328b84d3dc7155dc68 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Thu, 16 Mar 2023 16:14:58 +0200 Subject: [PATCH 370/778] ASoC: SOF: ipc4-topology: use common helper function in copier prepare MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the ipc4_set_fmt_mask() helper function instead of open-coding the logic in multiple places. Signed-off-by: Kai Vehmanen Reviewed-by: Péter Ujfalusi Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230316141458.13940-3-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index cf438f32b4ed..4fba8ada9a06 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -1363,21 +1363,9 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, out_sample_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(copier_data->out_format.fmt_cfg); snd_mask_none(fmt); - switch (out_sample_valid_bits) { - case 16: - snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE); - break; - case 24: - snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE); - break; - case 32: - snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S32_LE); - break; - default: - dev_err(sdev->dev, "invalid sample frame format %d\n", - params_format(pipeline_params)); - return -EINVAL; - } + ret = ipc4_set_fmt_mask(fmt, out_sample_valid_bits); + if (ret) + return ret; /* * Set the gateway dma_buffer_size to 2ms buffer size to meet the FW expectation. In the From 04b522a4d2acf8447d69bf87b3ab67d5e6d631a2 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 16 Mar 2023 17:11:32 +0200 Subject: [PATCH 371/778] ASoC: SOF: ipc4-topology: Move the kcontrol module_id update to helper Introduce a helper function to update the message template for a kcontrol associated with a widget. In this way the helper can be re-used by other components later. Signed-off-by: Peter Ujfalusi Reviewed-by: Ranjani Sridharan Reviewed-by: Jaska Uimonen Reviewed-by: Kai Vehmanen Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20230316151137.7598-2-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index e7b3bdc95dd7..c00df3956c02 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -320,6 +320,24 @@ static int sof_ipc4_widget_setup_msg(struct snd_sof_widget *swidget, struct sof_ return 0; } +static void sof_ipc4_widget_update_kcontrol_module_id(struct snd_sof_widget *swidget) +{ + struct snd_soc_component *scomp = swidget->scomp; + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); + struct sof_ipc4_fw_module *fw_module = swidget->module_info; + struct snd_sof_control *scontrol; + + /* update module ID for all kcontrols for this widget */ + list_for_each_entry(scontrol, &sdev->kcontrol_list, list) { + if (scontrol->comp_id == swidget->comp_id) { + struct sof_ipc4_control_data *cdata = scontrol->ipc_control_data; + struct sof_ipc4_msg *msg = &cdata->msg; + + msg->primary |= fw_module->man4_module_entry.id; + } + } +} + static int sof_ipc4_widget_setup_pcm(struct snd_sof_widget *swidget) { struct sof_ipc4_available_audio_format *available_fmt; @@ -627,9 +645,6 @@ err: static int sof_ipc4_widget_setup_comp_pga(struct snd_sof_widget *swidget) { struct snd_soc_component *scomp = swidget->scomp; - struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); - struct sof_ipc4_fw_module *fw_module; - struct snd_sof_control *scontrol; struct sof_ipc4_gain *gain; int ret; @@ -662,16 +677,7 @@ static int sof_ipc4_widget_setup_comp_pga(struct snd_sof_widget *swidget) if (ret) goto err; - fw_module = swidget->module_info; - - /* update module ID for all kcontrols for this widget */ - list_for_each_entry(scontrol, &sdev->kcontrol_list, list) - if (scontrol->comp_id == swidget->comp_id) { - struct sof_ipc4_control_data *cdata = scontrol->ipc_control_data; - struct sof_ipc4_msg *msg = &cdata->msg; - - msg->primary |= fw_module->man4_module_entry.id; - } + sof_ipc4_widget_update_kcontrol_module_id(swidget); return 0; err: From 7711a2bbc8447dd7185c6da9e405d89ce3ec2f0f Mon Sep 17 00:00:00 2001 From: Libin Yang Date: Thu, 16 Mar 2023 17:11:33 +0200 Subject: [PATCH 372/778] ASoC: SOF: ipc4-topology: add effect widget support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the general support of IPC4 effect widgets. IPC4 effect widgets, known as process modules, can be EQFIR, EQIIR, KEYWORD_DETECT, KPB, CHAN_SELECTOR, SMART_AMP and etc. Signed-off-by: Libin Yang Reviewed-by: Ranjani Sridharan Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230316151137.7598-3-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 124 ++++++++++++++++++++++++++++++++++ sound/soc/sof/ipc4-topology.h | 18 +++++ 2 files changed, 142 insertions(+) diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index c00df3956c02..76bd3487bf71 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -793,6 +793,69 @@ static void sof_ipc4_widget_free_comp_mixer(struct snd_sof_widget *swidget) swidget->private = NULL; } +/* + * Add the process modules support. The process modules are defined as snd_soc_dapm_effect modules. + */ +static int sof_ipc4_widget_setup_comp_process(struct snd_sof_widget *swidget) +{ + struct snd_soc_component *scomp = swidget->scomp; + struct sof_ipc4_process *process; + int cfg_size; + void *cfg; + int ret; + + process = kzalloc(sizeof(*process), GFP_KERNEL); + if (!process) + return -ENOMEM; + + swidget->private = process; + + ret = sof_ipc4_get_audio_fmt(scomp, swidget, &process->available_fmt, + &process->base_config); + if (ret) + goto err; + + cfg_size = sizeof(struct sof_ipc4_base_module_cfg); + + cfg = kzalloc(cfg_size, GFP_KERNEL); + if (!cfg) { + ret = -ENOMEM; + goto free_available_fmt; + } + + process->ipc_config_data = cfg; + process->ipc_config_size = cfg_size; + ret = sof_ipc4_widget_setup_msg(swidget, &process->msg); + if (ret) + goto free_cfg_data; + + sof_ipc4_widget_update_kcontrol_module_id(swidget); + + return 0; +free_cfg_data: + kfree(process->ipc_config_data); + process->ipc_config_data = NULL; +free_available_fmt: + sof_ipc4_free_audio_fmt(&process->available_fmt); +err: + kfree(process); + swidget->private = NULL; + return ret; +} + +static void sof_ipc4_widget_free_comp_process(struct snd_sof_widget *swidget) +{ + struct sof_ipc4_process *process = swidget->private; + + if (!process) + return; + + kfree(process->ipc_config_data); + sof_ipc4_free_audio_fmt(&process->available_fmt); + kfree(swidget->private); + swidget->private = NULL; +} + static void sof_ipc4_update_pipeline_mem_usage(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget, struct sof_ipc4_base_module_cfg *base_config) @@ -1454,6 +1517,38 @@ static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget, return 0; } +static int sof_ipc4_prepare_process_module(struct snd_sof_widget *swidget, + struct snd_pcm_hw_params *fe_params, + struct snd_sof_platform_stream_params *platform_params, + struct snd_pcm_hw_params *pipeline_params, int dir) +{ + struct snd_soc_component *scomp = swidget->scomp; + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); + struct sof_ipc4_process *process = swidget->private; + struct sof_ipc4_available_audio_format *available_fmt = &process->available_fmt; + void *cfg = process->ipc_config_data; + int ret; + + ret = sof_ipc4_init_audio_fmt(sdev, swidget, &process->base_config, + pipeline_params, available_fmt, + available_fmt->input_pin_fmts, + available_fmt->num_input_formats); + if (ret < 0) + return ret; + + /* update pipeline memory usage */ + sof_ipc4_update_pipeline_mem_usage(sdev, swidget, &process->base_config); + + /* + * ipc_config_data is composed of the base_config, optional output formats followed + * by the data required for module init in that order. + */ + memcpy(cfg, &process->base_config, sizeof(struct sof_ipc4_base_module_cfg)); + cfg += sizeof(struct sof_ipc4_base_module_cfg); + + return 0; +} + static int sof_ipc4_control_load_volume(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol) { struct sof_ipc4_control_data *control_data; @@ -1652,6 +1747,22 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget msg = &src->msg; break; } + case snd_soc_dapm_effect: + { + struct sof_ipc4_process *process = swidget->private; + + if (!process->ipc_config_size) { + dev_err(sdev->dev, "module %s has no config data!\n", + swidget->widget->name); + return -EINVAL; + } + + ipc_size = process->ipc_config_size; + ipc_data = process->ipc_config_data; + + msg = &process->msg; + break; + } default: dev_err(sdev->dev, "widget type %d not supported", swidget->id); return -EINVAL; @@ -2257,6 +2368,14 @@ static enum sof_tokens src_token_list[] = { SOF_COMP_EXT_TOKENS, }; +static enum sof_tokens process_token_list[] = { + SOF_COMP_TOKENS, + SOF_AUDIO_FMT_NUM_TOKENS, + SOF_IN_AUDIO_FORMAT_TOKENS, + SOF_OUT_AUDIO_FORMAT_TOKENS, + SOF_COMP_EXT_TOKENS, +}; + static const struct sof_ipc_tplg_widget_ops tplg_ipc4_widget_ops[SND_SOC_DAPM_TYPE_COUNT] = { [snd_soc_dapm_aif_in] = {sof_ipc4_widget_setup_pcm, sof_ipc4_widget_free_comp_pcm, common_copier_token_list, ARRAY_SIZE(common_copier_token_list), @@ -2294,6 +2413,11 @@ static const struct sof_ipc_tplg_widget_ops tplg_ipc4_widget_ops[SND_SOC_DAPM_TY src_token_list, ARRAY_SIZE(src_token_list), NULL, sof_ipc4_prepare_src_module, NULL}, + [snd_soc_dapm_effect] = {sof_ipc4_widget_setup_comp_process, + sof_ipc4_widget_free_comp_process, + process_token_list, ARRAY_SIZE(process_token_list), + NULL, sof_ipc4_prepare_process_module, + NULL}, }; const struct sof_ipc_tplg_ops ipc4_tplg_ops = { diff --git a/sound/soc/sof/ipc4-topology.h b/sound/soc/sof/ipc4-topology.h index fad7a628f782..9fcb978ebc63 100644 --- a/sound/soc/sof/ipc4-topology.h +++ b/sound/soc/sof/ipc4-topology.h @@ -347,4 +347,22 @@ struct sof_ipc4_src { struct sof_ipc4_msg msg; }; +/** + * struct sof_ipc4_process - process config data + * @base_config: IPC base config data + * @output_format: Output audio format + * @available_fmt: Available audio format + * @ipc_config_data: Process module config data + * @ipc_config_size: Size of process module config data + * @msg: IPC4 message struct containing header and data info + */ +struct sof_ipc4_process { + struct sof_ipc4_base_module_cfg base_config; + struct sof_ipc4_audio_format output_format; + struct sof_ipc4_available_audio_format available_fmt; + void *ipc_config_data; + uint32_t ipc_config_size; + struct sof_ipc4_msg msg; +}; + #endif From d0be868c5a6e0dafb53d0ee9f0b9d66e40d963f6 Mon Sep 17 00:00:00 2001 From: Chao Song Date: Thu, 16 Mar 2023 17:11:34 +0200 Subject: [PATCH 373/778] ASoC: SOF: ipc4-topology: add base module config extension structure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The modules currently supported by the SOF firmware use the base module config containing the audio format for the input/output pin 0 for initialization. But some processing modules with multiple input/output pins require the audio formats to be sent with the init instance IPC payload. Modules that require the base config extension will need to indicate this in the module information in the firmware manifest. Introduce a new struct sof_ipc4_base_module_cfg_ext which contains the pin formats for the input and output pins. This will be appended to the init instance IPC payload for modules that require it. Signed-off-by: Chao Song Signed-off-by: Ranjani Sridharan Reviewed-by: Péter Ujfalusi Reviewed-by: Kai Vehmanen Reviewed-by: Bard Liao Reviewed-by: Pierre-Louis Bossart Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230316151137.7598-4-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/sound/soc/sof/ipc4-topology.h b/sound/soc/sof/ipc4-topology.h index 9fcb978ebc63..97264454b8a6 100644 --- a/sound/soc/sof/ipc4-topology.h +++ b/sound/soc/sof/ipc4-topology.h @@ -347,6 +347,23 @@ struct sof_ipc4_src { struct sof_ipc4_msg msg; }; +/** + * struct sof_ipc4_base_module_cfg_ext - base module config extension containing the pin format + * information for the module. Both @num_input_pin_fmts and @num_output_pin_fmts cannot be 0 for a + * module. + * @num_input_pin_fmts: number of input pin formats in the @pin_formats array + * @num_output_pin_fmts: number of output pin formats in the @pin_formats array + * @reserved: reserved for future use + * @pin_formats: flexible array consisting of @num_input_pin_fmts input pin format items followed + * by @num_output_pin_fmts output pin format items + */ +struct sof_ipc4_base_module_cfg_ext { + u16 num_input_pin_fmts; + u16 num_output_pin_fmts; + u8 reserved[12]; + DECLARE_FLEX_ARRAY(struct sof_ipc4_pin_format, pin_formats); +} __packed; + /** * struct sof_ipc4_process - process config data * @base_config: IPC base config data From f9efae954905a07a9d152e9b30546a6632227eef Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Thu, 16 Mar 2023 17:11:35 +0200 Subject: [PATCH 374/778] ASoC: SOF: ipc4-topology: Add support for base config extension MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some processing modules need the audio formats for all their input and output pins appended to the base config during module init. So add support for building the base config extension using the available pin formats from topology. Signed-off-by: Ranjani Sridharan Reviewed-by: Péter Ujfalusi Reviewed-by: Kai Vehmanen Reviewed-by: Bard Liao Reviewed-by: Pierre-Louis Bossart Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230316151137.7598-5-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 147 ++++++++++++++++++++++++++++++---- sound/soc/sof/ipc4-topology.h | 10 +++ 2 files changed, 142 insertions(+), 15 deletions(-) diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index 76bd3487bf71..efd53e855601 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -6,6 +6,7 @@ // Copyright(c) 2022 Intel Corporation. All rights reserved. // // +#include #include #include #include @@ -799,8 +800,8 @@ static void sof_ipc4_widget_free_comp_mixer(struct snd_sof_widget *swidget) static int sof_ipc4_widget_setup_comp_process(struct snd_sof_widget *swidget) { struct snd_soc_component *scomp = swidget->scomp; + struct sof_ipc4_fw_module *fw_module; struct sof_ipc4_process *process; - int cfg_size; void *cfg; int ret; @@ -815,26 +816,50 @@ static int sof_ipc4_widget_setup_comp_process(struct snd_sof_widget *swidget) if (ret) goto err; - cfg_size = sizeof(struct sof_ipc4_base_module_cfg); + ret = sof_ipc4_widget_setup_msg(swidget, &process->msg); + if (ret) + goto err; - cfg = kzalloc(cfg_size, GFP_KERNEL); + /* parse process init module payload config type from module info */ + fw_module = swidget->module_info; + process->init_config = FIELD_GET(SOF_IPC4_MODULE_INIT_CONFIG_MASK, + fw_module->man4_module_entry.type); + + process->ipc_config_size = sizeof(struct sof_ipc4_base_module_cfg); + + /* allocate memory for base config extension if needed */ + if (process->init_config == SOF_IPC4_MODULE_INIT_CONFIG_TYPE_BASE_CFG_WITH_EXT) { + struct sof_ipc4_base_module_cfg_ext *base_cfg_ext; + u32 ext_size = struct_size(base_cfg_ext, pin_formats, + swidget->num_input_pins + swidget->num_output_pins); + + base_cfg_ext = kzalloc(ext_size, GFP_KERNEL); + if (!base_cfg_ext) { + ret = -ENOMEM; + goto free_available_fmt; + } + + base_cfg_ext->num_input_pin_fmts = swidget->num_input_pins; + base_cfg_ext->num_output_pin_fmts = swidget->num_output_pins; + process->base_config_ext = base_cfg_ext; + process->base_config_ext_size = ext_size; + process->ipc_config_size += ext_size; + } + + cfg = kzalloc(process->ipc_config_size, GFP_KERNEL); if (!cfg) { ret = -ENOMEM; - goto free_available_fmt; + goto free_base_cfg_ext; } process->ipc_config_data = cfg; - process->ipc_config_size = cfg_size; - ret = sof_ipc4_widget_setup_msg(swidget, &process->msg); - if (ret) - goto free_cfg_data; sof_ipc4_widget_update_kcontrol_module_id(swidget); return 0; -free_cfg_data: - kfree(process->ipc_config_data); - process->ipc_config_data = NULL; +free_base_cfg_ext: + kfree(process->base_config_ext); + process->base_config_ext = NULL; free_available_fmt: sof_ipc4_free_audio_fmt(&process->available_fmt); err: @@ -851,6 +876,7 @@ static void sof_ipc4_widget_free_comp_process(struct snd_sof_widget *swidget) return; kfree(process->ipc_config_data); + kfree(process->base_config_ext); sof_ipc4_free_audio_fmt(&process->available_fmt); kfree(swidget->private); swidget->private = NULL; @@ -1517,6 +1543,84 @@ static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget, return 0; } +static int +sof_ipc4_process_set_pin_formats(struct snd_sof_widget *swidget, int pin_type) +{ + struct sof_ipc4_process *process = swidget->private; + struct sof_ipc4_base_module_cfg_ext *base_cfg_ext = process->base_config_ext; + struct sof_ipc4_available_audio_format *available_fmt = &process->available_fmt; + struct sof_ipc4_pin_format *pin_format, *format_list_to_search; + struct snd_soc_component *scomp = swidget->scomp; + int num_pins, format_list_count; + int pin_format_offset = 0; + int i, j; + + /* set number of pins, offset of pin format and format list to search based on pin type */ + if (pin_type == SOF_PIN_TYPE_INPUT) { + num_pins = swidget->num_input_pins; + format_list_to_search = available_fmt->input_pin_fmts; + format_list_count = available_fmt->num_input_formats; + } else { + num_pins = swidget->num_output_pins; + pin_format_offset = swidget->num_input_pins; + format_list_to_search = available_fmt->output_pin_fmts; + format_list_count = available_fmt->num_output_formats; + } + + for (i = pin_format_offset; i < num_pins + pin_format_offset; i++) { + pin_format = &base_cfg_ext->pin_formats[i]; + + /* Pin 0 audio formats are derived from the base config input/output format */ + if (i == pin_format_offset) { + if (pin_type == SOF_PIN_TYPE_INPUT) { + pin_format->buffer_size = process->base_config.ibs; + pin_format->audio_fmt = process->base_config.audio_fmt; + } else { + pin_format->buffer_size = process->base_config.obs; + pin_format->audio_fmt = process->output_format; + } + continue; + } + + /* + * For all other pins, find the pin formats from those set in topology. If there + * is more than one format specified for a pin, this will pick the first available + * one. + */ + for (j = 0; j < format_list_count; j++) { + struct sof_ipc4_pin_format *pin_format_item = &format_list_to_search[j]; + + if (pin_format_item->pin_index == i - pin_format_offset) { + *pin_format = *pin_format_item; + break; + } + } + + if (j == format_list_count) { + dev_err(scomp->dev, "%s pin %d format not found for %s\n", + (pin_type == SOF_PIN_TYPE_INPUT) ? "input" : "output", + i - pin_format_offset, swidget->widget->name); + return -EINVAL; + } + } + + return 0; +} + +static int sof_ipc4_process_add_base_cfg_extn(struct snd_sof_widget *swidget) +{ + int ret, i; + + /* copy input and output pin formats */ + for (i = 0; i <= SOF_PIN_TYPE_OUTPUT; i++) { + ret = sof_ipc4_process_set_pin_formats(swidget, i); + if (ret < 0) + return ret; + } + + return 0; +} + static int sof_ipc4_prepare_process_module(struct snd_sof_widget *swidget, struct snd_pcm_hw_params *fe_params, struct snd_sof_platform_stream_params *platform_params, @@ -1536,16 +1640,29 @@ static int sof_ipc4_prepare_process_module(struct snd_sof_widget *swidget, if (ret < 0) return ret; + /* copy Pin 0 output format */ + if (available_fmt->num_output_formats && ret < available_fmt->num_output_formats && + !available_fmt->output_pin_fmts[ret].pin_index) + memcpy(&process->output_format, &available_fmt->output_pin_fmts[ret].audio_fmt, + sizeof(struct sof_ipc4_audio_format)); + /* update pipeline memory usage */ sof_ipc4_update_pipeline_mem_usage(sdev, swidget, &process->base_config); - /* - * ipc_config_data is composed of the base_config, optional output formats followed - * by the data required for module init in that order. - */ + /* ipc_config_data is composed of the base_config followed by an optional extension */ memcpy(cfg, &process->base_config, sizeof(struct sof_ipc4_base_module_cfg)); cfg += sizeof(struct sof_ipc4_base_module_cfg); + if (process->init_config == SOF_IPC4_MODULE_INIT_CONFIG_TYPE_BASE_CFG_WITH_EXT) { + struct sof_ipc4_base_module_cfg_ext *base_cfg_ext = process->base_config_ext; + + ret = sof_ipc4_process_add_base_cfg_extn(swidget); + if (ret < 0) + return ret; + + memcpy(cfg, base_cfg_ext, process->base_config_ext_size); + } + return 0; } diff --git a/sound/soc/sof/ipc4-topology.h b/sound/soc/sof/ipc4-topology.h index 97264454b8a6..015027b23588 100644 --- a/sound/soc/sof/ipc4-topology.h +++ b/sound/soc/sof/ipc4-topology.h @@ -26,6 +26,10 @@ #define SOF_IPC4_MODULE_LL BIT(5) #define SOF_IPC4_MODULE_DP BIT(6) #define SOF_IPC4_MODULE_LIB_CODE BIT(7) +#define SOF_IPC4_MODULE_INIT_CONFIG_MASK GENMASK(11, 8) + +#define SOF_IPC4_MODULE_INIT_CONFIG_TYPE_BASE_CFG 0 +#define SOF_IPC4_MODULE_INIT_CONFIG_TYPE_BASE_CFG_WITH_EXT 1 #define SOF_IPC4_MODULE_INSTANCE_LIST_ITEM_SIZE 12 #define SOF_IPC4_PIPELINE_OBJECT_SIZE 448 @@ -367,19 +371,25 @@ struct sof_ipc4_base_module_cfg_ext { /** * struct sof_ipc4_process - process config data * @base_config: IPC base config data + * @base_config_ext: Base config extension data for module init * @output_format: Output audio format * @available_fmt: Available audio format * @ipc_config_data: Process module config data * @ipc_config_size: Size of process module config data * @msg: IPC4 message struct containing header and data info + * @base_config_ext_size: Size of the base config extension data in bytes + * @init_config: Module init config type (SOF_IPC4_MODULE_INIT_CONFIG_TYPE_*) */ struct sof_ipc4_process { struct sof_ipc4_base_module_cfg base_config; + struct sof_ipc4_base_module_cfg_ext *base_config_ext; struct sof_ipc4_audio_format output_format; struct sof_ipc4_available_audio_format available_fmt; void *ipc_config_data; uint32_t ipc_config_size; struct sof_ipc4_msg msg; + u32 base_config_ext_size; + u32 init_config; }; #endif From 648fea12847695d60ddeebea86597114885ee76e Mon Sep 17 00:00:00 2001 From: Chao Song Date: Thu, 16 Mar 2023 17:11:36 +0200 Subject: [PATCH 375/778] ASoC: SOF: ipc4-topology: set copier output format for process module MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The copier output pin 0 format is set with module instance initialization, format for additional copier output pin should be set before the pin is used. If a process module is connected to additional copier output pin, the copier output pin format should be set according to the corresponding input pin format of the process module. Signed-off-by: Chao Song Co-developed-by: Ranjani Sridharan Signed-off-by: Ranjani Sridharan Reviewed-by: Péter Ujfalusi Reviewed-by: Kai Vehmanen Reviewed-by: Bard Liao Reviewed-by: Pierre-Louis Bossart Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230316151137.7598-6-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 46 ++++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index efd53e855601..962ec38b70cc 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -166,6 +166,37 @@ static void sof_ipc4_dbg_audio_format(struct device *dev, struct sof_ipc4_pin_fo } } +static const struct sof_ipc4_audio_format * +sof_ipc4_get_input_pin_audio_fmt(struct snd_sof_widget *swidget, int pin_index) +{ + struct sof_ipc4_base_module_cfg_ext *base_cfg_ext; + struct sof_ipc4_process *process; + int i; + + if (swidget->id != snd_soc_dapm_effect) { + struct sof_ipc4_base_module_cfg *base = swidget->private; + + /* For non-process modules, base module config format is used for all input pins */ + return &base->audio_fmt; + } + + process = swidget->private; + base_cfg_ext = process->base_config_ext; + + /* + * If there are multiple input formats available for a pin, the first available format + * is chosen. + */ + for (i = 0; i < base_cfg_ext->num_input_pin_fmts; i++) { + struct sof_ipc4_pin_format *pin_format = &base_cfg_ext->pin_formats[i]; + + if (pin_format->pin_index == pin_index) + return &pin_format->audio_fmt; + } + + return NULL; +} + /** * sof_ipc4_get_audio_fmt - get available audio formats from swidget->tuples * @scomp: pointer to pointer to SOC component @@ -2049,9 +2080,9 @@ static int sof_ipc4_set_copier_sink_format(struct snd_sof_dev *sdev, struct snd_sof_widget *sink_widget, int sink_id) { - struct sof_ipc4_base_module_cfg *sink_config = sink_widget->private; - struct sof_ipc4_base_module_cfg *src_config; struct sof_ipc4_copier_config_set_sink_format format; + struct sof_ipc4_base_module_cfg *src_config; + const struct sof_ipc4_audio_format *pin_fmt; struct sof_ipc4_fw_module *fw_module; struct sof_ipc4_msg msg = {{ 0 }}; u32 header, extension; @@ -2071,7 +2102,16 @@ static int sof_ipc4_set_copier_sink_format(struct snd_sof_dev *sdev, format.sink_id = sink_id; memcpy(&format.source_fmt, &src_config->audio_fmt, sizeof(format.source_fmt)); - memcpy(&format.sink_fmt, &sink_config->audio_fmt, sizeof(format.sink_fmt)); + + pin_fmt = sof_ipc4_get_input_pin_audio_fmt(sink_widget, sink_id); + if (!pin_fmt) { + dev_err(sdev->dev, "Unable to get pin %d format for %s", + sink_id, sink_widget->widget->name); + return -EINVAL; + } + + memcpy(&format.sink_fmt, pin_fmt, sizeof(format.sink_fmt)); + msg.data_size = sizeof(format); msg.data_ptr = &format; From 811a742f2d4d1b0aee686bc2f4282b51534898a2 Mon Sep 17 00:00:00 2001 From: Libin Yang Date: Thu, 16 Mar 2023 17:11:37 +0200 Subject: [PATCH 376/778] ASoC: SOF: ipc4-topology: update pipeline_params in process prepare MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some modules may modify the audio format during processing. So, update the pipeline params based on pin 0's output format during process prepare. Signed-off-by: Libin Yang Co-developed-by: Ranjani Sridharan Signed-off-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Reviewed-by: Chao Song Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230316151137.7598-7-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 50 ++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index 962ec38b70cc..963ec730381b 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -964,6 +964,48 @@ static int sof_ipc4_widget_assign_instance_id(struct snd_sof_dev *sdev, return 0; } +/* update hw_params based on the audio stream format */ +static int sof_ipc4_update_hw_params(struct snd_sof_dev *sdev, struct snd_pcm_hw_params *params, + struct sof_ipc4_audio_format *fmt) +{ + snd_pcm_format_t snd_fmt; + struct snd_interval *i; + struct snd_mask *m; + int valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt->fmt_cfg); + unsigned int channels, rate; + + switch (valid_bits) { + case 16: + snd_fmt = SNDRV_PCM_FORMAT_S16_LE; + break; + case 24: + snd_fmt = SNDRV_PCM_FORMAT_S24_LE; + break; + case 32: + snd_fmt = SNDRV_PCM_FORMAT_S32_LE; + break; + default: + dev_err(sdev->dev, "invalid PCM valid_bits %d\n", valid_bits); + return -EINVAL; + } + + m = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); + snd_mask_none(m); + snd_mask_set_format(m, snd_fmt); + + rate = fmt->sampling_frequency; + i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); + i->min = rate; + i->max = rate; + + channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(fmt->fmt_cfg); + i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); + i->min = channels; + i->max = channels; + + return 0; +} + static int sof_ipc4_init_audio_fmt(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget, struct sof_ipc4_base_module_cfg *base_config, @@ -1673,10 +1715,16 @@ static int sof_ipc4_prepare_process_module(struct snd_sof_widget *swidget, /* copy Pin 0 output format */ if (available_fmt->num_output_formats && ret < available_fmt->num_output_formats && - !available_fmt->output_pin_fmts[ret].pin_index) + !available_fmt->output_pin_fmts[ret].pin_index) { memcpy(&process->output_format, &available_fmt->output_pin_fmts[ret].audio_fmt, sizeof(struct sof_ipc4_audio_format)); + /* modify the pipeline params with the pin 0 output format */ + ret = sof_ipc4_update_hw_params(sdev, pipeline_params, &process->output_format); + if (ret) + return ret; + } + /* update pipeline memory usage */ sof_ipc4_update_pipeline_mem_usage(sdev, swidget, &process->base_config); From ef51cd1ebab63bb92bfef050fbf12b2265f5c7a5 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 17 Mar 2023 08:35:24 +0200 Subject: [PATCH 377/778] ASoC: SOF: ipc4-topology: Initialize in_format to NULL in sof_ipc4_get_audio_fmt If the available_fmt->num_input_formats is 0 and there is a failure during the output format parsing then a kfree() would be called on the uninitialized in_format pointer. By initializing the in_format to NULL, this error can be avoided. Fixes: 7ab6b1e8302c ("ASoC: SOF: ipc4-topology: Modify the type of available input/output formats") Signed-off-by: Peter Ujfalusi Reviewed-by: Bard Liao Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20230317063524.8280-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index e7b3bdc95dd7..2a2c4cda63fd 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -179,7 +179,8 @@ static int sof_ipc4_get_audio_fmt(struct snd_soc_component *scomp, struct sof_ipc4_available_audio_format *available_fmt, struct sof_ipc4_base_module_cfg *module_base_cfg) { - struct sof_ipc4_pin_format *out_format, *in_format; + struct sof_ipc4_pin_format *in_format = NULL; + struct sof_ipc4_pin_format *out_format; int ret; ret = sof_update_ipc_object(scomp, available_fmt, From b36bf721578bfe8229c1d7f2fcd0bd021cc8b2f4 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 17 Mar 2023 10:29:00 +0100 Subject: [PATCH 378/778] ASoC: dt-bindings: adi,adau17x1: fix indentation and example Fix errors in binding indentation and example: adi,adau17x1.yaml:8:2: [warning] wrong indentation: expected 2 but found 1 (indentation) adi,adau17x1.example.dts:29.3-30.1 syntax error Fixes: 87771c940258 ("ASoC: dt-bindings: adi,adau17x1: Convert to DT schema") Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230317092900.16770-1-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/adi,adau17x1.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/adi,adau17x1.yaml b/Documentation/devicetree/bindings/sound/adi,adau17x1.yaml index 45955f38b6fd..8ef1e7f6ec91 100644 --- a/Documentation/devicetree/bindings/sound/adi,adau17x1.yaml +++ b/Documentation/devicetree/bindings/sound/adi,adau17x1.yaml @@ -4,8 +4,7 @@ $id: http://devicetree.org/schemas/sound/adi,adau17x1.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: - Analog Devices ADAU1361/ADAU1461/ADAU1761/ADAU1961/ADAU1381/ADAU1781 Codec +title: Analog Devices ADAU1361/ADAU1461/ADAU1761/ADAU1961/ADAU1381/ADAU1781 Codec maintainers: - Lars-Peter Clausen @@ -50,3 +49,4 @@ examples: clock-names = "mclk"; clocks = <&audio_clock>; }; + }; From 47df94faa5e3775510177cdc0909e397300cc791 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 17 Mar 2023 09:21:37 +0100 Subject: [PATCH 379/778] ASoC: dt-bindings: renesas: rsnd: correct comments syntax MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit yamllint expect space after '#' comment mark: renesas,rsnd.yaml:282:4: [error] missing starting space in comment (comments) Fixes: 7f8b5b24bbb4 ("ASoC: dt-bindings: renesas,rsnd.yaml: add R-Car Gen4 support") Reported-by: Rafał Miłecki Link: https://lore.kernel.org/all/b2810924-169d-0bad-8f20-6ec2e683d170@gmail.com/ Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230317082137.12629-1-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/renesas,rsnd.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/renesas,rsnd.yaml b/Documentation/devicetree/bindings/sound/renesas,rsnd.yaml index 676dfe7a7f17..68a93b290433 100644 --- a/Documentation/devicetree/bindings/sound/renesas,rsnd.yaml +++ b/Documentation/devicetree/bindings/sound/renesas,rsnd.yaml @@ -279,9 +279,9 @@ required: allOf: - $ref: dai-common.yaml# - #-------------------- + # -------------------- # reg/reg-names - #-------------------- + # -------------------- # for Gen1 - if: properties: @@ -336,9 +336,9 @@ allOf: - ssi - sdmc - #-------------------- + # -------------------- # clock-names - #-------------------- + # -------------------- - if: properties: compatible: From eb0b8481c2e03a5ae01f6bea60b42109bd12b6fe Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Wed, 8 Mar 2023 09:34:56 +0200 Subject: [PATCH 380/778] ASoC: tegra: Support coupled mic-hp detection This quirk is used for cases when there is GPIO which detects any type of 3.5 Jack insertion and actual type of jack is defined by other GPIO. 3.5 Jack GPIO generates interrupt and MIC GPIO indicates type of Jack only if 3.5 Jack GPIO is active. Signed-off-by: Svyatoslav Ryhel Link: https://lore.kernel.org/r/20230308073502.5421-3-clamor95@gmail.com Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_asoc_machine.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/sound/soc/tegra/tegra_asoc_machine.c b/sound/soc/tegra/tegra_asoc_machine.c index 2dc1f44c5a8b..84a719ecae7f 100644 --- a/sound/soc/tegra/tegra_asoc_machine.c +++ b/sound/soc/tegra/tegra_asoc_machine.c @@ -51,6 +51,17 @@ static struct snd_soc_jack_gpio tegra_machine_headset_jack_gpio = { }; /* Mic Jack */ +static int coupled_mic_hp_check(void *data) +{ + struct tegra_machine *machine = (struct tegra_machine *)data; + + /* Detect mic insertion only if 3.5 jack is in */ + if (gpiod_get_value_cansleep(machine->gpiod_hp_det) && + gpiod_get_value_cansleep(machine->gpiod_mic_det)) + return SND_JACK_MICROPHONE; + + return 0; +} static struct snd_soc_jack tegra_machine_mic_jack; @@ -183,8 +194,15 @@ int tegra_asoc_machine_init(struct snd_soc_pcm_runtime *rtd) return err; } + tegra_machine_mic_jack_gpio.data = machine; tegra_machine_mic_jack_gpio.desc = machine->gpiod_mic_det; + if (of_property_read_bool(card->dev->of_node, + "nvidia,coupled-mic-hp-det")) { + tegra_machine_mic_jack_gpio.desc = machine->gpiod_hp_det; + tegra_machine_mic_jack_gpio.jack_status_check = coupled_mic_hp_check; + }; + err = snd_soc_jack_add_gpios(&tegra_machine_mic_jack, 1, &tegra_machine_mic_jack_gpio); if (err) From 44b2fc2edb61e956885b4305bddaaec7f05d93d2 Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Wed, 8 Mar 2023 09:34:59 +0200 Subject: [PATCH 381/778] ASoC: tegra: Support RT5631 by machine driver Add Realtek ALC5631/RT5631 codec support to the Tegra ASoC machine driver. The RT5631 codec is found on devices like ASUS Transformer TF201, TF700T and other Tegra-based Android tablets. Signed-off-by: Ion Agorria Signed-off-by: Svyatoslav Ryhel Link: https://lore.kernel.org/r/20230308073502.5421-6-clamor95@gmail.com Signed-off-by: Mark Brown --- sound/soc/tegra/Kconfig | 9 ++++ sound/soc/tegra/tegra_asoc_machine.c | 61 ++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig index 73a683d45526..dba70c7af150 100644 --- a/sound/soc/tegra/Kconfig +++ b/sound/soc/tegra/Kconfig @@ -189,6 +189,15 @@ config SND_SOC_TEGRA_AUDIO_GRAPH_CARD config SND_SOC_TEGRA_MACHINE_DRV tristate +config SND_SOC_TEGRA_RT5631 + tristate "SoC Audio support for Tegra boards using an RT5631 codec" + depends on SND_SOC_TEGRA && I2C && GPIOLIB + select SND_SOC_TEGRA_MACHINE_DRV + select SND_SOC_RT5631 + help + Say Y or M here if you want to add support for SoC audio on Tegra + boards using the RT5631 codec, such as Transformer. + config SND_SOC_TEGRA_RT5640 tristate "SoC Audio support for Tegra boards using an RT5640 codec" depends on I2C && GPIOLIB diff --git a/sound/soc/tegra/tegra_asoc_machine.c b/sound/soc/tegra/tegra_asoc_machine.c index 84a719ecae7f..b8cf5ab74acf 100644 --- a/sound/soc/tegra/tegra_asoc_machine.c +++ b/sound/soc/tegra/tegra_asoc_machine.c @@ -256,6 +256,32 @@ static unsigned int tegra_machine_mclk_rate_12mhz(unsigned int srate) return mclk; } +static unsigned int tegra_machine_mclk_rate_6mhz(unsigned int srate) +{ + unsigned int mclk; + + switch (srate) { + case 8000: + case 16000: + case 64000: + mclk = 8192000; + break; + case 11025: + case 22050: + case 88200: + mclk = 11289600; + break; + case 96000: + mclk = 12288000; + break; + default: + mclk = 256 * srate; + break; + } + + return mclk; +} + static int tegra_machine_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { @@ -883,6 +909,40 @@ static const struct tegra_asoc_data tegra_rt5632_data = { .add_headset_jack = true, }; +/* RT5631 machine */ + +SND_SOC_DAILINK_DEFS(rt5631_hifi, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "rt5631-hifi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +static struct snd_soc_dai_link tegra_rt5631_dai = { + .name = "RT5631", + .stream_name = "RT5631 PCM", + .init = tegra_asoc_machine_init, + .dai_fmt = SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAILINK_REG(rt5631_hifi), +}; + +static struct snd_soc_card snd_soc_tegra_rt5631 = { + .components = "codec:rt5631", + .dai_link = &tegra_rt5631_dai, + .num_links = 1, + .fully_routed = true, +}; + +static const struct tegra_asoc_data tegra_rt5631_data = { + .mclk_rate = tegra_machine_mclk_rate_6mhz, + .card = &snd_soc_tegra_rt5631, + .add_common_dapm_widgets = true, + .add_common_controls = true, + .add_common_snd_ops = true, + .add_mic_jack = true, + .add_hp_jack = true, +}; + static const struct of_device_id tegra_machine_of_match[] = { { .compatible = "nvidia,tegra-audio-trimslice", .data = &tegra_trimslice_data }, { .compatible = "nvidia,tegra-audio-max98090", .data = &tegra_max98090_data }, @@ -892,6 +952,7 @@ static const struct of_device_id tegra_machine_of_match[] = { { .compatible = "nvidia,tegra-audio-rt5677", .data = &tegra_rt5677_data }, { .compatible = "nvidia,tegra-audio-rt5640", .data = &tegra_rt5640_data }, { .compatible = "nvidia,tegra-audio-alc5632", .data = &tegra_rt5632_data }, + { .compatible = "nvidia,tegra-audio-rt5631", .data = &tegra_rt5631_data }, {}, }; MODULE_DEVICE_TABLE(of, tegra_machine_of_match); From d007a87bd7d181854b53b3e7fcbcf66c4bef86b2 Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Wed, 8 Mar 2023 09:35:02 +0200 Subject: [PATCH 382/778] ASoC: tegra: Support MAX9808x by machine driver Add Maxim MAX9808x codec support to the Tegra ASoC machine driver. This codec is found on LG T30 devices like Optimus 4X HD and Optimus Vu. Signed-off-by: Svyatoslav Ryhel Link: https://lore.kernel.org/r/20230308073502.5421-9-clamor95@gmail.com Signed-off-by: Mark Brown --- sound/soc/tegra/Kconfig | 9 ++++++ sound/soc/tegra/tegra_asoc_machine.c | 46 +++++++++++++++++++++++++--- 2 files changed, 51 insertions(+), 4 deletions(-) diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig index dba70c7af150..74effc57a7a0 100644 --- a/sound/soc/tegra/Kconfig +++ b/sound/soc/tegra/Kconfig @@ -263,6 +263,15 @@ config SND_SOC_TEGRA_MAX98090 Say Y or M here if you want to add support for SoC audio on Tegra boards using the MAX98090 codec, such as Venice2. +config SND_SOC_TEGRA_MAX98088 + tristate "SoC Audio support for Tegra boards using a MAX9808x codec" + depends on I2C && GPIOLIB + select SND_SOC_TEGRA_MACHINE_DRV + select SND_SOC_MAX98088 + help + Say Y or M here if you want to add support for SoC audio on Tegra + boards using the MAX98088 codec, such as LG X3. + config SND_SOC_TEGRA_RT5677 tristate "SoC Audio support for Tegra boards using a RT5677 codec" depends on I2C && GPIOLIB diff --git a/sound/soc/tegra/tegra_asoc_machine.c b/sound/soc/tegra/tegra_asoc_machine.c index b8cf5ab74acf..c2aaa496468c 100644 --- a/sound/soc/tegra/tegra_asoc_machine.c +++ b/sound/soc/tegra/tegra_asoc_machine.c @@ -86,11 +86,11 @@ static int tegra_machine_event(struct snd_soc_dapm_widget *w, gpiod_set_value_cansleep(machine->gpiod_spkr_en, SND_SOC_DAPM_EVENT_ON(event)); - if (!strcmp(w->name, "Mic Jack")) + if (!strcmp(w->name, "Mic Jack") || !strcmp(w->name, "Headset Mic")) gpiod_set_value_cansleep(machine->gpiod_ext_mic_en, SND_SOC_DAPM_EVENT_ON(event)); - if (!strcmp(w->name, "Int Mic")) + if (!strcmp(w->name, "Int Mic") || !strcmp(w->name, "Internal Mic 2")) gpiod_set_value_cansleep(machine->gpiod_int_mic_en, SND_SOC_DAPM_EVENT_ON(event)); @@ -108,11 +108,12 @@ static const struct snd_soc_dapm_widget tegra_machine_dapm_widgets[] = { SND_SOC_DAPM_HP("Headphones", NULL), SND_SOC_DAPM_SPK("Speakers", tegra_machine_event), SND_SOC_DAPM_SPK("Int Spk", tegra_machine_event), + SND_SOC_DAPM_SPK("Earpiece", NULL), SND_SOC_DAPM_MIC("Int Mic", tegra_machine_event), SND_SOC_DAPM_MIC("Mic Jack", tegra_machine_event), SND_SOC_DAPM_MIC("Internal Mic 1", NULL), - SND_SOC_DAPM_MIC("Internal Mic 2", NULL), - SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_MIC("Internal Mic 2", tegra_machine_event), + SND_SOC_DAPM_MIC("Headset Mic", tegra_machine_event), SND_SOC_DAPM_MIC("Digital Mic", NULL), SND_SOC_DAPM_MIC("Mic", NULL), SND_SOC_DAPM_LINE("Line In Jack", NULL), @@ -123,6 +124,7 @@ static const struct snd_soc_dapm_widget tegra_machine_dapm_widgets[] = { static const struct snd_kcontrol_new tegra_machine_controls[] = { SOC_DAPM_PIN_SWITCH("Speakers"), SOC_DAPM_PIN_SWITCH("Int Spk"), + SOC_DAPM_PIN_SWITCH("Earpiece"), SOC_DAPM_PIN_SWITCH("Int Mic"), SOC_DAPM_PIN_SWITCH("Headset Mic"), SOC_DAPM_PIN_SWITCH("Internal Mic 1"), @@ -718,6 +720,40 @@ static const struct tegra_asoc_data tegra_max98090_data = { .add_hp_jack = true, }; +/* MAX98088 machine */ + +SND_SOC_DAILINK_DEFS(max98088_hifi, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "HiFi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +static struct snd_soc_dai_link tegra_max98088_dai = { + .name = "MAX98088", + .stream_name = "MAX98088 PCM", + .init = tegra_asoc_machine_init, + .dai_fmt = SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAILINK_REG(max98088_hifi), +}; + +static struct snd_soc_card snd_soc_tegra_max98088 = { + .components = "codec:max98088", + .dai_link = &tegra_max98088_dai, + .num_links = 1, + .fully_routed = true, +}; + +static const struct tegra_asoc_data tegra_max98088_data = { + .mclk_rate = tegra_machine_mclk_rate_12mhz, + .card = &snd_soc_tegra_max98088, + .add_common_dapm_widgets = true, + .add_common_controls = true, + .add_common_snd_ops = true, + .add_mic_jack = true, + .add_hp_jack = true, +}; + /* SGTL5000 machine */ SND_SOC_DAILINK_DEFS(sgtl5000_hifi, @@ -946,6 +982,8 @@ static const struct tegra_asoc_data tegra_rt5631_data = { static const struct of_device_id tegra_machine_of_match[] = { { .compatible = "nvidia,tegra-audio-trimslice", .data = &tegra_trimslice_data }, { .compatible = "nvidia,tegra-audio-max98090", .data = &tegra_max98090_data }, + { .compatible = "nvidia,tegra-audio-max98088", .data = &tegra_max98088_data }, + { .compatible = "nvidia,tegra-audio-max98089", .data = &tegra_max98088_data }, { .compatible = "nvidia,tegra-audio-sgtl5000", .data = &tegra_sgtl5000_data }, { .compatible = "nvidia,tegra-audio-wm9712", .data = &tegra_wm9712_data }, { .compatible = "nvidia,tegra-audio-wm8753", .data = &tegra_wm8753_data }, From 2a7a8ebe85e1fa7e929f6f986a61f10321093c43 Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Wed, 8 Mar 2023 09:34:55 +0200 Subject: [PATCH 383/778] ASoC: nvidia,tegra-audio-common: add coupled-mic-hp-detect property Add nvidia,coupled-mic-hp-det property to use Mic detect GPIO only if HP GPIO is in active state. Acked-by: Rob Herring Signed-off-by: Svyatoslav Ryhel Link: https://lore.kernel.org/r/20230308073502.5421-2-clamor95@gmail.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/nvidia,tegra-audio-common.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-common.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-common.yaml index 82801b4f46dd..7c1e9895ce85 100644 --- a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-common.yaml +++ b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-common.yaml @@ -80,4 +80,8 @@ properties: type: boolean description: The Mic Jack represents state of the headset microphone pin + nvidia,coupled-mic-hp-det: + type: boolean + description: The Mic detect GPIO is viable only if HP detect GPIO is active + additionalProperties: true From 2060c9b8ae2a1f6abec483709f4209b6e3602b89 Mon Sep 17 00:00:00 2001 From: David Heidelberg Date: Wed, 8 Mar 2023 09:34:58 +0200 Subject: [PATCH 384/778] ASoC: nvidia,tegra-audio: add RT5631 CODEC Add dt-binding for RT5631 CODEC. Signed-off-by: David Heidelberg Signed-off-by: Svyatoslav Ryhel Link: https://lore.kernel.org/r/20230308073502.5421-5-clamor95@gmail.com Signed-off-by: Mark Brown --- .../sound/nvidia,tegra-audio-rt5631.yaml | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/nvidia,tegra-audio-rt5631.yaml diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-rt5631.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-rt5631.yaml new file mode 100644 index 000000000000..a04487002e88 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-rt5631.yaml @@ -0,0 +1,85 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/nvidia,tegra-audio-rt5631.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NVIDIA Tegra audio complex with RT5631 CODEC + +maintainers: + - Jon Hunter + - Thierry Reding + +allOf: + - $ref: nvidia,tegra-audio-common.yaml# + +properties: + compatible: + items: + - pattern: '^[a-z0-9]+,tegra-audio-rt5631(-[a-z0-9]+)+$' + - const: nvidia,tegra-audio-rt5631 + + nvidia,audio-routing: + $ref: /schemas/types.yaml#/definitions/non-unique-string-array + description: | + A list of the connections between audio components. + Each entry is a pair of strings, the first being the connection's sink, + the second being the connection's source. Valid names for sources and + sinks are the pins (documented in the binding document), + and the jacks on the board. + minItems: 2 + items: + enum: + # Board Connectors + - "Int Spk" + - "Headphone Jack" + - "Mic Jack" + - "Int Mic" + + # CODEC Pins + - MIC1 + - MIC2 + - AXIL + - AXIR + - MONOIN_RXN + - MONOIN_RXP + - DMIC + - MIC Bias1 + - MIC Bias2 + - MONO_IN + - AUXO1 + - AUXO2 + - SPOL + - SPOR + - HPOL + - HPOR + - MONO + +unevaluatedProperties: false + +examples: + - | + #include + #include + sound { + compatible = "asus,tegra-audio-rt5631-tf700t", + "nvidia,tegra-audio-rt5631"; + nvidia,model = "Asus Transformer Infinity TF700T RT5631"; + + nvidia,audio-routing = + "Headphone Jack", "HPOL", + "Headphone Jack", "HPOR", + "Int Spk", "SPOL", + "Int Spk", "SPOR", + "MIC1", "MIC Bias1", + "MIC Bias1", "Mic Jack", + "DMIC", "Int Mic"; + + nvidia,i2s-controller = <&tegra_i2s1>; + nvidia,audio-codec = <&rt5631>; + + clocks = <&tegra_car TEGRA30_CLK_PLL_A>, + <&tegra_car TEGRA30_CLK_PLL_A_OUT0>, + <&tegra_pmc TEGRA_PMC_CLK_OUT_1>; + clock-names = "pll_a", "pll_a_out0", "mclk"; + }; From 85a375fe8df906b2701346e03e71501e6861a75a Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Wed, 8 Mar 2023 09:35:01 +0200 Subject: [PATCH 385/778] ASoC: nvidia,tegra-audio: add MAX9808x CODEC Add dt-binding for MAX9808x CODEC. Signed-off-by: Svyatoslav Ryhel Link: https://lore.kernel.org/r/20230308073502.5421-8-clamor95@gmail.com Signed-off-by: Mark Brown --- .../sound/nvidia,tegra-audio-max9808x.yaml | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/nvidia,tegra-audio-max9808x.yaml diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-max9808x.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-max9808x.yaml new file mode 100644 index 000000000000..fc89dbd6bf24 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-max9808x.yaml @@ -0,0 +1,90 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/nvidia,tegra-audio-max9808x.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NVIDIA Tegra audio complex with MAX9808x CODEC + +maintainers: + - Jon Hunter + - Thierry Reding + +allOf: + - $ref: nvidia,tegra-audio-common.yaml# + +properties: + compatible: + oneOf: + - items: + - pattern: '^[a-z0-9]+,tegra-audio-max98088(-[a-z0-9]+)+$' + - const: nvidia,tegra-audio-max98088 + - items: + - pattern: '^[a-z0-9]+,tegra-audio-max98089(-[a-z0-9]+)+$' + - const: nvidia,tegra-audio-max98089 + + nvidia,audio-routing: + $ref: /schemas/types.yaml#/definitions/non-unique-string-array + description: | + A list of the connections between audio components. + Each entry is a pair of strings, the first being the connection's sink, + the second being the connection's source. Valid names for sources and + sinks are the pins (documented in the binding document), + and the jacks on the board. + minItems: 2 + items: + enum: + # Board Connectors + - "Int Spk" + - "Headphone Jack" + - "Earpiece" + - "Headset Mic" + - "Internal Mic 1" + - "Internal Mic 2" + + # CODEC Pins + - HPL + - HPR + - SPKL + - SPKR + - RECL + - RECR + - INA1 + - INA2 + - INB1 + - INB2 + - MIC1 + - MIC2 + - MICBIAS + +unevaluatedProperties: false + +examples: + - | + #include + #include + sound { + compatible = "lge,tegra-audio-max98089-p895", + "nvidia,tegra-audio-max98089"; + nvidia,model = "LG Optimus Vu MAX98089"; + + nvidia,audio-routing = + "Headphone Jack", "HPL", + "Headphone Jack", "HPR", + "Int Spk", "SPKL", + "Int Spk", "SPKR", + "Earpiece", "RECL", + "Earpiece", "RECR", + "INA1", "Headset Mic", + "MIC1", "MICBIAS", + "MICBIAS", "Internal Mic 1", + "MIC2", "Internal Mic 2"; + + nvidia,i2s-controller = <&tegra_i2s0>; + nvidia,audio-codec = <&codec>; + + clocks = <&tegra_car TEGRA30_CLK_PLL_A>, + <&tegra_car TEGRA30_CLK_PLL_A_OUT0>, + <&tegra_pmc TEGRA_PMC_CLK_OUT_1>; + clock-names = "pll_a", "pll_a_out0", "mclk"; + }; From e3a8459d726532be70fa917e39812570618b857e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:04:53 +0100 Subject: [PATCH 386/778] ALSA: sh: aica: Drop if blocks with always false condition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit snd_aica_remove() is only called after a successful call to snd_aica_probe(). With the latter it's sure that platform_set_drvdata() was called with a non-NULL argument. So platform_get_drvdata() won't return NULL and the check can be dropped. This prepares converting platform driver remove callbacks to return void. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-2-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/sh/aica.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sound/sh/aica.c b/sound/sh/aica.c index 6e9d6bd67369..459c907655d9 100644 --- a/sound/sh/aica.c +++ b/sound/sh/aica.c @@ -543,8 +543,6 @@ static int snd_aica_remove(struct platform_device *devptr) { struct snd_card_aica *dreamcastcard; dreamcastcard = platform_get_drvdata(devptr); - if (unlikely(!dreamcastcard)) - return -ENODEV; snd_card_free(dreamcastcard->card); kfree(dreamcastcard); return 0; From 9ac0d69ee5891c2d0f0425acbb13993ceef9cd12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:04:54 +0100 Subject: [PATCH 387/778] ASoC: amd: acp: rembrandt: Drop if blocks with always false condition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit rembrandt_audio_remove() is only called after a successful call to rembrandt_audio_probe(). With the latter it's sure that dev_get_platdata() returns a non-NULL value and also that ->base is non-NULL. So the corresponding check can be dropped. While touching these lines join declaration and assignment into a single line and make use of dev = &pdev->dev; This prepares converting platform driver remove callbacks to return void. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-3-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/amd/acp/acp-rembrandt.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/sound/soc/amd/acp/acp-rembrandt.c b/sound/soc/amd/acp/acp-rembrandt.c index 2b57c0ca4e99..15cd3f8cc82c 100644 --- a/sound/soc/amd/acp/acp-rembrandt.c +++ b/sound/soc/amd/acp/acp-rembrandt.c @@ -370,13 +370,7 @@ static int rembrandt_audio_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct acp_dev_data *adata = dev_get_drvdata(dev); - struct acp_chip_info *chip; - - chip = dev_get_platdata(&pdev->dev); - if (!chip || !chip->base) { - dev_err(&pdev->dev, "ACP chip data is NULL\n"); - return -ENODEV; - } + struct acp_chip_info *chip = dev_get_platdata(dev); rmb_acp_deinit(chip->base); From 3210e62ab2f63b3ecdacc2c06ca8c8a91d1bf656 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:04:55 +0100 Subject: [PATCH 388/778] ALSA: pxa2xx: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-4-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/arm/pxa2xx-ac97.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c index c162086455ad..2d83ad91f968 100644 --- a/sound/arm/pxa2xx-ac97.c +++ b/sound/arm/pxa2xx-ac97.c @@ -262,7 +262,7 @@ err_dev: return ret; } -static int pxa2xx_ac97_remove(struct platform_device *dev) +static void pxa2xx_ac97_remove(struct platform_device *dev) { struct snd_card *card = platform_get_drvdata(dev); @@ -270,13 +270,11 @@ static int pxa2xx_ac97_remove(struct platform_device *dev) snd_card_free(card); pxa2xx_ac97_hw_remove(dev); } - - return 0; } static struct platform_driver pxa2xx_ac97_driver = { .probe = pxa2xx_ac97_probe, - .remove = pxa2xx_ac97_remove, + .remove_new = pxa2xx_ac97_remove, .driver = { .name = "pxa2xx-ac97", #ifdef CONFIG_PM_SLEEP From 45cc35e81322117dfc27fbfded2e0263018175a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:04:56 +0100 Subject: [PATCH 389/778] ALSA: atmel: ac97: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Reviewed-by: Claudiu Beznea Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-5-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/atmel/ac97c.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/atmel/ac97c.c b/sound/atmel/ac97c.c index 66ecbd4d034e..c8912b8a1dc5 100644 --- a/sound/atmel/ac97c.c +++ b/sound/atmel/ac97c.c @@ -843,7 +843,7 @@ static SIMPLE_DEV_PM_OPS(atmel_ac97c_pm, atmel_ac97c_suspend, atmel_ac97c_resume #define ATMEL_AC97C_PM_OPS NULL #endif -static int atmel_ac97c_remove(struct platform_device *pdev) +static void atmel_ac97c_remove(struct platform_device *pdev) { struct snd_card *card = platform_get_drvdata(pdev); struct atmel_ac97c *chip = get_chip(card); @@ -858,13 +858,11 @@ static int atmel_ac97c_remove(struct platform_device *pdev) free_irq(chip->irq, chip); snd_card_free(card); - - return 0; } static struct platform_driver atmel_ac97c_driver = { .probe = atmel_ac97c_probe, - .remove = atmel_ac97c_remove, + .remove_new = atmel_ac97c_remove, .driver = { .name = "atmel_ac97c", .pm = ATMEL_AC97C_PM_OPS, From 5909d9e5b6c927ea91ace61365049a2f365a7d7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:04:57 +0100 Subject: [PATCH 390/778] ALSA: mts64: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-6-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/drivers/mts64.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/drivers/mts64.c b/sound/drivers/mts64.c index f0d34cf70c3e..5cfd0e99a13f 100644 --- a/sound/drivers/mts64.c +++ b/sound/drivers/mts64.c @@ -999,19 +999,17 @@ __err: return err; } -static int snd_mts64_remove(struct platform_device *pdev) +static void snd_mts64_remove(struct platform_device *pdev) { struct snd_card *card = platform_get_drvdata(pdev); if (card) snd_card_free(card); - - return 0; } static struct platform_driver snd_mts64_driver = { .probe = snd_mts64_probe, - .remove = snd_mts64_remove, + .remove_new = snd_mts64_remove, .driver = { .name = PLATFORM_DRIVER, } From 962bdc9645036b1300c4930e147b5e9a0c587c81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:04:58 +0100 Subject: [PATCH 391/778] ALSA: portman2x4: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-7-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/drivers/portman2x4.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/drivers/portman2x4.c b/sound/drivers/portman2x4.c index 52a656735365..a515c13a489f 100644 --- a/sound/drivers/portman2x4.c +++ b/sound/drivers/portman2x4.c @@ -795,20 +795,18 @@ __err: return err; } -static int snd_portman_remove(struct platform_device *pdev) +static void snd_portman_remove(struct platform_device *pdev) { struct snd_card *card = platform_get_drvdata(pdev); if (card) snd_card_free(card); - - return 0; } static struct platform_driver snd_portman_driver = { .probe = snd_portman_probe, - .remove = snd_portman_remove, + .remove_new = snd_portman_remove, .driver = { .name = PLATFORM_DRIVER, } From b54a2377ec02d52b7bb5dab381e9a45ba0bc617a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:04:59 +0100 Subject: [PATCH 392/778] ALSA: mips/hal2: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-8-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/mips/hal2.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/mips/hal2.c b/sound/mips/hal2.c index 9ac9b58d7c8c..3c26334227bb 100644 --- a/sound/mips/hal2.c +++ b/sound/mips/hal2.c @@ -877,17 +877,16 @@ static int hal2_probe(struct platform_device *pdev) return 0; } -static int hal2_remove(struct platform_device *pdev) +static void hal2_remove(struct platform_device *pdev) { struct snd_card *card = platform_get_drvdata(pdev); snd_card_free(card); - return 0; } static struct platform_driver hal2_driver = { .probe = hal2_probe, - .remove = hal2_remove, + .remove_new = hal2_remove, .driver = { .name = "sgihal2", } From 0505c87c00e8e0adb64c9cfb97ea4882899bea3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:00 +0100 Subject: [PATCH 393/778] ALSA: mips/sgio2audio: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-9-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/mips/sgio2audio.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/mips/sgio2audio.c b/sound/mips/sgio2audio.c index 989f656e2de7..a8551ccdd1bf 100644 --- a/sound/mips/sgio2audio.c +++ b/sound/mips/sgio2audio.c @@ -908,17 +908,16 @@ static int snd_sgio2audio_probe(struct platform_device *pdev) return 0; } -static int snd_sgio2audio_remove(struct platform_device *pdev) +static void snd_sgio2audio_remove(struct platform_device *pdev) { struct snd_card *card = platform_get_drvdata(pdev); snd_card_free(card); - return 0; } static struct platform_driver sgio2audio_driver = { .probe = snd_sgio2audio_probe, - .remove = snd_sgio2audio_remove, + .remove_new = snd_sgio2audio_remove, .driver = { .name = "sgio2audio", } From d8a3441b53682883c16d6997d059e1cc2ac739c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:01 +0100 Subject: [PATCH 394/778] ALSA: hda/tegra: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-10-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/pci/hda/hda_tegra.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c index c2bf86781894..9d0ab043880b 100644 --- a/sound/pci/hda/hda_tegra.c +++ b/sound/pci/hda/hda_tegra.c @@ -580,12 +580,10 @@ static void hda_tegra_probe_work(struct work_struct *work) return; /* no error return from async probe */ } -static int hda_tegra_remove(struct platform_device *pdev) +static void hda_tegra_remove(struct platform_device *pdev) { snd_card_free(dev_get_drvdata(&pdev->dev)); pm_runtime_disable(&pdev->dev); - - return 0; } static void hda_tegra_shutdown(struct platform_device *pdev) @@ -607,7 +605,7 @@ static struct platform_driver tegra_platform_hda = { .of_match_table = hda_tegra_match, }, .probe = hda_tegra_probe, - .remove = hda_tegra_remove, + .remove_new = hda_tegra_remove, .shutdown = hda_tegra_shutdown, }; module_platform_driver(tegra_platform_hda); From c3d8cb1929fc64e8c3d14f27e9540e72aee8ed08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:02 +0100 Subject: [PATCH 395/778] ALSA: ppc/powermac: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-11-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/ppc/powermac.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/ppc/powermac.c b/sound/ppc/powermac.c index db414b61157e..e17af46abddd 100644 --- a/sound/ppc/powermac.c +++ b/sound/ppc/powermac.c @@ -130,10 +130,9 @@ __error: } -static int snd_pmac_remove(struct platform_device *devptr) +static void snd_pmac_remove(struct platform_device *devptr) { snd_card_free(platform_get_drvdata(devptr)); - return 0; } #ifdef CONFIG_PM_SLEEP @@ -161,7 +160,7 @@ static SIMPLE_DEV_PM_OPS(snd_pmac_pm, snd_pmac_driver_suspend, snd_pmac_driver_r static struct platform_driver snd_pmac_driver = { .probe = snd_pmac_probe, - .remove = snd_pmac_remove, + .remove_new = snd_pmac_remove, .driver = { .name = SND_PMAC_DRIVER, .pm = SND_PMAC_PM_OPS, From de0f49b86d12384e8f3ddf7dc651a93c2c0c551b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:03 +0100 Subject: [PATCH 396/778] ALSA: sh: aica: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-12-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/sh/aica.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/sh/aica.c b/sound/sh/aica.c index 459c907655d9..320ac792c7fe 100644 --- a/sound/sh/aica.c +++ b/sound/sh/aica.c @@ -539,13 +539,12 @@ static int add_aicamixer_controls(struct snd_card_aica *dreamcastcard) return 0; } -static int snd_aica_remove(struct platform_device *devptr) +static void snd_aica_remove(struct platform_device *devptr) { struct snd_card_aica *dreamcastcard; dreamcastcard = platform_get_drvdata(devptr); snd_card_free(dreamcastcard->card); kfree(dreamcastcard); - return 0; } static int snd_aica_probe(struct platform_device *devptr) @@ -592,7 +591,7 @@ static int snd_aica_probe(struct platform_device *devptr) static struct platform_driver snd_aica_driver = { .probe = snd_aica_probe, - .remove = snd_aica_remove, + .remove_new = snd_aica_remove, .driver = { .name = SND_AICA_DRIVER, }, From a0f4aa0a9f841693a6487315751c12a2f5773574 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:04 +0100 Subject: [PATCH 397/778] ALSA: sh_dac_audio: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-13-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/sh/sh_dac_audio.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/sh/sh_dac_audio.c b/sound/sh/sh_dac_audio.c index 8ebd972846ac..8cf571955c9d 100644 --- a/sound/sh/sh_dac_audio.c +++ b/sound/sh/sh_dac_audio.c @@ -257,10 +257,9 @@ static int snd_sh_dac_pcm(struct snd_sh_dac *chip, int device) /* driver .remove -- destructor */ -static int snd_sh_dac_remove(struct platform_device *devptr) +static void snd_sh_dac_remove(struct platform_device *devptr) { snd_card_free(platform_get_drvdata(devptr)); - return 0; } /* free -- it has been defined by create */ @@ -403,7 +402,7 @@ probe_error: */ static struct platform_driver sh_dac_driver = { .probe = snd_sh_dac_probe, - .remove = snd_sh_dac_remove, + .remove_new = snd_sh_dac_remove, .driver = { .name = "dac_audio", }, From 711c5b4e36a3345cd0de597a9c5b7f5911abfd51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:05 +0100 Subject: [PATCH 398/778] ASoC: adi: axi-i2s: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-14-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/adi/axi-i2s.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/adi/axi-i2s.c b/sound/soc/adi/axi-i2s.c index b1342351bff4..d5b6f5187f8e 100644 --- a/sound/soc/adi/axi-i2s.c +++ b/sound/soc/adi/axi-i2s.c @@ -274,13 +274,11 @@ err_clk_disable: return ret; } -static int axi_i2s_dev_remove(struct platform_device *pdev) +static void axi_i2s_dev_remove(struct platform_device *pdev) { struct axi_i2s *i2s = platform_get_drvdata(pdev); clk_disable_unprepare(i2s->clk); - - return 0; } static const struct of_device_id axi_i2s_of_match[] = { @@ -295,7 +293,7 @@ static struct platform_driver axi_i2s_driver = { .of_match_table = axi_i2s_of_match, }, .probe = axi_i2s_probe, - .remove = axi_i2s_dev_remove, + .remove_new = axi_i2s_dev_remove, }; module_platform_driver(axi_i2s_driver); From a0d18db09ca5b43e832c913b2375f3f6d124cc3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:06 +0100 Subject: [PATCH 399/778] ASoC: adi: axi-spdif: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-15-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/adi/axi-spdif.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/adi/axi-spdif.c b/sound/soc/adi/axi-spdif.c index 51b968ea21da..e4c99bbc9cdd 100644 --- a/sound/soc/adi/axi-spdif.c +++ b/sound/soc/adi/axi-spdif.c @@ -239,13 +239,11 @@ err_clk_disable: return ret; } -static int axi_spdif_dev_remove(struct platform_device *pdev) +static void axi_spdif_dev_remove(struct platform_device *pdev) { struct axi_spdif *spdif = platform_get_drvdata(pdev); clk_disable_unprepare(spdif->clk); - - return 0; } static const struct of_device_id axi_spdif_of_match[] = { @@ -260,7 +258,7 @@ static struct platform_driver axi_spdif_driver = { .of_match_table = axi_spdif_of_match, }, .probe = axi_spdif_probe, - .remove = axi_spdif_dev_remove, + .remove_new = axi_spdif_dev_remove, }; module_platform_driver(axi_spdif_driver); From 6bbbbc24eb02518e3c5140b80144ec000bfa5bf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:07 +0100 Subject: [PATCH 400/778] ASoC: amd: acp-pcm-dma: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-16-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/amd/acp-pcm-dma.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c index 198358d28ea9..d41df316da58 100644 --- a/sound/soc/amd/acp-pcm-dma.c +++ b/sound/soc/amd/acp-pcm-dma.c @@ -1323,7 +1323,7 @@ static int acp_audio_probe(struct platform_device *pdev) return status; } -static int acp_audio_remove(struct platform_device *pdev) +static void acp_audio_remove(struct platform_device *pdev) { int status; struct audio_drv_data *adata = dev_get_drvdata(&pdev->dev); @@ -1332,8 +1332,6 @@ static int acp_audio_remove(struct platform_device *pdev) if (status) dev_err(&pdev->dev, "ACP Deinit failed status:%d\n", status); pm_runtime_disable(&pdev->dev); - - return 0; } static int acp_pcm_resume(struct device *dev) @@ -1428,7 +1426,7 @@ static const struct dev_pm_ops acp_pm_ops = { static struct platform_driver acp_dma_driver = { .probe = acp_audio_probe, - .remove = acp_audio_remove, + .remove_new = acp_audio_remove, .driver = { .name = DRV_NAME, .pm = &acp_pm_ops, From 37846af6d08ccdca8308e3d4bfec9f6d97e8eec2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:08 +0100 Subject: [PATCH 401/778] ASoC: amd: acp: rembrandt: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-17-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/amd/acp/acp-rembrandt.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/amd/acp/acp-rembrandt.c b/sound/soc/amd/acp/acp-rembrandt.c index 15cd3f8cc82c..5c455cc04113 100644 --- a/sound/soc/amd/acp/acp-rembrandt.c +++ b/sound/soc/amd/acp/acp-rembrandt.c @@ -366,7 +366,7 @@ static int rembrandt_audio_probe(struct platform_device *pdev) return 0; } -static int rembrandt_audio_remove(struct platform_device *pdev) +static void rembrandt_audio_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct acp_dev_data *adata = dev_get_drvdata(dev); @@ -376,12 +376,11 @@ static int rembrandt_audio_remove(struct platform_device *pdev) acp6x_disable_interrupts(adata); acp_platform_unregister(dev); - return 0; } static struct platform_driver rembrandt_driver = { .probe = rembrandt_audio_probe, - .remove = rembrandt_audio_remove, + .remove_new = rembrandt_audio_remove, .driver = { .name = "acp_asoc_rembrandt", }, From da8a3ceb45be5d711f109df5bb12261adb790391 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:09 +0100 Subject: [PATCH 402/778] ASoC: amd: acp: renoir: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-18-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/amd/acp/acp-renoir.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/amd/acp/acp-renoir.c b/sound/soc/amd/acp/acp-renoir.c index 2a89a0d2e601..b3cbc7f19ec5 100644 --- a/sound/soc/amd/acp/acp-renoir.c +++ b/sound/soc/amd/acp/acp-renoir.c @@ -313,7 +313,7 @@ static int renoir_audio_probe(struct platform_device *pdev) return 0; } -static int renoir_audio_remove(struct platform_device *pdev) +static void renoir_audio_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct acp_dev_data *adata = dev_get_drvdata(dev); @@ -329,12 +329,11 @@ static int renoir_audio_remove(struct platform_device *pdev) dev_err(&pdev->dev, "ACP de-init Failed (%pe)\n", ERR_PTR(ret)); acp_platform_unregister(dev); - return 0; } static struct platform_driver renoir_driver = { .probe = renoir_audio_probe, - .remove = renoir_audio_remove, + .remove_new = renoir_audio_remove, .driver = { .name = "acp_asoc_renoir", }, From 5b6bacfa1a7bc353d14189a628d8617a26e8381b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:10 +0100 Subject: [PATCH 403/778] ASoC: amd: ps: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-19-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/amd/ps/ps-pdm-dma.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/amd/ps/ps-pdm-dma.c b/sound/soc/amd/ps/ps-pdm-dma.c index 454dab062e4f..46b91327168f 100644 --- a/sound/soc/amd/ps/ps-pdm-dma.c +++ b/sound/soc/amd/ps/ps-pdm-dma.c @@ -399,10 +399,9 @@ static int acp63_pdm_audio_probe(struct platform_device *pdev) return 0; } -static int acp63_pdm_audio_remove(struct platform_device *pdev) +static void acp63_pdm_audio_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - return 0; } static int __maybe_unused acp63_pdm_resume(struct device *dev) @@ -451,7 +450,7 @@ static const struct dev_pm_ops acp63_pdm_pm_ops = { static struct platform_driver acp63_pdm_dma_driver = { .probe = acp63_pdm_audio_probe, - .remove = acp63_pdm_audio_remove, + .remove_new = acp63_pdm_audio_remove, .driver = { .name = "acp_ps_pdm_dma", .pm = &acp63_pdm_pm_ops, From 599914e146a772f7ceb39912a73565d90336e5e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:11 +0100 Subject: [PATCH 404/778] ASoC: amd: raven: acp3x-pcm-dma: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-20-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/amd/raven/acp3x-pcm-dma.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/amd/raven/acp3x-pcm-dma.c b/sound/soc/amd/raven/acp3x-pcm-dma.c index 6aec11cf0a6a..7362dd15ad30 100644 --- a/sound/soc/amd/raven/acp3x-pcm-dma.c +++ b/sound/soc/amd/raven/acp3x-pcm-dma.c @@ -421,10 +421,9 @@ static int acp3x_audio_probe(struct platform_device *pdev) return 0; } -static int acp3x_audio_remove(struct platform_device *pdev) +static void acp3x_audio_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - return 0; } static int acp3x_resume(struct device *dev) @@ -509,7 +508,7 @@ static const struct dev_pm_ops acp3x_pm_ops = { static struct platform_driver acp3x_dma_driver = { .probe = acp3x_audio_probe, - .remove = acp3x_audio_remove, + .remove_new = acp3x_audio_remove, .driver = { .name = "acp3x_rv_i2s_dma", .pm = &acp3x_pm_ops, From 725d4edfa528f07acfda3e080bf1827e5eea0399 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:12 +0100 Subject: [PATCH 405/778] ASoC: amd: raven: acp3x-pdm-dma: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-21-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/amd/renoir/acp3x-pdm-dma.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/amd/renoir/acp3x-pdm-dma.c b/sound/soc/amd/renoir/acp3x-pdm-dma.c index 0d8b693aecc9..4e299f96521f 100644 --- a/sound/soc/amd/renoir/acp3x-pdm-dma.c +++ b/sound/soc/amd/renoir/acp3x-pdm-dma.c @@ -435,10 +435,9 @@ static int acp_pdm_audio_probe(struct platform_device *pdev) return 0; } -static int acp_pdm_audio_remove(struct platform_device *pdev) +static void acp_pdm_audio_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - return 0; } static int acp_pdm_resume(struct device *dev) @@ -489,7 +488,7 @@ static const struct dev_pm_ops acp_pdm_pm_ops = { static struct platform_driver acp_pdm_dma_driver = { .probe = acp_pdm_audio_probe, - .remove = acp_pdm_audio_remove, + .remove_new = acp_pdm_audio_remove, .driver = { .name = "acp_rn_pdm_dma", .pm = &acp_pdm_pm_ops, From 8564d4f22ce7cbf989af4ba004b44b1878d1b984 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:13 +0100 Subject: [PATCH 406/778] ASoC: amd: vangogh: acp5x-pcm-dma: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-22-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/amd/vangogh/acp5x-pcm-dma.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/amd/vangogh/acp5x-pcm-dma.c b/sound/soc/amd/vangogh/acp5x-pcm-dma.c index d36bb718370f..29901ee4bfe3 100644 --- a/sound/soc/amd/vangogh/acp5x-pcm-dma.c +++ b/sound/soc/amd/vangogh/acp5x-pcm-dma.c @@ -415,10 +415,9 @@ static int acp5x_audio_probe(struct platform_device *pdev) return 0; } -static int acp5x_audio_remove(struct platform_device *pdev) +static void acp5x_audio_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - return 0; } static int __maybe_unused acp5x_pcm_resume(struct device *dev) @@ -500,7 +499,7 @@ static const struct dev_pm_ops acp5x_pm_ops = { static struct platform_driver acp5x_dma_driver = { .probe = acp5x_audio_probe, - .remove = acp5x_audio_remove, + .remove_new = acp5x_audio_remove, .driver = { .name = "acp5x_i2s_dma", .pm = &acp5x_pm_ops, From 0e940c75e307f61fdf049ee7ac21d672f91883f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:14 +0100 Subject: [PATCH 407/778] ASoC: amd: yc: acp6x-pdm-dma: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-23-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/amd/yc/acp6x-pdm-dma.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/amd/yc/acp6x-pdm-dma.c b/sound/soc/amd/yc/acp6x-pdm-dma.c index 294dd7fb43c9..d818eba48546 100644 --- a/sound/soc/amd/yc/acp6x-pdm-dma.c +++ b/sound/soc/amd/yc/acp6x-pdm-dma.c @@ -388,10 +388,9 @@ static int acp6x_pdm_audio_probe(struct platform_device *pdev) return 0; } -static int acp6x_pdm_audio_remove(struct platform_device *pdev) +static void acp6x_pdm_audio_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - return 0; } static int __maybe_unused acp6x_pdm_resume(struct device *dev) @@ -440,7 +439,7 @@ static const struct dev_pm_ops acp6x_pdm_pm_ops = { static struct platform_driver acp6x_pdm_dma_driver = { .probe = acp6x_pdm_audio_probe, - .remove = acp6x_pdm_audio_remove, + .remove_new = acp6x_pdm_audio_remove, .driver = { .name = "acp_yc_pdm_dma", .pm = &acp6x_pdm_pm_ops, From eb5a9cf29f1e5b6290e168d405eef98b42f158a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:15 +0100 Subject: [PATCH 408/778] ASoC: apple: mca: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-24-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/apple/mca.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/apple/mca.c b/sound/soc/apple/mca.c index 64750db9b963..ce77934f3eef 100644 --- a/sound/soc/apple/mca.c +++ b/sound/soc/apple/mca.c @@ -1159,13 +1159,12 @@ err_release: return ret; } -static int apple_mca_remove(struct platform_device *pdev) +static void apple_mca_remove(struct platform_device *pdev) { struct mca_data *mca = platform_get_drvdata(pdev); snd_soc_unregister_component(&pdev->dev); apple_mca_release(mca); - return 0; } static const struct of_device_id apple_mca_of_match[] = { @@ -1180,7 +1179,7 @@ static struct platform_driver apple_mca_driver = { .of_match_table = apple_mca_of_match, }, .probe = apple_mca_probe, - .remove = apple_mca_remove, + .remove_new = apple_mca_remove, }; module_platform_driver(apple_mca_driver); From d0486266a6ba028fe0197c721994f3de5d21550a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:16 +0100 Subject: [PATCH 409/778] ASoC: atmel: atmel-i2s: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Reviewed-by: Claudiu Beznea Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-25-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/atmel/atmel-i2s.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/atmel/atmel-i2s.c b/sound/soc/atmel/atmel-i2s.c index 425d66edbf86..49930baf5e4d 100644 --- a/sound/soc/atmel/atmel-i2s.c +++ b/sound/soc/atmel/atmel-i2s.c @@ -717,13 +717,11 @@ static int atmel_i2s_probe(struct platform_device *pdev) return 0; } -static int atmel_i2s_remove(struct platform_device *pdev) +static void atmel_i2s_remove(struct platform_device *pdev) { struct atmel_i2s_dev *dev = platform_get_drvdata(pdev); clk_disable_unprepare(dev->pclk); - - return 0; } static struct platform_driver atmel_i2s_driver = { @@ -732,7 +730,7 @@ static struct platform_driver atmel_i2s_driver = { .of_match_table = of_match_ptr(atmel_i2s_dt_ids), }, .probe = atmel_i2s_probe, - .remove = atmel_i2s_remove, + .remove_new = atmel_i2s_remove, }; module_platform_driver(atmel_i2s_driver); From 0278eb3275df6121ecbab848269495f9ca7f5c7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:17 +0100 Subject: [PATCH 410/778] ASoC: atmel: atmel_wm8904: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Reviewed-by: Claudiu Beznea Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-26-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/atmel/atmel_wm8904.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/atmel/atmel_wm8904.c b/sound/soc/atmel/atmel_wm8904.c index 9c974c4e187d..00e98136bec2 100644 --- a/sound/soc/atmel/atmel_wm8904.c +++ b/sound/soc/atmel/atmel_wm8904.c @@ -161,7 +161,7 @@ err_set_audio: return ret; } -static int atmel_asoc_wm8904_remove(struct platform_device *pdev) +static void atmel_asoc_wm8904_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct snd_soc_dai_link *dailink = &atmel_asoc_wm8904_dailink; @@ -171,8 +171,6 @@ static int atmel_asoc_wm8904_remove(struct platform_device *pdev) snd_soc_unregister_card(card); atmel_ssc_put_audio(id); - - return 0; } #ifdef CONFIG_OF @@ -190,7 +188,7 @@ static struct platform_driver atmel_asoc_wm8904_driver = { .pm = &snd_soc_pm_ops, }, .probe = atmel_asoc_wm8904_probe, - .remove = atmel_asoc_wm8904_remove, + .remove_new = atmel_asoc_wm8904_remove, }; module_platform_driver(atmel_asoc_wm8904_driver); From b0570709d123ee8bfed32f968d665366fb1a6d2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:18 +0100 Subject: [PATCH 411/778] ASoC: atmel: mchp-i2s-mcc: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Reviewed-by: Claudiu Beznea Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-27-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/atmel/mchp-i2s-mcc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/atmel/mchp-i2s-mcc.c b/sound/soc/atmel/mchp-i2s-mcc.c index 6dfb96c576ff..7c83d48ca1a0 100644 --- a/sound/soc/atmel/mchp-i2s-mcc.c +++ b/sound/soc/atmel/mchp-i2s-mcc.c @@ -1088,13 +1088,11 @@ static int mchp_i2s_mcc_probe(struct platform_device *pdev) return 0; } -static int mchp_i2s_mcc_remove(struct platform_device *pdev) +static void mchp_i2s_mcc_remove(struct platform_device *pdev) { struct mchp_i2s_mcc_dev *dev = platform_get_drvdata(pdev); clk_disable_unprepare(dev->pclk); - - return 0; } static struct platform_driver mchp_i2s_mcc_driver = { @@ -1103,7 +1101,7 @@ static struct platform_driver mchp_i2s_mcc_driver = { .of_match_table = of_match_ptr(mchp_i2s_mcc_dt_ids), }, .probe = mchp_i2s_mcc_probe, - .remove = mchp_i2s_mcc_remove, + .remove_new = mchp_i2s_mcc_remove, }; module_platform_driver(mchp_i2s_mcc_driver); From 86fdd4825459db4ec831d2d41a5e27d45dff2641 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:19 +0100 Subject: [PATCH 412/778] ASoC: atmel: mchp-pdmc: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Reviewed-by: Claudiu Beznea Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-28-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/atmel/mchp-pdmc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/atmel/mchp-pdmc.c b/sound/soc/atmel/mchp-pdmc.c index 81bfa98fd516..da23855a0e40 100644 --- a/sound/soc/atmel/mchp-pdmc.c +++ b/sound/soc/atmel/mchp-pdmc.c @@ -1129,7 +1129,7 @@ pm_runtime_suspend: return ret; } -static int mchp_pdmc_remove(struct platform_device *pdev) +static void mchp_pdmc_remove(struct platform_device *pdev) { struct mchp_pdmc *dd = platform_get_drvdata(pdev); @@ -1137,8 +1137,6 @@ static int mchp_pdmc_remove(struct platform_device *pdev) mchp_pdmc_runtime_suspend(dd->dev); pm_runtime_disable(dd->dev); - - return 0; } static const struct of_device_id mchp_pdmc_of_match[] = { @@ -1163,7 +1161,7 @@ static struct platform_driver mchp_pdmc_driver = { .pm = pm_ptr(&mchp_pdmc_pm_ops), }, .probe = mchp_pdmc_probe, - .remove = mchp_pdmc_remove, + .remove_new = mchp_pdmc_remove, }; module_platform_driver(mchp_pdmc_driver); From 879f2ce0a95701695f2b7648ca81aff543631b1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:20 +0100 Subject: [PATCH 413/778] ASoC: atmel: mchp-spdifrx: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Reviewed-by: Claudiu Beznea Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-29-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/atmel/mchp-spdifrx.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/atmel/mchp-spdifrx.c b/sound/soc/atmel/mchp-spdifrx.c index eb0c0ef4541e..ff6aba143aee 100644 --- a/sound/soc/atmel/mchp-spdifrx.c +++ b/sound/soc/atmel/mchp-spdifrx.c @@ -1183,20 +1183,18 @@ pm_runtime_disable: return err; } -static int mchp_spdifrx_remove(struct platform_device *pdev) +static void mchp_spdifrx_remove(struct platform_device *pdev) { struct mchp_spdifrx_dev *dev = platform_get_drvdata(pdev); pm_runtime_disable(dev->dev); if (!pm_runtime_status_suspended(dev->dev)) mchp_spdifrx_runtime_suspend(dev->dev); - - return 0; } static struct platform_driver mchp_spdifrx_driver = { .probe = mchp_spdifrx_probe, - .remove = mchp_spdifrx_remove, + .remove_new = mchp_spdifrx_remove, .driver = { .name = "mchp_spdifrx", .of_match_table = of_match_ptr(mchp_spdifrx_dt_ids), From c1d51c27d22af56e53e2d739cf533182c2a3fca3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:21 +0100 Subject: [PATCH 414/778] ASoC: atmel: mchp-spdiftx: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Reviewed-by: Claudiu Beznea Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-30-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/atmel/mchp-spdiftx.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/atmel/mchp-spdiftx.c b/sound/soc/atmel/mchp-spdiftx.c index 02a2fa7a42dd..1d3e17119888 100644 --- a/sound/soc/atmel/mchp-spdiftx.c +++ b/sound/soc/atmel/mchp-spdiftx.c @@ -876,7 +876,7 @@ pm_runtime_suspend: return err; } -static int mchp_spdiftx_remove(struct platform_device *pdev) +static void mchp_spdiftx_remove(struct platform_device *pdev) { struct mchp_spdiftx_dev *dev = platform_get_drvdata(pdev); @@ -884,13 +884,11 @@ static int mchp_spdiftx_remove(struct platform_device *pdev) mchp_spdiftx_runtime_suspend(dev->dev); pm_runtime_disable(dev->dev); - - return 0; } static struct platform_driver mchp_spdiftx_driver = { .probe = mchp_spdiftx_probe, - .remove = mchp_spdiftx_remove, + .remove_new = mchp_spdiftx_remove, .driver = { .name = "mchp_spdiftx", .of_match_table = of_match_ptr(mchp_spdiftx_dt_ids), From 2328c4871bd33ce3be5c56a413a79c6b23535217 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:22 +0100 Subject: [PATCH 415/778] ASoC: atmel: mikroe-proto: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Reviewed-by: Claudiu Beznea Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-31-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/atmel/mikroe-proto.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/atmel/mikroe-proto.c b/sound/soc/atmel/mikroe-proto.c index 954460719aa3..30c87c2c1b0b 100644 --- a/sound/soc/atmel/mikroe-proto.c +++ b/sound/soc/atmel/mikroe-proto.c @@ -155,11 +155,9 @@ put_codec_node: return ret; } -static int snd_proto_remove(struct platform_device *pdev) +static void snd_proto_remove(struct platform_device *pdev) { snd_soc_unregister_card(&snd_proto); - - return 0; } static const struct of_device_id snd_proto_of_match[] = { @@ -174,7 +172,7 @@ static struct platform_driver snd_proto_driver = { .of_match_table = snd_proto_of_match, }, .probe = snd_proto_probe, - .remove = snd_proto_remove, + .remove_new = snd_proto_remove, }; module_platform_driver(snd_proto_driver); From a186762b817329d6d55fb94419b534cb06aca3a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:23 +0100 Subject: [PATCH 416/778] ASoC: atmel: sam9g20_wm8731: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Reviewed-by: Claudiu Beznea Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-32-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/atmel/sam9g20_wm8731.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c index 785b9d01d8af..baf38964b491 100644 --- a/sound/soc/atmel/sam9g20_wm8731.c +++ b/sound/soc/atmel/sam9g20_wm8731.c @@ -186,14 +186,12 @@ err: return ret; } -static int at91sam9g20ek_audio_remove(struct platform_device *pdev) +static void at91sam9g20ek_audio_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); snd_soc_unregister_card(card); atmel_ssc_put_audio(0); - - return 0; } #ifdef CONFIG_OF @@ -210,7 +208,7 @@ static struct platform_driver at91sam9g20ek_audio_driver = { .of_match_table = of_match_ptr(at91sam9g20ek_wm8731_dt_ids), }, .probe = at91sam9g20ek_audio_probe, - .remove = at91sam9g20ek_audio_remove, + .remove_new = at91sam9g20ek_audio_remove, }; module_platform_driver(at91sam9g20ek_audio_driver); From c79ddc74c50979665d95382137aec0b4c81a61d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:24 +0100 Subject: [PATCH 417/778] ASoC: atmel: sam9x5_wm8731: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Reviewed-by: Claudiu Beznea Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-33-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/atmel/sam9x5_wm8731.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/atmel/sam9x5_wm8731.c b/sound/soc/atmel/sam9x5_wm8731.c index 99310e40e7a6..cd1d59a90e02 100644 --- a/sound/soc/atmel/sam9x5_wm8731.c +++ b/sound/soc/atmel/sam9x5_wm8731.c @@ -176,14 +176,12 @@ out: return ret; } -static int sam9x5_wm8731_driver_remove(struct platform_device *pdev) +static void sam9x5_wm8731_driver_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct sam9x5_drvdata *priv = card->drvdata; atmel_ssc_put_audio(priv->ssc_id); - - return 0; } static const struct of_device_id sam9x5_wm8731_of_match[] = { @@ -198,7 +196,7 @@ static struct platform_driver sam9x5_wm8731_driver = { .of_match_table = of_match_ptr(sam9x5_wm8731_of_match), }, .probe = sam9x5_wm8731_driver_probe, - .remove = sam9x5_wm8731_driver_remove, + .remove_new = sam9x5_wm8731_driver_remove, }; module_platform_driver(sam9x5_wm8731_driver); From d2679d8529096d7e6af2e3a36086075343b586dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:25 +0100 Subject: [PATCH 418/778] ASoC: atmel: tse850-pcm5142: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Reviewed-by: Claudiu Beznea Acked-by: Peter Rosin Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-34-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/atmel/tse850-pcm5142.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/atmel/tse850-pcm5142.c b/sound/soc/atmel/tse850-pcm5142.c index ef537de7719c..efead272d92b 100644 --- a/sound/soc/atmel/tse850-pcm5142.c +++ b/sound/soc/atmel/tse850-pcm5142.c @@ -412,15 +412,13 @@ err_disable_ana: return ret; } -static int tse850_remove(struct platform_device *pdev) +static void tse850_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct tse850_priv *tse850 = snd_soc_card_get_drvdata(card); snd_soc_unregister_card(card); regulator_disable(tse850->ana); - - return 0; } static const struct of_device_id tse850_dt_ids[] = { @@ -435,7 +433,7 @@ static struct platform_driver tse850_driver = { .of_match_table = of_match_ptr(tse850_dt_ids), }, .probe = tse850_probe, - .remove = tse850_remove, + .remove_new = tse850_remove, }; module_platform_driver(tse850_driver); From a69f0329d49be4b3a46f2e7b4b241f67be73d831 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:26 +0100 Subject: [PATCH 419/778] ASoC: au1x: ac97c: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-35-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/au1x/ac97c.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/au1x/ac97c.c b/sound/soc/au1x/ac97c.c index b18512ca2578..a11d6841afc2 100644 --- a/sound/soc/au1x/ac97c.c +++ b/sound/soc/au1x/ac97c.c @@ -285,7 +285,7 @@ static int au1xac97c_drvprobe(struct platform_device *pdev) return 0; } -static int au1xac97c_drvremove(struct platform_device *pdev) +static void au1xac97c_drvremove(struct platform_device *pdev) { struct au1xpsc_audio_data *ctx = platform_get_drvdata(pdev); @@ -294,8 +294,6 @@ static int au1xac97c_drvremove(struct platform_device *pdev) WR(ctx, AC97_ENABLE, EN_D); /* clock off, disable */ ac97c_workdata = NULL; /* MDEV */ - - return 0; } #ifdef CONFIG_PM @@ -338,7 +336,7 @@ static struct platform_driver au1xac97c_driver = { .pm = AU1XPSCAC97_PMOPS, }, .probe = au1xac97c_drvprobe, - .remove = au1xac97c_drvremove, + .remove_new = au1xac97c_drvremove, }; module_platform_driver(au1xac97c_driver); From ea7f61db28e24d328d0dcf28a07b6251f7beae26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:27 +0100 Subject: [PATCH 420/778] ASoC: au1x: i2sc: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-36-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/au1x/i2sc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/au1x/i2sc.c b/sound/soc/au1x/i2sc.c index b15c8baa9ee4..064406080d72 100644 --- a/sound/soc/au1x/i2sc.c +++ b/sound/soc/au1x/i2sc.c @@ -270,15 +270,13 @@ static int au1xi2s_drvprobe(struct platform_device *pdev) &au1xi2s_dai_driver, 1); } -static int au1xi2s_drvremove(struct platform_device *pdev) +static void au1xi2s_drvremove(struct platform_device *pdev) { struct au1xpsc_audio_data *ctx = platform_get_drvdata(pdev); snd_soc_unregister_component(&pdev->dev); WR(ctx, I2S_ENABLE, EN_D); /* clock off, disable */ - - return 0; } #ifdef CONFIG_PM @@ -315,7 +313,7 @@ static struct platform_driver au1xi2s_driver = { .pm = AU1XI2SC_PMOPS, }, .probe = au1xi2s_drvprobe, - .remove = au1xi2s_drvremove, + .remove_new = au1xi2s_drvremove, }; module_platform_driver(au1xi2s_driver); From c167a43dce9426bb244ca0be50d8e71b94b70532 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:28 +0100 Subject: [PATCH 421/778] ASoC: au1x: psc-ac97: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-37-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/au1x/psc-ac97.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/au1x/psc-ac97.c b/sound/soc/au1x/psc-ac97.c index b536394b9ca0..9fd91aea7d1a 100644 --- a/sound/soc/au1x/psc-ac97.c +++ b/sound/soc/au1x/psc-ac97.c @@ -421,7 +421,7 @@ static int au1xpsc_ac97_drvprobe(struct platform_device *pdev) return 0; } -static int au1xpsc_ac97_drvremove(struct platform_device *pdev) +static void au1xpsc_ac97_drvremove(struct platform_device *pdev) { struct au1xpsc_audio_data *wd = platform_get_drvdata(pdev); @@ -434,8 +434,6 @@ static int au1xpsc_ac97_drvremove(struct platform_device *pdev) wmb(); /* drain writebuffer */ au1xpsc_ac97_workdata = NULL; /* MDEV */ - - return 0; } #ifdef CONFIG_PM @@ -488,7 +486,7 @@ static struct platform_driver au1xpsc_ac97_driver = { .pm = AU1XPSCAC97_PMOPS, }, .probe = au1xpsc_ac97_drvprobe, - .remove = au1xpsc_ac97_drvremove, + .remove_new = au1xpsc_ac97_drvremove, }; module_platform_driver(au1xpsc_ac97_driver); From 045b9b33d5614b83150d33db688c9238bf370521 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:29 +0100 Subject: [PATCH 422/778] ASoC: au1x: psc-i2s: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-38-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/au1x/psc-i2s.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/au1x/psc-i2s.c b/sound/soc/au1x/psc-i2s.c index 79b5ae4e494c..52734dec8247 100644 --- a/sound/soc/au1x/psc-i2s.c +++ b/sound/soc/au1x/psc-i2s.c @@ -344,7 +344,7 @@ static int au1xpsc_i2s_drvprobe(struct platform_device *pdev) &au1xpsc_i2s_component, &wd->dai_drv, 1); } -static int au1xpsc_i2s_drvremove(struct platform_device *pdev) +static void au1xpsc_i2s_drvremove(struct platform_device *pdev) { struct au1xpsc_audio_data *wd = platform_get_drvdata(pdev); @@ -352,8 +352,6 @@ static int au1xpsc_i2s_drvremove(struct platform_device *pdev) wmb(); /* drain writebuffer */ __raw_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd)); wmb(); /* drain writebuffer */ - - return 0; } #ifdef CONFIG_PM @@ -406,7 +404,7 @@ static struct platform_driver au1xpsc_i2s_driver = { .pm = AU1XPSCI2S_PMOPS, }, .probe = au1xpsc_i2s_drvprobe, - .remove = au1xpsc_i2s_drvremove, + .remove_new = au1xpsc_i2s_drvremove, }; module_platform_driver(au1xpsc_i2s_driver); From ee357de34391b4d1a926c7ef736f1723d07feb9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:30 +0100 Subject: [PATCH 423/778] ASoC: bcm: bcm63xx-i2s-whistler: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-39-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/bcm/bcm63xx-i2s-whistler.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/bcm/bcm63xx-i2s-whistler.c b/sound/soc/bcm/bcm63xx-i2s-whistler.c index 2da1384ffe91..18c51dbbc8dc 100644 --- a/sound/soc/bcm/bcm63xx-i2s-whistler.c +++ b/sound/soc/bcm/bcm63xx-i2s-whistler.c @@ -289,10 +289,9 @@ static int bcm63xx_i2s_dev_probe(struct platform_device *pdev) return ret; } -static int bcm63xx_i2s_dev_remove(struct platform_device *pdev) +static void bcm63xx_i2s_dev_remove(struct platform_device *pdev) { bcm63xx_soc_platform_remove(pdev); - return 0; } #ifdef CONFIG_OF @@ -308,7 +307,7 @@ static struct platform_driver bcm63xx_i2s_driver = { .of_match_table = of_match_ptr(snd_soc_bcm_audio_match), }, .probe = bcm63xx_i2s_dev_probe, - .remove = bcm63xx_i2s_dev_remove, + .remove_new = bcm63xx_i2s_dev_remove, }; module_platform_driver(bcm63xx_i2s_driver); From cf004d9a2abaa70f36194274424031dd7c8b71c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:31 +0100 Subject: [PATCH 424/778] ASoC: bcm: cygnus-ssp: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-40-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/bcm/cygnus-ssp.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/bcm/cygnus-ssp.c b/sound/soc/bcm/cygnus-ssp.c index 2a92e33e1fbf..8638bf22ef5c 100644 --- a/sound/soc/bcm/cygnus-ssp.c +++ b/sound/soc/bcm/cygnus-ssp.c @@ -1377,11 +1377,9 @@ static int cygnus_ssp_probe(struct platform_device *pdev) return 0; } -static int cygnus_ssp_remove(struct platform_device *pdev) +static void cygnus_ssp_remove(struct platform_device *pdev) { cygnus_soc_platform_unregister(&pdev->dev); - - return 0; } static const struct of_device_id cygnus_ssp_of_match[] = { @@ -1392,7 +1390,7 @@ MODULE_DEVICE_TABLE(of, cygnus_ssp_of_match); static struct platform_driver cygnus_ssp_driver = { .probe = cygnus_ssp_probe, - .remove = cygnus_ssp_remove, + .remove_new = cygnus_ssp_remove, .driver = { .name = "cygnus-ssp", .of_match_table = cygnus_ssp_of_match, From e711b0fd45d861cb8a19fb5ce0dfc2d21eaefc3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:32 +0100 Subject: [PATCH 425/778] ASoC: cirrus: edb93xx: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-41-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/cirrus/edb93xx.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/cirrus/edb93xx.c b/sound/soc/cirrus/edb93xx.c index 385290202912..f49caab21a25 100644 --- a/sound/soc/cirrus/edb93xx.c +++ b/sound/soc/cirrus/edb93xx.c @@ -93,14 +93,12 @@ static int edb93xx_probe(struct platform_device *pdev) return ret; } -static int edb93xx_remove(struct platform_device *pdev) +static void edb93xx_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); snd_soc_unregister_card(card); ep93xx_i2s_release(); - - return 0; } static struct platform_driver edb93xx_driver = { @@ -108,7 +106,7 @@ static struct platform_driver edb93xx_driver = { .name = "edb93xx-audio", }, .probe = edb93xx_probe, - .remove = edb93xx_remove, + .remove_new = edb93xx_remove, }; module_platform_driver(edb93xx_driver); From 4b1bb8fd7ba5ddcf54cfc9e5568236a734e07f6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:33 +0100 Subject: [PATCH 426/778] ASoC: cirrus: ep93xx-i2s: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Reviewed-by: Alexander Sverdlin Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-42-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/cirrus/ep93xx-i2s.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/cirrus/ep93xx-i2s.c b/sound/soc/cirrus/ep93xx-i2s.c index 70840f27d4a7..9760453d9d79 100644 --- a/sound/soc/cirrus/ep93xx-i2s.c +++ b/sound/soc/cirrus/ep93xx-i2s.c @@ -495,19 +495,18 @@ fail: return err; } -static int ep93xx_i2s_remove(struct platform_device *pdev) +static void ep93xx_i2s_remove(struct platform_device *pdev) { struct ep93xx_i2s_info *info = dev_get_drvdata(&pdev->dev); clk_put(info->lrclk); clk_put(info->sclk); clk_put(info->mclk); - return 0; } static struct platform_driver ep93xx_i2s_driver = { .probe = ep93xx_i2s_probe, - .remove = ep93xx_i2s_remove, + .remove_new = ep93xx_i2s_remove, .driver = { .name = "ep93xx-i2s", }, From f57c2cf8d3bd4023347303f195b0ff991324ee2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:34 +0100 Subject: [PATCH 427/778] ASoC: codecs: cs47l15: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Charles Keepax Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-43-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/codecs/cs47l15.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/cs47l15.c b/sound/soc/codecs/cs47l15.c index 06c4214382e3..a6538dab6639 100644 --- a/sound/soc/codecs/cs47l15.c +++ b/sound/soc/codecs/cs47l15.c @@ -1468,7 +1468,7 @@ error_core: return ret; } -static int cs47l15_remove(struct platform_device *pdev) +static void cs47l15_remove(struct platform_device *pdev) { struct cs47l15 *cs47l15 = platform_get_drvdata(pdev); @@ -1482,8 +1482,6 @@ static int cs47l15_remove(struct platform_device *pdev) madera_free_irq(cs47l15->core.madera, MADERA_IRQ_DSP_IRQ1, cs47l15); madera_free_overheat(&cs47l15->core); madera_core_free(&cs47l15->core); - - return 0; } static struct platform_driver cs47l15_codec_driver = { @@ -1491,7 +1489,7 @@ static struct platform_driver cs47l15_codec_driver = { .name = "cs47l15-codec", }, .probe = &cs47l15_probe, - .remove = &cs47l15_remove, + .remove_new = cs47l15_remove, }; module_platform_driver(cs47l15_codec_driver); From 90fc2cd0c12535462fe7f71db909b6139a012b95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:35 +0100 Subject: [PATCH 428/778] ASoC: codecs: cs47l24: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Charles Keepax Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-44-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/codecs/cs47l24.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/cs47l24.c b/sound/soc/codecs/cs47l24.c index f9a2b865d717..a07b621d463e 100644 --- a/sound/soc/codecs/cs47l24.c +++ b/sound/soc/codecs/cs47l24.c @@ -1319,7 +1319,7 @@ err_dsp_irq: return ret; } -static int cs47l24_remove(struct platform_device *pdev) +static void cs47l24_remove(struct platform_device *pdev) { struct cs47l24_priv *cs47l24 = platform_get_drvdata(pdev); struct arizona *arizona = cs47l24->core.arizona; @@ -1333,8 +1333,6 @@ static int cs47l24_remove(struct platform_device *pdev) arizona_set_irq_wake(arizona, ARIZONA_IRQ_DSP_IRQ1, 0); arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, cs47l24); - - return 0; } static struct platform_driver cs47l24_codec_driver = { @@ -1342,7 +1340,7 @@ static struct platform_driver cs47l24_codec_driver = { .name = "cs47l24-codec", }, .probe = cs47l24_probe, - .remove = cs47l24_remove, + .remove_new = cs47l24_remove, }; module_platform_driver(cs47l24_codec_driver); From b9cc4f89852811c6af6de7653e68ee99cf4e524e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:36 +0100 Subject: [PATCH 429/778] ASoC: codecs: cs47l35: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Charles Keepax Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-45-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/codecs/cs47l35.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/cs47l35.c b/sound/soc/codecs/cs47l35.c index c1032d6c9143..c05c80c16c84 100644 --- a/sound/soc/codecs/cs47l35.c +++ b/sound/soc/codecs/cs47l35.c @@ -1744,7 +1744,7 @@ error_core: return ret; } -static int cs47l35_remove(struct platform_device *pdev) +static void cs47l35_remove(struct platform_device *pdev) { struct cs47l35 *cs47l35 = platform_get_drvdata(pdev); int i; @@ -1758,8 +1758,6 @@ static int cs47l35_remove(struct platform_device *pdev) madera_free_irq(cs47l35->core.madera, MADERA_IRQ_DSP_IRQ1, cs47l35); madera_free_overheat(&cs47l35->core); madera_core_free(&cs47l35->core); - - return 0; } static struct platform_driver cs47l35_codec_driver = { @@ -1767,7 +1765,7 @@ static struct platform_driver cs47l35_codec_driver = { .name = "cs47l35-codec", }, .probe = &cs47l35_probe, - .remove = &cs47l35_remove, + .remove_new = cs47l35_remove, }; module_platform_driver(cs47l35_codec_driver); From f71d98e5c6a979476bcf366b9764573c3fe578cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:37 +0100 Subject: [PATCH 430/778] ASoC: codecs: cs47l85: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Charles Keepax Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-46-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/codecs/cs47l85.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/cs47l85.c b/sound/soc/codecs/cs47l85.c index 215d8211aa59..dd7997a53e70 100644 --- a/sound/soc/codecs/cs47l85.c +++ b/sound/soc/codecs/cs47l85.c @@ -2695,7 +2695,7 @@ error_core: return ret; } -static int cs47l85_remove(struct platform_device *pdev) +static void cs47l85_remove(struct platform_device *pdev) { struct cs47l85 *cs47l85 = platform_get_drvdata(pdev); int i; @@ -2709,8 +2709,6 @@ static int cs47l85_remove(struct platform_device *pdev) madera_free_irq(cs47l85->core.madera, MADERA_IRQ_DSP_IRQ1, cs47l85); madera_free_overheat(&cs47l85->core); madera_core_free(&cs47l85->core); - - return 0; } static struct platform_driver cs47l85_codec_driver = { @@ -2718,7 +2716,7 @@ static struct platform_driver cs47l85_codec_driver = { .name = "cs47l85-codec", }, .probe = &cs47l85_probe, - .remove = &cs47l85_remove, + .remove_new = cs47l85_remove, }; module_platform_driver(cs47l85_codec_driver); From acd39a3729829587128a0d58dbd13c1b23066259 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:38 +0100 Subject: [PATCH 431/778] ASoC: codecs: cs47l90: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Charles Keepax Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-47-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/codecs/cs47l90.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/cs47l90.c b/sound/soc/codecs/cs47l90.c index 1ad6526c7871..cdd5e7e20b5d 100644 --- a/sound/soc/codecs/cs47l90.c +++ b/sound/soc/codecs/cs47l90.c @@ -2618,7 +2618,7 @@ error_core: return ret; } -static int cs47l90_remove(struct platform_device *pdev) +static void cs47l90_remove(struct platform_device *pdev) { struct cs47l90 *cs47l90 = platform_get_drvdata(pdev); int i; @@ -2633,8 +2633,6 @@ static int cs47l90_remove(struct platform_device *pdev) madera_set_irq_wake(cs47l90->core.madera, MADERA_IRQ_DSP_IRQ1, 0); madera_free_irq(cs47l90->core.madera, MADERA_IRQ_DSP_IRQ1, cs47l90); madera_core_free(&cs47l90->core); - - return 0; } static struct platform_driver cs47l90_codec_driver = { @@ -2642,7 +2640,7 @@ static struct platform_driver cs47l90_codec_driver = { .name = "cs47l90-codec", }, .probe = &cs47l90_probe, - .remove = &cs47l90_remove, + .remove_new = cs47l90_remove, }; module_platform_driver(cs47l90_codec_driver); From 516ef43d40e976e16b4eb1c51a7b96e579a297bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:39 +0100 Subject: [PATCH 432/778] ASoC: codecs: cs47l92: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Charles Keepax Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-48-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/codecs/cs47l92.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/cs47l92.c b/sound/soc/codecs/cs47l92.c index fe576d64e089..bc4d311d4778 100644 --- a/sound/soc/codecs/cs47l92.c +++ b/sound/soc/codecs/cs47l92.c @@ -2068,7 +2068,7 @@ error_core: return ret; } -static int cs47l92_remove(struct platform_device *pdev) +static void cs47l92_remove(struct platform_device *pdev) { struct cs47l92 *cs47l92 = platform_get_drvdata(pdev); @@ -2081,8 +2081,6 @@ static int cs47l92_remove(struct platform_device *pdev) madera_free_irq(cs47l92->core.madera, MADERA_IRQ_DSP_IRQ1, cs47l92); madera_core_free(&cs47l92->core); - - return 0; } static struct platform_driver cs47l92_codec_driver = { @@ -2090,7 +2088,7 @@ static struct platform_driver cs47l92_codec_driver = { .name = "cs47l92-codec", }, .probe = &cs47l92_probe, - .remove = &cs47l92_remove, + .remove_new = cs47l92_remove, }; module_platform_driver(cs47l92_codec_driver); From 8756b2ecbd2aa22d6981f6a48a804f0d2cec68a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:40 +0100 Subject: [PATCH 433/778] ASoC: codecs: inno_rk3036: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-49-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/codecs/inno_rk3036.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/inno_rk3036.c b/sound/soc/codecs/inno_rk3036.c index 8222cde6e3b9..11320423c69c 100644 --- a/sound/soc/codecs/inno_rk3036.c +++ b/sound/soc/codecs/inno_rk3036.c @@ -457,13 +457,11 @@ static int rk3036_codec_platform_probe(struct platform_device *pdev) return ret; } -static int rk3036_codec_platform_remove(struct platform_device *pdev) +static void rk3036_codec_platform_remove(struct platform_device *pdev) { struct rk3036_codec_priv *priv = dev_get_drvdata(&pdev->dev); clk_disable_unprepare(priv->pclk); - - return 0; } static const struct of_device_id rk3036_codec_of_match[] __maybe_unused = { @@ -478,7 +476,7 @@ static struct platform_driver rk3036_codec_platform_driver = { .of_match_table = of_match_ptr(rk3036_codec_of_match), }, .probe = rk3036_codec_platform_probe, - .remove = rk3036_codec_platform_remove, + .remove_new = rk3036_codec_platform_remove, }; module_platform_driver(rk3036_codec_platform_driver); From 5b06877205882a92aaf5ced177476697849fd1fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:41 +0100 Subject: [PATCH 434/778] ASoC: codecs: lpass-rx-macro: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-50-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/codecs/lpass-rx-macro.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/lpass-rx-macro.c b/sound/soc/codecs/lpass-rx-macro.c index a73a7d7a1c0a..9e0a4e8a46c3 100644 --- a/sound/soc/codecs/lpass-rx-macro.c +++ b/sound/soc/codecs/lpass-rx-macro.c @@ -3639,7 +3639,7 @@ err: return ret; } -static int rx_macro_remove(struct platform_device *pdev) +static void rx_macro_remove(struct platform_device *pdev) { struct rx_macro *rx = dev_get_drvdata(&pdev->dev); @@ -3650,8 +3650,6 @@ static int rx_macro_remove(struct platform_device *pdev) clk_disable_unprepare(rx->dcodec); lpass_macro_pds_exit(rx->pds); - - return 0; } static const struct of_device_id rx_macro_dt_match[] = { @@ -3723,7 +3721,7 @@ static struct platform_driver rx_macro_driver = { .pm = &rx_macro_pm_ops, }, .probe = rx_macro_probe, - .remove = rx_macro_remove, + .remove_new = rx_macro_remove, }; module_platform_driver(rx_macro_driver); From 10b4f1ed0499bb1cf8335d3956bd82da59314534 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:42 +0100 Subject: [PATCH 435/778] ASoC: codecs: lpass-tx-macro: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-51-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/codecs/lpass-tx-macro.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/lpass-tx-macro.c b/sound/soc/codecs/lpass-tx-macro.c index 473d3cd39554..b044c9c6f89b 100644 --- a/sound/soc/codecs/lpass-tx-macro.c +++ b/sound/soc/codecs/lpass-tx-macro.c @@ -2076,7 +2076,7 @@ err: return ret; } -static int tx_macro_remove(struct platform_device *pdev) +static void tx_macro_remove(struct platform_device *pdev) { struct tx_macro *tx = dev_get_drvdata(&pdev->dev); @@ -2087,8 +2087,6 @@ static int tx_macro_remove(struct platform_device *pdev) clk_disable_unprepare(tx->fsgen); lpass_macro_pds_exit(tx->pds); - - return 0; } static int __maybe_unused tx_macro_runtime_suspend(struct device *dev) @@ -2160,7 +2158,7 @@ static struct platform_driver tx_macro_driver = { .pm = &tx_macro_pm_ops, }, .probe = tx_macro_probe, - .remove = tx_macro_remove, + .remove_new = tx_macro_remove, }; module_platform_driver(tx_macro_driver); From b84affc1b4e2a9cec0720eea729c0f4d0490a0c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:43 +0100 Subject: [PATCH 436/778] ASoC: codecs: lpass-va-macro: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-52-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/codecs/lpass-va-macro.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/lpass-va-macro.c b/sound/soc/codecs/lpass-va-macro.c index fd62817d29a0..74724448da50 100644 --- a/sound/soc/codecs/lpass-va-macro.c +++ b/sound/soc/codecs/lpass-va-macro.c @@ -1575,7 +1575,7 @@ err: return ret; } -static int va_macro_remove(struct platform_device *pdev) +static void va_macro_remove(struct platform_device *pdev) { struct va_macro *va = dev_get_drvdata(&pdev->dev); @@ -1584,8 +1584,6 @@ static int va_macro_remove(struct platform_device *pdev) clk_disable_unprepare(va->macro); lpass_macro_pds_exit(va->pds); - - return 0; } static int __maybe_unused va_macro_runtime_suspend(struct device *dev) @@ -1639,7 +1637,7 @@ static struct platform_driver va_macro_driver = { .pm = &va_macro_pm_ops, }, .probe = va_macro_probe, - .remove = va_macro_remove, + .remove_new = va_macro_remove, }; module_platform_driver(va_macro_driver); From 23a3ef6545a91abc78249e72107a13b43a68d4f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:44 +0100 Subject: [PATCH 437/778] ASoC: codecs: lpass-wsa-macro: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-53-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/codecs/lpass-wsa-macro.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/lpass-wsa-macro.c b/sound/soc/codecs/lpass-wsa-macro.c index ba7480f3831e..728f26d12ab0 100644 --- a/sound/soc/codecs/lpass-wsa-macro.c +++ b/sound/soc/codecs/lpass-wsa-macro.c @@ -2486,7 +2486,7 @@ err: } -static int wsa_macro_remove(struct platform_device *pdev) +static void wsa_macro_remove(struct platform_device *pdev) { struct wsa_macro *wsa = dev_get_drvdata(&pdev->dev); @@ -2495,8 +2495,6 @@ static int wsa_macro_remove(struct platform_device *pdev) clk_disable_unprepare(wsa->mclk); clk_disable_unprepare(wsa->npl); clk_disable_unprepare(wsa->fsgen); - - return 0; } static int __maybe_unused wsa_macro_runtime_suspend(struct device *dev) @@ -2568,7 +2566,7 @@ static struct platform_driver wsa_macro_driver = { .pm = &wsa_macro_pm_ops, }, .probe = wsa_macro_probe, - .remove = wsa_macro_remove, + .remove_new = wsa_macro_remove, }; module_platform_driver(wsa_macro_driver); From 22b27fafbfaf398c1014726b679d5d1e8389d704 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:45 +0100 Subject: [PATCH 438/778] ASoC: codecs: msm8916-wcd-analog: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-54-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/codecs/msm8916-wcd-analog.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/msm8916-wcd-analog.c b/sound/soc/codecs/msm8916-wcd-analog.c index 78e543eb3c83..cec90cf920ff 100644 --- a/sound/soc/codecs/msm8916-wcd-analog.c +++ b/sound/soc/codecs/msm8916-wcd-analog.c @@ -1276,13 +1276,11 @@ err_disable_clk: return ret; } -static int pm8916_wcd_analog_spmi_remove(struct platform_device *pdev) +static void pm8916_wcd_analog_spmi_remove(struct platform_device *pdev) { struct pm8916_wcd_analog_priv *priv = dev_get_drvdata(&pdev->dev); clk_disable_unprepare(priv->mclk); - - return 0; } static const struct of_device_id pm8916_wcd_analog_spmi_match_table[] = { @@ -1298,7 +1296,7 @@ static struct platform_driver pm8916_wcd_analog_spmi_driver = { .of_match_table = pm8916_wcd_analog_spmi_match_table, }, .probe = pm8916_wcd_analog_spmi_probe, - .remove = pm8916_wcd_analog_spmi_remove, + .remove_new = pm8916_wcd_analog_spmi_remove, }; module_platform_driver(pm8916_wcd_analog_spmi_driver); From 004967ba3e8820ef8c48779ae9491cc1c6729b7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:46 +0100 Subject: [PATCH 439/778] ASoC: codecs: msm8916-wcd-digital: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-55-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/codecs/msm8916-wcd-digital.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/msm8916-wcd-digital.c b/sound/soc/codecs/msm8916-wcd-digital.c index d490a0f18675..978c4d056e81 100644 --- a/sound/soc/codecs/msm8916-wcd-digital.c +++ b/sound/soc/codecs/msm8916-wcd-digital.c @@ -1220,14 +1220,12 @@ err_clk: return ret; } -static int msm8916_wcd_digital_remove(struct platform_device *pdev) +static void msm8916_wcd_digital_remove(struct platform_device *pdev) { struct msm8916_wcd_digital_priv *priv = dev_get_drvdata(&pdev->dev); clk_disable_unprepare(priv->mclk); clk_disable_unprepare(priv->ahbclk); - - return 0; } static const struct of_device_id msm8916_wcd_digital_match_table[] = { @@ -1243,7 +1241,7 @@ static struct platform_driver msm8916_wcd_digital_driver = { .of_match_table = msm8916_wcd_digital_match_table, }, .probe = msm8916_wcd_digital_probe, - .remove = msm8916_wcd_digital_remove, + .remove_new = msm8916_wcd_digital_remove, }; module_platform_driver(msm8916_wcd_digital_driver); From 68dadf3eceb2d3d60d3364006a5b72da4050bdcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:47 +0100 Subject: [PATCH 440/778] ASoC: codecs: rk817_codec: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-56-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/codecs/rk817_codec.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/rk817_codec.c b/sound/soc/codecs/rk817_codec.c index 2a5b274bfc0f..d4da98469f8b 100644 --- a/sound/soc/codecs/rk817_codec.c +++ b/sound/soc/codecs/rk817_codec.c @@ -518,13 +518,11 @@ err_: return ret; } -static int rk817_platform_remove(struct platform_device *pdev) +static void rk817_platform_remove(struct platform_device *pdev) { struct rk817_codec_priv *rk817 = platform_get_drvdata(pdev); clk_disable_unprepare(rk817->mclk); - - return 0; } static struct platform_driver rk817_codec_driver = { @@ -532,7 +530,7 @@ static struct platform_driver rk817_codec_driver = { .name = "rk817-codec", }, .probe = rk817_platform_probe, - .remove = rk817_platform_remove, + .remove_new = rk817_platform_remove, }; module_platform_driver(rk817_codec_driver); From 7cd686a59b36860511965882dad1f76df2c25766 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:48 +0100 Subject: [PATCH 441/778] ASoC: codecs: wcd938x: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-57-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/codecs/wcd938x.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/wcd938x.c b/sound/soc/codecs/wcd938x.c index fcac763b04d1..f033f79ed238 100644 --- a/sound/soc/codecs/wcd938x.c +++ b/sound/soc/codecs/wcd938x.c @@ -4529,11 +4529,9 @@ static int wcd938x_probe(struct platform_device *pdev) return 0; } -static int wcd938x_remove(struct platform_device *pdev) +static void wcd938x_remove(struct platform_device *pdev) { component_master_del(&pdev->dev, &wcd938x_comp_ops); - - return 0; } #if defined(CONFIG_OF) @@ -4547,7 +4545,7 @@ MODULE_DEVICE_TABLE(of, wcd938x_dt_match); static struct platform_driver wcd938x_codec_driver = { .probe = wcd938x_probe, - .remove = wcd938x_remove, + .remove_new = wcd938x_remove, .driver = { .name = "wcd938x_codec", .of_match_table = of_match_ptr(wcd938x_dt_match), From 25a4c2697c1cb3ed1f1395f9fee4de4aed8d7503 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:49 +0100 Subject: [PATCH 442/778] ASoC: codecs: wm5102: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Charles Keepax Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-58-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/codecs/wm5102.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index adaf886b0a9d..3bdbdf3770b5 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c @@ -2148,7 +2148,7 @@ err_jack_codec_dev: return ret; } -static int wm5102_remove(struct platform_device *pdev) +static void wm5102_remove(struct platform_device *pdev) { struct wm5102_priv *wm5102 = platform_get_drvdata(pdev); struct arizona *arizona = wm5102->core.arizona; @@ -2163,8 +2163,6 @@ static int wm5102_remove(struct platform_device *pdev) arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, wm5102); arizona_jack_codec_dev_remove(&wm5102->core); - - return 0; } static struct platform_driver wm5102_codec_driver = { @@ -2172,7 +2170,7 @@ static struct platform_driver wm5102_codec_driver = { .name = "wm5102-codec", }, .probe = wm5102_probe, - .remove = wm5102_remove, + .remove_new = wm5102_remove, }; module_platform_driver(wm5102_codec_driver); From d1535277bf69de5e72e76a2fef15ff6ccd0ea1f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:50 +0100 Subject: [PATCH 443/778] ASoC: codecs: wm5110: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Charles Keepax Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-59-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/codecs/wm5110.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index e0b971620d0f..ad670300de8d 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c @@ -2506,7 +2506,7 @@ err_jack_codec_dev: return ret; } -static int wm5110_remove(struct platform_device *pdev) +static void wm5110_remove(struct platform_device *pdev) { struct wm5110_priv *wm5110 = platform_get_drvdata(pdev); struct arizona *arizona = wm5110->core.arizona; @@ -2523,8 +2523,6 @@ static int wm5110_remove(struct platform_device *pdev) arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, wm5110); arizona_jack_codec_dev_remove(&wm5110->core); - - return 0; } static struct platform_driver wm5110_codec_driver = { @@ -2532,7 +2530,7 @@ static struct platform_driver wm5110_codec_driver = { .name = "wm5110-codec", }, .probe = wm5110_probe, - .remove = wm5110_remove, + .remove_new = wm5110_remove, }; module_platform_driver(wm5110_codec_driver); From 63d3f580d95901e5b250105f3637b8e865219864 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:51 +0100 Subject: [PATCH 444/778] ASoC: codecs: wm8994: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Charles Keepax Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-60-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/codecs/wm8994.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 8fe9a75d1235..bca3ebe0dac4 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -4657,11 +4657,9 @@ static int wm8994_probe(struct platform_device *pdev) return ret; } -static int wm8994_remove(struct platform_device *pdev) +static void wm8994_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -4701,7 +4699,7 @@ static struct platform_driver wm8994_codec_driver = { .pm = &wm8994_pm_ops, }, .probe = wm8994_probe, - .remove = wm8994_remove, + .remove_new = wm8994_remove, }; module_platform_driver(wm8994_codec_driver); From e1df73df807721ce0f7be9c58ef6c751112f2aab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:52 +0100 Subject: [PATCH 445/778] ASoC: codecs: wm8997: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Charles Keepax Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-61-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/codecs/wm8997.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/wm8997.c b/sound/soc/codecs/wm8997.c index c0207e9a7d53..87442840f0af 100644 --- a/sound/soc/codecs/wm8997.c +++ b/sound/soc/codecs/wm8997.c @@ -1193,7 +1193,7 @@ err_jack_codec_dev: return ret; } -static int wm8997_remove(struct platform_device *pdev) +static void wm8997_remove(struct platform_device *pdev) { struct wm8997_priv *wm8997 = platform_get_drvdata(pdev); struct arizona *arizona = wm8997->core.arizona; @@ -1203,8 +1203,6 @@ static int wm8997_remove(struct platform_device *pdev) arizona_free_spk_irqs(arizona); arizona_jack_codec_dev_remove(&wm8997->core); - - return 0; } static struct platform_driver wm8997_codec_driver = { @@ -1212,7 +1210,7 @@ static struct platform_driver wm8997_codec_driver = { .name = "wm8997-codec", }, .probe = wm8997_probe, - .remove = wm8997_remove, + .remove_new = wm8997_remove, }; module_platform_driver(wm8997_codec_driver); From 52675c1e9bfaaecc9999b39caf1305a2688df6dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:53 +0100 Subject: [PATCH 446/778] ASoC: codecs: wm8998: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Charles Keepax Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-62-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/codecs/wm8998.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/wm8998.c b/sound/soc/codecs/wm8998.c index 79fc6bbaa3aa..3c2c4d12c08e 100644 --- a/sound/soc/codecs/wm8998.c +++ b/sound/soc/codecs/wm8998.c @@ -1409,7 +1409,7 @@ err_pm_disable: return ret; } -static int wm8998_remove(struct platform_device *pdev) +static void wm8998_remove(struct platform_device *pdev) { struct wm8998_priv *wm8998 = platform_get_drvdata(pdev); struct arizona *arizona = wm8998->core.arizona; @@ -1419,8 +1419,6 @@ static int wm8998_remove(struct platform_device *pdev) arizona_free_spk_irqs(arizona); arizona_jack_codec_dev_remove(&wm8998->core); - - return 0; } static struct platform_driver wm8998_codec_driver = { @@ -1428,7 +1426,7 @@ static struct platform_driver wm8998_codec_driver = { .name = "wm8998-codec", }, .probe = wm8998_probe, - .remove = wm8998_remove, + .remove_new = wm8998_remove, }; module_platform_driver(wm8998_codec_driver); From db3a56667e84503a7908a307cf74bf7f4e3f4fa5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:54 +0100 Subject: [PATCH 447/778] ASoC: dwc: dwc-i2s: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-63-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/dwc/dwc-i2s.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/dwc/dwc-i2s.c b/sound/soc/dwc/dwc-i2s.c index 7f7dd07c63b2..acdf98b2ee9c 100644 --- a/sound/soc/dwc/dwc-i2s.c +++ b/sound/soc/dwc/dwc-i2s.c @@ -730,7 +730,7 @@ err_clk_disable: return ret; } -static int dw_i2s_remove(struct platform_device *pdev) +static void dw_i2s_remove(struct platform_device *pdev) { struct dw_i2s_dev *dev = dev_get_drvdata(&pdev->dev); @@ -738,7 +738,6 @@ static int dw_i2s_remove(struct platform_device *pdev) clk_disable_unprepare(dev->clk); pm_runtime_disable(&pdev->dev); - return 0; } #ifdef CONFIG_OF @@ -756,7 +755,7 @@ static const struct dev_pm_ops dwc_pm_ops = { static struct platform_driver dw_i2s_driver = { .probe = dw_i2s_probe, - .remove = dw_i2s_remove, + .remove_new = dw_i2s_remove, .driver = { .name = "designware-i2s", .of_match_table = of_match_ptr(dw_i2s_of_match), From 01192ad23b06216c9abdca07ef9e7add33c69a72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:55 +0100 Subject: [PATCH 448/778] ASoC: fsl: eukrea-tlv320: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-64-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/fsl/eukrea-tlv320.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/fsl/eukrea-tlv320.c b/sound/soc/fsl/eukrea-tlv320.c index 9af4c4a35eb1..e65a85feba78 100644 --- a/sound/soc/fsl/eukrea-tlv320.c +++ b/sound/soc/fsl/eukrea-tlv320.c @@ -205,11 +205,9 @@ err: return ret; } -static int eukrea_tlv320_remove(struct platform_device *pdev) +static void eukrea_tlv320_remove(struct platform_device *pdev) { snd_soc_unregister_card(&eukrea_tlv320); - - return 0; } static const struct of_device_id imx_tlv320_dt_ids[] = { @@ -224,7 +222,7 @@ static struct platform_driver eukrea_tlv320_driver = { .of_match_table = imx_tlv320_dt_ids, }, .probe = eukrea_tlv320_probe, - .remove = eukrea_tlv320_remove, + .remove_new = eukrea_tlv320_remove, }; module_platform_driver(eukrea_tlv320_driver); From 7a2d15b9322b4233cfe6bd7f747ec89672d17889 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:56 +0100 Subject: [PATCH 449/778] ASoC: fsl: fsl_asrc: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-65-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_asrc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c index e16e7b3fa96c..adb8a59de2bd 100644 --- a/sound/soc/fsl/fsl_asrc.c +++ b/sound/soc/fsl/fsl_asrc.c @@ -1252,13 +1252,11 @@ err_pm_disable: return ret; } -static int fsl_asrc_remove(struct platform_device *pdev) +static void fsl_asrc_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) fsl_asrc_runtime_suspend(&pdev->dev); - - return 0; } static int fsl_asrc_runtime_resume(struct device *dev) @@ -1394,7 +1392,7 @@ MODULE_DEVICE_TABLE(of, fsl_asrc_ids); static struct platform_driver fsl_asrc_driver = { .probe = fsl_asrc_probe, - .remove = fsl_asrc_remove, + .remove_new = fsl_asrc_remove, .driver = { .name = "fsl-asrc", .of_match_table = fsl_asrc_ids, From 2a41b19201c8f22e10eebc6fc016cef5e6915ffb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:57 +0100 Subject: [PATCH 450/778] ASoC: fsl: fsl_aud2htx: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-66-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_aud2htx.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/fsl/fsl_aud2htx.c b/sound/soc/fsl/fsl_aud2htx.c index 1e421d9a03fb..46b0c5dcc4a5 100644 --- a/sound/soc/fsl/fsl_aud2htx.c +++ b/sound/soc/fsl/fsl_aud2htx.c @@ -257,11 +257,9 @@ static int fsl_aud2htx_probe(struct platform_device *pdev) return ret; } -static int fsl_aud2htx_remove(struct platform_device *pdev) +static void fsl_aud2htx_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - - return 0; } static int __maybe_unused fsl_aud2htx_runtime_suspend(struct device *dev) @@ -300,7 +298,7 @@ static const struct dev_pm_ops fsl_aud2htx_pm_ops = { static struct platform_driver fsl_aud2htx_driver = { .probe = fsl_aud2htx_probe, - .remove = fsl_aud2htx_remove, + .remove_new = fsl_aud2htx_remove, .driver = { .name = "fsl-aud2htx", .pm = &fsl_aud2htx_pm_ops, From fd24dfc35b49ee029ac8d3cc45cd4420ae1b455b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:58 +0100 Subject: [PATCH 451/778] ASoC: fsl: fsl_audmix: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-67-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_audmix.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/fsl/fsl_audmix.c b/sound/soc/fsl/fsl_audmix.c index 672148dd4b23..0ab2c1962117 100644 --- a/sound/soc/fsl/fsl_audmix.c +++ b/sound/soc/fsl/fsl_audmix.c @@ -506,7 +506,7 @@ err_disable_pm: return ret; } -static int fsl_audmix_remove(struct platform_device *pdev) +static void fsl_audmix_remove(struct platform_device *pdev) { struct fsl_audmix *priv = dev_get_drvdata(&pdev->dev); @@ -514,8 +514,6 @@ static int fsl_audmix_remove(struct platform_device *pdev) if (priv->pdev) platform_device_unregister(priv->pdev); - - return 0; } #ifdef CONFIG_PM @@ -558,7 +556,7 @@ static const struct dev_pm_ops fsl_audmix_pm = { static struct platform_driver fsl_audmix_driver = { .probe = fsl_audmix_probe, - .remove = fsl_audmix_remove, + .remove_new = fsl_audmix_remove, .driver = { .name = "fsl-audmix", .of_match_table = fsl_audmix_ids, From 2c8a5de60d210093dd4b98fb4d8cdbd637450bac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:05:59 +0100 Subject: [PATCH 452/778] ASoC: fsl: fsl_dma: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-68-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_dma.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c index 808fb61a7a0f..963f9774c883 100644 --- a/sound/soc/fsl/fsl_dma.c +++ b/sound/soc/fsl/fsl_dma.c @@ -890,15 +890,13 @@ static int fsl_soc_dma_probe(struct platform_device *pdev) return 0; } -static int fsl_soc_dma_remove(struct platform_device *pdev) +static void fsl_soc_dma_remove(struct platform_device *pdev) { struct dma_object *dma = dev_get_drvdata(&pdev->dev); iounmap(dma->channel); irq_dispose_mapping(dma->irq); kfree(dma); - - return 0; } static const struct of_device_id fsl_soc_dma_ids[] = { @@ -913,7 +911,7 @@ static struct platform_driver fsl_soc_dma_driver = { .of_match_table = fsl_soc_dma_ids, }, .probe = fsl_soc_dma_probe, - .remove = fsl_soc_dma_remove, + .remove_new = fsl_soc_dma_remove, }; module_platform_driver(fsl_soc_dma_driver); From 0c880ae7c01402e09a62d34356da3b03933c6603 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:00 +0100 Subject: [PATCH 453/778] ASoC: fsl: fsl_easrc: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-69-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_easrc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/fsl/fsl_easrc.c b/sound/soc/fsl/fsl_easrc.c index 3153d19136b2..670cbdb361b6 100644 --- a/sound/soc/fsl/fsl_easrc.c +++ b/sound/soc/fsl/fsl_easrc.c @@ -1979,11 +1979,9 @@ static int fsl_easrc_probe(struct platform_device *pdev) return 0; } -static int fsl_easrc_remove(struct platform_device *pdev) +static void fsl_easrc_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - - return 0; } static __maybe_unused int fsl_easrc_runtime_suspend(struct device *dev) @@ -2093,7 +2091,7 @@ static const struct dev_pm_ops fsl_easrc_pm_ops = { static struct platform_driver fsl_easrc_driver = { .probe = fsl_easrc_probe, - .remove = fsl_easrc_remove, + .remove_new = fsl_easrc_remove, .driver = { .name = "fsl-easrc", .pm = &fsl_easrc_pm_ops, From 0c85719ee2c6320ab2fdea7852a1008ac51a05f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:01 +0100 Subject: [PATCH 454/778] ASoC: fsl: fsl_esai: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-70-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_esai.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c index 17fefd27ec90..936f0cd4b06d 100644 --- a/sound/soc/fsl/fsl_esai.c +++ b/sound/soc/fsl/fsl_esai.c @@ -1101,7 +1101,7 @@ err_pm_disable: return ret; } -static int fsl_esai_remove(struct platform_device *pdev) +static void fsl_esai_remove(struct platform_device *pdev) { struct fsl_esai *esai_priv = platform_get_drvdata(pdev); @@ -1110,8 +1110,6 @@ static int fsl_esai_remove(struct platform_device *pdev) fsl_esai_runtime_suspend(&pdev->dev); cancel_work_sync(&esai_priv->work); - - return 0; } static const struct of_device_id fsl_esai_dt_ids[] = { @@ -1200,7 +1198,7 @@ static const struct dev_pm_ops fsl_esai_pm_ops = { static struct platform_driver fsl_esai_driver = { .probe = fsl_esai_probe, - .remove = fsl_esai_remove, + .remove_new = fsl_esai_remove, .driver = { .name = "fsl-esai-dai", .pm = &fsl_esai_pm_ops, From 4ff299cb33ae40367d38e66c5cba15242cbbe33c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:02 +0100 Subject: [PATCH 455/778] ASoC: fsl: fsl_mqs: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-71-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_mqs.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/fsl/fsl_mqs.c b/sound/soc/fsl/fsl_mqs.c index 4922e6795b73..3fb3d3e4d09a 100644 --- a/sound/soc/fsl/fsl_mqs.c +++ b/sound/soc/fsl/fsl_mqs.c @@ -261,10 +261,9 @@ err_free_gpr_np: return ret; } -static int fsl_mqs_remove(struct platform_device *pdev) +static void fsl_mqs_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - return 0; } #ifdef CONFIG_PM @@ -360,7 +359,7 @@ MODULE_DEVICE_TABLE(of, fsl_mqs_dt_ids); static struct platform_driver fsl_mqs_driver = { .probe = fsl_mqs_probe, - .remove = fsl_mqs_remove, + .remove_new = fsl_mqs_remove, .driver = { .name = "fsl-mqs", .of_match_table = fsl_mqs_dt_ids, From 126ce4328be219c12458e308feade8168dff588d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:03 +0100 Subject: [PATCH 456/778] ASoC: fsl: fsl_rpmsg: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-72-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_rpmsg.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/fsl/fsl_rpmsg.c b/sound/soc/fsl/fsl_rpmsg.c index 46c7868a2653..15b48b5ea856 100644 --- a/sound/soc/fsl/fsl_rpmsg.c +++ b/sound/soc/fsl/fsl_rpmsg.c @@ -247,14 +247,12 @@ static int fsl_rpmsg_probe(struct platform_device *pdev) return 0; } -static int fsl_rpmsg_remove(struct platform_device *pdev) +static void fsl_rpmsg_remove(struct platform_device *pdev) { struct fsl_rpmsg *rpmsg = platform_get_drvdata(pdev); if (rpmsg->card_pdev) platform_device_unregister(rpmsg->card_pdev); - - return 0; } #ifdef CONFIG_PM @@ -302,7 +300,7 @@ static const struct dev_pm_ops fsl_rpmsg_pm_ops = { static struct platform_driver fsl_rpmsg_driver = { .probe = fsl_rpmsg_probe, - .remove = fsl_rpmsg_remove, + .remove_new = fsl_rpmsg_remove, .driver = { .name = "fsl_rpmsg", .pm = &fsl_rpmsg_pm_ops, From 78c2698dd557e2c69d1ecfc2f458eeaff0adfed3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:04 +0100 Subject: [PATCH 457/778] ASoC: fsl: fsl_sai: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-73-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_sai.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index 4e6b75f1ddd0..07d13dca852e 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -1489,13 +1489,11 @@ err_pm_disable: return ret; } -static int fsl_sai_remove(struct platform_device *pdev) +static void fsl_sai_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) fsl_sai_runtime_suspend(&pdev->dev); - - return 0; } static const struct fsl_sai_soc_data fsl_sai_vf610_data = { @@ -1696,7 +1694,7 @@ static const struct dev_pm_ops fsl_sai_pm_ops = { static struct platform_driver fsl_sai_driver = { .probe = fsl_sai_probe, - .remove = fsl_sai_remove, + .remove_new = fsl_sai_remove, .driver = { .name = "fsl-sai", .pm = &fsl_sai_pm_ops, From c8c0bd47cf83c48d422b68b3cfb808f569d7453d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:05 +0100 Subject: [PATCH 458/778] ASoC: fsl: fsl_spdif: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-74-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_spdif.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c index 275aba8e0c46..015c3708aa04 100644 --- a/sound/soc/fsl/fsl_spdif.c +++ b/sound/soc/fsl/fsl_spdif.c @@ -1659,11 +1659,9 @@ err_pm_disable: return ret; } -static int fsl_spdif_remove(struct platform_device *pdev) +static void fsl_spdif_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - - return 0; } #ifdef CONFIG_PM @@ -1765,7 +1763,7 @@ static struct platform_driver fsl_spdif_driver = { .pm = &fsl_spdif_pm, }, .probe = fsl_spdif_probe, - .remove = fsl_spdif_remove, + .remove_new = fsl_spdif_remove, }; module_platform_driver(fsl_spdif_driver); From 2d1c82c460f2602282749825d5599688a46363ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:06 +0100 Subject: [PATCH 459/778] ASoC: fsl: fsl_ssi: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-75-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_ssi.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 6af00b62a60f..53ed3701b0b0 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -1671,7 +1671,7 @@ error_ac97_ops: return ret; } -static int fsl_ssi_remove(struct platform_device *pdev) +static void fsl_ssi_remove(struct platform_device *pdev) { struct fsl_ssi *ssi = dev_get_drvdata(&pdev->dev); @@ -1690,8 +1690,6 @@ static int fsl_ssi_remove(struct platform_device *pdev) snd_soc_set_ac97_ops(NULL); mutex_destroy(&ssi->ac97_reg_lock); } - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -1737,7 +1735,7 @@ static struct platform_driver fsl_ssi_driver = { .pm = &fsl_ssi_pm, }, .probe = fsl_ssi_probe, - .remove = fsl_ssi_remove, + .remove_new = fsl_ssi_remove, }; module_platform_driver(fsl_ssi_driver); From aefe902ea8d538a86d9eb7128d5878e0b838241f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:07 +0100 Subject: [PATCH 460/778] ASoC: fsl: fsl_xcvr: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-76-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_xcvr.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/fsl/fsl_xcvr.c b/sound/soc/fsl/fsl_xcvr.c index 2a78243df752..318fe77683f5 100644 --- a/sound/soc/fsl/fsl_xcvr.c +++ b/sound/soc/fsl/fsl_xcvr.c @@ -1339,10 +1339,9 @@ static int fsl_xcvr_probe(struct platform_device *pdev) return ret; } -static int fsl_xcvr_remove(struct platform_device *pdev) +static void fsl_xcvr_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - return 0; } static __maybe_unused int fsl_xcvr_runtime_suspend(struct device *dev) @@ -1478,7 +1477,7 @@ static struct platform_driver fsl_xcvr_driver = { .pm = &fsl_xcvr_pm_ops, .of_match_table = fsl_xcvr_dt_ids, }, - .remove = fsl_xcvr_remove, + .remove_new = fsl_xcvr_remove, }; module_platform_driver(fsl_xcvr_driver); From 51451f46d1f3134235f3a332f919e2b7af87fd49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:08 +0100 Subject: [PATCH 461/778] ASoC: fsl: imx-audmux: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-77-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/fsl/imx-audmux.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/fsl/imx-audmux.c b/sound/soc/fsl/imx-audmux.c index 582f1e2431ee..be003a117b39 100644 --- a/sound/soc/fsl/imx-audmux.c +++ b/sound/soc/fsl/imx-audmux.c @@ -315,12 +315,10 @@ static int imx_audmux_probe(struct platform_device *pdev) return 0; } -static int imx_audmux_remove(struct platform_device *pdev) +static void imx_audmux_remove(struct platform_device *pdev) { if (audmux_type == IMX31_AUDMUX) audmux_debugfs_remove(); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -359,7 +357,7 @@ static const struct dev_pm_ops imx_audmux_pm = { static struct platform_driver imx_audmux_driver = { .probe = imx_audmux_probe, - .remove = imx_audmux_remove, + .remove_new = imx_audmux_remove, .driver = { .name = DRIVER_NAME, .pm = &imx_audmux_pm, From a064945698110e2aa283026bd4f31e3c34e00e93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:09 +0100 Subject: [PATCH 462/778] ASoC: fsl: imx-pcm-rpmsg: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-78-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/fsl/imx-pcm-rpmsg.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/fsl/imx-pcm-rpmsg.c b/sound/soc/fsl/imx-pcm-rpmsg.c index 6614b3447649..765dad607bf6 100644 --- a/sound/soc/fsl/imx-pcm-rpmsg.c +++ b/sound/soc/fsl/imx-pcm-rpmsg.c @@ -743,14 +743,12 @@ fail: return ret; } -static int imx_rpmsg_pcm_remove(struct platform_device *pdev) +static void imx_rpmsg_pcm_remove(struct platform_device *pdev) { struct rpmsg_info *info = platform_get_drvdata(pdev); if (info->rpmsg_wq) destroy_workqueue(info->rpmsg_wq); - - return 0; } #ifdef CONFIG_PM @@ -821,7 +819,7 @@ static const struct dev_pm_ops imx_rpmsg_pcm_pm_ops = { static struct platform_driver imx_pcm_rpmsg_driver = { .probe = imx_rpmsg_pcm_probe, - .remove = imx_rpmsg_pcm_remove, + .remove_new = imx_rpmsg_pcm_remove, .driver = { .name = IMX_PCM_DRV_NAME, .pm = &imx_rpmsg_pcm_pm_ops, From b8a148daa7969839c6bfbdd223dffa476dee4325 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:10 +0100 Subject: [PATCH 463/778] ASoC: fsl: imx-sgtl5000: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-79-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/fsl/imx-sgtl5000.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/fsl/imx-sgtl5000.c b/sound/soc/fsl/imx-sgtl5000.c index 580a0d963f0e..26c22783927b 100644 --- a/sound/soc/fsl/imx-sgtl5000.c +++ b/sound/soc/fsl/imx-sgtl5000.c @@ -193,14 +193,12 @@ fail: return ret; } -static int imx_sgtl5000_remove(struct platform_device *pdev) +static void imx_sgtl5000_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct imx_sgtl5000_data *data = snd_soc_card_get_drvdata(card); clk_put(data->codec_clk); - - return 0; } static const struct of_device_id imx_sgtl5000_dt_ids[] = { @@ -216,7 +214,7 @@ static struct platform_driver imx_sgtl5000_driver = { .of_match_table = imx_sgtl5000_dt_ids, }, .probe = imx_sgtl5000_probe, - .remove = imx_sgtl5000_remove, + .remove_new = imx_sgtl5000_remove, }; module_platform_driver(imx_sgtl5000_driver); From 5ccf4bee004073af36e454c3f263a03d7a6ac72b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:11 +0100 Subject: [PATCH 464/778] ASoC: fsl: mpc5200_psc_ac97: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-80-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/fsl/mpc5200_psc_ac97.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/fsl/mpc5200_psc_ac97.c b/sound/soc/fsl/mpc5200_psc_ac97.c index a082ae636a4f..40a4a2667394 100644 --- a/sound/soc/fsl/mpc5200_psc_ac97.c +++ b/sound/soc/fsl/mpc5200_psc_ac97.c @@ -311,12 +311,11 @@ static int psc_ac97_of_probe(struct platform_device *op) return 0; } -static int psc_ac97_of_remove(struct platform_device *op) +static void psc_ac97_of_remove(struct platform_device *op) { mpc5200_audio_dma_destroy(op); snd_soc_unregister_component(&op->dev); snd_soc_set_ac97_ops(NULL); - return 0; } /* Match table for of_platform binding */ @@ -329,7 +328,7 @@ MODULE_DEVICE_TABLE(of, psc_ac97_match); static struct platform_driver psc_ac97_driver = { .probe = psc_ac97_of_probe, - .remove = psc_ac97_of_remove, + .remove_new = psc_ac97_of_remove, .driver = { .name = "mpc5200-psc-ac97", .of_match_table = psc_ac97_match, From 295dc79cfc05959f252546e34f0bddcc52aa7d8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:12 +0100 Subject: [PATCH 465/778] ASoC: fsl: mpc5200_psc_i2s: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-81-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/fsl/mpc5200_psc_i2s.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/fsl/mpc5200_psc_i2s.c b/sound/soc/fsl/mpc5200_psc_i2s.c index 73f3e61f208a..413df413b5eb 100644 --- a/sound/soc/fsl/mpc5200_psc_i2s.c +++ b/sound/soc/fsl/mpc5200_psc_i2s.c @@ -210,11 +210,10 @@ static int psc_i2s_of_probe(struct platform_device *op) } -static int psc_i2s_of_remove(struct platform_device *op) +static void psc_i2s_of_remove(struct platform_device *op) { mpc5200_audio_dma_destroy(op); snd_soc_unregister_component(&op->dev); - return 0; } /* Match table for of_platform binding */ @@ -227,7 +226,7 @@ MODULE_DEVICE_TABLE(of, psc_i2s_match); static struct platform_driver psc_i2s_driver = { .probe = psc_i2s_of_probe, - .remove = psc_i2s_of_remove, + .remove_new = psc_i2s_of_remove, .driver = { .name = "mpc5200-psc-i2s", .of_match_table = psc_i2s_match, From 9c4d8f48ac4f38dbb23a546b8a5489d37f04f926 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:13 +0100 Subject: [PATCH 466/778] ASoC: fsl: mpc8610_hpcd: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-82-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/fsl/mpc8610_hpcd.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c index e71a992fbf93..ea2076ea8afe 100644 --- a/sound/soc/fsl/mpc8610_hpcd.c +++ b/sound/soc/fsl/mpc8610_hpcd.c @@ -387,7 +387,7 @@ error_alloc: * * This function is called when the platform device is removed. */ -static int mpc8610_hpcd_remove(struct platform_device *pdev) +static void mpc8610_hpcd_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct mpc8610_hpcd_data *machine_data = @@ -395,13 +395,11 @@ static int mpc8610_hpcd_remove(struct platform_device *pdev) snd_soc_unregister_card(card); kfree(machine_data); - - return 0; } static struct platform_driver mpc8610_hpcd_driver = { .probe = mpc8610_hpcd_probe, - .remove = mpc8610_hpcd_remove, + .remove_new = mpc8610_hpcd_remove, .driver = { /* The name must match 'compatible' property in the device tree, * in lowercase letters. From 6a442e72940039bd69081320acdd4d7666f30a36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:14 +0100 Subject: [PATCH 467/778] ASoC: fsl: p1022_ds: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-83-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/fsl/p1022_ds.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/fsl/p1022_ds.c b/sound/soc/fsl/p1022_ds.c index b45742931b0d..0b1418abeb9c 100644 --- a/sound/soc/fsl/p1022_ds.c +++ b/sound/soc/fsl/p1022_ds.c @@ -396,7 +396,7 @@ error_put: * * This function is called when the platform device is removed. */ -static int p1022_ds_remove(struct platform_device *pdev) +static void p1022_ds_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct machine_data *mdata = @@ -404,13 +404,11 @@ static int p1022_ds_remove(struct platform_device *pdev) snd_soc_unregister_card(card); kfree(mdata); - - return 0; } static struct platform_driver p1022_ds_driver = { .probe = p1022_ds_probe, - .remove = p1022_ds_remove, + .remove_new = p1022_ds_remove, .driver = { /* * The name must match 'compatible' property in the device tree, From ca4957d3b1f08c04e3ea510ebb419feda7b959c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:15 +0100 Subject: [PATCH 468/778] ASoC: fsl: p1022_rdk: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-84-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/fsl/p1022_rdk.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/fsl/p1022_rdk.c b/sound/soc/fsl/p1022_rdk.c index b395adabe823..4d85b742114c 100644 --- a/sound/soc/fsl/p1022_rdk.c +++ b/sound/soc/fsl/p1022_rdk.c @@ -345,7 +345,7 @@ error_put: * * This function is called when the platform device is removed. */ -static int p1022_rdk_remove(struct platform_device *pdev) +static void p1022_rdk_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct machine_data *mdata = @@ -353,13 +353,11 @@ static int p1022_rdk_remove(struct platform_device *pdev) snd_soc_unregister_card(card); kfree(mdata); - - return 0; } static struct platform_driver p1022_rdk_driver = { .probe = p1022_rdk_probe, - .remove = p1022_rdk_remove, + .remove_new = p1022_rdk_remove, .driver = { /* * The name must match 'compatible' property in the device tree, From b7f036b9ff7f6accced758b21d4194d184709d95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:16 +0100 Subject: [PATCH 469/778] ASoC: fsl: pcm030-audio-fabric: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-85-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/fsl/pcm030-audio-fabric.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/fsl/pcm030-audio-fabric.c b/sound/soc/fsl/pcm030-audio-fabric.c index 997c3e66c636..d24c02e90878 100644 --- a/sound/soc/fsl/pcm030-audio-fabric.c +++ b/sound/soc/fsl/pcm030-audio-fabric.c @@ -109,14 +109,12 @@ static int pcm030_fabric_probe(struct platform_device *op) } -static int pcm030_fabric_remove(struct platform_device *op) +static void pcm030_fabric_remove(struct platform_device *op) { struct pcm030_audio_data *pdata = platform_get_drvdata(op); snd_soc_unregister_card(pdata->card); platform_device_unregister(pdata->codec_device); - - return 0; } static const struct of_device_id pcm030_audio_match[] = { @@ -127,7 +125,7 @@ MODULE_DEVICE_TABLE(of, pcm030_audio_match); static struct platform_driver pcm030_fabric_driver = { .probe = pcm030_fabric_probe, - .remove = pcm030_fabric_remove, + .remove_new = pcm030_fabric_remove, .driver = { .name = DRV_NAME, .of_match_table = pcm030_audio_match, From 53946256cb7e9b4093f533fd42118cb6eda9ebb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:17 +0100 Subject: [PATCH 470/778] ASoC: generic: test-component: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-86-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/generic/test-component.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/generic/test-component.c b/sound/soc/generic/test-component.c index 98c8990596a8..e10e5bf28432 100644 --- a/sound/soc/generic/test-component.c +++ b/sound/soc/generic/test-component.c @@ -635,11 +635,9 @@ static int test_driver_probe(struct platform_device *pdev) return 0; } -static int test_driver_remove(struct platform_device *pdev) +static void test_driver_remove(struct platform_device *pdev) { mile_stone_x(&pdev->dev); - - return 0; } static struct platform_driver test_driver = { @@ -648,7 +646,7 @@ static struct platform_driver test_driver = { .of_match_table = test_of_match, }, .probe = test_driver_probe, - .remove = test_driver_remove, + .remove_new = test_driver_remove, }; module_platform_driver(test_driver); From 4c9c73d88f927e7549852136ac82b8eb9978ceeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:18 +0100 Subject: [PATCH 471/778] ASoC: img: img-i2s-in: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-87-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/img/img-i2s-in.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/img/img-i2s-in.c b/sound/soc/img/img-i2s-in.c index 56bb7bbd3976..b7ab8467b5cf 100644 --- a/sound/soc/img/img-i2s-in.c +++ b/sound/soc/img/img-i2s-in.c @@ -532,13 +532,11 @@ err_pm_disable: return ret; } -static int img_i2s_in_dev_remove(struct platform_device *pdev) +static void img_i2s_in_dev_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) img_i2s_in_runtime_suspend(&pdev->dev); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -609,7 +607,7 @@ static struct platform_driver img_i2s_in_driver = { .pm = &img_i2s_in_pm_ops }, .probe = img_i2s_in_probe, - .remove = img_i2s_in_dev_remove + .remove_new = img_i2s_in_dev_remove }; module_platform_driver(img_i2s_in_driver); From 3573bca8286daaaf191aece525e617415b88dfcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:19 +0100 Subject: [PATCH 472/778] ASoC: img: img-i2s-out: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-88-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/img/img-i2s-out.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/img/img-i2s-out.c b/sound/soc/img/img-i2s-out.c index abeff7829310..fe95ddfb8407 100644 --- a/sound/soc/img/img-i2s-out.c +++ b/sound/soc/img/img-i2s-out.c @@ -532,13 +532,11 @@ err_pm_disable: return ret; } -static int img_i2s_out_dev_remove(struct platform_device *pdev) +static void img_i2s_out_dev_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) img_i2s_out_runtime_suspend(&pdev->dev); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -609,7 +607,7 @@ static struct platform_driver img_i2s_out_driver = { .pm = &img_i2s_out_pm_ops }, .probe = img_i2s_out_probe, - .remove = img_i2s_out_dev_remove + .remove_new = img_i2s_out_dev_remove }; module_platform_driver(img_i2s_out_driver); From 6a5e4aafe0fd1523f75974af1aec50c35a17dbb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:20 +0100 Subject: [PATCH 473/778] ASoC: img: img-parallel-out: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-89-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/img/img-parallel-out.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/img/img-parallel-out.c b/sound/soc/img/img-parallel-out.c index 08506b05e226..df1291ee2b3b 100644 --- a/sound/soc/img/img-parallel-out.c +++ b/sound/soc/img/img-parallel-out.c @@ -282,7 +282,7 @@ err_pm_disable: return ret; } -static int img_prl_out_dev_remove(struct platform_device *pdev) +static void img_prl_out_dev_remove(struct platform_device *pdev) { struct img_prl_out *prl = platform_get_drvdata(pdev); @@ -291,8 +291,6 @@ static int img_prl_out_dev_remove(struct platform_device *pdev) img_prl_out_suspend(&pdev->dev); clk_disable_unprepare(prl->clk_sys); - - return 0; } static const struct of_device_id img_prl_out_of_match[] = { @@ -313,7 +311,7 @@ static struct platform_driver img_prl_out_driver = { .pm = &img_prl_out_pm_ops }, .probe = img_prl_out_probe, - .remove = img_prl_out_dev_remove + .remove_new = img_prl_out_dev_remove }; module_platform_driver(img_prl_out_driver); From 029a00ae9718571520f18ebdfb9ac5a633205d16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:21 +0100 Subject: [PATCH 474/778] ASoC: img: img-spdif-in: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-90-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/img/img-spdif-in.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/img/img-spdif-in.c b/sound/soc/img/img-spdif-in.c index 3f1d1a7e8735..558062a1804a 100644 --- a/sound/soc/img/img-spdif-in.c +++ b/sound/soc/img/img-spdif-in.c @@ -810,13 +810,11 @@ err_pm_disable: return ret; } -static int img_spdif_in_dev_remove(struct platform_device *pdev) +static void img_spdif_in_dev_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) img_spdif_in_runtime_suspend(&pdev->dev); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -880,7 +878,7 @@ static struct platform_driver img_spdif_in_driver = { .pm = &img_spdif_in_pm_ops }, .probe = img_spdif_in_probe, - .remove = img_spdif_in_dev_remove + .remove_new = img_spdif_in_dev_remove }; module_platform_driver(img_spdif_in_driver); From 4e894b2ec67c5c11cf9aa3d7c758102f02a3d08a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:22 +0100 Subject: [PATCH 475/778] ASoC: img: img-spdif-out: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-91-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/img/img-spdif-out.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/img/img-spdif-out.c b/sound/soc/img/img-spdif-out.c index 983761d3fa7e..b13e128e50d6 100644 --- a/sound/soc/img/img-spdif-out.c +++ b/sound/soc/img/img-spdif-out.c @@ -402,13 +402,11 @@ err_pm_disable: return ret; } -static int img_spdif_out_dev_remove(struct platform_device *pdev) +static void img_spdif_out_dev_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) img_spdif_out_runtime_suspend(&pdev->dev); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -470,7 +468,7 @@ static struct platform_driver img_spdif_out_driver = { .pm = &img_spdif_out_pm_ops }, .probe = img_spdif_out_probe, - .remove = img_spdif_out_dev_remove + .remove_new = img_spdif_out_dev_remove }; module_platform_driver(img_spdif_out_driver); From ab44348955bfc3b9ca127dfb36d0c3231adacf07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:23 +0100 Subject: [PATCH 476/778] ASoC: img: pistachio-internal-dac: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-92-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/img/pistachio-internal-dac.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/img/pistachio-internal-dac.c b/sound/soc/img/pistachio-internal-dac.c index e3b858643bd5..da6251680e41 100644 --- a/sound/soc/img/pistachio-internal-dac.c +++ b/sound/soc/img/pistachio-internal-dac.c @@ -215,15 +215,13 @@ err_regulator: return ret; } -static int pistachio_internal_dac_remove(struct platform_device *pdev) +static void pistachio_internal_dac_remove(struct platform_device *pdev) { struct pistachio_internal_dac *dac = dev_get_drvdata(&pdev->dev); pm_runtime_disable(&pdev->dev); pistachio_internal_dac_pwr_off(dac); regulator_disable(dac->supply); - - return 0; } #ifdef CONFIG_PM @@ -273,7 +271,7 @@ static struct platform_driver pistachio_internal_dac_plat_driver = { .pm = &pistachio_internal_dac_pm_ops }, .probe = pistachio_internal_dac_probe, - .remove = pistachio_internal_dac_remove + .remove_new = pistachio_internal_dac_remove }; module_platform_driver(pistachio_internal_dac_plat_driver); From 0d31e8adf3e01cd344070ca33e51dac61b833bd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:24 +0100 Subject: [PATCH 477/778] ASoC: Intel: sst-mfld-platform-pcm: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-93-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/intel/atom/sst-mfld-platform-pcm.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/intel/atom/sst-mfld-platform-pcm.c b/sound/soc/intel/atom/sst-mfld-platform-pcm.c index c75616a5fd0a..ba4597bdf32e 100644 --- a/sound/soc/intel/atom/sst-mfld-platform-pcm.c +++ b/sound/soc/intel/atom/sst-mfld-platform-pcm.c @@ -741,10 +741,9 @@ static int sst_platform_probe(struct platform_device *pdev) return ret; } -static int sst_platform_remove(struct platform_device *pdev) +static void sst_platform_remove(struct platform_device *pdev) { dev_dbg(&pdev->dev, "sst_platform_remove success\n"); - return 0; } #ifdef CONFIG_PM_SLEEP @@ -813,7 +812,7 @@ static struct platform_driver sst_platform_driver = { .pm = &sst_platform_pm, }, .probe = sst_platform_probe, - .remove = sst_platform_remove, + .remove_new = sst_platform_remove, }; module_platform_driver(sst_platform_driver); From c524f1674fc765b4adffd9329e89591169922269 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:25 +0100 Subject: [PATCH 478/778] ASoC: Intel: sst: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-94-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/intel/atom/sst/sst_acpi.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/intel/atom/sst/sst_acpi.c b/sound/soc/intel/atom/sst/sst_acpi.c index 3be64430c256..d3973936426a 100644 --- a/sound/soc/intel/atom/sst/sst_acpi.c +++ b/sound/soc/intel/atom/sst/sst_acpi.c @@ -335,14 +335,13 @@ static int sst_acpi_probe(struct platform_device *pdev) * This function is called by OS when a device is unloaded * This frees the interrupt etc */ -static int sst_acpi_remove(struct platform_device *pdev) +static void sst_acpi_remove(struct platform_device *pdev) { struct intel_sst_drv *ctx; ctx = platform_get_drvdata(pdev); sst_context_cleanup(ctx); platform_set_drvdata(pdev, NULL); - return 0; } static const struct acpi_device_id sst_acpi_ids[] = { @@ -360,7 +359,7 @@ static struct platform_driver sst_acpi_driver = { .pm = &intel_sst_pm, }, .probe = sst_acpi_probe, - .remove = sst_acpi_remove, + .remove_new = sst_acpi_remove, }; module_platform_driver(sst_acpi_driver); From 9c5b13d50b2eb039a43af2d06a31813bff717fa7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:26 +0100 Subject: [PATCH 479/778] ASoC: Intel: bytcht_es8316: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-95-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/intel/boards/bytcht_es8316.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/intel/boards/bytcht_es8316.c b/sound/soc/intel/boards/bytcht_es8316.c index df157b01df8b..7a30d2d36f19 100644 --- a/sound/soc/intel/boards/bytcht_es8316.c +++ b/sound/soc/intel/boards/bytcht_es8316.c @@ -628,7 +628,7 @@ err_put_codec: return ret; } -static int snd_byt_cht_es8316_mc_remove(struct platform_device *pdev) +static void snd_byt_cht_es8316_mc_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct byt_cht_es8316_private *priv = snd_soc_card_get_drvdata(card); @@ -636,7 +636,6 @@ static int snd_byt_cht_es8316_mc_remove(struct platform_device *pdev) gpiod_put(priv->speaker_en_gpio); device_remove_software_node(priv->codec_dev); put_device(priv->codec_dev); - return 0; } static struct platform_driver snd_byt_cht_es8316_mc_driver = { @@ -644,7 +643,7 @@ static struct platform_driver snd_byt_cht_es8316_mc_driver = { .name = "bytcht_es8316", }, .probe = snd_byt_cht_es8316_mc_probe, - .remove = snd_byt_cht_es8316_mc_remove, + .remove_new = snd_byt_cht_es8316_mc_remove, }; module_platform_driver(snd_byt_cht_es8316_mc_driver); From 2dc1d3c55d96973ded9c7fab8a22b7e323ae43e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:27 +0100 Subject: [PATCH 480/778] ASoC: Intel: bytcr_rt5640: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-96-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/intel/boards/bytcr_rt5640.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index 79e0039c79a3..789609eb0884 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -1844,7 +1844,7 @@ err_device: return ret_val; } -static int snd_byt_rt5640_mc_remove(struct platform_device *pdev) +static void snd_byt_rt5640_mc_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card); @@ -1854,7 +1854,6 @@ static int snd_byt_rt5640_mc_remove(struct platform_device *pdev) device_remove_software_node(priv->codec_dev); put_device(priv->codec_dev); - return 0; } static struct platform_driver snd_byt_rt5640_mc_driver = { @@ -1862,7 +1861,7 @@ static struct platform_driver snd_byt_rt5640_mc_driver = { .name = "bytcr_rt5640", }, .probe = snd_byt_rt5640_mc_probe, - .remove = snd_byt_rt5640_mc_remove, + .remove_new = snd_byt_rt5640_mc_remove, }; module_platform_driver(snd_byt_rt5640_mc_driver); From 00f2ac22d63c54fbe2cc0a98a4f25c640b224b44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:28 +0100 Subject: [PATCH 481/778] ASoC: Intel: boards: bytcr_rt5651: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-97-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/intel/boards/bytcr_rt5651.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c index 8fca9b82d4d0..805afaf47b29 100644 --- a/sound/soc/intel/boards/bytcr_rt5651.c +++ b/sound/soc/intel/boards/bytcr_rt5651.c @@ -1127,14 +1127,13 @@ err_device: return ret_val; } -static int snd_byt_rt5651_mc_remove(struct platform_device *pdev) +static void snd_byt_rt5651_mc_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct byt_rt5651_private *priv = snd_soc_card_get_drvdata(card); device_remove_software_node(priv->codec_dev); put_device(priv->codec_dev); - return 0; } static struct platform_driver snd_byt_rt5651_mc_driver = { @@ -1142,7 +1141,7 @@ static struct platform_driver snd_byt_rt5651_mc_driver = { .name = "bytcr_rt5651", }, .probe = snd_byt_rt5651_mc_probe, - .remove = snd_byt_rt5651_mc_remove, + .remove_new = snd_byt_rt5651_mc_remove, }; module_platform_driver(snd_byt_rt5651_mc_driver); From 2cd3f347aa0b82ab1c7ed8afe7e22234ac1b06f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:29 +0100 Subject: [PATCH 482/778] ASoC: Intel: bytcr_wm5102: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-98-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/intel/boards/bytcr_wm5102.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/intel/boards/bytcr_wm5102.c b/sound/soc/intel/boards/bytcr_wm5102.c index c0706537f673..f2382d4cb76f 100644 --- a/sound/soc/intel/boards/bytcr_wm5102.c +++ b/sound/soc/intel/boards/bytcr_wm5102.c @@ -466,13 +466,12 @@ out_put_gpio: return ret; } -static int snd_byt_wm5102_mc_remove(struct platform_device *pdev) +static void snd_byt_wm5102_mc_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct byt_wm5102_private *priv = snd_soc_card_get_drvdata(card); gpiod_put(priv->spkvdd_en_gpio); - return 0; } static struct platform_driver snd_byt_wm5102_mc_driver = { @@ -480,7 +479,7 @@ static struct platform_driver snd_byt_wm5102_mc_driver = { .name = "bytcr_wm5102", }, .probe = snd_byt_wm5102_mc_probe, - .remove = snd_byt_wm5102_mc_remove, + .remove_new = snd_byt_wm5102_mc_remove, }; module_platform_driver(snd_byt_wm5102_mc_driver); From 76a32d30dce2b101592ac76b4d74ae9fc9b9309b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:30 +0100 Subject: [PATCH 483/778] ASoC: Intel: cht_bsw_max98090_ti: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-99-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/intel/boards/cht_bsw_max98090_ti.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/intel/boards/cht_bsw_max98090_ti.c b/sound/soc/intel/boards/cht_bsw_max98090_ti.c index 2c086e901aae..850310de774b 100644 --- a/sound/soc/intel/boards/cht_bsw_max98090_ti.c +++ b/sound/soc/intel/boards/cht_bsw_max98090_ti.c @@ -623,15 +623,13 @@ static int snd_cht_mc_probe(struct platform_device *pdev) return ret_val; } -static int snd_cht_mc_remove(struct platform_device *pdev) +static void snd_cht_mc_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct cht_mc_private *ctx = snd_soc_card_get_drvdata(card); if (ctx->quirks & QUIRK_PMC_PLT_CLK_0) clk_disable_unprepare(ctx->mclk); - - return 0; } static struct platform_driver snd_cht_mc_driver = { @@ -639,7 +637,7 @@ static struct platform_driver snd_cht_mc_driver = { .name = "cht-bsw-max98090", }, .probe = snd_cht_mc_probe, - .remove = snd_cht_mc_remove, + .remove_new = snd_cht_mc_remove, }; module_platform_driver(snd_cht_mc_driver) From c1f0f19e3f206354c7f5759456f0789776394d17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:31 +0100 Subject: [PATCH 484/778] ASoC: Intel: sof_es8336: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-100-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_es8336.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/intel/boards/sof_es8336.c b/sound/soc/intel/boards/sof_es8336.c index 894b6610b9e2..adf5852b2c9a 100644 --- a/sound/soc/intel/boards/sof_es8336.c +++ b/sound/soc/intel/boards/sof_es8336.c @@ -780,7 +780,7 @@ err_put_codec: return ret; } -static int sof_es8336_remove(struct platform_device *pdev) +static void sof_es8336_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct sof_es8336_private *priv = snd_soc_card_get_drvdata(card); @@ -789,8 +789,6 @@ static int sof_es8336_remove(struct platform_device *pdev) gpiod_put(priv->gpio_speakers); device_remove_software_node(priv->codec_dev); put_device(priv->codec_dev); - - return 0; } static const struct platform_device_id board_ids[] = { @@ -817,7 +815,7 @@ static struct platform_driver sof_es8336_driver = { .pm = &snd_soc_pm_ops, }, .probe = sof_es8336_probe, - .remove = sof_es8336_remove, + .remove_new = sof_es8336_remove, .id_table = board_ids, }; module_platform_driver(sof_es8336_driver); From b6c85e141938c353ff390c112d7b226872712429 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:32 +0100 Subject: [PATCH 485/778] ASoC: Intel: sof_pcm512x: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-101-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_pcm512x.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/intel/boards/sof_pcm512x.c b/sound/soc/intel/boards/sof_pcm512x.c index d4c67d5340a9..5192e02b3cee 100644 --- a/sound/soc/intel/boards/sof_pcm512x.c +++ b/sound/soc/intel/boards/sof_pcm512x.c @@ -416,7 +416,7 @@ static int sof_audio_probe(struct platform_device *pdev) &sof_audio_card_pcm512x); } -static int sof_pcm512x_remove(struct platform_device *pdev) +static void sof_pcm512x_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct snd_soc_component *component; @@ -427,13 +427,11 @@ static int sof_pcm512x_remove(struct platform_device *pdev) break; } } - - return 0; } static struct platform_driver sof_audio = { .probe = sof_audio_probe, - .remove = sof_pcm512x_remove, + .remove_new = sof_pcm512x_remove, .driver = { .name = "sof_pcm512x", .pm = &snd_soc_pm_ops, From 51a4a7ecd85f9a714b47caa4d8c2ee7ea1e5b81f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:33 +0100 Subject: [PATCH 486/778] ASoC: Intel: sof_sdw: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-102-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index d2ed807abde9..4ea69197791c 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1602,13 +1602,11 @@ static int mc_probe(struct platform_device *pdev) return ret; } -static int mc_remove(struct platform_device *pdev) +static void mc_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); mc_dailink_exit_loop(card); - - return 0; } static struct platform_driver sof_sdw_driver = { @@ -1617,7 +1615,7 @@ static struct platform_driver sof_sdw_driver = { .pm = &snd_soc_pm_ops, }, .probe = mc_probe, - .remove = mc_remove, + .remove_new = mc_remove, }; module_platform_driver(sof_sdw_driver); From 674dd2c5f2b9466d9e8dfcd5e6f7a68d26fbc923 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:34 +0100 Subject: [PATCH 487/778] ASoC: Intel: sof_wm8804: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-103-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_wm8804.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/intel/boards/sof_wm8804.c b/sound/soc/intel/boards/sof_wm8804.c index fbad5a73de44..17224d26d9d6 100644 --- a/sound/soc/intel/boards/sof_wm8804.c +++ b/sound/soc/intel/boards/sof_wm8804.c @@ -278,11 +278,10 @@ static int sof_wm8804_probe(struct platform_device *pdev) return devm_snd_soc_register_card(&pdev->dev, card); } -static int sof_wm8804_remove(struct platform_device *pdev) +static void sof_wm8804_remove(struct platform_device *pdev) { if (sof_wm8804_quirk & SOF_WM8804_UP2_QUIRK) gpiod_remove_lookup_table(&up2_gpios_table); - return 0; } static struct platform_driver sof_wm8804_driver = { @@ -291,7 +290,7 @@ static struct platform_driver sof_wm8804_driver = { .pm = &snd_soc_pm_ops, }, .probe = sof_wm8804_probe, - .remove = sof_wm8804_remove, + .remove_new = sof_wm8804_remove, }; module_platform_driver(sof_wm8804_driver); From 4b6f92559390e016b6264b5f6d25f192ea83acba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:35 +0100 Subject: [PATCH 488/778] ASoC: Intel: catpt: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-104-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/intel/catpt/device.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/intel/catpt/device.c b/sound/soc/intel/catpt/device.c index d5d08bd766c7..cac3dffbd0d9 100644 --- a/sound/soc/intel/catpt/device.c +++ b/sound/soc/intel/catpt/device.c @@ -293,7 +293,7 @@ static int catpt_acpi_probe(struct platform_device *pdev) return catpt_probe_components(cdev); } -static int catpt_acpi_remove(struct platform_device *pdev) +static void catpt_acpi_remove(struct platform_device *pdev) { struct catpt_dev *cdev = platform_get_drvdata(pdev); @@ -305,8 +305,6 @@ static int catpt_acpi_remove(struct platform_device *pdev) catpt_sram_free(&cdev->iram); catpt_sram_free(&cdev->dram); - - return 0; } static struct snd_soc_acpi_mach lpt_machines[] = { @@ -376,7 +374,7 @@ MODULE_DEVICE_TABLE(acpi, catpt_ids); static struct platform_driver catpt_acpi_driver = { .probe = catpt_acpi_probe, - .remove = catpt_acpi_remove, + .remove_new = catpt_acpi_remove, .driver = { .name = "intel_catpt", .acpi_match_table = catpt_ids, From 394b2a11d9c238eb23e4fc087cc69f797b365f4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:36 +0100 Subject: [PATCH 489/778] ASoC: Intel: skl-ssp-clk: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-105-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl-ssp-clk.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/intel/skylake/skl-ssp-clk.c b/sound/soc/intel/skylake/skl-ssp-clk.c index a3a73c26f9aa..50e93c3707e8 100644 --- a/sound/soc/intel/skylake/skl-ssp-clk.c +++ b/sound/soc/intel/skylake/skl-ssp-clk.c @@ -402,15 +402,13 @@ err_unreg_skl_clk: return ret; } -static int skl_clk_dev_remove(struct platform_device *pdev) +static void skl_clk_dev_remove(struct platform_device *pdev) { struct skl_clk_data *data; data = platform_get_drvdata(pdev); unregister_src_clk(data); unregister_parent_src_clk(data->parent, SKL_MAX_CLK_SRC); - - return 0; } static struct platform_driver skl_clk_driver = { @@ -418,7 +416,7 @@ static struct platform_driver skl_clk_driver = { .name = "skl-ssp-clk", }, .probe = skl_clk_dev_probe, - .remove = skl_clk_dev_remove, + .remove_new = skl_clk_dev_remove, }; module_platform_driver(skl_clk_driver); From 8c078706e9862c7cd8bcb22d34133262024c26bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:37 +0100 Subject: [PATCH 490/778] ASoC: kirkwood: kirkwood-i2s: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Reviewed-by: Andrew Lunn Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-106-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/kirkwood/kirkwood-i2s.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/kirkwood/kirkwood-i2s.c b/sound/soc/kirkwood/kirkwood-i2s.c index afdf7d61e4c5..d1eb90310afa 100644 --- a/sound/soc/kirkwood/kirkwood-i2s.c +++ b/sound/soc/kirkwood/kirkwood-i2s.c @@ -736,7 +736,7 @@ static int kirkwood_i2s_dev_probe(struct platform_device *pdev) return err; } -static int kirkwood_i2s_dev_remove(struct platform_device *pdev) +static void kirkwood_i2s_dev_remove(struct platform_device *pdev) { struct kirkwood_dma_data *priv = dev_get_drvdata(&pdev->dev); @@ -744,8 +744,6 @@ static int kirkwood_i2s_dev_remove(struct platform_device *pdev) if (!IS_ERR(priv->extclk)) clk_disable_unprepare(priv->extclk); clk_disable_unprepare(priv->clk); - - return 0; } #ifdef CONFIG_OF @@ -761,7 +759,7 @@ MODULE_DEVICE_TABLE(of, mvebu_audio_of_match); static struct platform_driver kirkwood_i2s_driver = { .probe = kirkwood_i2s_dev_probe, - .remove = kirkwood_i2s_dev_remove, + .remove_new = kirkwood_i2s_dev_remove, .driver = { .name = DRV_NAME, .of_match_table = of_match_ptr(mvebu_audio_of_match), From 09f8cf0495b03dee0d567cebd4f47294c6293cd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:38 +0100 Subject: [PATCH 491/778] ASoC: mediatek: mtk-btcvsd: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Reviewed-by: AngeloGioacchino Del Regno Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-107-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/mediatek/common/mtk-btcvsd.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/mediatek/common/mtk-btcvsd.c b/sound/soc/mediatek/common/mtk-btcvsd.c index 1c28b41e4311..1ba0633e542f 100644 --- a/sound/soc/mediatek/common/mtk-btcvsd.c +++ b/sound/soc/mediatek/common/mtk-btcvsd.c @@ -1387,13 +1387,12 @@ unmap_pkv_err: return ret; } -static int mtk_btcvsd_snd_remove(struct platform_device *pdev) +static void mtk_btcvsd_snd_remove(struct platform_device *pdev) { struct mtk_btcvsd_snd *btcvsd = dev_get_drvdata(&pdev->dev); iounmap(btcvsd->bt_pkv_base); iounmap(btcvsd->bt_sram_bank2_base); - return 0; } static const struct of_device_id mtk_btcvsd_snd_dt_match[] = { @@ -1408,7 +1407,7 @@ static struct platform_driver mtk_btcvsd_snd_driver = { .of_match_table = mtk_btcvsd_snd_dt_match, }, .probe = mtk_btcvsd_snd_probe, - .remove = mtk_btcvsd_snd_remove, + .remove_new = mtk_btcvsd_snd_remove, }; module_platform_driver(mtk_btcvsd_snd_driver); From b3dff59e57a2d7c319590afe127a541917a06e1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:39 +0100 Subject: [PATCH 492/778] ASoC: mediatek: mt2701-afe-pcm: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Reviewed-by: AngeloGioacchino Del Regno Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-108-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/mediatek/mt2701/mt2701-afe-pcm.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c index 0f178de92a0f..c9d4420e9b4c 100644 --- a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c +++ b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c @@ -1439,14 +1439,12 @@ err_pm_disable: return ret; } -static int mt2701_afe_pcm_dev_remove(struct platform_device *pdev) +static void mt2701_afe_pcm_dev_remove(struct platform_device *pdev) { pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) mt2701_afe_runtime_suspend(&pdev->dev); - - return 0; } static const struct mt2701_soc_variants mt2701_soc_v1 = { @@ -1477,7 +1475,7 @@ static struct platform_driver mt2701_afe_pcm_driver = { .pm = &mt2701_afe_pm_ops, }, .probe = mt2701_afe_pcm_dev_probe, - .remove = mt2701_afe_pcm_dev_remove, + .remove_new = mt2701_afe_pcm_dev_remove, }; module_platform_driver(mt2701_afe_pcm_driver); From edd8a5cde6c73d436b7970635b14a974b9a6e45c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:40 +0100 Subject: [PATCH 493/778] ASoC: mediatek: mt6797-afe-pcm: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Reviewed-by: AngeloGioacchino Del Regno Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-109-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/mediatek/mt6797/mt6797-afe-pcm.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/mediatek/mt6797/mt6797-afe-pcm.c b/sound/soc/mediatek/mt6797/mt6797-afe-pcm.c index fb4abec9aa5f..43038444c43d 100644 --- a/sound/soc/mediatek/mt6797/mt6797-afe-pcm.c +++ b/sound/soc/mediatek/mt6797/mt6797-afe-pcm.c @@ -876,14 +876,12 @@ err_pm_disable: return ret; } -static int mt6797_afe_pcm_dev_remove(struct platform_device *pdev) +static void mt6797_afe_pcm_dev_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) mt6797_afe_runtime_suspend(&pdev->dev); pm_runtime_put_sync(&pdev->dev); - - return 0; } static const struct of_device_id mt6797_afe_pcm_dt_match[] = { @@ -904,7 +902,7 @@ static struct platform_driver mt6797_afe_pcm_driver = { .pm = &mt6797_afe_pm_ops, }, .probe = mt6797_afe_pcm_dev_probe, - .remove = mt6797_afe_pcm_dev_remove, + .remove_new = mt6797_afe_pcm_dev_remove, }; module_platform_driver(mt6797_afe_pcm_driver); From 98a11bf9e7d904803fd4d91b909e3cad43719fba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:41 +0100 Subject: [PATCH 494/778] ASoC: mediatek: mt8173-afe-pcm: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Reviewed-by: AngeloGioacchino Del Regno Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-110-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8173/mt8173-afe-pcm.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c b/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c index bc155dd937e0..f93c2ec8beb7 100644 --- a/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c +++ b/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c @@ -1195,14 +1195,13 @@ err_pm_disable: return ret; } -static int mt8173_afe_pcm_dev_remove(struct platform_device *pdev) +static void mt8173_afe_pcm_dev_remove(struct platform_device *pdev) { snd_soc_unregister_component(&pdev->dev); pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) mt8173_afe_runtime_suspend(&pdev->dev); - return 0; } static const struct of_device_id mt8173_afe_pcm_dt_match[] = { @@ -1223,7 +1222,7 @@ static struct platform_driver mt8173_afe_pcm_driver = { .pm = &mt8173_afe_pm_ops, }, .probe = mt8173_afe_pcm_dev_probe, - .remove = mt8173_afe_pcm_dev_remove, + .remove_new = mt8173_afe_pcm_dev_remove, }; module_platform_driver(mt8173_afe_pcm_driver); From 718041d46c4c69f86135f3e38c7295a41523d7bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:42 +0100 Subject: [PATCH 495/778] ASoC: mediatek: mt8183-afe-pcm: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Reviewed-by: AngeloGioacchino Del Regno Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-111-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8183/mt8183-afe-pcm.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c b/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c index 86c8a523fe9e..90422ed2bbcc 100644 --- a/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c +++ b/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c @@ -1255,13 +1255,11 @@ err_pm_disable: return ret; } -static int mt8183_afe_pcm_dev_remove(struct platform_device *pdev) +static void mt8183_afe_pcm_dev_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) mt8183_afe_runtime_suspend(&pdev->dev); - - return 0; } static const struct of_device_id mt8183_afe_pcm_dt_match[] = { @@ -1282,7 +1280,7 @@ static struct platform_driver mt8183_afe_pcm_driver = { .pm = &mt8183_afe_pm_ops, }, .probe = mt8183_afe_pcm_dev_probe, - .remove = mt8183_afe_pcm_dev_remove, + .remove_new = mt8183_afe_pcm_dev_remove, }; module_platform_driver(mt8183_afe_pcm_driver); From bb5ba5fe26ac53de23f1c85e97cb8cef31df343f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:43 +0100 Subject: [PATCH 496/778] ASoC: mediatek: mt8188-afe-pcm: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Trevor Wu Reviewed-by: AngeloGioacchino Del Regno Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-112-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8188/mt8188-afe-pcm.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c b/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c index e8e84de86542..e5f9373bed56 100644 --- a/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c +++ b/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c @@ -3323,11 +3323,9 @@ err_pm_put: return ret; } -static int mt8188_afe_pcm_dev_remove(struct platform_device *pdev) +static void mt8188_afe_pcm_dev_remove(struct platform_device *pdev) { snd_soc_unregister_component(&pdev->dev); - - return 0; } static const struct of_device_id mt8188_afe_pcm_dt_match[] = { @@ -3348,7 +3346,7 @@ static struct platform_driver mt8188_afe_pcm_driver = { .pm = &mt8188_afe_pm_ops, }, .probe = mt8188_afe_pcm_dev_probe, - .remove = mt8188_afe_pcm_dev_remove, + .remove_new = mt8188_afe_pcm_dev_remove, }; module_platform_driver(mt8188_afe_pcm_driver); From 26530339aca3e55cf44895303344ea6a91fa8bb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:44 +0100 Subject: [PATCH 497/778] ASoC: mediatek: mt8192-afe-pcm: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Reviewed-by: AngeloGioacchino Del Regno Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-113-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8192/mt8192-afe-pcm.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c b/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c index 333e0ee98c5a..d0520e7e1d79 100644 --- a/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c +++ b/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c @@ -2349,7 +2349,7 @@ err_pm_disable: return ret; } -static int mt8192_afe_pcm_dev_remove(struct platform_device *pdev) +static void mt8192_afe_pcm_dev_remove(struct platform_device *pdev) { struct mtk_base_afe *afe = platform_get_drvdata(pdev); @@ -2359,7 +2359,6 @@ static int mt8192_afe_pcm_dev_remove(struct platform_device *pdev) /* disable afe clock */ mt8192_afe_disable_clock(afe); - return 0; } static const struct of_device_id mt8192_afe_pcm_dt_match[] = { @@ -2380,7 +2379,7 @@ static struct platform_driver mt8192_afe_pcm_driver = { .pm = &mt8192_afe_pm_ops, }, .probe = mt8192_afe_pcm_dev_probe, - .remove = mt8192_afe_pcm_dev_remove, + .remove_new = mt8192_afe_pcm_dev_remove, }; module_platform_driver(mt8192_afe_pcm_driver); From 6461fee68064ba970e3ba90241fe5f5e038aa9d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:45 +0100 Subject: [PATCH 498/778] ASoC: mediatek: mt8195-afe-pcm: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Reviewed-by: AngeloGioacchino Del Regno Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-114-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8195/mt8195-afe-pcm.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/mediatek/mt8195/mt8195-afe-pcm.c b/sound/soc/mediatek/mt8195/mt8195-afe-pcm.c index 72b2c6d629b9..9e45efeada55 100644 --- a/sound/soc/mediatek/mt8195/mt8195-afe-pcm.c +++ b/sound/soc/mediatek/mt8195/mt8195-afe-pcm.c @@ -3253,7 +3253,7 @@ err_pm_put: return ret; } -static int mt8195_afe_pcm_dev_remove(struct platform_device *pdev) +static void mt8195_afe_pcm_dev_remove(struct platform_device *pdev) { struct mtk_base_afe *afe = platform_get_drvdata(pdev); @@ -3264,7 +3264,6 @@ static int mt8195_afe_pcm_dev_remove(struct platform_device *pdev) mt8195_afe_runtime_suspend(&pdev->dev); mt8195_afe_deinit_clock(afe); - return 0; } static const struct of_device_id mt8195_afe_pcm_dt_match[] = { @@ -3285,7 +3284,7 @@ static struct platform_driver mt8195_afe_pcm_driver = { .pm = &mt8195_afe_pm_ops, }, .probe = mt8195_afe_pcm_dev_probe, - .remove = mt8195_afe_pcm_dev_remove, + .remove_new = mt8195_afe_pcm_dev_remove, }; module_platform_driver(mt8195_afe_pcm_driver); From ed354c69dd370ebac8c438d3570aade296afce05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:46 +0100 Subject: [PATCH 499/778] ASoC: meson: aiu: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Martin Blumenstingl Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-115-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/meson/aiu.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/meson/aiu.c b/sound/soc/meson/aiu.c index 88e611e64d14..da351a60df0c 100644 --- a/sound/soc/meson/aiu.c +++ b/sound/soc/meson/aiu.c @@ -331,11 +331,9 @@ err: return ret; } -static int aiu_remove(struct platform_device *pdev) +static void aiu_remove(struct platform_device *pdev) { snd_soc_unregister_component(&pdev->dev); - - return 0; } static const struct aiu_platform_data aiu_gxbb_pdata = { @@ -364,7 +362,7 @@ MODULE_DEVICE_TABLE(of, aiu_of_match); static struct platform_driver aiu_pdrv = { .probe = aiu_probe, - .remove = aiu_remove, + .remove_new = aiu_remove, .driver = { .name = "meson-aiu", .of_match_table = aiu_of_match, From 75c1ed916145ecb5ae8a5e4a282aaea84fa9724e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:47 +0100 Subject: [PATCH 500/778] ASoC: mxs: mxs-sgtl5000: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-116-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/mxs/mxs-sgtl5000.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/mxs/mxs-sgtl5000.c b/sound/soc/mxs/mxs-sgtl5000.c index a55e7256a4c3..457c3a72a414 100644 --- a/sound/soc/mxs/mxs-sgtl5000.c +++ b/sound/soc/mxs/mxs-sgtl5000.c @@ -169,11 +169,9 @@ static int mxs_sgtl5000_probe(struct platform_device *pdev) return 0; } -static int mxs_sgtl5000_remove(struct platform_device *pdev) +static void mxs_sgtl5000_remove(struct platform_device *pdev) { mxs_saif_put_mclk(0); - - return 0; } static const struct of_device_id mxs_sgtl5000_dt_ids[] = { @@ -188,7 +186,7 @@ static struct platform_driver mxs_sgtl5000_audio_driver = { .of_match_table = mxs_sgtl5000_dt_ids, }, .probe = mxs_sgtl5000_probe, - .remove = mxs_sgtl5000_remove, + .remove_new = mxs_sgtl5000_remove, }; module_platform_driver(mxs_sgtl5000_audio_driver); From 15c71a4c84ba66f95c49b50fa934ab0395a1010f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:48 +0100 Subject: [PATCH 501/778] ASoC: pxa: mmp-sspa: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-117-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/pxa/mmp-sspa.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/sound/soc/pxa/mmp-sspa.c b/sound/soc/pxa/mmp-sspa.c index b3c1744eff91..a1ed141b8795 100644 --- a/sound/soc/pxa/mmp-sspa.c +++ b/sound/soc/pxa/mmp-sspa.c @@ -545,7 +545,7 @@ static int asoc_mmp_sspa_probe(struct platform_device *pdev) return 0; } -static int asoc_mmp_sspa_remove(struct platform_device *pdev) +static void asoc_mmp_sspa_remove(struct platform_device *pdev) { struct sspa_priv *sspa = platform_get_drvdata(pdev); @@ -553,11 +553,10 @@ static int asoc_mmp_sspa_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); if (pdev->dev.of_node) - return 0; + return; clk_put(sspa->audio_clk); clk_put(sspa->sysclk); - return 0; } #ifdef CONFIG_OF @@ -575,7 +574,7 @@ static struct platform_driver asoc_mmp_sspa_driver = { .of_match_table = of_match_ptr(mmp_sspa_of_match), }, .probe = asoc_mmp_sspa_probe, - .remove = asoc_mmp_sspa_remove, + .remove_new = asoc_mmp_sspa_remove, }; module_platform_driver(asoc_mmp_sspa_driver); From acb6a6982d6b83c08014f5110b443f4e8bca459b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:49 +0100 Subject: [PATCH 502/778] ASoC: pxa: pxa2xx-ac97: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-118-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/pxa/pxa2xx-ac97.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c index 809ea34736ed..e73bd62c033c 100644 --- a/sound/soc/pxa/pxa2xx-ac97.c +++ b/sound/soc/pxa/pxa2xx-ac97.c @@ -263,13 +263,12 @@ static int pxa2xx_ac97_dev_probe(struct platform_device *pdev) pxa_ac97_dai_driver, ARRAY_SIZE(pxa_ac97_dai_driver)); } -static int pxa2xx_ac97_dev_remove(struct platform_device *pdev) +static void pxa2xx_ac97_dev_remove(struct platform_device *pdev) { struct ac97_controller *ctrl = platform_get_drvdata(pdev); snd_ac97_controller_unregister(ctrl); pxa2xx_ac97_hw_remove(pdev); - return 0; } #ifdef CONFIG_PM_SLEEP @@ -289,7 +288,7 @@ static SIMPLE_DEV_PM_OPS(pxa2xx_ac97_pm_ops, static struct platform_driver pxa2xx_ac97_driver = { .probe = pxa2xx_ac97_dev_probe, - .remove = pxa2xx_ac97_dev_remove, + .remove_new = pxa2xx_ac97_dev_remove, .driver = { .name = "pxa2xx-ac97", #ifdef CONFIG_PM_SLEEP From 60835c5c7d014cdb73166ee9e1b678d53562e3e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:50 +0100 Subject: [PATCH 503/778] ASoC: qcom: qdsp6: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-119-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/qcom/qdsp6/q6routing.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/qcom/qdsp6/q6routing.c b/sound/soc/qcom/qdsp6/q6routing.c index 928fd23e2c27..bba07899f8fc 100644 --- a/sound/soc/qcom/qdsp6/q6routing.c +++ b/sound/soc/qcom/qdsp6/q6routing.c @@ -1140,12 +1140,10 @@ static int q6pcm_routing_probe(struct platform_device *pdev) NULL, 0); } -static int q6pcm_routing_remove(struct platform_device *pdev) +static void q6pcm_routing_remove(struct platform_device *pdev) { kfree(routing_data); routing_data = NULL; - - return 0; } #ifdef CONFIG_OF @@ -1162,7 +1160,7 @@ static struct platform_driver q6pcm_routing_platform_driver = { .of_match_table = of_match_ptr(q6pcm_routing_device_id), }, .probe = q6pcm_routing_probe, - .remove = q6pcm_routing_remove, + .remove_new = q6pcm_routing_remove, }; module_platform_driver(q6pcm_routing_platform_driver); From f348dd337e20e2e82b655062e613dbc63a6d4d01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:51 +0100 Subject: [PATCH 504/778] ASoC: rockchip: rockchip_i2s: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-120-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/rockchip/rockchip_i2s.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c index a8758ad68442..79abec24a5a2 100644 --- a/sound/soc/rockchip/rockchip_i2s.c +++ b/sound/soc/rockchip/rockchip_i2s.c @@ -850,7 +850,7 @@ err_clk: return ret; } -static int rockchip_i2s_remove(struct platform_device *pdev) +static void rockchip_i2s_remove(struct platform_device *pdev) { struct rk_i2s_dev *i2s = dev_get_drvdata(&pdev->dev); @@ -859,8 +859,6 @@ static int rockchip_i2s_remove(struct platform_device *pdev) i2s_runtime_suspend(&pdev->dev); clk_disable_unprepare(i2s->hclk); - - return 0; } static const struct dev_pm_ops rockchip_i2s_pm_ops = { @@ -870,7 +868,7 @@ static const struct dev_pm_ops rockchip_i2s_pm_ops = { static struct platform_driver rockchip_i2s_driver = { .probe = rockchip_i2s_probe, - .remove = rockchip_i2s_remove, + .remove_new = rockchip_i2s_remove, .driver = { .name = DRV_NAME, .of_match_table = of_match_ptr(rockchip_i2s_match), From 61785600e2b9513fe782857dd53ae9f920d6ff85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:53 +0100 Subject: [PATCH 505/778] ASoC: rockchip: rockchip_pdm: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-122-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/rockchip/rockchip_pdm.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/rockchip/rockchip_pdm.c b/sound/soc/rockchip/rockchip_pdm.c index 6ce92b1db790..52f9aae60be8 100644 --- a/sound/soc/rockchip/rockchip_pdm.c +++ b/sound/soc/rockchip/rockchip_pdm.c @@ -661,7 +661,7 @@ err_pm_disable: return ret; } -static int rockchip_pdm_remove(struct platform_device *pdev) +static void rockchip_pdm_remove(struct platform_device *pdev) { struct rk_pdm_dev *pdm = dev_get_drvdata(&pdev->dev); @@ -671,8 +671,6 @@ static int rockchip_pdm_remove(struct platform_device *pdev) clk_disable_unprepare(pdm->clk); clk_disable_unprepare(pdm->hclk); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -710,7 +708,7 @@ static const struct dev_pm_ops rockchip_pdm_pm_ops = { static struct platform_driver rockchip_pdm_driver = { .probe = rockchip_pdm_probe, - .remove = rockchip_pdm_remove, + .remove_new = rockchip_pdm_remove, .driver = { .name = "rockchip-pdm", .of_match_table = of_match_ptr(rockchip_pdm_match), From ed1e0f5a273c2dcbfede81831aa14c1039ad6930 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:54 +0100 Subject: [PATCH 506/778] ASoC: rockchip: rockchip_rt5645: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-123-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/rockchip/rockchip_rt5645.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/rockchip/rockchip_rt5645.c b/sound/soc/rockchip/rockchip_rt5645.c index d07cc5c813f2..e73a342b7953 100644 --- a/sound/soc/rockchip/rockchip_rt5645.c +++ b/sound/soc/rockchip/rockchip_rt5645.c @@ -206,14 +206,12 @@ put_codec_of_node: return ret; } -static int snd_rk_mc_remove(struct platform_device *pdev) +static void snd_rk_mc_remove(struct platform_device *pdev) { of_node_put(rk_dailink.cpus->of_node); rk_dailink.cpus->of_node = NULL; of_node_put(rk_dailink.codecs->of_node); rk_dailink.codecs->of_node = NULL; - - return 0; } static const struct of_device_id rockchip_rt5645_of_match[] = { @@ -225,7 +223,7 @@ MODULE_DEVICE_TABLE(of, rockchip_rt5645_of_match); static struct platform_driver snd_rk_mc_driver = { .probe = snd_rk_mc_probe, - .remove = snd_rk_mc_remove, + .remove_new = snd_rk_mc_remove, .driver = { .name = DRV_NAME, .pm = &snd_soc_pm_ops, From cdce778344bc7f6c8b52027deab3f35cc05c4b3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:55 +0100 Subject: [PATCH 507/778] ASoC: rockchip: rockchip_spdif: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-124-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/rockchip/rockchip_spdif.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/rockchip/rockchip_spdif.c b/sound/soc/rockchip/rockchip_spdif.c index 2d937fcf357d..0b73fe94e4bb 100644 --- a/sound/soc/rockchip/rockchip_spdif.c +++ b/sound/soc/rockchip/rockchip_spdif.c @@ -367,13 +367,11 @@ err_pm_runtime: return ret; } -static int rk_spdif_remove(struct platform_device *pdev) +static void rk_spdif_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) rk_spdif_runtime_suspend(&pdev->dev); - - return 0; } static const struct dev_pm_ops rk_spdif_pm_ops = { @@ -383,7 +381,7 @@ static const struct dev_pm_ops rk_spdif_pm_ops = { static struct platform_driver rk_spdif_driver = { .probe = rk_spdif_probe, - .remove = rk_spdif_remove, + .remove_new = rk_spdif_remove, .driver = { .name = "rockchip-spdif", .of_match_table = of_match_ptr(rk_spdif_match), From 2149a1afa7f0d24164c7ae4ef66fdb98c607325c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:56 +0100 Subject: [PATCH 508/778] ASoC: samsung: arndale: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-125-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/samsung/arndale.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/samsung/arndale.c b/sound/soc/samsung/arndale.c index a5dc640d0d76..fdff83e72d29 100644 --- a/sound/soc/samsung/arndale.c +++ b/sound/soc/samsung/arndale.c @@ -185,12 +185,11 @@ err_put_of_nodes: return ret; } -static int arndale_audio_remove(struct platform_device *pdev) +static void arndale_audio_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); arndale_put_of_nodes(card); - return 0; } static const struct of_device_id arndale_audio_of_match[] = { @@ -208,7 +207,7 @@ static struct platform_driver arndale_audio_driver = { .of_match_table = arndale_audio_of_match, }, .probe = arndale_audio_probe, - .remove = arndale_audio_remove, + .remove_new = arndale_audio_remove, }; module_platform_driver(arndale_audio_driver); From 0b309358b8e461f3d99235d6b8b75cbffb61de57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:57 +0100 Subject: [PATCH 509/778] ASoC: samsung: i2s: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-126-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/samsung/i2s.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index 083e278aa021..f3d98abd5f0d 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -1560,13 +1560,13 @@ err_disable_clk: return ret; } -static int samsung_i2s_remove(struct platform_device *pdev) +static void samsung_i2s_remove(struct platform_device *pdev) { struct samsung_i2s_priv *priv = dev_get_drvdata(&pdev->dev); /* The secondary device has no driver data assigned */ if (!priv) - return 0; + return; pm_runtime_get_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); @@ -1576,8 +1576,6 @@ static int samsung_i2s_remove(struct platform_device *pdev) clk_disable_unprepare(priv->clk); pm_runtime_put_noidle(&pdev->dev); - - return 0; } static void fsd_i2s_fixup_early(struct snd_pcm_substream *substream, @@ -1746,7 +1744,7 @@ static const struct dev_pm_ops samsung_i2s_pm = { static struct platform_driver samsung_i2s_driver = { .probe = samsung_i2s_probe, - .remove = samsung_i2s_remove, + .remove_new = samsung_i2s_remove, .id_table = samsung_i2s_driver_ids, .driver = { .name = "samsung-i2s", From d530e675e0189f68fc644668209eafc835d50efb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:58 +0100 Subject: [PATCH 510/778] ASoC: samsung: odroid: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-127-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/samsung/odroid.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/samsung/odroid.c b/sound/soc/samsung/odroid.c index 1e0fefa89ad5..fd95a79cc9fa 100644 --- a/sound/soc/samsung/odroid.c +++ b/sound/soc/samsung/odroid.c @@ -331,15 +331,13 @@ err_put_node: return ret; } -static int odroid_audio_remove(struct platform_device *pdev) +static void odroid_audio_remove(struct platform_device *pdev) { struct odroid_priv *priv = platform_get_drvdata(pdev); snd_soc_of_put_dai_link_codecs(&priv->card.dai_link[1]); clk_put(priv->sclk_i2s); clk_put(priv->clk_i2s_bus); - - return 0; } static const struct of_device_id odroid_audio_of_match[] = { @@ -358,7 +356,7 @@ static struct platform_driver odroid_audio_driver = { .pm = &snd_soc_pm_ops, }, .probe = odroid_audio_probe, - .remove = odroid_audio_remove, + .remove_new = odroid_audio_remove, }; module_platform_driver(odroid_audio_driver); From 9f82db9dbb53567fc4c8de7a9fb41a8b6b4ea0e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:06:59 +0100 Subject: [PATCH 511/778] ASoC: samsung: pcm: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-128-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/samsung/pcm.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/samsung/pcm.c b/sound/soc/samsung/pcm.c index e859252ae5e6..335fe5cb9cfc 100644 --- a/sound/soc/samsung/pcm.c +++ b/sound/soc/samsung/pcm.c @@ -579,20 +579,18 @@ err_dis_cclk: return ret; } -static int s3c_pcm_dev_remove(struct platform_device *pdev) +static void s3c_pcm_dev_remove(struct platform_device *pdev) { struct s3c_pcm_info *pcm = &s3c_pcm[pdev->id]; pm_runtime_disable(&pdev->dev); clk_disable_unprepare(pcm->cclk); clk_disable_unprepare(pcm->pclk); - - return 0; } static struct platform_driver s3c_pcm_driver = { .probe = s3c_pcm_dev_probe, - .remove = s3c_pcm_dev_remove, + .remove_new = s3c_pcm_dev_remove, .driver = { .name = "samsung-pcm", }, From 3224f4407d67c9504d9c779ebe79cd90be887cec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:07:00 +0100 Subject: [PATCH 512/778] ASoC: samsung: snow: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-129-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/samsung/snow.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/samsung/snow.c b/sound/soc/samsung/snow.c index da342da03880..334080e631af 100644 --- a/sound/soc/samsung/snow.c +++ b/sound/soc/samsung/snow.c @@ -219,7 +219,7 @@ static int snow_probe(struct platform_device *pdev) return 0; } -static int snow_remove(struct platform_device *pdev) +static void snow_remove(struct platform_device *pdev) { struct snow_priv *priv = platform_get_drvdata(pdev); struct snd_soc_dai_link *link = &priv->dai_link; @@ -229,8 +229,6 @@ static int snow_remove(struct platform_device *pdev) snd_soc_of_put_dai_link_codecs(link); clk_put(priv->clk_i2s_bus); - - return 0; } static const struct of_device_id snow_of_match[] = { @@ -248,7 +246,7 @@ static struct platform_driver snow_driver = { .of_match_table = snow_of_match, }, .probe = snow_probe, - .remove = snow_remove, + .remove_new = snow_remove, }; module_platform_driver(snow_driver); From 7695582fd463ef3158d21253130cd2f1510c4e9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:07:01 +0100 Subject: [PATCH 513/778] ASoC: samsung: spdif: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-130-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/samsung/spdif.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/samsung/spdif.c b/sound/soc/samsung/spdif.c index 7d815e237e5c..28dc1bbfc8e7 100644 --- a/sound/soc/samsung/spdif.c +++ b/sound/soc/samsung/spdif.c @@ -460,7 +460,7 @@ err0: return ret; } -static int spdif_remove(struct platform_device *pdev) +static void spdif_remove(struct platform_device *pdev) { struct samsung_spdif_info *spdif = &spdif_info; struct resource *mem_res; @@ -472,13 +472,11 @@ static int spdif_remove(struct platform_device *pdev) clk_disable_unprepare(spdif->sclk); clk_disable_unprepare(spdif->pclk); - - return 0; } static struct platform_driver samsung_spdif_driver = { .probe = spdif_probe, - .remove = spdif_remove, + .remove_new = spdif_remove, .driver = { .name = "samsung-spdif", }, From 08719f469b638c09c642896878a1e7c2b7e046c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:07:02 +0100 Subject: [PATCH 514/778] ASoC: sh: fsi: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Kuninori Morimoto Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-131-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/sh/fsi.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 9f3f1af6349f..1051c306292f 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c @@ -2030,7 +2030,7 @@ exit_fsia: return ret; } -static int fsi_remove(struct platform_device *pdev) +static void fsi_remove(struct platform_device *pdev) { struct fsi_master *master; @@ -2040,8 +2040,6 @@ static int fsi_remove(struct platform_device *pdev) fsi_stream_remove(&master->fsia); fsi_stream_remove(&master->fsib); - - return 0; } static void __fsi_suspend(struct fsi_priv *fsi, @@ -2108,7 +2106,7 @@ static struct platform_driver fsi_driver = { .of_match_table = fsi_of_match, }, .probe = fsi_probe, - .remove = fsi_remove, + .remove_new = fsi_remove, .id_table = fsi_id_table, }; From 9baee32e889a646bba175fd365c4f807e42c4123 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:07:03 +0100 Subject: [PATCH 515/778] ASoC: sh: hac: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-132-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/sh/hac.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/sh/hac.c b/sound/soc/sh/hac.c index 46d145cbaf29..cc200f45826c 100644 --- a/sound/soc/sh/hac.c +++ b/sound/soc/sh/hac.c @@ -323,10 +323,9 @@ static int hac_soc_platform_probe(struct platform_device *pdev) sh4_hac_dai, ARRAY_SIZE(sh4_hac_dai)); } -static int hac_soc_platform_remove(struct platform_device *pdev) +static void hac_soc_platform_remove(struct platform_device *pdev) { snd_soc_set_ac97_ops(NULL); - return 0; } static struct platform_driver hac_pcm_driver = { @@ -335,7 +334,7 @@ static struct platform_driver hac_pcm_driver = { }, .probe = hac_soc_platform_probe, - .remove = hac_soc_platform_remove, + .remove_new = hac_soc_platform_remove, }; module_platform_driver(hac_pcm_driver); From 5310f0a3315b7c7c6757b0d4b01733efd537049e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:07:04 +0100 Subject: [PATCH 516/778] ASoC: sh: rcar: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Kuninori Morimoto Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-133-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/sh/rcar/core.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index cb17f7d0cf0c..6a522e6dd85a 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -1987,7 +1987,7 @@ exit_snd_probe: return ret; } -static int rsnd_remove(struct platform_device *pdev) +static void rsnd_remove(struct platform_device *pdev) { struct rsnd_priv *priv = dev_get_drvdata(&pdev->dev); struct rsnd_dai *rdai; @@ -2019,8 +2019,6 @@ static int rsnd_remove(struct platform_device *pdev) for (i = 0; i < ARRAY_SIZE(remove_func); i++) remove_func[i](priv); - - return 0; } static int __maybe_unused rsnd_suspend(struct device *dev) @@ -2052,7 +2050,7 @@ static struct platform_driver rsnd_driver = { .of_match_table = rsnd_of_match, }, .probe = rsnd_probe, - .remove = rsnd_remove, + .remove_new = rsnd_remove, }; module_platform_driver(rsnd_driver); From b89438c71d72a9afbf72836630bfc995fed59e68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:07:05 +0100 Subject: [PATCH 517/778] ASoC: sh: rz-ssi: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-134-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/sh/rz-ssi.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/sh/rz-ssi.c b/sound/soc/sh/rz-ssi.c index d502aa55c5a8..fe79eb90e1e5 100644 --- a/sound/soc/sh/rz-ssi.c +++ b/sound/soc/sh/rz-ssi.c @@ -1075,7 +1075,7 @@ err_reset: return ret; } -static int rz_ssi_remove(struct platform_device *pdev) +static void rz_ssi_remove(struct platform_device *pdev) { struct rz_ssi_priv *ssi = dev_get_drvdata(&pdev->dev); @@ -1084,8 +1084,6 @@ static int rz_ssi_remove(struct platform_device *pdev) pm_runtime_put(ssi->dev); pm_runtime_disable(ssi->dev); reset_control_assert(ssi->rstc); - - return 0; } static const struct of_device_id rz_ssi_of_match[] = { @@ -1100,7 +1098,7 @@ static struct platform_driver rz_ssi_driver = { .of_match_table = rz_ssi_of_match, }, .probe = rz_ssi_probe, - .remove = rz_ssi_remove, + .remove_new = rz_ssi_remove, }; module_platform_driver(rz_ssi_driver); From 4136b45d25b2120355bbb8f35cc5102ec7e5b428 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:07:06 +0100 Subject: [PATCH 518/778] ASoC: sh: siu_dai: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-135-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/sh/siu_dai.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/sh/siu_dai.c b/sound/soc/sh/siu_dai.c index f2a386fcd92e..84e1b14e68e4 100644 --- a/sound/soc/sh/siu_dai.c +++ b/sound/soc/sh/siu_dai.c @@ -778,10 +778,9 @@ static int siu_probe(struct platform_device *pdev) return 0; } -static int siu_remove(struct platform_device *pdev) +static void siu_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - return 0; } static struct platform_driver siu_driver = { @@ -789,7 +788,7 @@ static struct platform_driver siu_driver = { .name = "siu-pcm-audio", }, .probe = siu_probe, - .remove = siu_remove, + .remove_new = siu_remove, }; module_platform_driver(siu_driver); From ed771e2beafa5687eba623fbde24d88ec61aa9aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:07:07 +0100 Subject: [PATCH 519/778] ASoC: sprd: sprd-mcdt: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-136-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/sprd/sprd-mcdt.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/sprd/sprd-mcdt.c b/sound/soc/sprd/sprd-mcdt.c index f6a55fa60c1b..688419c6b092 100644 --- a/sound/soc/sprd/sprd-mcdt.c +++ b/sound/soc/sprd/sprd-mcdt.c @@ -973,7 +973,7 @@ static int sprd_mcdt_probe(struct platform_device *pdev) return 0; } -static int sprd_mcdt_remove(struct platform_device *pdev) +static void sprd_mcdt_remove(struct platform_device *pdev) { struct sprd_mcdt_chan *chan, *temp; @@ -983,8 +983,6 @@ static int sprd_mcdt_remove(struct platform_device *pdev) list_del(&chan->list); mutex_unlock(&sprd_mcdt_list_mutex); - - return 0; } static const struct of_device_id sprd_mcdt_of_match[] = { @@ -995,7 +993,7 @@ MODULE_DEVICE_TABLE(of, sprd_mcdt_of_match); static struct platform_driver sprd_mcdt_driver = { .probe = sprd_mcdt_probe, - .remove = sprd_mcdt_remove, + .remove_new = sprd_mcdt_remove, .driver = { .name = "sprd-mcdt", .of_match_table = sprd_mcdt_of_match, From 6cd293d206ad4b3c42854685a00b5e5d10a10aee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:07:08 +0100 Subject: [PATCH 520/778] ASoC: stm: stm32_adfsdm: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-137-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/stm/stm32_adfsdm.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/stm/stm32_adfsdm.c b/sound/soc/stm/stm32_adfsdm.c index 837c1848d9bf..a8fff7378641 100644 --- a/sound/soc/stm/stm32_adfsdm.c +++ b/sound/soc/stm/stm32_adfsdm.c @@ -386,12 +386,10 @@ static int stm32_adfsdm_probe(struct platform_device *pdev) return ret; } -static int stm32_adfsdm_remove(struct platform_device *pdev) +static void stm32_adfsdm_remove(struct platform_device *pdev) { snd_soc_unregister_component(&pdev->dev); pm_runtime_disable(&pdev->dev); - - return 0; } static struct platform_driver stm32_adfsdm_driver = { @@ -400,7 +398,7 @@ static struct platform_driver stm32_adfsdm_driver = { .of_match_table = stm32_adfsdm_of_match, }, .probe = stm32_adfsdm_probe, - .remove = stm32_adfsdm_remove, + .remove_new = stm32_adfsdm_remove, }; module_platform_driver(stm32_adfsdm_driver); From 607e4cf57396ebd5d4f45dfdf18933207704b1e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:07:09 +0100 Subject: [PATCH 521/778] ASoC: stm: stm32_i2s: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-138-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/stm/stm32_i2s.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/stm/stm32_i2s.c b/sound/soc/stm/stm32_i2s.c index 9dad85ecb93f..387130701960 100644 --- a/sound/soc/stm/stm32_i2s.c +++ b/sound/soc/stm/stm32_i2s.c @@ -1097,13 +1097,11 @@ static int stm32_i2s_parse_dt(struct platform_device *pdev, return 0; } -static int stm32_i2s_remove(struct platform_device *pdev) +static void stm32_i2s_remove(struct platform_device *pdev) { snd_dmaengine_pcm_unregister(&pdev->dev); snd_soc_unregister_component(&pdev->dev); pm_runtime_disable(&pdev->dev); - - return 0; } static int stm32_i2s_probe(struct platform_device *pdev) @@ -1221,7 +1219,7 @@ static struct platform_driver stm32_i2s_driver = { .pm = &stm32_i2s_pm_ops, }, .probe = stm32_i2s_probe, - .remove = stm32_i2s_remove, + .remove_new = stm32_i2s_remove, }; module_platform_driver(stm32_i2s_driver); From a3bd37e2e2bce4fb1757a940fa985d556662ba80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:07:10 +0100 Subject: [PATCH 522/778] ASoC: stm: stm32_sai_sub: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-139-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/stm/stm32_sai_sub.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c index 8ba4206f751d..f6695dee353b 100644 --- a/sound/soc/stm/stm32_sai_sub.c +++ b/sound/soc/stm/stm32_sai_sub.c @@ -1559,7 +1559,7 @@ static int stm32_sai_sub_probe(struct platform_device *pdev) return 0; } -static int stm32_sai_sub_remove(struct platform_device *pdev) +static void stm32_sai_sub_remove(struct platform_device *pdev) { struct stm32_sai_sub_data *sai = dev_get_drvdata(&pdev->dev); @@ -1567,8 +1567,6 @@ static int stm32_sai_sub_remove(struct platform_device *pdev) snd_dmaengine_pcm_unregister(&pdev->dev); snd_soc_unregister_component(&pdev->dev); pm_runtime_disable(&pdev->dev); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -1618,7 +1616,7 @@ static struct platform_driver stm32_sai_sub_driver = { .pm = &stm32_sai_sub_pm_ops, }, .probe = stm32_sai_sub_probe, - .remove = stm32_sai_sub_remove, + .remove_new = stm32_sai_sub_remove, }; module_platform_driver(stm32_sai_sub_driver); From c4d4ce48f8f59a464e4351258d2160a5215bb350 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:07:11 +0100 Subject: [PATCH 523/778] ASoC: stm: stm32_spdifrx: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-140-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/stm/stm32_spdifrx.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/stm/stm32_spdifrx.c b/sound/soc/stm/stm32_spdifrx.c index d399c906bb92..a4066f271f2d 100644 --- a/sound/soc/stm/stm32_spdifrx.c +++ b/sound/soc/stm/stm32_spdifrx.c @@ -939,7 +939,7 @@ static int stm32_spdifrx_parse_of(struct platform_device *pdev, return 0; } -static int stm32_spdifrx_remove(struct platform_device *pdev) +static void stm32_spdifrx_remove(struct platform_device *pdev) { struct stm32_spdifrx_data *spdifrx = platform_get_drvdata(pdev); @@ -952,8 +952,6 @@ static int stm32_spdifrx_remove(struct platform_device *pdev) snd_dmaengine_pcm_unregister(&pdev->dev); snd_soc_unregister_component(&pdev->dev); pm_runtime_disable(&pdev->dev); - - return 0; } static int stm32_spdifrx_probe(struct platform_device *pdev) @@ -1078,7 +1076,7 @@ static struct platform_driver stm32_spdifrx_driver = { .pm = &stm32_spdifrx_pm_ops, }, .probe = stm32_spdifrx_probe, - .remove = stm32_spdifrx_remove, + .remove_new = stm32_spdifrx_remove, }; module_platform_driver(stm32_spdifrx_driver); From f56a1b1026ff2e04d6f8ac83d31be3bf163888ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:07:12 +0100 Subject: [PATCH 524/778] ASoC: sunxi: sun4i-codec: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Jernej Skrabec Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-141-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/sunxi/sun4i-codec.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c index 835dc3404367..55328850aef5 100644 --- a/sound/soc/sunxi/sun4i-codec.c +++ b/sound/soc/sunxi/sun4i-codec.c @@ -1821,7 +1821,7 @@ err_clk_disable: return ret; } -static int sun4i_codec_remove(struct platform_device *pdev) +static void sun4i_codec_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct sun4i_codec *scodec = snd_soc_card_get_drvdata(card); @@ -1830,8 +1830,6 @@ static int sun4i_codec_remove(struct platform_device *pdev) if (scodec->rst) reset_control_assert(scodec->rst); clk_disable_unprepare(scodec->clk_apb); - - return 0; } static struct platform_driver sun4i_codec_driver = { @@ -1840,7 +1838,7 @@ static struct platform_driver sun4i_codec_driver = { .of_match_table = sun4i_codec_of_match, }, .probe = sun4i_codec_probe, - .remove = sun4i_codec_remove, + .remove_new = sun4i_codec_remove, }; module_platform_driver(sun4i_codec_driver); From 5423c00ee28f6cc3013b74bd1ac4090c625e91c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:07:13 +0100 Subject: [PATCH 525/778] ASoC: sunxi: sun4i-i2s: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Jernej Skrabec Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-142-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/sunxi/sun4i-i2s.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c index 6028871825ba..669d712bbe9f 100644 --- a/sound/soc/sunxi/sun4i-i2s.c +++ b/sound/soc/sunxi/sun4i-i2s.c @@ -1606,7 +1606,7 @@ err_pm_disable: return ret; } -static int sun4i_i2s_remove(struct platform_device *pdev) +static void sun4i_i2s_remove(struct platform_device *pdev) { struct sun4i_i2s *i2s = dev_get_drvdata(&pdev->dev); @@ -1616,8 +1616,6 @@ static int sun4i_i2s_remove(struct platform_device *pdev) if (!IS_ERR(i2s->rst)) reset_control_assert(i2s->rst); - - return 0; } static const struct of_device_id sun4i_i2s_match[] = { @@ -1660,7 +1658,7 @@ static const struct dev_pm_ops sun4i_i2s_pm_ops = { static struct platform_driver sun4i_i2s_driver = { .probe = sun4i_i2s_probe, - .remove = sun4i_i2s_remove, + .remove_new = sun4i_i2s_remove, .driver = { .name = "sun4i-i2s", .of_match_table = sun4i_i2s_match, From b9d01c8254899d176ef4a387232bd8166ff769b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:07:14 +0100 Subject: [PATCH 526/778] ASoC: sunxi: sun4i-spdif: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Jernej Skrabec Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-143-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/sunxi/sun4i-spdif.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/sunxi/sun4i-spdif.c b/sound/soc/sunxi/sun4i-spdif.c index bcceebca915a..ff18d4113aac 100644 --- a/sound/soc/sunxi/sun4i-spdif.c +++ b/sound/soc/sunxi/sun4i-spdif.c @@ -703,13 +703,11 @@ err_unregister: return ret; } -static int sun4i_spdif_remove(struct platform_device *pdev) +static void sun4i_spdif_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) sun4i_spdif_runtime_suspend(&pdev->dev); - - return 0; } static const struct dev_pm_ops sun4i_spdif_pm = { @@ -724,7 +722,7 @@ static struct platform_driver sun4i_spdif_driver = { .pm = &sun4i_spdif_pm, }, .probe = sun4i_spdif_probe, - .remove = sun4i_spdif_remove, + .remove_new = sun4i_spdif_remove, }; module_platform_driver(sun4i_spdif_driver); From 116d6c70fa3da6123e1529c071b521ad16af3fa5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:07:15 +0100 Subject: [PATCH 527/778] ASoC: sunxi: sun50i-dmic: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Ban Tao Acked-by: Jernej Skrabec Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-144-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/sunxi/sun50i-dmic.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/sunxi/sun50i-dmic.c b/sound/soc/sunxi/sun50i-dmic.c index 069c993acb31..c10439b9e0a2 100644 --- a/sound/soc/sunxi/sun50i-dmic.c +++ b/sound/soc/sunxi/sun50i-dmic.c @@ -373,13 +373,11 @@ err_disable_runtime_pm: return ret; } -static int sun50i_dmic_remove(struct platform_device *pdev) +static void sun50i_dmic_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) sun50i_dmic_runtime_suspend(&pdev->dev); - - return 0; } static const struct dev_pm_ops sun50i_dmic_pm = { @@ -394,7 +392,7 @@ static struct platform_driver sun50i_dmic_driver = { .pm = &sun50i_dmic_pm, }, .probe = sun50i_dmic_probe, - .remove = sun50i_dmic_remove, + .remove_new = sun50i_dmic_remove, }; module_platform_driver(sun50i_dmic_driver); From a594f423aed833bbc1d8d25dc1f9e387d2c7fddb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:07:16 +0100 Subject: [PATCH 528/778] ASoC: sunxi: sun8i-codec: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Jernej Skrabec Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-145-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/sunxi/sun8i-codec.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c index 9844978d91e6..4c0d0d7d3e58 100644 --- a/sound/soc/sunxi/sun8i-codec.c +++ b/sound/soc/sunxi/sun8i-codec.c @@ -1349,13 +1349,11 @@ err_pm_disable: return ret; } -static int sun8i_codec_remove(struct platform_device *pdev) +static void sun8i_codec_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) sun8i_codec_runtime_suspend(&pdev->dev); - - return 0; } static const struct sun8i_codec_quirks sun8i_a33_quirks = { @@ -1385,7 +1383,7 @@ static struct platform_driver sun8i_codec_driver = { .pm = &sun8i_codec_pm_ops, }, .probe = sun8i_codec_probe, - .remove = sun8i_codec_remove, + .remove_new = sun8i_codec_remove, }; module_platform_driver(sun8i_codec_driver); From 1e482d82b813ab0ec1fb4c28f54f8728580eb515 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:07:17 +0100 Subject: [PATCH 529/778] ASoC: tegra: tegra186_asrc: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-146-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/tegra/tegra186_asrc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/tegra/tegra186_asrc.c b/sound/soc/tegra/tegra186_asrc.c index 9f12faaa609d..e016a6a7f7c4 100644 --- a/sound/soc/tegra/tegra186_asrc.c +++ b/sound/soc/tegra/tegra186_asrc.c @@ -1016,11 +1016,9 @@ static int tegra186_asrc_platform_probe(struct platform_device *pdev) return 0; } -static int tegra186_asrc_platform_remove(struct platform_device *pdev) +static void tegra186_asrc_platform_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - - return 0; } static const struct dev_pm_ops tegra186_asrc_pm_ops = { @@ -1037,7 +1035,7 @@ static struct platform_driver tegra186_asrc_driver = { .pm = &tegra186_asrc_pm_ops, }, .probe = tegra186_asrc_platform_probe, - .remove = tegra186_asrc_platform_remove, + .remove_new = tegra186_asrc_platform_remove, }; module_platform_driver(tegra186_asrc_driver) From e04913cba6a651f9fbdfec397735a6df53ec0212 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:07:18 +0100 Subject: [PATCH 530/778] ASoC: tegra: tegra186_dspk: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-147-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/tegra/tegra186_dspk.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/tegra/tegra186_dspk.c b/sound/soc/tegra/tegra186_dspk.c index a74c980ee775..a0ce7eb11de9 100644 --- a/sound/soc/tegra/tegra186_dspk.c +++ b/sound/soc/tegra/tegra186_dspk.c @@ -524,11 +524,9 @@ static int tegra186_dspk_platform_probe(struct platform_device *pdev) return 0; } -static int tegra186_dspk_platform_remove(struct platform_device *pdev) +static void tegra186_dspk_platform_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - - return 0; } static const struct dev_pm_ops tegra186_dspk_pm_ops = { @@ -545,7 +543,7 @@ static struct platform_driver tegra186_dspk_driver = { .pm = &tegra186_dspk_pm_ops, }, .probe = tegra186_dspk_platform_probe, - .remove = tegra186_dspk_platform_remove, + .remove_new = tegra186_dspk_platform_remove, }; module_platform_driver(tegra186_dspk_driver); From 41067828420de3250df957b2b0c50a33ba8e569e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:07:19 +0100 Subject: [PATCH 531/778] ASoC: tegra: tegra20_ac97: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-148-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/tegra/tegra20_ac97.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/tegra/tegra20_ac97.c b/sound/soc/tegra/tegra20_ac97.c index d23d88a10899..fea6955f7f43 100644 --- a/sound/soc/tegra/tegra20_ac97.c +++ b/sound/soc/tegra/tegra20_ac97.c @@ -429,7 +429,7 @@ err: return ret; } -static int tegra20_ac97_platform_remove(struct platform_device *pdev) +static void tegra20_ac97_platform_remove(struct platform_device *pdev) { struct tegra20_ac97 *ac97 = dev_get_drvdata(&pdev->dev); @@ -439,8 +439,6 @@ static int tegra20_ac97_platform_remove(struct platform_device *pdev) clk_disable_unprepare(ac97->clk_ac97); snd_soc_set_ac97_ops(NULL); - - return 0; } static const struct of_device_id tegra20_ac97_of_match[] = { @@ -454,7 +452,7 @@ static struct platform_driver tegra20_ac97_driver = { .of_match_table = tegra20_ac97_of_match, }, .probe = tegra20_ac97_platform_probe, - .remove = tegra20_ac97_platform_remove, + .remove_new = tegra20_ac97_platform_remove, }; module_platform_driver(tegra20_ac97_driver); From 81ab73dbfe6864efbcf2c7d8effff0225cac286e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:07:20 +0100 Subject: [PATCH 532/778] ASoC: tegra: tegra20_i2s: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-149-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/tegra/tegra20_i2s.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/tegra/tegra20_i2s.c b/sound/soc/tegra/tegra20_i2s.c index d37a9f2603e8..e1a0f50969c1 100644 --- a/sound/soc/tegra/tegra20_i2s.c +++ b/sound/soc/tegra/tegra20_i2s.c @@ -475,13 +475,11 @@ err: return ret; } -static int tegra20_i2s_platform_remove(struct platform_device *pdev) +static void tegra20_i2s_platform_remove(struct platform_device *pdev) { tegra_pcm_platform_unregister(&pdev->dev); snd_soc_unregister_component(&pdev->dev); pm_runtime_disable(&pdev->dev); - - return 0; } static const struct of_device_id tegra20_i2s_of_match[] = { @@ -503,7 +501,7 @@ static struct platform_driver tegra20_i2s_driver = { .pm = &tegra20_i2s_pm_ops, }, .probe = tegra20_i2s_platform_probe, - .remove = tegra20_i2s_platform_remove, + .remove_new = tegra20_i2s_platform_remove, }; module_platform_driver(tegra20_i2s_driver); From 8097e8afb9f6ec2a5c47a325f66e0163eadcdd5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:07:21 +0100 Subject: [PATCH 533/778] ASoC: tegra: tegra210_admaif: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-150-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/tegra/tegra210_admaif.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/tegra/tegra210_admaif.c b/sound/soc/tegra/tegra210_admaif.c index 100a2b6e6063..6868508585a0 100644 --- a/sound/soc/tegra/tegra210_admaif.c +++ b/sound/soc/tegra/tegra210_admaif.c @@ -842,11 +842,9 @@ static int tegra_admaif_probe(struct platform_device *pdev) return 0; } -static int tegra_admaif_remove(struct platform_device *pdev) +static void tegra_admaif_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - - return 0; } static const struct dev_pm_ops tegra_admaif_pm_ops = { @@ -858,7 +856,7 @@ static const struct dev_pm_ops tegra_admaif_pm_ops = { static struct platform_driver tegra_admaif_driver = { .probe = tegra_admaif_probe, - .remove = tegra_admaif_remove, + .remove_new = tegra_admaif_remove, .driver = { .name = "tegra210-admaif", .of_match_table = tegra_admaif_of_match, From f129152cbce6ea54ff4a4cc05a263c2c2f105c06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:07:22 +0100 Subject: [PATCH 534/778] ASoC: tegra: tegra210_adx: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-151-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/tegra/tegra210_adx.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/tegra/tegra210_adx.c b/sound/soc/tegra/tegra210_adx.c index 49691d2cce50..41117c1d61fb 100644 --- a/sound/soc/tegra/tegra210_adx.c +++ b/sound/soc/tegra/tegra210_adx.c @@ -504,11 +504,9 @@ static int tegra210_adx_platform_probe(struct platform_device *pdev) return 0; } -static int tegra210_adx_platform_remove(struct platform_device *pdev) +static void tegra210_adx_platform_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - - return 0; } static const struct dev_pm_ops tegra210_adx_pm_ops = { @@ -525,7 +523,7 @@ static struct platform_driver tegra210_adx_driver = { .pm = &tegra210_adx_pm_ops, }, .probe = tegra210_adx_platform_probe, - .remove = tegra210_adx_platform_remove, + .remove_new = tegra210_adx_platform_remove, }; module_platform_driver(tegra210_adx_driver); From f1790c464b21c42cbf5d56138c4f8791b25193f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:07:23 +0100 Subject: [PATCH 535/778] ASoC: tegra: tegra210_ahub: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-152-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/tegra/tegra210_ahub.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/tegra/tegra210_ahub.c b/sound/soc/tegra/tegra210_ahub.c index b38d205b69cc..8c00c09eeefb 100644 --- a/sound/soc/tegra/tegra210_ahub.c +++ b/sound/soc/tegra/tegra210_ahub.c @@ -1410,11 +1410,9 @@ static int tegra_ahub_probe(struct platform_device *pdev) return 0; } -static int tegra_ahub_remove(struct platform_device *pdev) +static void tegra_ahub_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - - return 0; } static const struct dev_pm_ops tegra_ahub_pm_ops = { @@ -1426,7 +1424,7 @@ static const struct dev_pm_ops tegra_ahub_pm_ops = { static struct platform_driver tegra_ahub_driver = { .probe = tegra_ahub_probe, - .remove = tegra_ahub_remove, + .remove_new = tegra_ahub_remove, .driver = { .name = "tegra210-ahub", .of_match_table = tegra_ahub_of_match, From f3ac69d50c58340640b4e15466cbf32c0f040f67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:07:24 +0100 Subject: [PATCH 536/778] ASoC: tegra: tegra210_amx: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-153-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/tegra/tegra210_amx.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/tegra/tegra210_amx.c b/sound/soc/tegra/tegra210_amx.c index d064cc67fea6..782a141b65c0 100644 --- a/sound/soc/tegra/tegra210_amx.c +++ b/sound/soc/tegra/tegra210_amx.c @@ -573,11 +573,9 @@ static int tegra210_amx_platform_probe(struct platform_device *pdev) return 0; } -static int tegra210_amx_platform_remove(struct platform_device *pdev) +static void tegra210_amx_platform_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - - return 0; } static const struct dev_pm_ops tegra210_amx_pm_ops = { @@ -594,7 +592,7 @@ static struct platform_driver tegra210_amx_driver = { .pm = &tegra210_amx_pm_ops, }, .probe = tegra210_amx_platform_probe, - .remove = tegra210_amx_platform_remove, + .remove_new = tegra210_amx_platform_remove, }; module_platform_driver(tegra210_amx_driver); From 7ffba01bcd3e5e4e6ebb13348b6d9975015ab9e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:07:25 +0100 Subject: [PATCH 537/778] ASoC: tegra: tegra210_dmic: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-154-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/tegra/tegra210_dmic.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/tegra/tegra210_dmic.c b/sound/soc/tegra/tegra210_dmic.c index db95794530f4..763b206cd52b 100644 --- a/sound/soc/tegra/tegra210_dmic.c +++ b/sound/soc/tegra/tegra210_dmic.c @@ -534,11 +534,9 @@ static int tegra210_dmic_probe(struct platform_device *pdev) return 0; } -static int tegra210_dmic_remove(struct platform_device *pdev) +static void tegra210_dmic_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - - return 0; } static const struct dev_pm_ops tegra210_dmic_pm_ops = { @@ -561,7 +559,7 @@ static struct platform_driver tegra210_dmic_driver = { .pm = &tegra210_dmic_pm_ops, }, .probe = tegra210_dmic_probe, - .remove = tegra210_dmic_remove, + .remove_new = tegra210_dmic_remove, }; module_platform_driver(tegra210_dmic_driver) From e29df600149b08dc4b045da5c05df49c48b99436 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:07:26 +0100 Subject: [PATCH 538/778] ASoC: tegra: tegra210_i2s: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-155-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/tegra/tegra210_i2s.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/tegra/tegra210_i2s.c b/sound/soc/tegra/tegra210_i2s.c index 39ffa4d76b59..21724cd3525e 100644 --- a/sound/soc/tegra/tegra210_i2s.c +++ b/sound/soc/tegra/tegra210_i2s.c @@ -931,11 +931,9 @@ static int tegra210_i2s_probe(struct platform_device *pdev) return 0; } -static int tegra210_i2s_remove(struct platform_device *pdev) +static void tegra210_i2s_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - - return 0; } static const struct dev_pm_ops tegra210_i2s_pm_ops = { @@ -958,7 +956,7 @@ static struct platform_driver tegra210_i2s_driver = { .pm = &tegra210_i2s_pm_ops, }, .probe = tegra210_i2s_probe, - .remove = tegra210_i2s_remove, + .remove_new = tegra210_i2s_remove, }; module_platform_driver(tegra210_i2s_driver) From e0d782fad1f23dfa9d5b2e7144a433d502fd5845 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:07:27 +0100 Subject: [PATCH 539/778] ASoC: tegra: tegra210_mixer: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-156-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/tegra/tegra210_mixer.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/tegra/tegra210_mixer.c b/sound/soc/tegra/tegra210_mixer.c index 16e679a95658..035e9035b533 100644 --- a/sound/soc/tegra/tegra210_mixer.c +++ b/sound/soc/tegra/tegra210_mixer.c @@ -656,11 +656,9 @@ static int tegra210_mixer_platform_probe(struct platform_device *pdev) return 0; } -static int tegra210_mixer_platform_remove(struct platform_device *pdev) +static void tegra210_mixer_platform_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - - return 0; } static const struct dev_pm_ops tegra210_mixer_pm_ops = { @@ -677,7 +675,7 @@ static struct platform_driver tegra210_mixer_driver = { .pm = &tegra210_mixer_pm_ops, }, .probe = tegra210_mixer_platform_probe, - .remove = tegra210_mixer_platform_remove, + .remove_new = tegra210_mixer_platform_remove, }; module_platform_driver(tegra210_mixer_driver); From f94195ff022e5f39b6a1d4e2bcfa6f49dc32b4b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:07:28 +0100 Subject: [PATCH 540/778] ASoC: tegra: tegra210_mvc: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-157-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/tegra/tegra210_mvc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/tegra/tegra210_mvc.c b/sound/soc/tegra/tegra210_mvc.c index 725385e17d84..44f465e11bee 100644 --- a/sound/soc/tegra/tegra210_mvc.c +++ b/sound/soc/tegra/tegra210_mvc.c @@ -748,11 +748,9 @@ static int tegra210_mvc_platform_probe(struct platform_device *pdev) return 0; } -static int tegra210_mvc_platform_remove(struct platform_device *pdev) +static void tegra210_mvc_platform_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - - return 0; } static const struct dev_pm_ops tegra210_mvc_pm_ops = { @@ -769,7 +767,7 @@ static struct platform_driver tegra210_mvc_driver = { .pm = &tegra210_mvc_pm_ops, }, .probe = tegra210_mvc_platform_probe, - .remove = tegra210_mvc_platform_remove, + .remove_new = tegra210_mvc_platform_remove, }; module_platform_driver(tegra210_mvc_driver) From 37831f8c144136ddb5a9f8794a5581bc8030f3f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:07:29 +0100 Subject: [PATCH 541/778] ASoC: tegra: tegra210_ope: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-158-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/tegra/tegra210_ope.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/tegra/tegra210_ope.c b/sound/soc/tegra/tegra210_ope.c index 3dd2bdec657b..98e726432615 100644 --- a/sound/soc/tegra/tegra210_ope.c +++ b/sound/soc/tegra/tegra210_ope.c @@ -347,11 +347,9 @@ static int tegra210_ope_probe(struct platform_device *pdev) return 0; } -static int tegra210_ope_remove(struct platform_device *pdev) +static void tegra210_ope_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - - return 0; } static int __maybe_unused tegra210_ope_runtime_suspend(struct device *dev) @@ -410,7 +408,7 @@ static struct platform_driver tegra210_ope_driver = { .pm = &tegra210_ope_pm_ops, }, .probe = tegra210_ope_probe, - .remove = tegra210_ope_remove, + .remove_new = tegra210_ope_remove, }; module_platform_driver(tegra210_ope_driver) From 0e25bed50aafe5d7fe46671f9bd4f3480ef19e10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:07:30 +0100 Subject: [PATCH 542/778] ASoC: tegra: tegra210_sfc: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-159-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/tegra/tegra210_sfc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/tegra/tegra210_sfc.c b/sound/soc/tegra/tegra210_sfc.c index 368f077e7bee..e9df1ffc8a58 100644 --- a/sound/soc/tegra/tegra210_sfc.c +++ b/sound/soc/tegra/tegra210_sfc.c @@ -3584,11 +3584,9 @@ static int tegra210_sfc_platform_probe(struct platform_device *pdev) return 0; } -static int tegra210_sfc_platform_remove(struct platform_device *pdev) +static void tegra210_sfc_platform_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - - return 0; } static const struct dev_pm_ops tegra210_sfc_pm_ops = { @@ -3605,7 +3603,7 @@ static struct platform_driver tegra210_sfc_driver = { .pm = &tegra210_sfc_pm_ops, }, .probe = tegra210_sfc_platform_probe, - .remove = tegra210_sfc_platform_remove, + .remove_new = tegra210_sfc_platform_remove, }; module_platform_driver(tegra210_sfc_driver) From b17cf43d704bd556f866057af9e8c227e0c382ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:07:31 +0100 Subject: [PATCH 543/778] ASoC: tegra: tegra30_ahub: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-160-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/tegra/tegra30_ahub.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/tegra/tegra30_ahub.c b/sound/soc/tegra/tegra30_ahub.c index ef011a488ceb..d2e8078e444a 100644 --- a/sound/soc/tegra/tegra30_ahub.c +++ b/sound/soc/tegra/tegra30_ahub.c @@ -592,13 +592,11 @@ err_unset_ahub: return ret; } -static int tegra30_ahub_remove(struct platform_device *pdev) +static void tegra30_ahub_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); ahub = NULL; - - return 0; } static const struct dev_pm_ops tegra30_ahub_pm_ops = { @@ -610,7 +608,7 @@ static const struct dev_pm_ops tegra30_ahub_pm_ops = { static struct platform_driver tegra30_ahub_driver = { .probe = tegra30_ahub_probe, - .remove = tegra30_ahub_remove, + .remove_new = tegra30_ahub_remove, .driver = { .name = DRV_NAME, .of_match_table = tegra30_ahub_of_match, From d148a8d46583590166711ff7c3f3644242b7563a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:07:32 +0100 Subject: [PATCH 544/778] ASoC: tegra: tegra30_i2s: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-161-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/tegra/tegra30_i2s.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c index c26f960c6afd..644280603095 100644 --- a/sound/soc/tegra/tegra30_i2s.c +++ b/sound/soc/tegra/tegra30_i2s.c @@ -531,7 +531,7 @@ err: return ret; } -static int tegra30_i2s_platform_remove(struct platform_device *pdev) +static void tegra30_i2s_platform_remove(struct platform_device *pdev) { struct tegra30_i2s *i2s = dev_get_drvdata(&pdev->dev); @@ -545,8 +545,6 @@ static int tegra30_i2s_platform_remove(struct platform_device *pdev) tegra30_ahub_free_tx_fifo(i2s->playback_fifo_cif); pm_runtime_disable(&pdev->dev); - - return 0; } static const struct dev_pm_ops tegra30_i2s_pm_ops = { @@ -563,7 +561,7 @@ static struct platform_driver tegra30_i2s_driver = { .pm = &tegra30_i2s_pm_ops, }, .probe = tegra30_i2s_platform_probe, - .remove = tegra30_i2s_platform_remove, + .remove_new = tegra30_i2s_platform_remove, }; module_platform_driver(tegra30_i2s_driver); From 2ade2cf2b00c8746f26ed64cb9bb32daa5efbed0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:07:33 +0100 Subject: [PATCH 545/778] ASoC: ti: ams-delta: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-162-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/ti/ams-delta.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/ti/ams-delta.c b/sound/soc/ti/ams-delta.c index 438e2fa843a0..1028b5efcfff 100644 --- a/sound/soc/ti/ams-delta.c +++ b/sound/soc/ti/ams-delta.c @@ -578,7 +578,7 @@ static int ams_delta_probe(struct platform_device *pdev) return 0; } -static int ams_delta_remove(struct platform_device *pdev) +static void ams_delta_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); @@ -586,7 +586,6 @@ static int ams_delta_remove(struct platform_device *pdev) snd_soc_unregister_card(card); card->dev = NULL; - return 0; } #define DRV_NAME "ams-delta-audio" @@ -596,7 +595,7 @@ static struct platform_driver ams_delta_driver = { .name = DRV_NAME, }, .probe = ams_delta_probe, - .remove = ams_delta_remove, + .remove_new = ams_delta_remove, }; module_platform_driver(ams_delta_driver); From a4d121f6f7e9d46a54abd7efed46112cee28188f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:07:34 +0100 Subject: [PATCH 546/778] ASoC: ti: davinci-i2s: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-163-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/ti/davinci-i2s.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/ti/davinci-i2s.c b/sound/soc/ti/davinci-i2s.c index 3ccd0cfca008..97dd1634b6be 100644 --- a/sound/soc/ti/davinci-i2s.c +++ b/sound/soc/ti/davinci-i2s.c @@ -739,7 +739,7 @@ err_put_clk: return ret; } -static int davinci_i2s_remove(struct platform_device *pdev) +static void davinci_i2s_remove(struct platform_device *pdev) { struct davinci_mcbsp_dev *dev = dev_get_drvdata(&pdev->dev); @@ -748,8 +748,6 @@ static int davinci_i2s_remove(struct platform_device *pdev) clk_disable(dev->clk); clk_put(dev->clk); dev->clk = NULL; - - return 0; } static const struct of_device_id davinci_i2s_match[] __maybe_unused = { @@ -760,7 +758,7 @@ MODULE_DEVICE_TABLE(of, davinci_i2s_match); static struct platform_driver davinci_mcbsp_driver = { .probe = davinci_i2s_probe, - .remove = davinci_i2s_remove, + .remove_new = davinci_i2s_remove, .driver = { .name = "davinci-mcbsp", .of_match_table = of_match_ptr(davinci_i2s_match), From 09382b0150f0ced1d70330a11fe23c42137c0bd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:07:35 +0100 Subject: [PATCH 547/778] ASoC: ti: davinci-mcasp: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-164-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/ti/davinci-mcasp.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c index 578254549d2d..c0892be2992b 100644 --- a/sound/soc/ti/davinci-mcasp.c +++ b/sound/soc/ti/davinci-mcasp.c @@ -2461,11 +2461,9 @@ err: return ret; } -static int davinci_mcasp_remove(struct platform_device *pdev) +static void davinci_mcasp_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - - return 0; } #ifdef CONFIG_PM @@ -2531,7 +2529,7 @@ static const struct dev_pm_ops davinci_mcasp_pm_ops = { static struct platform_driver davinci_mcasp_driver = { .probe = davinci_mcasp_probe, - .remove = davinci_mcasp_remove, + .remove_new = davinci_mcasp_remove, .driver = { .name = "davinci-mcasp", .pm = &davinci_mcasp_pm_ops, From f12b0d036382dec00815780a3c2d998c1c92a422 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:07:36 +0100 Subject: [PATCH 548/778] ASoC: ti: omap-hdmi: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-165-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/ti/omap-hdmi.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/ti/omap-hdmi.c b/sound/soc/ti/omap-hdmi.c index 0dc0475670ff..ad37785e05d8 100644 --- a/sound/soc/ti/omap-hdmi.c +++ b/sound/soc/ti/omap-hdmi.c @@ -398,12 +398,11 @@ static int omap_hdmi_audio_probe(struct platform_device *pdev) return 0; } -static int omap_hdmi_audio_remove(struct platform_device *pdev) +static void omap_hdmi_audio_remove(struct platform_device *pdev) { struct hdmi_audio_data *ad = platform_get_drvdata(pdev); snd_soc_unregister_card(ad->card); - return 0; } static struct platform_driver hdmi_audio_driver = { @@ -411,7 +410,7 @@ static struct platform_driver hdmi_audio_driver = { .name = DRV_NAME, }, .probe = omap_hdmi_audio_probe, - .remove = omap_hdmi_audio_remove, + .remove_new = omap_hdmi_audio_remove, }; module_platform_driver(hdmi_audio_driver); From 9b6818bb3c58de41f987554bf27db3058c5e6838 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:07:37 +0100 Subject: [PATCH 549/778] ASoC: ti: omap-mcbsp: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-166-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/ti/omap-mcbsp.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/ti/omap-mcbsp.c b/sound/soc/ti/omap-mcbsp.c index 7c539a41a6a3..21fa7b978799 100644 --- a/sound/soc/ti/omap-mcbsp.c +++ b/sound/soc/ti/omap-mcbsp.c @@ -1412,7 +1412,7 @@ static int asoc_mcbsp_probe(struct platform_device *pdev) return sdma_pcm_platform_register(&pdev->dev, "tx", "rx"); } -static int asoc_mcbsp_remove(struct platform_device *pdev) +static void asoc_mcbsp_remove(struct platform_device *pdev) { struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev); @@ -1421,8 +1421,6 @@ static int asoc_mcbsp_remove(struct platform_device *pdev) if (cpu_latency_qos_request_active(&mcbsp->pm_qos_req)) cpu_latency_qos_remove_request(&mcbsp->pm_qos_req); - - return 0; } static struct platform_driver asoc_mcbsp_driver = { @@ -1432,7 +1430,7 @@ static struct platform_driver asoc_mcbsp_driver = { }, .probe = asoc_mcbsp_probe, - .remove = asoc_mcbsp_remove, + .remove_new = asoc_mcbsp_remove, }; module_platform_driver(asoc_mcbsp_driver); From 048d658978107f1a6b517297acb2eb08dd70b4c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:07:38 +0100 Subject: [PATCH 550/778] ASoC: uniphier: evea: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-167-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/uniphier/evea.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/uniphier/evea.c b/sound/soc/uniphier/evea.c index 42403ae8e31b..d90b3e4b0104 100644 --- a/sound/soc/uniphier/evea.c +++ b/sound/soc/uniphier/evea.c @@ -536,7 +536,7 @@ err_out_clock: return ret; } -static int evea_remove(struct platform_device *pdev) +static void evea_remove(struct platform_device *pdev) { struct evea_priv *evea = platform_get_drvdata(pdev); @@ -546,8 +546,6 @@ static int evea_remove(struct platform_device *pdev) clk_disable_unprepare(evea->clk_exiv); clk_disable_unprepare(evea->clk); - - return 0; } static const struct of_device_id evea_of_match[] __maybe_unused = { @@ -562,7 +560,7 @@ static struct platform_driver evea_codec_driver = { .of_match_table = of_match_ptr(evea_of_match), }, .probe = evea_probe, - .remove = evea_remove, + .remove_new = evea_remove, }; module_platform_driver(evea_codec_driver); From d2b6d5b85a651f4678e7c8343df4d93cc736489b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:07:39 +0100 Subject: [PATCH 551/778] ASoC: ux500: mop500: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Linus Walleij Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-168-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/ux500/mop500.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/ux500/mop500.c b/sound/soc/ux500/mop500.c index 325e75e96136..e0ab4534fe3e 100644 --- a/sound/soc/ux500/mop500.c +++ b/sound/soc/ux500/mop500.c @@ -134,7 +134,7 @@ static int mop500_probe(struct platform_device *pdev) return ret; } -static int mop500_remove(struct platform_device *pdev) +static void mop500_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); @@ -143,8 +143,6 @@ static int mop500_remove(struct platform_device *pdev) snd_soc_unregister_card(card); mop500_ab8500_remove(card); mop500_of_node_put(); - - return 0; } static const struct of_device_id snd_soc_mop500_match[] = { @@ -159,7 +157,7 @@ static struct platform_driver snd_soc_mop500_driver = { .of_match_table = snd_soc_mop500_match, }, .probe = mop500_probe, - .remove = mop500_remove, + .remove_new = mop500_remove, }; module_platform_driver(snd_soc_mop500_driver); From 316a6bbfb878b710cd0c28c4fcce47a299bbd64c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:07:40 +0100 Subject: [PATCH 552/778] ASoC: ux500: ux500_msp_dai: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Linus Walleij Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-169-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/ux500/ux500_msp_dai.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/ux500/ux500_msp_dai.c b/sound/soc/ux500/ux500_msp_dai.c index 6fb1a5c207bc..44e88dad8584 100644 --- a/sound/soc/ux500/ux500_msp_dai.c +++ b/sound/soc/ux500/ux500_msp_dai.c @@ -791,7 +791,7 @@ err_reg_plat: return ret; } -static int ux500_msp_drv_remove(struct platform_device *pdev) +static void ux500_msp_drv_remove(struct platform_device *pdev) { struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(&pdev->dev); @@ -802,8 +802,6 @@ static int ux500_msp_drv_remove(struct platform_device *pdev) prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP, "ux500_msp_i2s"); ux500_msp_i2s_cleanup_msp(pdev, drvdata->msp); - - return 0; } static const struct of_device_id ux500_msp_i2s_match[] = { @@ -818,7 +816,7 @@ static struct platform_driver msp_i2s_driver = { .of_match_table = ux500_msp_i2s_match, }, .probe = ux500_msp_drv_probe, - .remove = ux500_msp_drv_remove, + .remove_new = ux500_msp_drv_remove, }; module_platform_driver(msp_i2s_driver); From bf6b5ced96cdaec0af1621ecd4f245a907ed3b06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:07:41 +0100 Subject: [PATCH 553/778] ASoC: xilinx: xlnx_formatter_pcm: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-170-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/xilinx/xlnx_formatter_pcm.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/xilinx/xlnx_formatter_pcm.c b/sound/soc/xilinx/xlnx_formatter_pcm.c index ff1fe62fea70..299cfb5e2022 100644 --- a/sound/soc/xilinx/xlnx_formatter_pcm.c +++ b/sound/soc/xilinx/xlnx_formatter_pcm.c @@ -687,7 +687,7 @@ clk_err: return ret; } -static int xlnx_formatter_pcm_remove(struct platform_device *pdev) +static void xlnx_formatter_pcm_remove(struct platform_device *pdev) { int ret = 0; struct xlnx_pcm_drv_data *adata = dev_get_drvdata(&pdev->dev); @@ -703,7 +703,6 @@ static int xlnx_formatter_pcm_remove(struct platform_device *pdev) dev_err(&pdev->dev, "audio formatter reset failed\n"); clk_disable_unprepare(adata->axi_clk); - return 0; } static const struct of_device_id xlnx_formatter_pcm_of_match[] = { @@ -714,7 +713,7 @@ MODULE_DEVICE_TABLE(of, xlnx_formatter_pcm_of_match); static struct platform_driver xlnx_formatter_pcm_driver = { .probe = xlnx_formatter_pcm_probe, - .remove = xlnx_formatter_pcm_remove, + .remove_new = xlnx_formatter_pcm_remove, .driver = { .name = DRV_NAME, .of_match_table = xlnx_formatter_pcm_of_match, From 407a27b72e168aac1c192c4b977cc3ad6b41caa2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:07:42 +0100 Subject: [PATCH 554/778] ASoC: xilinx: xlnx_spdif: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-171-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/xilinx/xlnx_spdif.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/xilinx/xlnx_spdif.c b/sound/soc/xilinx/xlnx_spdif.c index 7342048e9875..d52d5fc7b5b8 100644 --- a/sound/soc/xilinx/xlnx_spdif.c +++ b/sound/soc/xilinx/xlnx_spdif.c @@ -312,12 +312,11 @@ clk_err: return ret; } -static int xlnx_spdif_remove(struct platform_device *pdev) +static void xlnx_spdif_remove(struct platform_device *pdev) { struct spdif_dev_data *ctx = dev_get_drvdata(&pdev->dev); clk_disable_unprepare(ctx->axi_clk); - return 0; } static struct platform_driver xlnx_spdif_driver = { @@ -326,7 +325,7 @@ static struct platform_driver xlnx_spdif_driver = { .of_match_table = xlnx_spdif_of_match, }, .probe = xlnx_spdif_probe, - .remove = xlnx_spdif_remove, + .remove_new = xlnx_spdif_remove, }; module_platform_driver(xlnx_spdif_driver); From cbde81bc5573ddade3d2560fe7b5e4fa80db8f7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:07:43 +0100 Subject: [PATCH 555/778] ASoC: xtensa: xtfpga-i2s: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-172-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/xtensa/xtfpga-i2s.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/xtensa/xtfpga-i2s.c b/sound/soc/xtensa/xtfpga-i2s.c index a8f156540b50..287407714af4 100644 --- a/sound/soc/xtensa/xtfpga-i2s.c +++ b/sound/soc/xtensa/xtfpga-i2s.c @@ -605,7 +605,7 @@ err: return err; } -static int xtfpga_i2s_remove(struct platform_device *pdev) +static void xtfpga_i2s_remove(struct platform_device *pdev) { struct xtfpga_i2s *i2s = dev_get_drvdata(&pdev->dev); @@ -618,7 +618,6 @@ static int xtfpga_i2s_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) xtfpga_i2s_runtime_suspend(&pdev->dev); - return 0; } #ifdef CONFIG_OF @@ -636,7 +635,7 @@ static const struct dev_pm_ops xtfpga_i2s_pm_ops = { static struct platform_driver xtfpga_i2s_driver = { .probe = xtfpga_i2s_probe, - .remove = xtfpga_i2s_remove, + .remove_new = xtfpga_i2s_remove, .driver = { .name = "xtfpga-i2s", .of_match_table = of_match_ptr(xtfpga_i2s_of_match), From 44e4b6ee0486e301bfd8f4b2948905893bcf1314 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:07:44 +0100 Subject: [PATCH 556/778] ALSA: sparc/cs4231: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-173-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/sparc/cs4231.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c index 2942c8c7a236..31bac355ec4d 100644 --- a/sound/sparc/cs4231.c +++ b/sound/sparc/cs4231.c @@ -2069,13 +2069,11 @@ static int cs4231_probe(struct platform_device *op) return -ENODEV; } -static int cs4231_remove(struct platform_device *op) +static void cs4231_remove(struct platform_device *op) { struct snd_cs4231 *chip = dev_get_drvdata(&op->dev); snd_card_free(chip->card); - - return 0; } static const struct of_device_id cs4231_match[] = { @@ -2097,7 +2095,7 @@ static struct platform_driver cs4231_driver = { .of_match_table = cs4231_match, }, .probe = cs4231_probe, - .remove = cs4231_remove, + .remove_new = cs4231_remove, }; module_platform_driver(cs4231_driver); From 9fa6137d0c7843209472bb07277f9fcffa80847a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 16:07:45 +0100 Subject: [PATCH 557/778] ALSA: sparc/dbri: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-174-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/sparc/dbri.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c index 3881e1c1b08a..376aed136a45 100644 --- a/sound/sparc/dbri.c +++ b/sound/sparc/dbri.c @@ -2656,14 +2656,12 @@ _err: return err; } -static int dbri_remove(struct platform_device *op) +static void dbri_remove(struct platform_device *op) { struct snd_card *card = dev_get_drvdata(&op->dev); snd_dbri_free(card->private_data); snd_card_free(card); - - return 0; } static const struct of_device_id dbri_match[] = { @@ -2684,7 +2682,7 @@ static struct platform_driver dbri_sbus_driver = { .of_match_table = dbri_match, }, .probe = dbri_probe, - .remove = dbri_remove, + .remove_new = dbri_remove, }; module_platform_driver(dbri_sbus_driver); From 2f43ef99ac623b6d9154c26d4f6785df18b4d8e4 Mon Sep 17 00:00:00 2001 From: Cristian Ciocaltea Date: Wed, 15 Mar 2023 13:47:58 +0200 Subject: [PATCH 558/778] ASoC: dt-bindings: everest,es8316: Document audio graph port The ES8316 codec is currently used in conjunction with audio-graph-card to provide an endpoint for binding with the other side of the audio link. This is achieved via the 'port' property, which is not allowed: rk3399-rockpro64.dtb: codec@11: Unevaluated properties are not allowed ('port' was unexpected) Fix the issue by documenting the missing property. Signed-off-by: Cristian Ciocaltea Link: https://lore.kernel.org/r/20230315114806.3819515-4-cristian.ciocaltea@collabora.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/everest,es8316.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/everest,es8316.yaml b/Documentation/devicetree/bindings/sound/everest,es8316.yaml index d9f8f0c7f6bb..80cd81ecae6f 100644 --- a/Documentation/devicetree/bindings/sound/everest,es8316.yaml +++ b/Documentation/devicetree/bindings/sound/everest,es8316.yaml @@ -28,6 +28,10 @@ properties: items: - const: mclk + port: + $ref: audio-graph-port.yaml# + unevaluatedProperties: false + "#sound-dai-cells": const: 0 From bf4062b7420d01b4fafd7211fd2dc68b916591bd Mon Sep 17 00:00:00 2001 From: Cristian Ciocaltea Date: Wed, 15 Mar 2023 13:47:59 +0200 Subject: [PATCH 559/778] ASoC: dt-bindings: rockchip: Document audio graph port The Rockchip I2S controller is currently used in conjunction with audio-graph-card to provide an endpoint for binding with the other side of the audio link. This is achieved via the 'port' property, which is not allowed: rk3399-rockpro64.dtb: i2s@ff890000: Unevaluated properties are not allowed ('port' was unexpected) Fix the issue by documenting the missing property. Signed-off-by: Cristian Ciocaltea Link: https://lore.kernel.org/r/20230315114806.3819515-5-cristian.ciocaltea@collabora.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/rockchip-i2s.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/rockchip-i2s.yaml b/Documentation/devicetree/bindings/sound/rockchip-i2s.yaml index 1cb4da300607..c32b4750651c 100644 --- a/Documentation/devicetree/bindings/sound/rockchip-i2s.yaml +++ b/Documentation/devicetree/bindings/sound/rockchip-i2s.yaml @@ -82,6 +82,10 @@ properties: resets: maxItems: 2 + port: + $ref: audio-graph-port.yaml# + unevaluatedProperties: false + rockchip,capture-channels: $ref: /schemas/types.yaml#/definitions/uint32 default: 2 From bfbae373c55e3b1c15a6ba656211dbbe7c390aa1 Mon Sep 17 00:00:00 2001 From: Cristian Ciocaltea Date: Wed, 15 Mar 2023 13:48:00 +0200 Subject: [PATCH 560/778] ASoC: dt-bindings: rockchip: i2s-tdm: Document audio graph port Document the 'port' property to allow the Rockchip I2S TDM controller to be used in conjunction with the audio-graph-card. The property will be used to provide an endpoint for binding to the other side of the audio link. Signed-off-by: Cristian Ciocaltea Link: https://lore.kernel.org/r/20230315114806.3819515-6-cristian.ciocaltea@collabora.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/rockchip,i2s-tdm.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/rockchip,i2s-tdm.yaml b/Documentation/devicetree/bindings/sound/rockchip,i2s-tdm.yaml index 4c95895de75e..7d2c2991c566 100644 --- a/Documentation/devicetree/bindings/sound/rockchip,i2s-tdm.yaml +++ b/Documentation/devicetree/bindings/sound/rockchip,i2s-tdm.yaml @@ -86,6 +86,10 @@ properties: - tx-m - rx-m + port: + $ref: audio-graph-port.yaml# + unevaluatedProperties: false + rockchip,grf: $ref: /schemas/types.yaml#/definitions/phandle description: From 9971f3358338950d9d3345184fb2c0cfc6fc8552 Mon Sep 17 00:00:00 2001 From: Cristian Ciocaltea Date: Wed, 15 Mar 2023 13:48:01 +0200 Subject: [PATCH 561/778] ASoC: dt-bindings: rockchip: i2s-tdm: Document power-domains The binding document is missing the power-domains property. Add it. Signed-off-by: Cristian Ciocaltea Link: https://lore.kernel.org/r/20230315114806.3819515-7-cristian.ciocaltea@collabora.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/rockchip,i2s-tdm.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/rockchip,i2s-tdm.yaml b/Documentation/devicetree/bindings/sound/rockchip,i2s-tdm.yaml index 7d2c2991c566..7bb6c5dff786 100644 --- a/Documentation/devicetree/bindings/sound/rockchip,i2s-tdm.yaml +++ b/Documentation/devicetree/bindings/sound/rockchip,i2s-tdm.yaml @@ -90,6 +90,9 @@ properties: $ref: audio-graph-port.yaml# unevaluatedProperties: false + power-domains: + maxItems: 1 + rockchip,grf: $ref: /schemas/types.yaml#/definitions/phandle description: From b0fe6a91fa9d5599ba3cace2748906e086c5a56e Mon Sep 17 00:00:00 2001 From: Cristian Ciocaltea Date: Wed, 15 Mar 2023 13:48:02 +0200 Subject: [PATCH 562/778] ASoC: dt-bindings: rockchip: Add compatible for RK3588 Add new compatible string for the Rockchip I2S/PCM controller found on RK3588 and RK3588S SoCs. Signed-off-by: Cristian Ciocaltea Link: https://lore.kernel.org/r/20230315114806.3819515-8-cristian.ciocaltea@collabora.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/rockchip-i2s.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/sound/rockchip-i2s.yaml b/Documentation/devicetree/bindings/sound/rockchip-i2s.yaml index c32b4750651c..fcb01abffa97 100644 --- a/Documentation/devicetree/bindings/sound/rockchip-i2s.yaml +++ b/Documentation/devicetree/bindings/sound/rockchip-i2s.yaml @@ -34,6 +34,7 @@ properties: - rockchip,rk3366-i2s - rockchip,rk3368-i2s - rockchip,rk3399-i2s + - rockchip,rk3588-i2s - rockchip,rv1126-i2s - const: rockchip,rk3066-i2s From 0e6c37610934e9b91f6f5f2599de5e2f1ab59e72 Mon Sep 17 00:00:00 2001 From: Cristian Ciocaltea Date: Wed, 15 Mar 2023 13:48:03 +0200 Subject: [PATCH 563/778] ASoC: rockchip: i2s: Add compatible for RK3588 The Rockchip I2S driver supports the RK3588/RK3588S SoCs, hence add the corresponding compatible string. Signed-off-by: Cristian Ciocaltea Link: https://lore.kernel.org/r/20230315114806.3819515-9-cristian.ciocaltea@collabora.com Signed-off-by: Mark Brown --- sound/soc/rockchip/rockchip_i2s.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c index a8758ad68442..2e24cc0570eb 100644 --- a/sound/soc/rockchip/rockchip_i2s.c +++ b/sound/soc/rockchip/rockchip_i2s.c @@ -659,6 +659,7 @@ static const struct of_device_id rockchip_i2s_match[] __maybe_unused = { { .compatible = "rockchip,rk3366-i2s", }, { .compatible = "rockchip,rk3368-i2s", }, { .compatible = "rockchip,rk3399-i2s", .data = &rk3399_i2s_pins }, + { .compatible = "rockchip,rk3588-i2s", }, { .compatible = "rockchip,rv1126-i2s", }, {}, }; From d9e909e219a843c6bf49f9affe536660f830d6fc Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 17 Mar 2023 18:36:10 -0500 Subject: [PATCH 564/778] ASoC: dt-bindings: Drop unneeded quotes Cleanup bindings dropping unneeded quotes. Once all these are fixed, checking for this can be enabled in yamllint. Signed-off-by: Rob Herring Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230317233612.3967849-1-robh@kernel.org Signed-off-by: Mark Brown --- .../bindings/sound/adi,adau1372.yaml | 2 +- .../bindings/sound/adi,max98396.yaml | 8 +++--- .../bindings/sound/audio-graph-port.yaml | 22 ++++++++-------- .../bindings/sound/audio-graph.yaml | 8 +++--- .../bindings/sound/cirrus,cs35l45.yaml | 2 +- .../bindings/sound/cirrus,cs42l42.yaml | 12 ++++----- .../bindings/sound/mt8186-afe-pcm.yaml | 6 ++--- .../sound/mt8186-mt6366-da7219-max98357.yaml | 2 +- .../sound/mt8186-mt6366-rt1019-rt5682s.yaml | 2 +- .../bindings/sound/mt8192-afe-pcm.yaml | 6 ++--- .../sound/mt8192-mt6359-rt1015-rt5682.yaml | 4 +-- .../bindings/sound/mt8195-afe-pcm.yaml | 2 +- .../bindings/sound/mt8195-mt6359.yaml | 8 +++--- .../sound/nvidia,tegra-audio-alc5632.yaml | 8 +++--- .../sound/nvidia,tegra-audio-max98090.yaml | 8 +++--- .../sound/nvidia,tegra-audio-rt5640.yaml | 6 ++--- .../sound/nvidia,tegra-audio-rt5677.yaml | 26 +++++++++---------- .../sound/nvidia,tegra-audio-sgtl5000.yaml | 6 ++--- .../sound/nvidia,tegra-audio-wm8753.yaml | 6 ++--- .../sound/nvidia,tegra-audio-wm8903.yaml | 8 +++--- .../sound/nvidia,tegra-audio-wm9712.yaml | 8 +++--- .../bindings/sound/qcom,q6asm-dais.yaml | 2 +- .../bindings/sound/renesas,rsnd.yaml | 2 +- .../devicetree/bindings/sound/sgtl5000.yaml | 6 ++--- .../bindings/sound/simple-card.yaml | 2 +- .../sound/socionext,uniphier-aio.yaml | 2 +- 26 files changed, 87 insertions(+), 87 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/adi,adau1372.yaml b/Documentation/devicetree/bindings/sound/adi,adau1372.yaml index 044bcd370d49..ea62e51aba90 100644 --- a/Documentation/devicetree/bindings/sound/adi,adau1372.yaml +++ b/Documentation/devicetree/bindings/sound/adi,adau1372.yaml @@ -32,7 +32,7 @@ properties: maxItems: 1 clock-names: - const: "mclk" + const: mclk powerdown-gpios: description: GPIO used for hardware power-down. diff --git a/Documentation/devicetree/bindings/sound/adi,max98396.yaml b/Documentation/devicetree/bindings/sound/adi,max98396.yaml index fd5aa61b467f..bdc10d4204ec 100644 --- a/Documentation/devicetree/bindings/sound/adi,max98396.yaml +++ b/Documentation/devicetree/bindings/sound/adi,max98396.yaml @@ -41,21 +41,21 @@ properties: adi,vmon-slot-no: description: slot number of the voltage sense monitor - $ref: "/schemas/types.yaml#/definitions/uint32" + $ref: /schemas/types.yaml#/definitions/uint32 minimum: 0 maximum: 15 default: 0 adi,imon-slot-no: description: slot number of the current sense monitor - $ref: "/schemas/types.yaml#/definitions/uint32" + $ref: /schemas/types.yaml#/definitions/uint32 minimum: 0 maximum: 15 default: 1 adi,spkfb-slot-no: description: slot number of speaker DSP monitor - $ref: "/schemas/types.yaml#/definitions/uint32" + $ref: /schemas/types.yaml#/definitions/uint32 minimum: 0 maximum: 15 default: 2 @@ -64,7 +64,7 @@ properties: description: Selects the PCM data input channel that is routed to the speaker audio processing bypass path. - $ref: "/schemas/types.yaml#/definitions/uint32" + $ref: /schemas/types.yaml#/definitions/uint32 minimum: 0 maximum: 15 default: 0 diff --git a/Documentation/devicetree/bindings/sound/audio-graph-port.yaml b/Documentation/devicetree/bindings/sound/audio-graph-port.yaml index 6b4e02a0695a..fa9f9a853365 100644 --- a/Documentation/devicetree/bindings/sound/audio-graph-port.yaml +++ b/Documentation/devicetree/bindings/sound/audio-graph-port.yaml @@ -16,19 +16,19 @@ definitions: $ref: /schemas/graph.yaml#/$defs/port-base properties: convert-rate: - $ref: "/schemas/sound/dai-params.yaml#/$defs/dai-sample-rate" + $ref: /schemas/sound/dai-params.yaml#/$defs/dai-sample-rate convert-channels: - $ref: "/schemas/sound/dai-params.yaml#/$defs/dai-channels" + $ref: /schemas/sound/dai-params.yaml#/$defs/dai-channels convert-sample-format: - $ref: "/schemas/sound/dai-params.yaml#/$defs/dai-sample-format" + $ref: /schemas/sound/dai-params.yaml#/$defs/dai-sample-format mclk-fs: - $ref: "simple-card.yaml#/definitions/mclk-fs" + $ref: simple-card.yaml#/definitions/mclk-fs endpoint-base: $ref: /schemas/graph.yaml#/$defs/endpoint-base properties: mclk-fs: - $ref: "simple-card.yaml#/definitions/mclk-fs" + $ref: simple-card.yaml#/definitions/mclk-fs frame-inversion: description: dai-link uses frame clock inversion $ref: /schemas/types.yaml#/definitions/flag @@ -49,11 +49,11 @@ definitions: description: Indicates system clock $ref: /schemas/types.yaml#/definitions/phandle system-clock-frequency: - $ref: "simple-card.yaml#/definitions/system-clock-frequency" + $ref: simple-card.yaml#/definitions/system-clock-frequency system-clock-direction-out: - $ref: "simple-card.yaml#/definitions/system-clock-direction-out" + $ref: simple-card.yaml#/definitions/system-clock-direction-out system-clock-fixed: - $ref: "simple-card.yaml#/definitions/system-clock-fixed" + $ref: simple-card.yaml#/definitions/system-clock-fixed dai-format: description: audio format. @@ -69,11 +69,11 @@ definitions: - msb - lsb convert-rate: - $ref: "/schemas/sound/dai-params.yaml#/$defs/dai-sample-rate" + $ref: /schemas/sound/dai-params.yaml#/$defs/dai-sample-rate convert-channels: - $ref: "/schemas/sound/dai-params.yaml#/$defs/dai-channels" + $ref: /schemas/sound/dai-params.yaml#/$defs/dai-channels convert-sample-format: - $ref: "/schemas/sound/dai-params.yaml#/$defs/dai-sample-format" + $ref: /schemas/sound/dai-params.yaml#/$defs/dai-sample-format dai-tdm-slot-num: description: Number of slots in use. diff --git a/Documentation/devicetree/bindings/sound/audio-graph.yaml b/Documentation/devicetree/bindings/sound/audio-graph.yaml index d59baedee180..c87eb91de159 100644 --- a/Documentation/devicetree/bindings/sound/audio-graph.yaml +++ b/Documentation/devicetree/bindings/sound/audio-graph.yaml @@ -15,7 +15,7 @@ properties: label: maxItems: 1 prefix: - description: "device name prefix" + description: device name prefix $ref: /schemas/types.yaml#/definitions/string routing: description: | @@ -27,11 +27,11 @@ properties: description: User specified audio sound widgets. $ref: /schemas/types.yaml#/definitions/non-unique-string-array convert-rate: - $ref: "/schemas/sound/dai-params.yaml#/$defs/dai-sample-rate" + $ref: /schemas/sound/dai-params.yaml#/$defs/dai-sample-rate convert-channels: - $ref: "/schemas/sound/dai-params.yaml#/$defs/dai-channels" + $ref: /schemas/sound/dai-params.yaml#/$defs/dai-channels convert-sample-format: - $ref: "/schemas/sound/dai-params.yaml#/$defs/dai-sample-format" + $ref: /schemas/sound/dai-params.yaml#/$defs/dai-sample-format pa-gpios: maxItems: 1 diff --git a/Documentation/devicetree/bindings/sound/cirrus,cs35l45.yaml b/Documentation/devicetree/bindings/sound/cirrus,cs35l45.yaml index 88a0ca474c3d..b79990cf4f9f 100644 --- a/Documentation/devicetree/bindings/sound/cirrus,cs35l45.yaml +++ b/Documentation/devicetree/bindings/sound/cirrus,cs35l45.yaml @@ -45,7 +45,7 @@ properties: Audio serial port SDOUT Hi-Z control. Sets the Hi-Z configuration for SDOUT pin of amplifier. Logical OR of CS35L45_ASP_TX_HIZ_xxx values. - $ref: "/schemas/types.yaml#/definitions/uint32" + $ref: /schemas/types.yaml#/definitions/uint32 minimum: 0 maximum: 3 default: 2 diff --git a/Documentation/devicetree/bindings/sound/cirrus,cs42l42.yaml b/Documentation/devicetree/bindings/sound/cirrus,cs42l42.yaml index 7356084a2ca2..af599d8735e2 100644 --- a/Documentation/devicetree/bindings/sound/cirrus,cs42l42.yaml +++ b/Documentation/devicetree/bindings/sound/cirrus,cs42l42.yaml @@ -68,7 +68,7 @@ properties: This is "normal tip sense (TS)" in the datasheet. The CS42L42_TS_INV_* defines are available for this. - $ref: "/schemas/types.yaml#/definitions/uint32" + $ref: /schemas/types.yaml#/definitions/uint32 minimum: 0 maximum: 1 @@ -87,7 +87,7 @@ properties: 7 - 1.5s The CS42L42_TS_DBNCE_* defines are available for this. - $ref: "/schemas/types.yaml#/definitions/uint32" + $ref: /schemas/types.yaml#/definitions/uint32 minimum: 0 maximum: 7 @@ -106,7 +106,7 @@ properties: 7 - 1.5s The CS42L42_TS_DBNCE_* defines are available for this. - $ref: "/schemas/types.yaml#/definitions/uint32" + $ref: /schemas/types.yaml#/definitions/uint32 minimum: 0 maximum: 7 @@ -120,7 +120,7 @@ properties: 0ms - 200ms, Default = 100ms - $ref: "/schemas/types.yaml#/definitions/uint32" + $ref: /schemas/types.yaml#/definitions/uint32 minimum: 0 maximum: 200 @@ -133,7 +133,7 @@ properties: 0ms - 20ms, Default = 10ms - $ref: "/schemas/types.yaml#/definitions/uint32" + $ref: /schemas/types.yaml#/definitions/uint32 minimum: 0 maximum: 20 @@ -169,7 +169,7 @@ properties: 3 - Slowest The CS42L42_HSBIAS_RAMP_* defines are available for this. - $ref: "/schemas/types.yaml#/definitions/uint32" + $ref: /schemas/types.yaml#/definitions/uint32 minimum: 0 maximum: 3 diff --git a/Documentation/devicetree/bindings/sound/mt8186-afe-pcm.yaml b/Documentation/devicetree/bindings/sound/mt8186-afe-pcm.yaml index 88f82d096443..7fe85b08f9df 100644 --- a/Documentation/devicetree/bindings/sound/mt8186-afe-pcm.yaml +++ b/Documentation/devicetree/bindings/sound/mt8186-afe-pcm.yaml @@ -26,15 +26,15 @@ properties: const: audiosys mediatek,apmixedsys: - $ref: "/schemas/types.yaml#/definitions/phandle" + $ref: /schemas/types.yaml#/definitions/phandle description: The phandle of the mediatek apmixedsys controller mediatek,infracfg: - $ref: "/schemas/types.yaml#/definitions/phandle" + $ref: /schemas/types.yaml#/definitions/phandle description: The phandle of the mediatek infracfg controller mediatek,topckgen: - $ref: "/schemas/types.yaml#/definitions/phandle" + $ref: /schemas/types.yaml#/definitions/phandle description: The phandle of the mediatek topckgen controller clocks: diff --git a/Documentation/devicetree/bindings/sound/mt8186-mt6366-da7219-max98357.yaml b/Documentation/devicetree/bindings/sound/mt8186-mt6366-da7219-max98357.yaml index d427f7f623db..9853c11a1330 100644 --- a/Documentation/devicetree/bindings/sound/mt8186-mt6366-da7219-max98357.yaml +++ b/Documentation/devicetree/bindings/sound/mt8186-mt6366-da7219-max98357.yaml @@ -18,7 +18,7 @@ properties: - mediatek,mt8186-mt6366-da7219-max98357-sound mediatek,platform: - $ref: "/schemas/types.yaml#/definitions/phandle" + $ref: /schemas/types.yaml#/definitions/phandle description: The phandle of MT8186 ASoC platform. headset-codec: diff --git a/Documentation/devicetree/bindings/sound/mt8186-mt6366-rt1019-rt5682s.yaml b/Documentation/devicetree/bindings/sound/mt8186-mt6366-rt1019-rt5682s.yaml index aa23b0024c46..d80083df03eb 100644 --- a/Documentation/devicetree/bindings/sound/mt8186-mt6366-rt1019-rt5682s.yaml +++ b/Documentation/devicetree/bindings/sound/mt8186-mt6366-rt1019-rt5682s.yaml @@ -19,7 +19,7 @@ properties: - mediatek,mt8186-mt6366-rt5682s-max98360-sound mediatek,platform: - $ref: "/schemas/types.yaml#/definitions/phandle" + $ref: /schemas/types.yaml#/definitions/phandle description: The phandle of MT8186 ASoC platform. dmic-gpios: diff --git a/Documentation/devicetree/bindings/sound/mt8192-afe-pcm.yaml b/Documentation/devicetree/bindings/sound/mt8192-afe-pcm.yaml index 7a25bc9b8060..064ef172bef4 100644 --- a/Documentation/devicetree/bindings/sound/mt8192-afe-pcm.yaml +++ b/Documentation/devicetree/bindings/sound/mt8192-afe-pcm.yaml @@ -24,15 +24,15 @@ properties: const: audiosys mediatek,apmixedsys: - $ref: "/schemas/types.yaml#/definitions/phandle" + $ref: /schemas/types.yaml#/definitions/phandle description: The phandle of the mediatek apmixedsys controller mediatek,infracfg: - $ref: "/schemas/types.yaml#/definitions/phandle" + $ref: /schemas/types.yaml#/definitions/phandle description: The phandle of the mediatek infracfg controller mediatek,topckgen: - $ref: "/schemas/types.yaml#/definitions/phandle" + $ref: /schemas/types.yaml#/definitions/phandle description: The phandle of the mediatek topckgen controller power-domains: diff --git a/Documentation/devicetree/bindings/sound/mt8192-mt6359-rt1015-rt5682.yaml b/Documentation/devicetree/bindings/sound/mt8192-mt6359-rt1015-rt5682.yaml index c6e614c1c30b..7e50f5d65c8f 100644 --- a/Documentation/devicetree/bindings/sound/mt8192-mt6359-rt1015-rt5682.yaml +++ b/Documentation/devicetree/bindings/sound/mt8192-mt6359-rt1015-rt5682.yaml @@ -21,11 +21,11 @@ properties: - mediatek,mt8192_mt6359_rt1015p_rt5682s mediatek,platform: - $ref: "/schemas/types.yaml#/definitions/phandle" + $ref: /schemas/types.yaml#/definitions/phandle description: The phandle of MT8192 ASoC platform. mediatek,hdmi-codec: - $ref: "/schemas/types.yaml#/definitions/phandle" + $ref: /schemas/types.yaml#/definitions/phandle description: The phandle of HDMI codec. headset-codec: diff --git a/Documentation/devicetree/bindings/sound/mt8195-afe-pcm.yaml b/Documentation/devicetree/bindings/sound/mt8195-afe-pcm.yaml index 4452a4070eff..d5adf07d46e0 100644 --- a/Documentation/devicetree/bindings/sound/mt8195-afe-pcm.yaml +++ b/Documentation/devicetree/bindings/sound/mt8195-afe-pcm.yaml @@ -32,7 +32,7 @@ properties: See ../reserved-memory/reserved-memory.txt for details. mediatek,topckgen: - $ref: "/schemas/types.yaml#/definitions/phandle" + $ref: /schemas/types.yaml#/definitions/phandle description: The phandle of the mediatek topckgen controller power-domains: diff --git a/Documentation/devicetree/bindings/sound/mt8195-mt6359.yaml b/Documentation/devicetree/bindings/sound/mt8195-mt6359.yaml index ad3447ff8b2c..c1ddbf672ca3 100644 --- a/Documentation/devicetree/bindings/sound/mt8195-mt6359.yaml +++ b/Documentation/devicetree/bindings/sound/mt8195-mt6359.yaml @@ -24,19 +24,19 @@ properties: description: User specified audio sound card name mediatek,platform: - $ref: "/schemas/types.yaml#/definitions/phandle" + $ref: /schemas/types.yaml#/definitions/phandle description: The phandle of MT8195 ASoC platform. mediatek,dptx-codec: - $ref: "/schemas/types.yaml#/definitions/phandle" + $ref: /schemas/types.yaml#/definitions/phandle description: The phandle of MT8195 Display Port Tx codec node. mediatek,hdmi-codec: - $ref: "/schemas/types.yaml#/definitions/phandle" + $ref: /schemas/types.yaml#/definitions/phandle description: The phandle of MT8195 HDMI codec node. mediatek,adsp: - $ref: "/schemas/types.yaml#/definitions/phandle" + $ref: /schemas/types.yaml#/definitions/phandle description: The phandle of MT8195 ADSP platform. mediatek,dai-link: diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-alc5632.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-alc5632.yaml index 7ef774910e5c..96f2f927a6f5 100644 --- a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-alc5632.yaml +++ b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-alc5632.yaml @@ -31,10 +31,10 @@ properties: items: enum: # Board Connectors - - "Headset Stereophone" - - "Int Spk" - - "Headset Mic" - - "Digital Mic" + - Headset Stereophone + - Int Spk + - Headset Mic + - Digital Mic # CODEC Pins - SPKOUT diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-max98090.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-max98090.yaml index ccc2ee77ca30..4d912458b18b 100644 --- a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-max98090.yaml +++ b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-max98090.yaml @@ -38,10 +38,10 @@ properties: items: enum: # Board Connectors - - "Headphones" - - "Speakers" - - "Mic Jack" - - "Int Mic" + - Headphones + - Speakers + - Mic Jack + - Int Mic # CODEC Pins - MIC1 diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-rt5640.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-rt5640.yaml index b1deaf271afa..2638592435b2 100644 --- a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-rt5640.yaml +++ b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-rt5640.yaml @@ -31,9 +31,9 @@ properties: items: enum: # Board Connectors - - "Headphones" - - "Speakers" - - "Mic Jack" + - Headphones + - Speakers + - Mic Jack # CODEC Pins - DMIC1 diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-rt5677.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-rt5677.yaml index a49997d6028b..09e1d0b18d27 100644 --- a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-rt5677.yaml +++ b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-rt5677.yaml @@ -31,11 +31,11 @@ properties: items: enum: # Board Connectors - - "Headphone" - - "Speaker" - - "Headset Mic" - - "Internal Mic 1" - - "Internal Mic 2" + - Headphone + - Speaker + - Headset Mic + - Internal Mic 1 + - Internal Mic 2 # CODEC Pins - IN1P @@ -47,14 +47,14 @@ properties: - DMIC2 - DMIC3 - DMIC4 - - "DMIC L1" - - "DMIC L2" - - "DMIC L3" - - "DMIC L4" - - "DMIC R1" - - "DMIC R2" - - "DMIC R3" - - "DMIC R4" + - DMIC L1 + - DMIC L2 + - DMIC L3 + - DMIC L4 + - DMIC R1 + - DMIC R2 + - DMIC R3 + - DMIC R4 - LOUT1 - LOUT2 - LOUT3 diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-sgtl5000.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-sgtl5000.yaml index 943e7c01741c..e5bc6a6ade24 100644 --- a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-sgtl5000.yaml +++ b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-sgtl5000.yaml @@ -31,9 +31,9 @@ properties: items: enum: # Board Connectors - - "Headphone Jack" - - "Line In Jack" - - "Mic Jack" + - Headphone Jack + - Line In Jack + - Mic Jack # CODEC Pins - HP_OUT diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm8753.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm8753.yaml index a5b431d7d0c2..3323d6a438f5 100644 --- a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm8753.yaml +++ b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm8753.yaml @@ -31,8 +31,8 @@ properties: items: enum: # Board Connectors - - "Headphone Jack" - - "Mic Jack" + - Headphone Jack + - Mic Jack # CODEC Pins - LOUT1 @@ -53,7 +53,7 @@ properties: - MIC1 - MIC2N - MIC2 - - "Mic Bias" + - Mic Bias required: - nvidia,i2s-controller diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm8903.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm8903.yaml index 1b836acab980..1be25ce4514b 100644 --- a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm8903.yaml +++ b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm8903.yaml @@ -35,10 +35,10 @@ properties: items: enum: # Board Connectors - - "Headphone Jack" - - "Int Spk" - - "Mic Jack" - - "Int Mic" + - Headphone Jack + - Int Spk + - Mic Jack + - Int Mic # CODEC Pins - IN1L diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm9712.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm9712.yaml index a1448283344b..397306b8800d 100644 --- a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm9712.yaml +++ b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm9712.yaml @@ -31,9 +31,9 @@ properties: items: enum: # Board Connectors - - "Headphone" - - "LineIn" - - "Mic" + - Headphone + - LineIn + - Mic # CODEC Pins - MONOOUT @@ -48,7 +48,7 @@ properties: - PCBEEP - MIC1 - MIC2 - - "Mic Bias" + - Mic Bias required: - nvidia,ac97-controller diff --git a/Documentation/devicetree/bindings/sound/qcom,q6asm-dais.yaml b/Documentation/devicetree/bindings/sound/qcom,q6asm-dais.yaml index 0110b38f6de9..ce811942a9f1 100644 --- a/Documentation/devicetree/bindings/sound/qcom,q6asm-dais.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,q6asm-dais.yaml @@ -56,7 +56,7 @@ patternProperties: Compress offload dai. dependencies: - is-compress-dai: ["direction"] + is-compress-dai: [ direction ] required: - reg diff --git a/Documentation/devicetree/bindings/sound/renesas,rsnd.yaml b/Documentation/devicetree/bindings/sound/renesas,rsnd.yaml index 68a93b290433..8a821dec9526 100644 --- a/Documentation/devicetree/bindings/sound/renesas,rsnd.yaml +++ b/Documentation/devicetree/bindings/sound/renesas,rsnd.yaml @@ -145,7 +145,7 @@ properties: dmas: maxItems: 1 dma-names: - const: "tx" + const: tx required: - dmas - dma-names diff --git a/Documentation/devicetree/bindings/sound/sgtl5000.yaml b/Documentation/devicetree/bindings/sound/sgtl5000.yaml index 02059d66b084..1353c051488f 100644 --- a/Documentation/devicetree/bindings/sound/sgtl5000.yaml +++ b/Documentation/devicetree/bindings/sound/sgtl5000.yaml @@ -50,7 +50,7 @@ properties: description: The bias voltage to be used in mVolts. The voltage can take values from 1.25V to 3V by 250mV steps. If this node is not mentioned or the value is unknown, then the value is set to 1.25V. - $ref: "/schemas/types.yaml#/definitions/uint32" + $ref: /schemas/types.yaml#/definitions/uint32 enum: [ 1250, 1500, 1750, 2000, 2250, 2500, 2750, 3000 ] lrclk-strength: @@ -63,7 +63,7 @@ properties: 1 = 1.66 mA 2.87 mA 4.02 mA 2 = 3.33 mA 5.74 mA 8.03 mA 3 = 4.99 mA 8.61 mA 12.05 mA - $ref: "/schemas/types.yaml#/definitions/uint32" + $ref: /schemas/types.yaml#/definitions/uint32 enum: [ 0, 1, 2, 3 ] sclk-strength: @@ -76,7 +76,7 @@ properties: 1 = 1.66 mA 2.87 mA 4.02 mA 2 = 3.33 mA 5.74 mA 8.03 mA 3 = 4.99 mA 8.61 mA 12.05 mA - $ref: "/schemas/types.yaml#/definitions/uint32" + $ref: /schemas/types.yaml#/definitions/uint32 enum: [ 0, 1, 2, 3 ] port: diff --git a/Documentation/devicetree/bindings/sound/simple-card.yaml b/Documentation/devicetree/bindings/sound/simple-card.yaml index f0d81bfe2598..066f632105b7 100644 --- a/Documentation/devicetree/bindings/sound/simple-card.yaml +++ b/Documentation/devicetree/bindings/sound/simple-card.yaml @@ -78,7 +78,7 @@ definitions: $ref: /schemas/types.yaml#/definitions/uint32 prefix: - description: "device name prefix" + description: device name prefix $ref: /schemas/types.yaml#/definitions/string label: diff --git a/Documentation/devicetree/bindings/sound/socionext,uniphier-aio.yaml b/Documentation/devicetree/bindings/sound/socionext,uniphier-aio.yaml index 9cf0efaed88e..8600520d7c47 100644 --- a/Documentation/devicetree/bindings/sound/socionext,uniphier-aio.yaml +++ b/Documentation/devicetree/bindings/sound/socionext,uniphier-aio.yaml @@ -42,7 +42,7 @@ properties: Specifies a phandle to soc-glue, which is used for changing mode of S/PDIF signal pin to output from Hi-Z. This property is optional if you use I2S signal pins only. - $ref: "/schemas/types.yaml#/definitions/phandle" + $ref: /schemas/types.yaml#/definitions/phandle "#sound-dai-cells": const: 1 From 1d52cba3b99278f178bfadf88e666648a217a813 Mon Sep 17 00:00:00 2001 From: Alexander Stein Date: Thu, 16 Mar 2023 13:36:10 +0100 Subject: [PATCH 565/778] ASoC: fsl: define a common DRIVER_NAME Instead of copying the driver name manually, use a common define. No functional change. Signed-off-by: Alexander Stein Acked-by: Shengjiu Wang Link: https://lore.kernel.org/r/20230316123611.3495597-1-alexander.stein@ew.tq-group.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl-asoc-card.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c index cdfca9fd1eb0..e956abfd50f8 100644 --- a/sound/soc/fsl/fsl-asoc-card.c +++ b/sound/soc/fsl/fsl-asoc-card.c @@ -28,6 +28,8 @@ #include "../codecs/wm8994.h" #include "../codecs/tlv320aic31xx.h" +#define DRIVER_NAME "fsl-asoc-card" + #define CS427x_SYSCLK_MCLK 0 #define RX 0 @@ -915,7 +917,7 @@ MODULE_DEVICE_TABLE(of, fsl_asoc_card_dt_ids); static struct platform_driver fsl_asoc_card_driver = { .probe = fsl_asoc_card_probe, .driver = { - .name = "fsl-asoc-card", + .name = DRIVER_NAME, .pm = &snd_soc_pm_ops, .of_match_table = fsl_asoc_card_dt_ids, }, @@ -924,5 +926,5 @@ module_platform_driver(fsl_asoc_card_driver); MODULE_DESCRIPTION("Freescale Generic ASoC Sound Card driver with ASRC"); MODULE_AUTHOR("Nicolin Chen "); -MODULE_ALIAS("platform:fsl-asoc-card"); +MODULE_ALIAS("platform:" DRIVER_NAME); MODULE_LICENSE("GPL"); From 9934844f6b49fb9964f878f12912abe689eaed5d Mon Sep 17 00:00:00 2001 From: Alexander Stein Date: Thu, 16 Mar 2023 13:36:11 +0100 Subject: [PATCH 566/778] ASoC: fsl: Specify driver name in ASoC card Set the snd_soc_card driver name which fixes the warning: fsl-asoc-card sound: ASoC: driver name too long 'imx-audio-tlv320aic32x4' -> 'imx-audio-tlv32' Signed-off-by: Alexander Stein Acked-by: Shengjiu Wang Link: https://lore.kernel.org/r/20230316123611.3495597-2-alexander.stein@ew.tq-group.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl-asoc-card.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c index e956abfd50f8..bffa1048d31e 100644 --- a/sound/soc/fsl/fsl-asoc-card.c +++ b/sound/soc/fsl/fsl-asoc-card.c @@ -609,6 +609,7 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) priv->card.dapm_routes = audio_map; priv->card.num_dapm_routes = ARRAY_SIZE(audio_map); + priv->card.driver_name = DRIVER_NAME; /* Diversify the card configurations */ if (of_device_is_compatible(np, "fsl,imx-audio-cs42888")) { codec_dai_name = "cs42888"; From 00a7ef3242f42c38c9ffdf14ab2d729fd9754391 Mon Sep 17 00:00:00 2001 From: Jianhua Lu Date: Sat, 18 Mar 2023 22:14:39 +0800 Subject: [PATCH 567/778] ASoC: cs35l41: Add 12288000 clk freq to cs35l41_fs_mon clk config There are 8 cs35l41 speaker amplifier connected to TDM in my Xiaomi Mi Pad 5 Pro tablet. In this case, it's necessary to set 12288000 (48000 * 32 * 8) clk freq for it. rate=48000, slot_width=32, slots=8. Signed-off-by: Jianhua Lu Reviewed-by: David Rhodes Link: https://lore.kernel.org/r/20230318141440.29023-1-lujianhua000@gmail.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l41.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/codecs/cs35l41.c b/sound/soc/codecs/cs35l41.c index 9ec01a5f09ca..6ac501f008ec 100644 --- a/sound/soc/codecs/cs35l41.c +++ b/sound/soc/codecs/cs35l41.c @@ -150,6 +150,7 @@ static const struct cs35l41_fs_mon_config cs35l41_fs_mon[] = { { 5644800, 16, 24 }, { 6000000, 16, 24 }, { 6144000, 16, 24 }, + { 12288000, 0, 0 }, }; static int cs35l41_get_fs_mon_config_index(int freq) From 7062e1c727ec99a9c5b40586964304d60a43f240 Mon Sep 17 00:00:00 2001 From: Simon Trimmer Date: Mon, 20 Mar 2023 11:22:38 +0000 Subject: [PATCH 568/778] firmware: cs_dsp: Introduce no_core_startstop for self-booting DSPs There are devices containing Halo Core DSPs that self-boot, cs_dsp is used to manage the running firmware but the host does not have direct control over starting and stopping the DSP and so cs_dsp should consider the DSP to be always running. Signed-off-by: Simon Trimmer Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/20230320112245.115720-2-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- drivers/firmware/cirrus/cs_dsp.c | 14 +++++++++++++- include/linux/firmware/cirrus/cs_dsp.h | 1 + 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/firmware/cirrus/cs_dsp.c b/drivers/firmware/cirrus/cs_dsp.c index f558b390fbfe..97b73a254380 100644 --- a/drivers/firmware/cirrus/cs_dsp.c +++ b/drivers/firmware/cirrus/cs_dsp.c @@ -301,6 +301,7 @@ struct cs_dsp_ops { static const struct cs_dsp_ops cs_dsp_adsp1_ops; static const struct cs_dsp_ops cs_dsp_adsp2_ops[]; static const struct cs_dsp_ops cs_dsp_halo_ops; +static const struct cs_dsp_ops cs_dsp_halo_ao_ops; struct cs_dsp_buf { struct list_head list; @@ -2821,7 +2822,10 @@ EXPORT_SYMBOL_NS_GPL(cs_dsp_adsp2_init, FW_CS_DSP); */ int cs_dsp_halo_init(struct cs_dsp *dsp) { - dsp->ops = &cs_dsp_halo_ops; + if (dsp->no_core_startstop) + dsp->ops = &cs_dsp_halo_ao_ops; + else + dsp->ops = &cs_dsp_halo_ops; return cs_dsp_common_init(dsp); } @@ -3187,6 +3191,14 @@ static const struct cs_dsp_ops cs_dsp_halo_ops = { .stop_core = cs_dsp_halo_stop_core, }; +static const struct cs_dsp_ops cs_dsp_halo_ao_ops = { + .parse_sizes = cs_dsp_adsp2_parse_sizes, + .validate_version = cs_dsp_halo_validate_version, + .setup_algs = cs_dsp_halo_setup_algs, + .region_to_reg = cs_dsp_halo_region_to_reg, + .show_fw_status = cs_dsp_halo_show_fw_status, +}; + /** * cs_dsp_chunk_write() - Format data to a DSP memory chunk * @ch: Pointer to the chunk structure diff --git a/include/linux/firmware/cirrus/cs_dsp.h b/include/linux/firmware/cirrus/cs_dsp.h index cad828e21c72..29cd11d5a3cf 100644 --- a/include/linux/firmware/cirrus/cs_dsp.h +++ b/include/linux/firmware/cirrus/cs_dsp.h @@ -156,6 +156,7 @@ struct cs_dsp { unsigned int sysclk_reg; unsigned int sysclk_mask; unsigned int sysclk_shift; + bool no_core_startstop; struct list_head alg_regions; From 0cd1fd571719e19bd6824a98855382a70e47d932 Mon Sep 17 00:00:00 2001 From: Simon Trimmer Date: Mon, 20 Mar 2023 11:22:39 +0000 Subject: [PATCH 569/778] ASoC: wm_adsp: Use no_core_startstop to prevent creating preload control The no_core_startstop flag indicates a self-booting DSP - they are considered to be always running and therefore cannot be pre-loaded. Signed-off-by: Simon Trimmer Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/20230320112245.115720-3-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm_adsp.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index ea0dbc634ecf..854d9366a745 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -1102,8 +1102,10 @@ int wm_adsp2_component_probe(struct wm_adsp *dsp, struct snd_soc_component *comp { char preload[32]; - snprintf(preload, ARRAY_SIZE(preload), "%s Preload", dsp->cs_dsp.name); - snd_soc_component_disable_pin(component, preload); + if (!dsp->cs_dsp.no_core_startstop) { + snprintf(preload, ARRAY_SIZE(preload), "%s Preload", dsp->cs_dsp.name); + snd_soc_component_disable_pin(component, preload); + } cs_dsp_init_debugfs(&dsp->cs_dsp, component->debugfs_root); From 107c167419e75213e078e4f2468c0f2f55fdd11a Mon Sep 17 00:00:00 2001 From: Simon Trimmer Date: Mon, 20 Mar 2023 11:22:40 +0000 Subject: [PATCH 570/778] firmware: cs_dsp: Support DSPs that don't require firmware download When a DSP can self-boot from ROM it is not necessary to download firmware during the powering up sequence. A DSP that required firmware download would fail in a previous configuration step if firmware was not available. Signed-off-by: Simon Trimmer Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/20230320112245.115720-4-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- drivers/firmware/cirrus/cs_dsp.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/firmware/cirrus/cs_dsp.c b/drivers/firmware/cirrus/cs_dsp.c index 97b73a254380..513136a924cf 100644 --- a/drivers/firmware/cirrus/cs_dsp.c +++ b/drivers/firmware/cirrus/cs_dsp.c @@ -1301,6 +1301,9 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware, int regions = 0; int ret, offset, type; + if (!firmware) + return 0; + ret = -EINVAL; pos = sizeof(*header) + sizeof(*adsp1_sizes) + sizeof(*footer); From 65a314b7ddc09f6b1bad8decc6670e68d45ef07d Mon Sep 17 00:00:00 2001 From: Simon Trimmer Date: Mon, 20 Mar 2023 11:22:41 +0000 Subject: [PATCH 571/778] ASoC: wm_adsp: Support DSPs that don't require firmware download When a DSP can self-boot from ROM it is not necessary to download firmware - when the DSP has the wmfw_optional flag set not finding a wmfw firmware file is a successful outcome and not an error condition. Signed-off-by: Simon Trimmer Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/167931140130.26.15590061696793062038@mailman-core.alsa-project.org Signed-off-by: Mark Brown --- sound/soc/codecs/wm_adsp.c | 3 +++ sound/soc/codecs/wm_adsp.h | 1 + 2 files changed, 4 insertions(+) diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 854d9366a745..8176b6173de9 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -850,6 +850,9 @@ static int wm_adsp_request_firmware_files(struct wm_adsp *dsp, return 0; } + if (dsp->wmfw_optional) + return 0; + adsp_err(dsp, "Failed to request firmware <%s>%s-%s-%s<-%s<%s>>.wmfw\n", cirrus_dir, dsp->part, dsp->fwf_name, wm_adsp_fw[dsp->fw].file, system_name, asoc_component_prefix); diff --git a/sound/soc/codecs/wm_adsp.h b/sound/soc/codecs/wm_adsp.h index dc2f7a096e26..173dcae2c260 100644 --- a/sound/soc/codecs/wm_adsp.h +++ b/sound/soc/codecs/wm_adsp.h @@ -34,6 +34,7 @@ struct wm_adsp { unsigned int sys_config_size; int fw; + bool wmfw_optional; struct work_struct boot_work; int (*pre_run)(struct wm_adsp *dsp); From 11520b87e2232c6e3defed69ec94f0e28fb80f84 Mon Sep 17 00:00:00 2001 From: Simon Trimmer Date: Mon, 20 Mar 2023 11:22:42 +0000 Subject: [PATCH 572/778] ASoC: wm_adsp: Expose the DSP boot work actions as wm_adsp_power_up() To support self-booting DSPs that are considered always running, the work that is usually invoked as part of a DAPM sequence needs to be triggered by a client of wm_adsp as part of it's startup sequence. These actions load firmware files that might create ALSA controls and apply configuration to the device. Signed-off-by: Simon Trimmer Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/20230320112245.115720-6-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm_adsp.c | 27 ++++++++++++++++++--------- sound/soc/codecs/wm_adsp.h | 2 ++ 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 8176b6173de9..d4bffa2f7005 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -998,11 +998,8 @@ int wm_adsp2_preloader_put(struct snd_kcontrol *kcontrol, } EXPORT_SYMBOL_GPL(wm_adsp2_preloader_put); -static void wm_adsp_boot_work(struct work_struct *work) +int wm_adsp_power_up(struct wm_adsp *dsp) { - struct wm_adsp *dsp = container_of(work, - struct wm_adsp, - boot_work); int ret = 0; char *wmfw_filename = NULL; const struct firmware *wmfw_firmware = NULL; @@ -1013,16 +1010,28 @@ static void wm_adsp_boot_work(struct work_struct *work) &wmfw_firmware, &wmfw_filename, &coeff_firmware, &coeff_filename); if (ret) - return; + return ret; - cs_dsp_power_up(&dsp->cs_dsp, - wmfw_firmware, wmfw_filename, - coeff_firmware, coeff_filename, - wm_adsp_fw_text[dsp->fw]); + ret = cs_dsp_power_up(&dsp->cs_dsp, + wmfw_firmware, wmfw_filename, + coeff_firmware, coeff_filename, + wm_adsp_fw_text[dsp->fw]); wm_adsp_release_firmware_files(dsp, wmfw_firmware, wmfw_filename, coeff_firmware, coeff_filename); + + return ret; +} +EXPORT_SYMBOL_GPL(wm_adsp_power_up); + +static void wm_adsp_boot_work(struct work_struct *work) +{ + struct wm_adsp *dsp = container_of(work, + struct wm_adsp, + boot_work); + + wm_adsp_power_up(dsp); } int wm_adsp_early_event(struct snd_soc_dapm_widget *w, diff --git a/sound/soc/codecs/wm_adsp.h b/sound/soc/codecs/wm_adsp.h index 173dcae2c260..769904d34a87 100644 --- a/sound/soc/codecs/wm_adsp.h +++ b/sound/soc/codecs/wm_adsp.h @@ -91,6 +91,8 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w, int wm_adsp_early_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event); +int wm_adsp_power_up(struct wm_adsp *dsp); + irqreturn_t wm_adsp2_bus_error(int irq, void *data); irqreturn_t wm_halo_bus_error(int irq, void *data); irqreturn_t wm_halo_wdt_expire(int irq, void *data); From 0e7d82cbea8bc0db8ced613aea04da17ac0f0249 Mon Sep 17 00:00:00 2001 From: Simon Trimmer Date: Mon, 20 Mar 2023 11:22:43 +0000 Subject: [PATCH 573/778] ASoC: wm_adsp: Add support for loading bin files without wmfw A self-booted DSP may have a file of coefficients to apply to the device even when there is no firmware to download. Signed-off-by: Simon Trimmer Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/20230320112245.115720-7-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm_adsp.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index d4bffa2f7005..c23c306dc38d 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -850,8 +850,29 @@ static int wm_adsp_request_firmware_files(struct wm_adsp *dsp, return 0; } - if (dsp->wmfw_optional) + if (dsp->wmfw_optional) { + if (system_name) { + if (asoc_component_prefix) + wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename, + cirrus_dir, system_name, + asoc_component_prefix, "bin"); + + if (!*coeff_firmware) + wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename, + cirrus_dir, system_name, + NULL, "bin"); + } + + if (!*coeff_firmware) + wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename, + "", NULL, NULL, "bin"); + + if (!*coeff_firmware) + wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename, + cirrus_dir, NULL, NULL, "bin"); + return 0; + } adsp_err(dsp, "Failed to request firmware <%s>%s-%s-%s<-%s<%s>>.wmfw\n", cirrus_dir, dsp->part, dsp->fwf_name, wm_adsp_fw[dsp->fw].file, From 991b1de830f61076b7dc29bec081a4d2e50724cf Mon Sep 17 00:00:00 2001 From: Simon Trimmer Date: Mon, 20 Mar 2023 11:22:44 +0000 Subject: [PATCH 574/778] ASoC: wm_adsp: Simplify the logging of requested firmware files This change makes the logging of firmware files more consistent and simplifies the code - a debug message is logged whether the requested file was found or not and this applies to both wmfw and bin files. Signed-off-by: Simon Trimmer Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/20230320112245.115720-8-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm_adsp.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index c23c306dc38d..216120b68b64 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -787,6 +787,8 @@ static int wm_adsp_request_firmware_file(struct wm_adsp *dsp, adsp_dbg(dsp, "Failed to request '%s'\n", *filename); kfree(*filename); *filename = NULL; + } else { + adsp_dbg(dsp, "Found '%s'\n", *filename); } return ret; @@ -807,7 +809,6 @@ static int wm_adsp_request_firmware_files(struct wm_adsp *dsp, if (!wm_adsp_request_firmware_file(dsp, wmfw_firmware, wmfw_filename, cirrus_dir, system_name, asoc_component_prefix, "wmfw")) { - adsp_dbg(dsp, "Found '%s'\n", *wmfw_filename); wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename, cirrus_dir, system_name, asoc_component_prefix, "bin"); @@ -819,7 +820,6 @@ static int wm_adsp_request_firmware_files(struct wm_adsp *dsp, if (!wm_adsp_request_firmware_file(dsp, wmfw_firmware, wmfw_filename, cirrus_dir, system_name, NULL, "wmfw")) { - adsp_dbg(dsp, "Found '%s'\n", *wmfw_filename); if (asoc_component_prefix) wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename, cirrus_dir, system_name, @@ -835,7 +835,6 @@ static int wm_adsp_request_firmware_files(struct wm_adsp *dsp, if (!wm_adsp_request_firmware_file(dsp, wmfw_firmware, wmfw_filename, "", NULL, NULL, "wmfw")) { - adsp_dbg(dsp, "Found '%s'\n", *wmfw_filename); wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename, "", NULL, NULL, "bin"); return 0; @@ -844,7 +843,6 @@ static int wm_adsp_request_firmware_files(struct wm_adsp *dsp, ret = wm_adsp_request_firmware_file(dsp, wmfw_firmware, wmfw_filename, cirrus_dir, NULL, NULL, "wmfw"); if (!ret) { - adsp_dbg(dsp, "Found '%s'\n", *wmfw_filename); wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename, cirrus_dir, NULL, NULL, "bin"); return 0; From e496112529006ce0c2cfe67d1136186e2786d2e8 Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Mon, 20 Mar 2023 11:22:45 +0000 Subject: [PATCH 575/778] ASoC: cs35l56: Add driver for Cirrus Logic CS35L56 The CS35L56 combines a high-performance mono audio amplifier, Class-H tracking inductive boost converter, Halo Core(TM) DSP and a DC-DC boost converter supporting Class-H tracking. Supported control interfaces are I2C, SPI or SoundWire. Supported audio interfaces are I2S/TDM or SoundWire. Most chip functionality is controlled by on-board ROM firmware that is always running. The driver must apply patch/tune to the firmware before using the CS35L56. Signed-off-by: Simon Trimmer Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/20230320112245.115720-9-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- MAINTAINERS | 1 + include/sound/cs35l56.h | 266 ++++++ sound/soc/codecs/Kconfig | 40 + sound/soc/codecs/Makefile | 10 + sound/soc/codecs/cs35l56-i2c.c | 83 ++ sound/soc/codecs/cs35l56-sdw.c | 528 +++++++++++ sound/soc/codecs/cs35l56-shared.c | 390 ++++++++ sound/soc/codecs/cs35l56-spi.c | 81 ++ sound/soc/codecs/cs35l56.c | 1461 +++++++++++++++++++++++++++++ sound/soc/codecs/cs35l56.h | 77 ++ 10 files changed, 2937 insertions(+) create mode 100644 include/sound/cs35l56.h create mode 100644 sound/soc/codecs/cs35l56-i2c.c create mode 100644 sound/soc/codecs/cs35l56-sdw.c create mode 100644 sound/soc/codecs/cs35l56-shared.c create mode 100644 sound/soc/codecs/cs35l56-spi.c create mode 100644 sound/soc/codecs/cs35l56.c create mode 100644 sound/soc/codecs/cs35l56.h diff --git a/MAINTAINERS b/MAINTAINERS index 02fe90adf0af..e52938f962b5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4905,6 +4905,7 @@ L: patches@opensource.cirrus.com S: Maintained F: Documentation/devicetree/bindings/sound/cirrus,cs* F: include/dt-bindings/sound/cs* +F: include/sound/cs* F: sound/pci/hda/cs* F: sound/pci/hda/hda_cs_dsp_ctl.* F: sound/soc/codecs/cs* diff --git a/include/sound/cs35l56.h b/include/sound/cs35l56.h new file mode 100644 index 000000000000..5f8ea2dfaa21 --- /dev/null +++ b/include/sound/cs35l56.h @@ -0,0 +1,266 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Common definitions for Cirrus Logic CS35L56 smart amp + * + * Copyright (C) 2023 Cirrus Logic, Inc. and + * Cirrus Logic International Semiconductor Ltd. + */ + +#ifndef __CS35L56_H +#define __CS35L56_H + +#include +#include +#include + +#define CS35L56_DEVID 0x0000000 +#define CS35L56_REVID 0x0000004 +#define CS35L56_RELID 0x000000C +#define CS35L56_OTPID 0x0000010 +#define CS35L56_SFT_RESET 0x0000020 +#define CS35L56_GLOBAL_ENABLES 0x0002014 +#define CS35L56_BLOCK_ENABLES 0x0002018 +#define CS35L56_BLOCK_ENABLES2 0x000201C +#define CS35L56_REFCLK_INPUT 0x0002C04 +#define CS35L56_GLOBAL_SAMPLE_RATE 0x0002C0C +#define CS35L56_ASP1_ENABLES1 0x0004800 +#define CS35L56_ASP1_CONTROL1 0x0004804 +#define CS35L56_ASP1_CONTROL2 0x0004808 +#define CS35L56_ASP1_CONTROL3 0x000480C +#define CS35L56_ASP1_FRAME_CONTROL1 0x0004810 +#define CS35L56_ASP1_FRAME_CONTROL5 0x0004820 +#define CS35L56_ASP1_DATA_CONTROL1 0x0004830 +#define CS35L56_ASP1_DATA_CONTROL5 0x0004840 +#define CS35L56_DACPCM1_INPUT 0x0004C00 +#define CS35L56_DACPCM2_INPUT 0x0004C08 +#define CS35L56_ASP1TX1_INPUT 0x0004C20 +#define CS35L56_ASP1TX2_INPUT 0x0004C24 +#define CS35L56_ASP1TX3_INPUT 0x0004C28 +#define CS35L56_ASP1TX4_INPUT 0x0004C2C +#define CS35L56_DSP1RX1_INPUT 0x0004C40 +#define CS35L56_DSP1RX2_INPUT 0x0004C44 +#define CS35L56_SWIRE_DP3_CH1_INPUT 0x0004C70 +#define CS35L56_SWIRE_DP3_CH2_INPUT 0x0004C74 +#define CS35L56_SWIRE_DP3_CH3_INPUT 0x0004C78 +#define CS35L56_SWIRE_DP3_CH4_INPUT 0x0004C7C +#define CS35L56_SWIRE_DP3_CH5_INPUT 0x0004C80 +#define CS35L56_SWIRE_DP3_CH6_INPUT 0x0004C84 +#define CS35L56_IRQ1_CFG 0x000E000 +#define CS35L56_IRQ1_STATUS 0x000E004 +#define CS35L56_IRQ1_EINT_1 0x000E010 +#define CS35L56_IRQ1_EINT_2 0x000E014 +#define CS35L56_IRQ1_EINT_4 0x000E01C +#define CS35L56_IRQ1_EINT_8 0x000E02C +#define CS35L56_IRQ1_EINT_18 0x000E054 +#define CS35L56_IRQ1_EINT_20 0x000E05C +#define CS35L56_IRQ1_MASK_1 0x000E090 +#define CS35L56_IRQ1_MASK_2 0x000E094 +#define CS35L56_IRQ1_MASK_4 0x000E09C +#define CS35L56_IRQ1_MASK_8 0x000E0AC +#define CS35L56_IRQ1_MASK_18 0x000E0D4 +#define CS35L56_IRQ1_MASK_20 0x000E0DC +#define CS35L56_DSP_VIRTUAL1_MBOX_1 0x0011020 +#define CS35L56_DSP_VIRTUAL1_MBOX_2 0x0011024 +#define CS35L56_DSP_VIRTUAL1_MBOX_3 0x0011028 +#define CS35L56_DSP_VIRTUAL1_MBOX_4 0x001102C +#define CS35L56_DSP_VIRTUAL1_MBOX_5 0x0011030 +#define CS35L56_DSP_VIRTUAL1_MBOX_6 0x0011034 +#define CS35L56_DSP_VIRTUAL1_MBOX_7 0x0011038 +#define CS35L56_DSP_VIRTUAL1_MBOX_8 0x001103C +#define CS35L56_DSP_RESTRICT_STS1 0x00190F0 +#define CS35L56_DSP1_XMEM_PACKED_0 0x2000000 +#define CS35L56_DSP1_XMEM_PACKED_6143 0x2005FFC +#define CS35L56_DSP1_XMEM_UNPACKED32_0 0x2400000 +#define CS35L56_DSP1_XMEM_UNPACKED32_4095 0x2403FFC +#define CS35L56_DSP1_SYS_INFO_ID 0x25E0000 +#define CS35L56_DSP1_SYS_INFO_END 0x25E004C +#define CS35L56_DSP1_AHBM_WINDOW_DEBUG_0 0x25E2040 +#define CS35L56_DSP1_AHBM_WINDOW_DEBUG_1 0x25E2044 +#define CS35L56_DSP1_XMEM_UNPACKED24_0 0x2800000 +#define CS35L56_DSP1_HALO_STATE_A1 0x2801E58 +#define CS35L56_DSP1_HALO_STATE 0x28021E0 +#define CS35L56_DSP1_PM_CUR_STATE_A1 0x2804000 +#define CS35L56_DSP1_PM_CUR_STATE 0x2804308 +#define CS35L56_DSP1_XMEM_UNPACKED24_8191 0x2807FFC +#define CS35L56_DSP1_CORE_BASE 0x2B80000 +#define CS35L56_DSP1_SCRATCH1 0x2B805C0 +#define CS35L56_DSP1_SCRATCH2 0x2B805C8 +#define CS35L56_DSP1_SCRATCH3 0x2B805D0 +#define CS35L56_DSP1_SCRATCH4 0x2B805D8 +#define CS35L56_DSP1_YMEM_PACKED_0 0x2C00000 +#define CS35L56_DSP1_YMEM_PACKED_4604 0x2C047F0 +#define CS35L56_DSP1_YMEM_UNPACKED32_0 0x3000000 +#define CS35L56_DSP1_YMEM_UNPACKED32_3070 0x3002FF8 +#define CS35L56_DSP1_YMEM_UNPACKED24_0 0x3400000 +#define CS35L56_MAIN_RENDER_USER_MUTE 0x3400024 +#define CS35L56_MAIN_RENDER_USER_VOLUME 0x340002C +#define CS35L56_MAIN_POSTURE_NUMBER 0x3400094 +#define CS35L56_TRANSDUCER_ACTUAL_PS 0x3400150 +#define CS35L56_DSP1_YMEM_UNPACKED24_6141 0x3405FF4 +#define CS35L56_DSP1_PMEM_0 0x3800000 +#define CS35L56_DSP1_PMEM_5114 0x3804FE8 + +/* DEVID */ +#define CS35L56_DEVID_MASK 0x00FFFFFF + +/* REVID */ +#define CS35L56_AREVID_MASK 0x000000F0 +#define CS35L56_MTLREVID_MASK 0x0000000F +#define CS35L56_REVID_B0 0x000000B0 + +/* ASP_ENABLES1 */ +#define CS35L56_ASP_RX2_EN_SHIFT 17 +#define CS35L56_ASP_RX1_EN_SHIFT 16 +#define CS35L56_ASP_TX4_EN_SHIFT 3 +#define CS35L56_ASP_TX3_EN_SHIFT 2 +#define CS35L56_ASP_TX2_EN_SHIFT 1 +#define CS35L56_ASP_TX1_EN_SHIFT 0 + +/* ASP_CONTROL1 */ +#define CS35L56_ASP_BCLK_FREQ_MASK 0x0000003F +#define CS35L56_ASP_BCLK_FREQ_SHIFT 0 + +/* ASP_CONTROL2 */ +#define CS35L56_ASP_RX_WIDTH_MASK 0xFF000000 +#define CS35L56_ASP_RX_WIDTH_SHIFT 24 +#define CS35L56_ASP_TX_WIDTH_MASK 0x00FF0000 +#define CS35L56_ASP_TX_WIDTH_SHIFT 16 +#define CS35L56_ASP_FMT_MASK 0x00000700 +#define CS35L56_ASP_FMT_SHIFT 8 +#define CS35L56_ASP_BCLK_INV_MASK 0x00000040 +#define CS35L56_ASP_FSYNC_INV_MASK 0x00000004 + +/* ASP_CONTROL3 */ +#define CS35L56_ASP1_DOUT_HIZ_CTRL_MASK 0x00000003 + +/* ASP_DATA_CONTROL1 */ +#define CS35L56_ASP_TX_WL_MASK 0x0000003F + +/* ASP_DATA_CONTROL5 */ +#define CS35L56_ASP_RX_WL_MASK 0x0000003F + +/* ASPTXn_INPUT */ +#define CS35L56_ASP_TXn_SRC_MASK 0x0000007F + +/* SWIRETX[1..7]_SRC SDWTXn INPUT */ +#define CS35L56_SWIRETXn_SRC_MASK 0x0000007F + +/* IRQ1_STATUS */ +#define CS35L56_IRQ1_STS_MASK 0x00000001 + +/* IRQ1_EINT_1 */ +#define CS35L56_AMP_SHORT_ERR_EINT1_MASK 0x80000000 + +/* IRQ1_EINT_2 */ +#define CS35L56_DSP_VIRTUAL2_MBOX_WR_EINT1_MASK 0x00200000 + +/* IRQ1_EINT_4 */ +#define CS35L56_OTP_BOOT_DONE_MASK 0x00000002 + +/* IRQ1_EINT_8 */ +#define CS35L56_TEMP_ERR_EINT1_MASK 0x80000000 + +/* Mixer input sources */ +#define CS35L56_INPUT_SRC_NONE 0x00 +#define CS35L56_INPUT_SRC_ASP1RX1 0x08 +#define CS35L56_INPUT_SRC_ASP1RX2 0x09 +#define CS35L56_INPUT_SRC_VMON 0x18 +#define CS35L56_INPUT_SRC_IMON 0x19 +#define CS35L56_INPUT_SRC_ERR_VOL 0x20 +#define CS35L56_INPUT_SRC_CLASSH 0x21 +#define CS35L56_INPUT_SRC_VDDBMON 0x28 +#define CS35L56_INPUT_SRC_VBSTMON 0x29 +#define CS35L56_INPUT_SRC_DSP1TX1 0x32 +#define CS35L56_INPUT_SRC_DSP1TX2 0x33 +#define CS35L56_INPUT_SRC_DSP1TX3 0x34 +#define CS35L56_INPUT_SRC_DSP1TX4 0x35 +#define CS35L56_INPUT_SRC_DSP1TX5 0x36 +#define CS35L56_INPUT_SRC_DSP1TX6 0x37 +#define CS35L56_INPUT_SRC_DSP1TX7 0x38 +#define CS35L56_INPUT_SRC_DSP1TX8 0x39 +#define CS35L56_INPUT_SRC_TEMPMON 0x3A +#define CS35L56_INPUT_SRC_INTERPOLATOR 0x40 +#define CS35L56_INPUT_SRC_SWIRE_RX1 0x44 +#define CS35L56_INPUT_SRC_SWIRE_RX2 0x45 +#define CS35L56_INPUT_SRC_SWIRE_RX3 0x46 +#define CS35L56_INPUT_MASK 0x7F + +#define CS35L56_NUM_INPUT_SRC 22 + +/* ASP formats */ +#define CS35L56_ASP_FMT_DSP_A 0 +#define CS35L56_ASP_FMT_I2S 2 + +/* ASP HiZ modes */ +#define CS35L56_ASP_UNUSED_HIZ_OFF_HIZ 3 + +/* MAIN_RENDER_ACTUAL_PS */ +#define CS35L56_PS0 0 +#define CS35L56_PS3 3 + +/* CS35L56_DSP_RESTRICT_STS1 */ +#define CS35L56_RESTRICTED_MASK 0x7 + +/* CS35L56_MAIN_RENDER_USER_MUTE */ +#define CS35L56_MAIN_RENDER_USER_MUTE_MASK 1 + +/* CS35L56_MAIN_RENDER_USER_VOLUME */ +#define CS35L56_MAIN_RENDER_USER_VOLUME_MIN -400 +#define CS35L56_MAIN_RENDER_USER_VOLUME_MAX 400 +#define CS35L56_MAIN_RENDER_USER_VOLUME_MASK 0x0000FFC0 +#define CS35L56_MAIN_RENDER_USER_VOLUME_SHIFT 6 +#define CS35L56_MAIN_RENDER_USER_VOLUME_SIGNBIT 9 + +/* CS35L56_MAIN_POSTURE_NUMBER */ +#define CS35L56_MAIN_POSTURE_MIN 0 +#define CS35L56_MAIN_POSTURE_MAX 255 +#define CS35L56_MAIN_POSTURE_MASK CS35L56_MAIN_POSTURE_MAX + +/* Software Values */ +#define CS35L56_HALO_STATE_SHUTDOWN 1 +#define CS35L56_HALO_STATE_BOOT_DONE 2 + +#define CS35L56_MBOX_CMD_AUDIO_PLAY 0x0B000001 +#define CS35L56_MBOX_CMD_AUDIO_PAUSE 0x0B000002 +#define CS35L56_MBOX_CMD_HIBERNATE_NOW 0x02000001 +#define CS35L56_MBOX_CMD_WAKEUP 0x02000002 +#define CS35L56_MBOX_CMD_PREVENT_AUTO_HIBERNATE 0x02000003 +#define CS35L56_MBOX_CMD_ALLOW_AUTO_HIBERNATE 0x02000004 +#define CS35L56_MBOX_CMD_SHUTDOWN 0x02000005 +#define CS35L56_MBOX_CMD_SYSTEM_RESET 0x02000007 + +#define CS35L56_MBOX_TIMEOUT_US 5000 +#define CS35L56_MBOX_POLL_US 250 + +#define CS35L56_PS0_POLL_US 500 +#define CS35L56_PS0_TIMEOUT_US 50000 +#define CS35L56_PS3_POLL_US 500 +#define CS35L56_PS3_TIMEOUT_US 300000 + +#define CS35L56_CONTROL_PORT_READY_US 2200 +#define CS35L56_HALO_STATE_POLL_US 1000 +#define CS35L56_HALO_STATE_TIMEOUT_US 50000 +#define CS35L56_HIBERNATE_WAKE_POLL_US 500 +#define CS35L56_HIBERNATE_WAKE_TIMEOUT_US 5000 +#define CS35L56_RESET_PULSE_MIN_US 1100 + +#define CS35L56_SDW1_PLAYBACK_PORT 1 +#define CS35L56_SDW1_CAPTURE_PORT 3 + +#define CS35L56_NUM_BULK_SUPPLIES 3 +#define CS35L56_NUM_DSP_REGIONS 5 + +extern struct regmap_config cs35l56_regmap_i2c; +extern struct regmap_config cs35l56_regmap_spi; +extern struct regmap_config cs35l56_regmap_sdw; + +extern const struct cs_dsp_region cs35l56_dsp1_regions[CS35L56_NUM_DSP_REGIONS]; +extern const char * const cs35l56_tx_input_texts[CS35L56_NUM_INPUT_SRC]; +extern const unsigned int cs35l56_tx_input_values[CS35L56_NUM_INPUT_SRC]; + +void cs35l56_patch(struct device *dev, struct regmap *regmap, u8 revid); +void cs35l56_reread_firmware_registers(struct device *dev, struct regmap *regmap); +int cs35l56_get_bclk_freq_id(unsigned int freq); +void cs35l56_fill_supply_names(struct regulator_bulk_data *data); + +#endif /* ifndef __CS35L56_H */ diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 07747565c3b5..c9fb09cf8e6b 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -68,6 +68,9 @@ config SND_SOC_ALL_CODECS imply SND_SOC_CS35L41_I2C imply SND_SOC_CS35L45_I2C imply SND_SOC_CS35L45_SPI + imply SND_SOC_CS35L56_I2C + imply SND_SOC_CS35L56_SPI + imply SND_SOC_CS35L56_SDW imply SND_SOC_CS42L42 imply SND_SOC_CS42L42_SDW imply SND_SOC_CS42L51_I2C @@ -364,6 +367,7 @@ config SND_SOC_WM_ADSP default y if SND_SOC_WM2200=y default y if SND_SOC_CS35L41_SPI=y default y if SND_SOC_CS35L41_I2C=y + default y if SND_SOC_CS35L56=y default m if SND_SOC_MADERA=m default m if SND_SOC_CS47L24=m default m if SND_SOC_WM5102=m @@ -371,6 +375,7 @@ config SND_SOC_WM_ADSP default m if SND_SOC_WM2200=m default m if SND_SOC_CS35L41_SPI=m default m if SND_SOC_CS35L41_I2C=m + default m if SND_SOC_CS35L56=m config SND_SOC_AB8500_CODEC tristate @@ -711,6 +716,41 @@ config SND_SOC_CS35L45_I2C Enable support for Cirrus Logic CS35L45 smart speaker amplifier with I2C control. +config SND_SOC_CS35L56 + tristate + +config SND_SOC_CS35L56_SHARED + tristate + +config SND_SOC_CS35L56_I2C + tristate "Cirrus Logic CS35L56 CODEC (I2C)" + depends on I2C + depends on SOUNDWIRE || !SOUNDWIRE + select REGMAP_I2C + select SND_SOC_CS35L56 + select SND_SOC_CS35L56_SHARED + help + Enable support for Cirrus Logic CS35L56 boosted amplifier with I2C control + +config SND_SOC_CS35L56_SPI + tristate "Cirrus Logic CS35L56 CODEC (SPI)" + depends on SPI_MASTER + depends on SOUNDWIRE || !SOUNDWIRE + select REGMAP_SPI + select SND_SOC_CS35L56 + select SND_SOC_CS35L56_SHARED + help + Enable support for Cirrus Logic CS35L56 boosted amplifier with SPI control + +config SND_SOC_CS35L56_SDW + tristate "Cirrus Logic CS35L56 CODEC (SDW)" + depends on SOUNDWIRE + select REGMAP + select SND_SOC_CS35L56 + select SND_SOC_CS35L56_SHARED + help + Enable support for Cirrus Logic CS35L56 boosted amplifier with SoundWire control + config SND_SOC_CS42L42_CORE tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index f1ca18f7946c..25ebce58a0ba 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -66,6 +66,11 @@ snd-soc-cs35l41-i2c-objs := cs35l41-i2c.o snd-soc-cs35l45-objs := cs35l45.o cs35l45-tables.o snd-soc-cs35l45-spi-objs := cs35l45-spi.o snd-soc-cs35l45-i2c-objs := cs35l45-i2c.o +snd-soc-cs35l56-objs := cs35l56.o +snd-soc-cs35l56-shared-objs := cs35l56-shared.o +snd-soc-cs35l56-i2c-objs := cs35l56-i2c.o +snd-soc-cs35l56-spi-objs := cs35l56-spi.o +snd-soc-cs35l56-sdw-objs := cs35l56-sdw.o snd-soc-cs42l42-objs := cs42l42.o snd-soc-cs42l42-i2c-objs := cs42l42-i2c.o snd-soc-cs42l42-sdw-objs := cs42l42-sdw.o @@ -433,6 +438,11 @@ obj-$(CONFIG_SND_SOC_CS35L41_I2C) += snd-soc-cs35l41-i2c.o obj-$(CONFIG_SND_SOC_CS35L45) += snd-soc-cs35l45.o obj-$(CONFIG_SND_SOC_CS35L45_SPI) += snd-soc-cs35l45-spi.o obj-$(CONFIG_SND_SOC_CS35L45_I2C) += snd-soc-cs35l45-i2c.o +obj-$(CONFIG_SND_SOC_CS35L56) += snd-soc-cs35l56.o +obj-$(CONFIG_SND_SOC_CS35L56_SHARED) += snd-soc-cs35l56-shared.o +obj-$(CONFIG_SND_SOC_CS35L56_I2C) += snd-soc-cs35l56-i2c.o +obj-$(CONFIG_SND_SOC_CS35L56_SPI) += snd-soc-cs35l56-spi.o +obj-$(CONFIG_SND_SOC_CS35L56_SDW) += snd-soc-cs35l56-sdw.o obj-$(CONFIG_SND_SOC_CS42L42_CORE) += snd-soc-cs42l42.o obj-$(CONFIG_SND_SOC_CS42L42) += snd-soc-cs42l42-i2c.o obj-$(CONFIG_SND_SOC_CS42L42_SDW) += snd-soc-cs42l42-sdw.o diff --git a/sound/soc/codecs/cs35l56-i2c.c b/sound/soc/codecs/cs35l56-i2c.c new file mode 100644 index 000000000000..4b7f034a7670 --- /dev/null +++ b/sound/soc/codecs/cs35l56-i2c.c @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// CS35L56 ALSA SoC audio driver I2C binding +// +// Copyright (C) 2023 Cirrus Logic, Inc. and +// Cirrus Logic International Semiconductor Ltd. + +#include +#include +#include +#include +#include +#include +#include + +#include "cs35l56.h" + +static int cs35l56_i2c_probe(struct i2c_client *client) +{ + struct cs35l56_private *cs35l56; + struct device *dev = &client->dev; + const struct regmap_config *regmap_config = &cs35l56_regmap_i2c; + int ret; + + cs35l56 = devm_kzalloc(dev, sizeof(struct cs35l56_private), GFP_KERNEL); + if (!cs35l56) + return -ENOMEM; + + cs35l56->dev = dev; + cs35l56->irq = client->irq; + cs35l56->can_hibernate = true; + + i2c_set_clientdata(client, cs35l56); + cs35l56->regmap = devm_regmap_init_i2c(client, regmap_config); + if (IS_ERR(cs35l56->regmap)) { + ret = PTR_ERR(cs35l56->regmap); + return dev_err_probe(cs35l56->dev, ret, "Failed to allocate register map\n"); + } + + ret = cs35l56_common_probe(cs35l56); + if (ret != 0) + return ret; + + ret = cs35l56_init(cs35l56); + if (ret == 0) + ret = cs35l56_irq_request(cs35l56); + if (ret < 0) + cs35l56_remove(cs35l56); + + return ret; +} + +static void cs35l56_i2c_remove(struct i2c_client *client) +{ + struct cs35l56_private *cs35l56 = i2c_get_clientdata(client); + + cs35l56_remove(cs35l56); +} + +static const struct i2c_device_id cs35l56_id_i2c[] = { + { "cs35l56", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, cs35l56_id_i2c); + +static struct i2c_driver cs35l56_i2c_driver = { + .driver = { + .name = "cs35l56", + .pm = &cs35l56_pm_ops_i2c_spi, + }, + .id_table = cs35l56_id_i2c, + .probe_new = cs35l56_i2c_probe, + .remove = cs35l56_i2c_remove, +}; + +module_i2c_driver(cs35l56_i2c_driver); + +MODULE_DESCRIPTION("ASoC CS35L56 I2C driver"); +MODULE_IMPORT_NS(SND_SOC_CS35L56_CORE); +MODULE_IMPORT_NS(SND_SOC_CS35L56_SHARED); +MODULE_AUTHOR("Richard Fitzgerald "); +MODULE_AUTHOR("Simon Trimmer "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/cs35l56-sdw.c b/sound/soc/codecs/cs35l56-sdw.c new file mode 100644 index 000000000000..448ef3609f4c --- /dev/null +++ b/sound/soc/codecs/cs35l56-sdw.c @@ -0,0 +1,528 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// CS35L56 ALSA SoC audio driver SoundWire binding +// +// Copyright (C) 2023 Cirrus Logic, Inc. and +// Cirrus Logic International Semiconductor Ltd. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cs35l56.h" + +/* Register addresses are offset when sent over SoundWire */ +#define CS35L56_SDW_ADDR_OFFSET 0x8000 + +static int cs35l56_sdw_read_one(struct sdw_slave *peripheral, unsigned int reg, void *buf) +{ + int ret; + + ret = sdw_nread_no_pm(peripheral, reg, 4, (u8 *)buf); + if (ret != 0) { + dev_err(&peripheral->dev, "Read failed @%#x:%d\n", reg, ret); + return ret; + } + + swab32s((u32 *)buf); + + return 0; +} + +static int cs35l56_sdw_read(void *context, const void *reg_buf, + const size_t reg_size, void *val_buf, + size_t val_size) +{ + struct sdw_slave *peripheral = context; + u8 *buf8 = val_buf; + unsigned int reg, bytes; + int ret; + + reg = le32_to_cpu(*(const __le32 *)reg_buf); + reg += CS35L56_SDW_ADDR_OFFSET; + + if (val_size == 4) + return cs35l56_sdw_read_one(peripheral, reg, val_buf); + + while (val_size) { + bytes = SDW_REG_NO_PAGE - (reg & SDW_REGADDR); /* to end of page */ + if (bytes > val_size) + bytes = val_size; + + ret = sdw_nread_no_pm(peripheral, reg, bytes, buf8); + if (ret != 0) { + dev_err(&peripheral->dev, "Read failed @%#x..%#x:%d\n", + reg, reg + bytes - 1, ret); + return ret; + } + + swab32_array((u32 *)buf8, bytes / 4); + val_size -= bytes; + reg += bytes; + buf8 += bytes; + } + + return 0; +} + +static inline void cs35l56_swab_copy(void *dest, const void *src, size_t nbytes) +{ + u32 *dest32 = dest; + const u32 *src32 = src; + + for (; nbytes > 0; nbytes -= 4) + *dest32++ = swab32(*src32++); +} + +static int cs35l56_sdw_write_one(struct sdw_slave *peripheral, unsigned int reg, const void *buf) +{ + u32 val_le = swab32(*(u32 *)buf); + int ret; + + ret = sdw_nwrite_no_pm(peripheral, reg, 4, (u8 *)&val_le); + if (ret != 0) { + dev_err(&peripheral->dev, "Write failed @%#x:%d\n", reg, ret); + return ret; + } + + return 0; +} + +static int cs35l56_sdw_gather_write(void *context, + const void *reg_buf, size_t reg_size, + const void *val_buf, size_t val_size) +{ + struct sdw_slave *peripheral = context; + const u8 *src_be = val_buf; + u32 val_le_buf[64]; /* Define u32 so it is 32-bit aligned */ + unsigned int reg, bytes; + int ret; + + reg = le32_to_cpu(*(const __le32 *)reg_buf); + reg += CS35L56_SDW_ADDR_OFFSET; + + if (val_size == 4) + return cs35l56_sdw_write_one(peripheral, reg, src_be); + + while (val_size) { + bytes = SDW_REG_NO_PAGE - (reg & SDW_REGADDR); /* to end of page */ + if (bytes > val_size) + bytes = val_size; + if (bytes > sizeof(val_le_buf)) + bytes = sizeof(val_le_buf); + + cs35l56_swab_copy(val_le_buf, src_be, bytes); + + ret = sdw_nwrite_no_pm(peripheral, reg, bytes, (u8 *)val_le_buf); + if (ret != 0) { + dev_err(&peripheral->dev, "Write failed @%#x..%#x:%d\n", + reg, reg + bytes - 1, ret); + return ret; + } + + val_size -= bytes; + reg += bytes; + src_be += bytes; + } + + return 0; +} + +static int cs35l56_sdw_write(void *context, const void *val_buf, size_t val_size) +{ + const u8 *src_buf = val_buf; + + /* First word of val_buf contains the destination address */ + return cs35l56_sdw_gather_write(context, &src_buf[0], 4, &src_buf[4], val_size - 4); +} + +/* + * Registers are big-endian on I2C and SPI but little-endian on SoundWire. + * Exported firmware controls are big-endian on I2C/SPI but little-endian on + * SoundWire. Firmware files are always big-endian and are opaque blobs. + * Present a big-endian regmap and hide the endianness swap, so that the ALSA + * byte controls always have the same byte order, and firmware file blobs + * can be written verbatim. + */ +static const struct regmap_bus cs35l56_regmap_bus_sdw = { + .read = cs35l56_sdw_read, + .write = cs35l56_sdw_write, + .gather_write = cs35l56_sdw_gather_write, + .reg_format_endian_default = REGMAP_ENDIAN_LITTLE, + .val_format_endian_default = REGMAP_ENDIAN_BIG, +}; + +static void cs35l56_sdw_init(struct sdw_slave *peripheral) +{ + struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev); + int ret; + + pm_runtime_get_noresume(cs35l56->dev); + + regcache_cache_only(cs35l56->regmap, false); + + ret = cs35l56_init(cs35l56); + if (ret < 0) { + regcache_cache_only(cs35l56->regmap, true); + goto out; + } + + /* + * cs35l56_init can return with !init_done if it triggered + * a soft reset. + */ + if (cs35l56->init_done) { + /* Enable SoundWire interrupts */ + sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_MASK_1, + CS35L56_SDW_INT_MASK_CODEC_IRQ); + } + +out: + pm_runtime_mark_last_busy(cs35l56->dev); + pm_runtime_put_autosuspend(cs35l56->dev); +} + +static int cs35l56_sdw_interrupt(struct sdw_slave *peripheral, + struct sdw_slave_intr_status *status) +{ + struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev); + + /* SoundWire core holds our pm_runtime when calling this function. */ + + dev_dbg(cs35l56->dev, "int control_port=%#x\n", status->control_port); + + if ((status->control_port & SDW_SCP_INT1_IMPL_DEF) == 0) + return 0; + + /* + * Prevent bus manager suspending and possibly issuing a + * bus-reset before the queued work has run. + */ + pm_runtime_get_noresume(cs35l56->dev); + + /* + * Mask and clear until it has been handled. The read of GEN_INT_STAT_1 + * is required as per the SoundWire spec for interrupt status bits + * to clear. GEN_INT_MASK_1 masks the _inputs_ to GEN_INT_STAT1. + * None of the interrupts are time-critical so use the + * power-efficient queue. + */ + sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_MASK_1, 0); + sdw_read_no_pm(peripheral, CS35L56_SDW_GEN_INT_STAT_1); + sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_STAT_1, 0xFF); + queue_work(system_power_efficient_wq, &cs35l56->sdw_irq_work); + + return 0; +} + +static void cs35l56_sdw_irq_work(struct work_struct *work) +{ + struct cs35l56_private *cs35l56 = container_of(work, + struct cs35l56_private, + sdw_irq_work); + + cs35l56_irq(-1, cs35l56); + + /* unmask interrupts */ + if (!cs35l56->sdw_irq_no_unmask) + sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_MASK_1, + CS35L56_SDW_INT_MASK_CODEC_IRQ); + + pm_runtime_put_autosuspend(cs35l56->dev); +} + +static int cs35l56_sdw_read_prop(struct sdw_slave *peripheral) +{ + struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev); + struct sdw_slave_prop *prop = &peripheral->prop; + struct sdw_dpn_prop *ports; + + ports = devm_kcalloc(cs35l56->dev, 2, sizeof(*ports), GFP_KERNEL); + if (!ports) + return -ENOMEM; + + prop->source_ports = BIT(CS35L56_SDW1_CAPTURE_PORT); + prop->sink_ports = BIT(CS35L56_SDW1_PLAYBACK_PORT); + prop->paging_support = true; + prop->clk_stop_mode1 = false; + prop->quirks = SDW_SLAVE_QUIRKS_INVALID_INITIAL_PARITY; + prop->scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY | SDW_SCP_INT1_IMPL_DEF; + + /* DP1 - playback */ + ports[0].num = CS35L56_SDW1_PLAYBACK_PORT; + ports[0].type = SDW_DPN_FULL; + ports[0].ch_prep_timeout = 10; + prop->sink_dpn_prop = &ports[0]; + + /* DP3 - capture */ + ports[1].num = CS35L56_SDW1_CAPTURE_PORT; + ports[1].type = SDW_DPN_FULL; + ports[1].ch_prep_timeout = 10; + prop->src_dpn_prop = &ports[1]; + + return 0; +} + +static int cs35l56_sdw_update_status(struct sdw_slave *peripheral, + enum sdw_slave_status status) +{ + struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev); + + switch (status) { + case SDW_SLAVE_ATTACHED: + dev_dbg(cs35l56->dev, "%s: ATTACHED\n", __func__); + if (cs35l56->sdw_attached) + break; + + if (!cs35l56->init_done || cs35l56->soft_resetting) + cs35l56_sdw_init(peripheral); + + cs35l56->sdw_attached = true; + break; + case SDW_SLAVE_UNATTACHED: + dev_dbg(cs35l56->dev, "%s: UNATTACHED\n", __func__); + cs35l56->sdw_attached = false; + break; + default: + break; + } + + return 0; +} + +static int cs35l56_a1_kick_divider(struct cs35l56_private *cs35l56, + struct sdw_slave *peripheral) +{ + unsigned int curr_scale_reg, next_scale_reg; + int curr_scale, next_scale, ret; + + if (!cs35l56->init_done) + return 0; + + if (peripheral->bus->params.curr_bank) { + curr_scale_reg = SDW_SCP_BUSCLOCK_SCALE_B1; + next_scale_reg = SDW_SCP_BUSCLOCK_SCALE_B0; + } else { + curr_scale_reg = SDW_SCP_BUSCLOCK_SCALE_B0; + next_scale_reg = SDW_SCP_BUSCLOCK_SCALE_B1; + } + + /* + * Current clock scale value must be different to new value. + * Modify current to guarantee this. If next still has the dummy + * value we wrote when it was current, the core code has not set + * a new scale so restore its original good value + */ + curr_scale = sdw_read_no_pm(peripheral, curr_scale_reg); + if (curr_scale < 0) { + dev_err(cs35l56->dev, "Failed to read current clock scale: %d\n", curr_scale); + return curr_scale; + } + + next_scale = sdw_read_no_pm(peripheral, next_scale_reg); + if (next_scale < 0) { + dev_err(cs35l56->dev, "Failed to read next clock scale: %d\n", next_scale); + return next_scale; + } + + if (next_scale == CS35L56_SDW_INVALID_BUS_SCALE) { + next_scale = cs35l56->old_sdw_clock_scale; + ret = sdw_write_no_pm(peripheral, next_scale_reg, next_scale); + if (ret < 0) { + dev_err(cs35l56->dev, "Failed to modify current clock scale: %d\n", ret); + return ret; + } + } + + cs35l56->old_sdw_clock_scale = curr_scale; + ret = sdw_write_no_pm(peripheral, curr_scale_reg, CS35L56_SDW_INVALID_BUS_SCALE); + if (ret < 0) { + dev_err(cs35l56->dev, "Failed to modify current clock scale: %d\n", ret); + return ret; + } + + dev_dbg(cs35l56->dev, "Next bus scale: %#x\n", next_scale); + + return 0; +} + +static int cs35l56_sdw_bus_config(struct sdw_slave *peripheral, + struct sdw_bus_params *params) +{ + struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev); + int sclk; + + sclk = params->curr_dr_freq / 2; + dev_dbg(cs35l56->dev, "%s: sclk=%u c=%u r=%u\n", __func__, sclk, params->col, params->row); + + if (cs35l56->rev < 0xb0) + return cs35l56_a1_kick_divider(cs35l56, peripheral); + + return 0; +} + +static int __maybe_unused cs35l56_sdw_clk_stop(struct sdw_slave *peripheral, + enum sdw_clk_stop_mode mode, + enum sdw_clk_stop_type type) +{ + struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev); + + dev_dbg(cs35l56->dev, "%s: mode:%d type:%d\n", __func__, mode, type); + + return 0; +} + +static const struct sdw_slave_ops cs35l56_sdw_ops = { + .read_prop = cs35l56_sdw_read_prop, + .interrupt_callback = cs35l56_sdw_interrupt, + .update_status = cs35l56_sdw_update_status, + .bus_config = cs35l56_sdw_bus_config, +#ifdef DEBUG + .clk_stop = cs35l56_sdw_clk_stop, +#endif +}; + +static int __maybe_unused cs35l56_sdw_handle_unattach(struct cs35l56_private *cs35l56) +{ + struct sdw_slave *peripheral = cs35l56->sdw_peripheral; + + if (peripheral->unattach_request) { + /* Cannot access registers until bus is re-initialized. */ + dev_dbg(cs35l56->dev, "Wait for initialization_complete\n"); + if (!wait_for_completion_timeout(&peripheral->initialization_complete, + msecs_to_jiffies(5000))) { + dev_err(cs35l56->dev, "initialization_complete timed out\n"); + return -ETIMEDOUT; + } + + peripheral->unattach_request = 0; + + /* + * Don't call regcache_mark_dirty(), we can't be sure that the + * Manager really did issue a Bus Reset. + */ + } + + return 0; +} + +static int __maybe_unused cs35l56_sdw_runtime_suspend(struct device *dev) +{ + struct cs35l56_private *cs35l56 = dev_get_drvdata(dev); + + if (!cs35l56->init_done) + return 0; + + return cs35l56_runtime_suspend(dev); +} + +static int __maybe_unused cs35l56_sdw_runtime_resume(struct device *dev) +{ + struct cs35l56_private *cs35l56 = dev_get_drvdata(dev); + int ret; + + dev_dbg(dev, "Runtime resume\n"); + + if (!cs35l56->init_done) + return 0; + + ret = cs35l56_sdw_handle_unattach(cs35l56); + if (ret < 0) + return ret; + + ret = cs35l56_runtime_resume_common(cs35l56); + if (ret) + return ret; + + /* Re-enable SoundWire interrupts */ + sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_MASK_1, + CS35L56_SDW_INT_MASK_CODEC_IRQ); + + return 0; +} + +static int cs35l56_sdw_probe(struct sdw_slave *peripheral, const struct sdw_device_id *id) +{ + struct device *dev = &peripheral->dev; + struct cs35l56_private *cs35l56; + int ret; + + cs35l56 = devm_kzalloc(dev, sizeof(*cs35l56), GFP_KERNEL); + if (!cs35l56) + return -ENOMEM; + + cs35l56->dev = dev; + cs35l56->sdw_peripheral = peripheral; + INIT_WORK(&cs35l56->sdw_irq_work, cs35l56_sdw_irq_work); + + dev_set_drvdata(dev, cs35l56); + + cs35l56->regmap = devm_regmap_init(dev, &cs35l56_regmap_bus_sdw, + peripheral, &cs35l56_regmap_sdw); + if (IS_ERR(cs35l56->regmap)) { + ret = PTR_ERR(cs35l56->regmap); + return dev_err_probe(dev, ret, "Failed to allocate register map\n"); + } + + /* Start in cache-only until device is enumerated */ + regcache_cache_only(cs35l56->regmap, true); + + ret = cs35l56_common_probe(cs35l56); + if (ret != 0) + return ret; + + return 0; +} + +static int cs35l56_sdw_remove(struct sdw_slave *peripheral) +{ + struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev); + + /* Disable SoundWire interrupts */ + cs35l56->sdw_irq_no_unmask = true; + cancel_work_sync(&cs35l56->sdw_irq_work); + sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_MASK_1, 0); + sdw_read_no_pm(peripheral, CS35L56_SDW_GEN_INT_STAT_1); + sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_STAT_1, 0xFF); + + return cs35l56_remove(cs35l56); +} + +static const struct dev_pm_ops cs35l56_sdw_pm = { + SET_RUNTIME_PM_OPS(cs35l56_sdw_runtime_suspend, cs35l56_sdw_runtime_resume, NULL) +}; + +static const struct sdw_device_id cs35l56_sdw_id[] = { + SDW_SLAVE_ENTRY(0x01FA, 0x3556, 0), + {}, +}; +MODULE_DEVICE_TABLE(sdw, cs35l56_sdw_id); + +static struct sdw_driver cs35l56_sdw_driver = { + .driver = { + .name = "cs35l56", + .pm = &cs35l56_sdw_pm, + }, + .probe = cs35l56_sdw_probe, + .remove = cs35l56_sdw_remove, + .ops = &cs35l56_sdw_ops, + .id_table = cs35l56_sdw_id, +}; + +module_sdw_driver(cs35l56_sdw_driver); + +MODULE_DESCRIPTION("ASoC CS35L56 SoundWire driver"); +MODULE_IMPORT_NS(SND_SOC_CS35L56_CORE); +MODULE_IMPORT_NS(SND_SOC_CS35L56_SHARED); +MODULE_AUTHOR("Richard Fitzgerald "); +MODULE_AUTHOR("Simon Trimmer "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/cs35l56-shared.c b/sound/soc/codecs/cs35l56-shared.c new file mode 100644 index 000000000000..d8bc06ad4888 --- /dev/null +++ b/sound/soc/codecs/cs35l56-shared.c @@ -0,0 +1,390 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Components shared between ASoC and HDA CS35L56 drivers +// +// Copyright (C) 2023 Cirrus Logic, Inc. and +// Cirrus Logic International Semiconductor Ltd. + +#include +#include +#include + +#include "cs35l56.h" + +static const struct reg_default cs35l56_reg_defaults[] = { + { CS35L56_ASP1_ENABLES1, 0x00000000 }, + { CS35L56_ASP1_CONTROL1, 0x00000028 }, + { CS35L56_ASP1_CONTROL2, 0x18180200 }, + { CS35L56_ASP1_CONTROL3, 0x00000002 }, + { CS35L56_ASP1_FRAME_CONTROL1, 0x03020100 }, + { CS35L56_ASP1_FRAME_CONTROL5, 0x00020100 }, + { CS35L56_ASP1_DATA_CONTROL1, 0x00000018 }, + { CS35L56_ASP1_DATA_CONTROL5, 0x00000018 }, + { CS35L56_ASP1TX1_INPUT, 0x00000018 }, + { CS35L56_ASP1TX2_INPUT, 0x00000019 }, + { CS35L56_ASP1TX3_INPUT, 0x00000020 }, + { CS35L56_ASP1TX4_INPUT, 0x00000028 }, + { CS35L56_SWIRE_DP3_CH1_INPUT, 0x00000018 }, + { CS35L56_SWIRE_DP3_CH2_INPUT, 0x00000019 }, + { CS35L56_SWIRE_DP3_CH3_INPUT, 0x00000029 }, + { CS35L56_SWIRE_DP3_CH4_INPUT, 0x00000028 }, + { CS35L56_SWIRE_DP3_CH5_INPUT, 0x00000018 }, + { CS35L56_SWIRE_DP3_CH6_INPUT, 0x00000018 }, + { CS35L56_IRQ1_CFG, 0x00000000 }, + { CS35L56_IRQ1_MASK_1, 0x83ffffff }, + { CS35L56_IRQ1_MASK_2, 0xffff7fff }, + { CS35L56_IRQ1_MASK_4, 0xe0ffffff }, + { CS35L56_IRQ1_MASK_8, 0xfc000fff }, + { CS35L56_IRQ1_MASK_18, 0x1f7df0ff }, + { CS35L56_IRQ1_MASK_20, 0x15c00000 }, + /* CS35L56_MAIN_RENDER_USER_MUTE - soft register, no default */ + /* CS35L56_MAIN_RENDER_USER_VOLUME - soft register, no default */ + /* CS35L56_MAIN_POSTURE_NUMBER - soft register, no default */ +}; + +/* + * The Ax devices have different default register values to that of B0, + * establish a common set of register defaults. + */ +static const struct reg_sequence cs35l56_reva_patch[] = { + { CS35L56_SWIRE_DP3_CH5_INPUT, 0x00000018 }, + { CS35L56_SWIRE_DP3_CH6_INPUT, 0x00000018 }, +}; + +void cs35l56_patch(struct device *dev, struct regmap *regmap, u8 revid) +{ + int ret; + + if (revid >= CS35L56_REVID_B0) + return; + + ret = regmap_register_patch(regmap, cs35l56_reva_patch, + ARRAY_SIZE(cs35l56_reva_patch)); + if (ret) + dev_err(dev, "Failed to apply patch: %d\n", ret); +} +EXPORT_SYMBOL_NS_GPL(cs35l56_patch, SND_SOC_CS35L56_SHARED); + +static bool cs35l56_is_dsp_memory(unsigned int reg) +{ + switch (reg) { + case CS35L56_DSP1_XMEM_PACKED_0 ... CS35L56_DSP1_XMEM_PACKED_6143: + case CS35L56_DSP1_XMEM_UNPACKED32_0 ... CS35L56_DSP1_XMEM_UNPACKED32_4095: + case CS35L56_DSP1_XMEM_UNPACKED24_0 ... CS35L56_DSP1_XMEM_UNPACKED24_8191: + case CS35L56_DSP1_YMEM_PACKED_0 ... CS35L56_DSP1_YMEM_PACKED_4604: + case CS35L56_DSP1_YMEM_UNPACKED32_0 ... CS35L56_DSP1_YMEM_UNPACKED32_3070: + case CS35L56_DSP1_YMEM_UNPACKED24_0 ... CS35L56_DSP1_YMEM_UNPACKED24_6141: + case CS35L56_DSP1_PMEM_0 ... CS35L56_DSP1_PMEM_5114: + return true; + default: + return false; + } +} + +static bool cs35l56_readable_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case CS35L56_DEVID: + case CS35L56_REVID: + case CS35L56_RELID: + case CS35L56_OTPID: + case CS35L56_SFT_RESET: + case CS35L56_GLOBAL_ENABLES: + case CS35L56_BLOCK_ENABLES: + case CS35L56_BLOCK_ENABLES2: + case CS35L56_REFCLK_INPUT: + case CS35L56_GLOBAL_SAMPLE_RATE: + case CS35L56_ASP1_ENABLES1: + case CS35L56_ASP1_CONTROL1: + case CS35L56_ASP1_CONTROL2: + case CS35L56_ASP1_CONTROL3: + case CS35L56_ASP1_FRAME_CONTROL1: + case CS35L56_ASP1_FRAME_CONTROL5: + case CS35L56_ASP1_DATA_CONTROL1: + case CS35L56_ASP1_DATA_CONTROL5: + case CS35L56_DACPCM1_INPUT: + case CS35L56_DACPCM2_INPUT: + case CS35L56_ASP1TX1_INPUT: + case CS35L56_ASP1TX2_INPUT: + case CS35L56_ASP1TX3_INPUT: + case CS35L56_ASP1TX4_INPUT: + case CS35L56_DSP1RX1_INPUT: + case CS35L56_DSP1RX2_INPUT: + case CS35L56_SWIRE_DP3_CH1_INPUT: + case CS35L56_SWIRE_DP3_CH2_INPUT: + case CS35L56_SWIRE_DP3_CH3_INPUT: + case CS35L56_SWIRE_DP3_CH4_INPUT: + case CS35L56_SWIRE_DP3_CH5_INPUT: + case CS35L56_SWIRE_DP3_CH6_INPUT: + case CS35L56_IRQ1_CFG: + case CS35L56_IRQ1_STATUS: + case CS35L56_IRQ1_EINT_1 ... CS35L56_IRQ1_EINT_8: + case CS35L56_IRQ1_EINT_18: + case CS35L56_IRQ1_EINT_20: + case CS35L56_IRQ1_MASK_1: + case CS35L56_IRQ1_MASK_2: + case CS35L56_IRQ1_MASK_4: + case CS35L56_IRQ1_MASK_8: + case CS35L56_IRQ1_MASK_18: + case CS35L56_IRQ1_MASK_20: + case CS35L56_DSP_VIRTUAL1_MBOX_1: + case CS35L56_DSP_VIRTUAL1_MBOX_2: + case CS35L56_DSP_VIRTUAL1_MBOX_3: + case CS35L56_DSP_VIRTUAL1_MBOX_4: + case CS35L56_DSP_VIRTUAL1_MBOX_5: + case CS35L56_DSP_VIRTUAL1_MBOX_6: + case CS35L56_DSP_VIRTUAL1_MBOX_7: + case CS35L56_DSP_VIRTUAL1_MBOX_8: + case CS35L56_DSP_RESTRICT_STS1: + case CS35L56_DSP1_SYS_INFO_ID ... CS35L56_DSP1_SYS_INFO_END: + case CS35L56_DSP1_AHBM_WINDOW_DEBUG_0: + case CS35L56_DSP1_AHBM_WINDOW_DEBUG_1: + case CS35L56_DSP1_SCRATCH1: + case CS35L56_DSP1_SCRATCH2: + case CS35L56_DSP1_SCRATCH3: + case CS35L56_DSP1_SCRATCH4: + return true; + default: + return cs35l56_is_dsp_memory(reg); + } +} + +static bool cs35l56_precious_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case CS35L56_DSP1_XMEM_PACKED_0 ... CS35L56_DSP1_XMEM_PACKED_6143: + case CS35L56_DSP1_YMEM_PACKED_0 ... CS35L56_DSP1_YMEM_PACKED_4604: + case CS35L56_DSP1_PMEM_0 ... CS35L56_DSP1_PMEM_5114: + return true; + default: + return false; + } +} + +static bool cs35l56_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case CS35L56_DEVID: + case CS35L56_REVID: + case CS35L56_RELID: + case CS35L56_OTPID: + case CS35L56_SFT_RESET: + case CS35L56_GLOBAL_ENABLES: /* owned by firmware */ + case CS35L56_BLOCK_ENABLES: /* owned by firmware */ + case CS35L56_BLOCK_ENABLES2: /* owned by firmware */ + case CS35L56_REFCLK_INPUT: /* owned by firmware */ + case CS35L56_GLOBAL_SAMPLE_RATE: /* owned by firmware */ + case CS35L56_DACPCM1_INPUT: /* owned by firmware */ + case CS35L56_DACPCM2_INPUT: /* owned by firmware */ + case CS35L56_DSP1RX1_INPUT: /* owned by firmware */ + case CS35L56_DSP1RX2_INPUT: /* owned by firmware */ + case CS35L56_IRQ1_STATUS: + case CS35L56_IRQ1_EINT_1 ... CS35L56_IRQ1_EINT_8: + case CS35L56_IRQ1_EINT_18: + case CS35L56_IRQ1_EINT_20: + case CS35L56_DSP_VIRTUAL1_MBOX_1: + case CS35L56_DSP_VIRTUAL1_MBOX_2: + case CS35L56_DSP_VIRTUAL1_MBOX_3: + case CS35L56_DSP_VIRTUAL1_MBOX_4: + case CS35L56_DSP_VIRTUAL1_MBOX_5: + case CS35L56_DSP_VIRTUAL1_MBOX_6: + case CS35L56_DSP_VIRTUAL1_MBOX_7: + case CS35L56_DSP_VIRTUAL1_MBOX_8: + case CS35L56_DSP_RESTRICT_STS1: + case CS35L56_DSP1_SYS_INFO_ID ... CS35L56_DSP1_SYS_INFO_END: + case CS35L56_DSP1_AHBM_WINDOW_DEBUG_0: + case CS35L56_DSP1_AHBM_WINDOW_DEBUG_1: + case CS35L56_DSP1_SCRATCH1: + case CS35L56_DSP1_SCRATCH2: + case CS35L56_DSP1_SCRATCH3: + case CS35L56_DSP1_SCRATCH4: + return true; + case CS35L56_MAIN_RENDER_USER_MUTE: + case CS35L56_MAIN_RENDER_USER_VOLUME: + case CS35L56_MAIN_POSTURE_NUMBER: + return false; + default: + return cs35l56_is_dsp_memory(reg); + } +} + +static const u32 cs35l56_firmware_registers[] = { + CS35L56_MAIN_RENDER_USER_MUTE, + CS35L56_MAIN_RENDER_USER_VOLUME, + CS35L56_MAIN_POSTURE_NUMBER, +}; + +void cs35l56_reread_firmware_registers(struct device *dev, struct regmap *regmap) +{ + int i; + unsigned int val; + + for (i = 0; i < ARRAY_SIZE(cs35l56_firmware_registers); i++) { + regmap_read(regmap, cs35l56_firmware_registers[i], &val); + dev_dbg(dev, "%s: %d: %#x: %#x\n", __func__, + i, cs35l56_firmware_registers[i], val); + } +} +EXPORT_SYMBOL_NS_GPL(cs35l56_reread_firmware_registers, SND_SOC_CS35L56_SHARED); + +const struct cs_dsp_region cs35l56_dsp1_regions[] = { + { .type = WMFW_HALO_PM_PACKED, .base = CS35L56_DSP1_PMEM_0 }, + { .type = WMFW_HALO_XM_PACKED, .base = CS35L56_DSP1_XMEM_PACKED_0 }, + { .type = WMFW_HALO_YM_PACKED, .base = CS35L56_DSP1_YMEM_PACKED_0 }, + { .type = WMFW_ADSP2_XM, .base = CS35L56_DSP1_XMEM_UNPACKED24_0 }, + { .type = WMFW_ADSP2_YM, .base = CS35L56_DSP1_YMEM_UNPACKED24_0 }, +}; +EXPORT_SYMBOL_NS_GPL(cs35l56_dsp1_regions, SND_SOC_CS35L56_SHARED); + +static const u32 cs35l56_bclk_valid_for_pll_freq_table[] = { + [0x0C] = 128000, + [0x0F] = 256000, + [0x11] = 384000, + [0x12] = 512000, + [0x15] = 768000, + [0x17] = 1024000, + [0x1A] = 1500000, + [0x1B] = 1536000, + [0x1C] = 2000000, + [0x1D] = 2048000, + [0x1E] = 2400000, + [0x20] = 3000000, + [0x21] = 3072000, + [0x23] = 4000000, + [0x24] = 4096000, + [0x25] = 4800000, + [0x27] = 6000000, + [0x28] = 6144000, + [0x29] = 6250000, + [0x2A] = 6400000, + [0x2E] = 8000000, + [0x2F] = 8192000, + [0x30] = 9600000, + [0x32] = 12000000, + [0x33] = 12288000, + [0x37] = 13500000, + [0x38] = 19200000, + [0x39] = 22579200, + [0x3B] = 24576000, +}; + +int cs35l56_get_bclk_freq_id(unsigned int freq) +{ + int i; + + if (freq == 0) + return -EINVAL; + + /* The BCLK frequency must be a valid PLL REFCLK */ + for (i = 0; i < ARRAY_SIZE(cs35l56_bclk_valid_for_pll_freq_table); ++i) { + if (cs35l56_bclk_valid_for_pll_freq_table[i] == freq) + return i; + } + + return -EINVAL; +} +EXPORT_SYMBOL_NS_GPL(cs35l56_get_bclk_freq_id, SND_SOC_CS35L56_SHARED); + +static const char * const cs35l56_supplies[/* auto-sized */] = { + "VDD_P", + "VDD_IO", + "VDD_A", +}; + +void cs35l56_fill_supply_names(struct regulator_bulk_data *data) +{ + int i; + + BUILD_BUG_ON(ARRAY_SIZE(cs35l56_supplies) != CS35L56_NUM_BULK_SUPPLIES); + for (i = 0; i < ARRAY_SIZE(cs35l56_supplies); i++) + data[i].supply = cs35l56_supplies[i]; +} +EXPORT_SYMBOL_NS_GPL(cs35l56_fill_supply_names, SND_SOC_CS35L56_SHARED); + +const char * const cs35l56_tx_input_texts[] = { + "None", "ASP1RX1", "ASP1RX2", "VMON", "IMON", "ERRVOL", "CLASSH", + "VDDBMON", "VBSTMON", "DSP1TX1", "DSP1TX2", "DSP1TX3", "DSP1TX4", + "DSP1TX5", "DSP1TX6", "DSP1TX7", "DSP1TX8", "TEMPMON", + "INTERPOLATOR", "SDW1RX1", "SDW1RX2", "SDW2RX1", +}; +EXPORT_SYMBOL_NS_GPL(cs35l56_tx_input_texts, SND_SOC_CS35L56_SHARED); + +const unsigned int cs35l56_tx_input_values[] = { + CS35L56_INPUT_SRC_NONE, + CS35L56_INPUT_SRC_ASP1RX1, + CS35L56_INPUT_SRC_ASP1RX2, + CS35L56_INPUT_SRC_VMON, + CS35L56_INPUT_SRC_IMON, + CS35L56_INPUT_SRC_ERR_VOL, + CS35L56_INPUT_SRC_CLASSH, + CS35L56_INPUT_SRC_VDDBMON, + CS35L56_INPUT_SRC_VBSTMON, + CS35L56_INPUT_SRC_DSP1TX1, + CS35L56_INPUT_SRC_DSP1TX2, + CS35L56_INPUT_SRC_DSP1TX3, + CS35L56_INPUT_SRC_DSP1TX4, + CS35L56_INPUT_SRC_DSP1TX5, + CS35L56_INPUT_SRC_DSP1TX6, + CS35L56_INPUT_SRC_DSP1TX7, + CS35L56_INPUT_SRC_DSP1TX8, + CS35L56_INPUT_SRC_TEMPMON, + CS35L56_INPUT_SRC_INTERPOLATOR, + CS35L56_INPUT_SRC_SWIRE_RX1, + CS35L56_INPUT_SRC_SWIRE_RX2, + CS35L56_INPUT_SRC_SWIRE_RX3, +}; +EXPORT_SYMBOL_NS_GPL(cs35l56_tx_input_values, SND_SOC_CS35L56_SHARED); + +struct regmap_config cs35l56_regmap_i2c = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .reg_format_endian = REGMAP_ENDIAN_BIG, + .val_format_endian = REGMAP_ENDIAN_BIG, + .max_register = CS35L56_DSP1_PMEM_5114, + .reg_defaults = cs35l56_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(cs35l56_reg_defaults), + .volatile_reg = cs35l56_volatile_reg, + .readable_reg = cs35l56_readable_reg, + .precious_reg = cs35l56_precious_reg, + .cache_type = REGCACHE_RBTREE, +}; +EXPORT_SYMBOL_NS_GPL(cs35l56_regmap_i2c, SND_SOC_CS35L56_SHARED); + +struct regmap_config cs35l56_regmap_spi = { + .reg_bits = 32, + .val_bits = 32, + .pad_bits = 16, + .reg_stride = 4, + .reg_format_endian = REGMAP_ENDIAN_BIG, + .val_format_endian = REGMAP_ENDIAN_BIG, + .max_register = CS35L56_DSP1_PMEM_5114, + .reg_defaults = cs35l56_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(cs35l56_reg_defaults), + .volatile_reg = cs35l56_volatile_reg, + .readable_reg = cs35l56_readable_reg, + .precious_reg = cs35l56_precious_reg, + .cache_type = REGCACHE_RBTREE, +}; +EXPORT_SYMBOL_NS_GPL(cs35l56_regmap_spi, SND_SOC_CS35L56_SHARED); + +struct regmap_config cs35l56_regmap_sdw = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .reg_format_endian = REGMAP_ENDIAN_LITTLE, + .val_format_endian = REGMAP_ENDIAN_BIG, + .max_register = CS35L56_DSP1_PMEM_5114, + .reg_defaults = cs35l56_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(cs35l56_reg_defaults), + .volatile_reg = cs35l56_volatile_reg, + .readable_reg = cs35l56_readable_reg, + .precious_reg = cs35l56_precious_reg, + .cache_type = REGCACHE_RBTREE, +}; +EXPORT_SYMBOL_NS_GPL(cs35l56_regmap_sdw, SND_SOC_CS35L56_SHARED); + +MODULE_DESCRIPTION("ASoC CS35L56 Shared"); +MODULE_AUTHOR("Richard Fitzgerald "); +MODULE_AUTHOR("Simon Trimmer "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/cs35l56-spi.c b/sound/soc/codecs/cs35l56-spi.c new file mode 100644 index 000000000000..80dcf37daae2 --- /dev/null +++ b/sound/soc/codecs/cs35l56-spi.c @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// CS35L56 ALSA SoC audio driver SPI binding +// +// Copyright (C) 2023 Cirrus Logic, Inc. and +// Cirrus Logic International Semiconductor Ltd. + +#include +#include +#include +#include +#include +#include + +#include "cs35l56.h" + +static int cs35l56_spi_probe(struct spi_device *spi) +{ + const struct regmap_config *regmap_config = &cs35l56_regmap_spi; + struct cs35l56_private *cs35l56; + int ret; + + cs35l56 = devm_kzalloc(&spi->dev, sizeof(struct cs35l56_private), GFP_KERNEL); + if (!cs35l56) + return -ENOMEM; + + spi_set_drvdata(spi, cs35l56); + cs35l56->regmap = devm_regmap_init_spi(spi, regmap_config); + if (IS_ERR(cs35l56->regmap)) { + ret = PTR_ERR(cs35l56->regmap); + return dev_err_probe(&spi->dev, ret, "Failed to allocate register map\n"); + return ret; + } + + cs35l56->dev = &spi->dev; + cs35l56->irq = spi->irq; + + ret = cs35l56_common_probe(cs35l56); + if (ret != 0) + return ret; + + ret = cs35l56_init(cs35l56); + if (ret == 0) + ret = cs35l56_irq_request(cs35l56); + if (ret < 0) + cs35l56_remove(cs35l56); + + return ret; +} + +static void cs35l56_spi_remove(struct spi_device *spi) +{ + struct cs35l56_private *cs35l56 = spi_get_drvdata(spi); + + cs35l56_remove(cs35l56); +} + +static const struct spi_device_id cs35l56_id_spi[] = { + { "cs35l56", 0 }, + {} +}; +MODULE_DEVICE_TABLE(spi, cs35l56_id_spi); + +static struct spi_driver cs35l56_spi_driver = { + .driver = { + .name = "cs35l56", + .pm = &cs35l56_pm_ops_i2c_spi, + }, + .id_table = cs35l56_id_spi, + .probe = cs35l56_spi_probe, + .remove = cs35l56_spi_remove, +}; + +module_spi_driver(cs35l56_spi_driver); + +MODULE_DESCRIPTION("ASoC CS35L56 SPI driver"); +MODULE_IMPORT_NS(SND_SOC_CS35L56_CORE); +MODULE_IMPORT_NS(SND_SOC_CS35L56_SHARED); +MODULE_AUTHOR("Richard Fitzgerald "); +MODULE_AUTHOR("Simon Trimmer "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c new file mode 100644 index 000000000000..90fc79b5666d --- /dev/null +++ b/sound/soc/codecs/cs35l56.c @@ -0,0 +1,1461 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Driver for Cirrus Logic CS35L56 smart amp +// +// Copyright (C) 2023 Cirrus Logic, Inc. and +// Cirrus Logic International Semiconductor Ltd. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "wm_adsp.h" +#include "cs35l56.h" + +static int cs35l56_dsp_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event); + +static int cs35l56_wait_dsp_ready(struct cs35l56_private *cs35l56) +{ + int ret; + + if (!cs35l56->fw_patched) { + /* block until firmware download completes */ + ret = wait_for_completion_timeout(&cs35l56->dsp_ready_completion, + msecs_to_jiffies(25000)); + if (!ret) { + dev_err(cs35l56->dev, "dsp_ready_completion timeout\n"); + return -ETIMEDOUT; + } + } + + return 0; +} + +static int cs35l56_dspwait_get_volsw(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component); + int ret = cs35l56_wait_dsp_ready(cs35l56); + + if (ret) + return ret; + + return snd_soc_get_volsw(kcontrol, ucontrol); +} + +static int cs35l56_dspwait_put_volsw(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component); + int ret = cs35l56_wait_dsp_ready(cs35l56); + + if (ret) + return ret; + + return snd_soc_put_volsw(kcontrol, ucontrol); +} + +static DECLARE_TLV_DB_SCALE(vol_tlv, -10000, 25, 0); + +static const struct snd_kcontrol_new cs35l56_controls[] = { + SOC_SINGLE_EXT("Speaker Switch", + CS35L56_MAIN_RENDER_USER_MUTE, 0, 1, 1, + cs35l56_dspwait_get_volsw, cs35l56_dspwait_put_volsw), + SOC_SINGLE_S_EXT_TLV("Speaker Volume", + CS35L56_MAIN_RENDER_USER_VOLUME, + 6, -400, 400, 9, 0, + cs35l56_dspwait_get_volsw, + cs35l56_dspwait_put_volsw, + vol_tlv), + SOC_SINGLE_EXT("Posture Number", CS35L56_MAIN_POSTURE_NUMBER, + 0, 255, 0, + cs35l56_dspwait_get_volsw, cs35l56_dspwait_put_volsw), +}; + +static SOC_VALUE_ENUM_SINGLE_DECL(cs35l56_asp1tx1_enum, + CS35L56_ASP1TX1_INPUT, + 0, CS35L56_ASP_TXn_SRC_MASK, + cs35l56_tx_input_texts, + cs35l56_tx_input_values); + +static const struct snd_kcontrol_new asp1_tx1_mux = + SOC_DAPM_ENUM("ASP1TX1 SRC", cs35l56_asp1tx1_enum); + +static SOC_VALUE_ENUM_SINGLE_DECL(cs35l56_asp1tx2_enum, + CS35L56_ASP1TX2_INPUT, + 0, CS35L56_ASP_TXn_SRC_MASK, + cs35l56_tx_input_texts, + cs35l56_tx_input_values); + +static const struct snd_kcontrol_new asp1_tx2_mux = + SOC_DAPM_ENUM("ASP1TX2 SRC", cs35l56_asp1tx2_enum); + +static SOC_VALUE_ENUM_SINGLE_DECL(cs35l56_asp1tx3_enum, + CS35L56_ASP1TX3_INPUT, + 0, CS35L56_ASP_TXn_SRC_MASK, + cs35l56_tx_input_texts, + cs35l56_tx_input_values); + +static const struct snd_kcontrol_new asp1_tx3_mux = + SOC_DAPM_ENUM("ASP1TX3 SRC", cs35l56_asp1tx3_enum); + +static SOC_VALUE_ENUM_SINGLE_DECL(cs35l56_asp1tx4_enum, + CS35L56_ASP1TX4_INPUT, + 0, CS35L56_ASP_TXn_SRC_MASK, + cs35l56_tx_input_texts, + cs35l56_tx_input_values); + +static const struct snd_kcontrol_new asp1_tx4_mux = + SOC_DAPM_ENUM("ASP1TX4 SRC", cs35l56_asp1tx4_enum); + +static SOC_VALUE_ENUM_SINGLE_DECL(cs35l56_sdw1tx1_enum, + CS35L56_SWIRE_DP3_CH1_INPUT, + 0, CS35L56_SWIRETXn_SRC_MASK, + cs35l56_tx_input_texts, + cs35l56_tx_input_values); + +static const struct snd_kcontrol_new sdw1_tx1_mux = + SOC_DAPM_ENUM("SDW1TX1 SRC", cs35l56_sdw1tx1_enum); + +static SOC_VALUE_ENUM_SINGLE_DECL(cs35l56_sdw1tx2_enum, + CS35L56_SWIRE_DP3_CH2_INPUT, + 0, CS35L56_SWIRETXn_SRC_MASK, + cs35l56_tx_input_texts, + cs35l56_tx_input_values); + +static const struct snd_kcontrol_new sdw1_tx2_mux = + SOC_DAPM_ENUM("SDW1TX2 SRC", cs35l56_sdw1tx2_enum); + +static SOC_VALUE_ENUM_SINGLE_DECL(cs35l56_sdw1tx3_enum, + CS35L56_SWIRE_DP3_CH3_INPUT, + 0, CS35L56_SWIRETXn_SRC_MASK, + cs35l56_tx_input_texts, + cs35l56_tx_input_values); + +static const struct snd_kcontrol_new sdw1_tx3_mux = + SOC_DAPM_ENUM("SDW1TX3 SRC", cs35l56_sdw1tx3_enum); + +static SOC_VALUE_ENUM_SINGLE_DECL(cs35l56_sdw1tx4_enum, + CS35L56_SWIRE_DP3_CH4_INPUT, + 0, CS35L56_SWIRETXn_SRC_MASK, + cs35l56_tx_input_texts, + cs35l56_tx_input_values); + +static const struct snd_kcontrol_new sdw1_tx4_mux = + SOC_DAPM_ENUM("SDW1TX4 SRC", cs35l56_sdw1tx4_enum); + +static SOC_VALUE_ENUM_SINGLE_DECL(cs35l56_sdw1tx5_enum, + CS35L56_SWIRE_DP3_CH5_INPUT, + 0, CS35L56_SWIRETXn_SRC_MASK, + cs35l56_tx_input_texts, + cs35l56_tx_input_values); + +static const struct snd_kcontrol_new sdw1_tx5_mux = + SOC_DAPM_ENUM("SDW1TX5 SRC", cs35l56_sdw1tx5_enum); + +static SOC_VALUE_ENUM_SINGLE_DECL(cs35l56_sdw1tx6_enum, + CS35L56_SWIRE_DP3_CH6_INPUT, + 0, CS35L56_SWIRETXn_SRC_MASK, + cs35l56_tx_input_texts, + cs35l56_tx_input_values); + +static const struct snd_kcontrol_new sdw1_tx6_mux = + SOC_DAPM_ENUM("SDW1TX6 SRC", cs35l56_sdw1tx6_enum); + +static const struct snd_soc_dapm_widget cs35l56_dapm_widgets[] = { + SND_SOC_DAPM_REGULATOR_SUPPLY("VDD_B", 0, 0), + SND_SOC_DAPM_REGULATOR_SUPPLY("VDD_AMP", 0, 0), + + SND_SOC_DAPM_OUT_DRV("AMP", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_OUTPUT("SPK"), + + SND_SOC_DAPM_PGA_E("DSP1", SND_SOC_NOPM, 0, 0, NULL, 0, cs35l56_dsp_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + + SND_SOC_DAPM_AIF_IN("ASP1RX1", NULL, 0, CS35L56_ASP1_ENABLES1, + CS35L56_ASP_RX1_EN_SHIFT, 0), + SND_SOC_DAPM_AIF_IN("ASP1RX2", NULL, 1, CS35L56_ASP1_ENABLES1, + CS35L56_ASP_RX2_EN_SHIFT, 0), + SND_SOC_DAPM_AIF_OUT("ASP1TX1", NULL, 0, CS35L56_ASP1_ENABLES1, + CS35L56_ASP_TX1_EN_SHIFT, 0), + SND_SOC_DAPM_AIF_OUT("ASP1TX2", NULL, 1, CS35L56_ASP1_ENABLES1, + CS35L56_ASP_TX2_EN_SHIFT, 0), + SND_SOC_DAPM_AIF_OUT("ASP1TX3", NULL, 2, CS35L56_ASP1_ENABLES1, + CS35L56_ASP_TX3_EN_SHIFT, 0), + SND_SOC_DAPM_AIF_OUT("ASP1TX4", NULL, 3, CS35L56_ASP1_ENABLES1, + CS35L56_ASP_TX4_EN_SHIFT, 0), + + SND_SOC_DAPM_MUX("ASP1 TX1 Source", SND_SOC_NOPM, 0, 0, &asp1_tx1_mux), + SND_SOC_DAPM_MUX("ASP1 TX2 Source", SND_SOC_NOPM, 0, 0, &asp1_tx2_mux), + SND_SOC_DAPM_MUX("ASP1 TX3 Source", SND_SOC_NOPM, 0, 0, &asp1_tx3_mux), + SND_SOC_DAPM_MUX("ASP1 TX4 Source", SND_SOC_NOPM, 0, 0, &asp1_tx4_mux), + + SND_SOC_DAPM_MUX("SDW1 TX1 Source", SND_SOC_NOPM, 0, 0, &sdw1_tx1_mux), + SND_SOC_DAPM_MUX("SDW1 TX2 Source", SND_SOC_NOPM, 0, 0, &sdw1_tx2_mux), + SND_SOC_DAPM_MUX("SDW1 TX3 Source", SND_SOC_NOPM, 0, 0, &sdw1_tx3_mux), + SND_SOC_DAPM_MUX("SDW1 TX4 Source", SND_SOC_NOPM, 0, 0, &sdw1_tx4_mux), + SND_SOC_DAPM_MUX("SDW1 TX5 Source", SND_SOC_NOPM, 0, 0, &sdw1_tx5_mux), + SND_SOC_DAPM_MUX("SDW1 TX6 Source", SND_SOC_NOPM, 0, 0, &sdw1_tx6_mux), + + SND_SOC_DAPM_SIGGEN("VMON ADC"), + SND_SOC_DAPM_SIGGEN("IMON ADC"), + SND_SOC_DAPM_SIGGEN("ERRVOL ADC"), + SND_SOC_DAPM_SIGGEN("CLASSH ADC"), + SND_SOC_DAPM_SIGGEN("VDDBMON ADC"), + SND_SOC_DAPM_SIGGEN("VBSTMON ADC"), + SND_SOC_DAPM_SIGGEN("TEMPMON ADC"), +}; + +#define CS35L56_SRC_ROUTE(name) \ + { name" Source", "ASP1RX1", "ASP1RX1" }, \ + { name" Source", "ASP1RX2", "ASP1RX2" }, \ + { name" Source", "VMON", "VMON ADC" }, \ + { name" Source", "IMON", "IMON ADC" }, \ + { name" Source", "ERRVOL", "ERRVOL ADC" }, \ + { name" Source", "CLASSH", "CLASSH ADC" }, \ + { name" Source", "VDDBMON", "VDDBMON ADC" }, \ + { name" Source", "VBSTMON", "VBSTMON ADC" }, \ + { name" Source", "DSP1TX1", "DSP1" }, \ + { name" Source", "DSP1TX2", "DSP1" }, \ + { name" Source", "DSP1TX3", "DSP1" }, \ + { name" Source", "DSP1TX4", "DSP1" }, \ + { name" Source", "DSP1TX5", "DSP1" }, \ + { name" Source", "DSP1TX6", "DSP1" }, \ + { name" Source", "DSP1TX7", "DSP1" }, \ + { name" Source", "DSP1TX8", "DSP1" }, \ + { name" Source", "TEMPMON", "TEMPMON ADC" }, \ + { name" Source", "INTERPOLATOR", "AMP" }, \ + { name" Source", "SDW1RX1", "SDW1 Playback" }, \ + { name" Source", "SDW1RX2", "SDW1 Playback" }, + +static const struct snd_soc_dapm_route cs35l56_audio_map[] = { + { "AMP", NULL, "VDD_B" }, + { "AMP", NULL, "VDD_AMP" }, + + { "ASP1RX1", NULL, "ASP1 Playback" }, + { "ASP1RX2", NULL, "ASP1 Playback" }, + { "DSP1", NULL, "ASP1RX1" }, + { "DSP1", NULL, "ASP1RX2" }, + { "DSP1", NULL, "SDW1 Playback" }, + { "AMP", NULL, "DSP1" }, + { "SPK", NULL, "AMP" }, + + CS35L56_SRC_ROUTE("ASP1 TX1") + CS35L56_SRC_ROUTE("ASP1 TX2") + CS35L56_SRC_ROUTE("ASP1 TX3") + CS35L56_SRC_ROUTE("ASP1 TX4") + + { "ASP1TX1", NULL, "ASP1 TX1 Source" }, + { "ASP1TX2", NULL, "ASP1 TX2 Source" }, + { "ASP1TX3", NULL, "ASP1 TX3 Source" }, + { "ASP1TX4", NULL, "ASP1 TX4 Source" }, + { "ASP1 Capture", NULL, "ASP1TX1" }, + { "ASP1 Capture", NULL, "ASP1TX2" }, + { "ASP1 Capture", NULL, "ASP1TX3" }, + { "ASP1 Capture", NULL, "ASP1TX4" }, + + CS35L56_SRC_ROUTE("SDW1 TX1") + CS35L56_SRC_ROUTE("SDW1 TX2") + CS35L56_SRC_ROUTE("SDW1 TX3") + CS35L56_SRC_ROUTE("SDW1 TX4") + CS35L56_SRC_ROUTE("SDW1 TX5") + CS35L56_SRC_ROUTE("SDW1 TX6") + { "SDW1 Capture", NULL, "SDW1 TX1 Source" }, + { "SDW1 Capture", NULL, "SDW1 TX2 Source" }, + { "SDW1 Capture", NULL, "SDW1 TX3 Source" }, + { "SDW1 Capture", NULL, "SDW1 TX4 Source" }, + { "SDW1 Capture", NULL, "SDW1 TX5 Source" }, + { "SDW1 Capture", NULL, "SDW1 TX6 Source" }, +}; + +static int cs35l56_mbox_send(struct cs35l56_private *cs35l56, unsigned int command) +{ + unsigned int val; + int ret; + + regmap_write(cs35l56->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, command); + ret = regmap_read_poll_timeout(cs35l56->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, + val, (val == 0), + CS35L56_MBOX_POLL_US, CS35L56_MBOX_TIMEOUT_US); + if (ret) { + dev_warn(cs35l56->dev, "MBOX command %#x failed: %d\n", command, ret); + return ret; + } + + return 0; +} + +static int cs35l56_dsp_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component); + + dev_dbg(cs35l56->dev, "%s: %d\n", __func__, event); + + return wm_adsp_event(w, kcontrol, event); +} + +irqreturn_t cs35l56_irq(int irq, void *data) +{ + struct cs35l56_private *cs35l56 = data; + unsigned int status1 = 0, status8 = 0, status20 = 0; + unsigned int mask1, mask8, mask20; + unsigned int rv, val; + irqreturn_t ret = IRQ_NONE; + + if (!cs35l56->init_done) + return IRQ_NONE; + + mutex_lock(&cs35l56->irq_lock); + + rv = pm_runtime_resume_and_get(cs35l56->dev); + if (rv < 0) { + dev_err(cs35l56->dev, "irq: failed to get pm_runtime: %d\n", rv); + goto err_unlock; + } + + regmap_read(cs35l56->regmap, CS35L56_IRQ1_STATUS, &val); + if ((val & CS35L56_IRQ1_STS_MASK) == 0) { + dev_dbg(cs35l56->dev, "Spurious IRQ: no pending interrupt\n"); + goto err; + } + + /* Ack interrupts */ + regmap_read(cs35l56->regmap, CS35L56_IRQ1_EINT_1, &status1); + regmap_read(cs35l56->regmap, CS35L56_IRQ1_MASK_1, &mask1); + status1 &= ~mask1; + regmap_write(cs35l56->regmap, CS35L56_IRQ1_EINT_1, status1); + + regmap_read(cs35l56->regmap, CS35L56_IRQ1_EINT_8, &status8); + regmap_read(cs35l56->regmap, CS35L56_IRQ1_MASK_8, &mask8); + status8 &= ~mask8; + regmap_write(cs35l56->regmap, CS35L56_IRQ1_EINT_8, status8); + + regmap_read(cs35l56->regmap, CS35L56_IRQ1_EINT_20, &status20); + regmap_read(cs35l56->regmap, CS35L56_IRQ1_MASK_20, &mask20); + status20 &= ~mask20; + /* We don't want EINT20 but they default to unmasked: force mask */ + regmap_write(cs35l56->regmap, CS35L56_IRQ1_MASK_20, 0xffffffff); + + dev_dbg(cs35l56->dev, "%s: %#x %#x\n", __func__, status1, status8); + + /* Check to see if unmasked bits are active */ + if (!status1 && !status8 && !status20) + goto err; + + if (status1 & CS35L56_AMP_SHORT_ERR_EINT1_MASK) + dev_crit(cs35l56->dev, "Amp short error\n"); + + if (status8 & CS35L56_TEMP_ERR_EINT1_MASK) + dev_crit(cs35l56->dev, "Overtemp error\n"); + + ret = IRQ_HANDLED; + +err: + pm_runtime_put(cs35l56->dev); +err_unlock: + mutex_unlock(&cs35l56->irq_lock); + + return ret; +} +EXPORT_SYMBOL_NS_GPL(cs35l56_irq, SND_SOC_CS35L56_CORE); + +int cs35l56_irq_request(struct cs35l56_private *cs35l56) +{ + int ret; + + if (!cs35l56->irq) + return 0; + + ret = devm_request_threaded_irq(cs35l56->dev, cs35l56->irq, NULL, + cs35l56_irq, + IRQF_ONESHOT | IRQF_SHARED | IRQF_TRIGGER_LOW, + "cs35l56", cs35l56); + if (ret < 0) + dev_err(cs35l56->dev, "Failed to get IRQ: %d\n", ret); + + return ret; +} +EXPORT_SYMBOL_NS_GPL(cs35l56_irq_request, SND_SOC_CS35L56_CORE); + +static int cs35l56_asp_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) +{ + struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(codec_dai->component); + unsigned int val; + + dev_dbg(cs35l56->dev, "%s: %#x\n", __func__, fmt); + + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_CBC_CFC: + break; + default: + dev_err(cs35l56->dev, "Unsupported clock source mode\n"); + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_DSP_A: + val = CS35L56_ASP_FMT_DSP_A << CS35L56_ASP_FMT_SHIFT; + cs35l56->tdm_mode = true; + break; + case SND_SOC_DAIFMT_I2S: + val = CS35L56_ASP_FMT_I2S << CS35L56_ASP_FMT_SHIFT; + cs35l56->tdm_mode = false; + break; + default: + dev_err(cs35l56->dev, "Unsupported DAI format\n"); + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_IF: + val |= CS35L56_ASP_FSYNC_INV_MASK; + break; + case SND_SOC_DAIFMT_IB_NF: + val |= CS35L56_ASP_BCLK_INV_MASK; + break; + case SND_SOC_DAIFMT_IB_IF: + val |= CS35L56_ASP_BCLK_INV_MASK | CS35L56_ASP_FSYNC_INV_MASK; + break; + case SND_SOC_DAIFMT_NB_NF: + break; + default: + dev_err(cs35l56->dev, "Invalid clock invert\n"); + return -EINVAL; + } + + regmap_update_bits(cs35l56->regmap, + CS35L56_ASP1_CONTROL2, + CS35L56_ASP_FMT_MASK | + CS35L56_ASP_BCLK_INV_MASK | CS35L56_ASP_FSYNC_INV_MASK, + val); + + /* Hi-Z DOUT in unused slots and when all TX are disabled */ + regmap_update_bits(cs35l56->regmap, CS35L56_ASP1_CONTROL3, + CS35L56_ASP1_DOUT_HIZ_CTRL_MASK, + CS35L56_ASP_UNUSED_HIZ_OFF_HIZ); + + return 0; +} + +static void cs35l56_set_asp_slot_positions(struct cs35l56_private *cs35l56, + unsigned int reg, unsigned long mask) +{ + unsigned int reg_val, channel_shift; + int bit_num; + + /* Init all slots to 63 */ + switch (reg) { + case CS35L56_ASP1_FRAME_CONTROL1: + reg_val = 0x3f3f3f3f; + break; + case CS35L56_ASP1_FRAME_CONTROL5: + reg_val = 0x3f3f3f; + break; + } + + /* Enable consecutive TX1..TXn for each of the slots set in mask */ + channel_shift = 0; + for_each_set_bit(bit_num, &mask, 32) { + reg_val &= ~(0x3f << channel_shift); + reg_val |= bit_num << channel_shift; + channel_shift += 8; + } + + regmap_write(cs35l56->regmap, reg, reg_val); +} + +static int cs35l56_asp_dai_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, + unsigned int rx_mask, int slots, int slot_width) +{ + struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(dai->component); + + if ((slots == 0) || (slot_width == 0)) { + dev_dbg(cs35l56->dev, "tdm config cleared\n"); + cs35l56->asp_slot_width = 0; + cs35l56->asp_slot_count = 0; + return 0; + } + + if (slot_width > (CS35L56_ASP_RX_WIDTH_MASK >> CS35L56_ASP_RX_WIDTH_SHIFT)) { + dev_err(cs35l56->dev, "tdm invalid slot width %d\n", slot_width); + return -EINVAL; + } + + /* More than 32 slots would give an unsupportable BCLK frequency */ + if (slots > 32) { + dev_err(cs35l56->dev, "tdm invalid slot count %d\n", slots); + return -EINVAL; + } + + cs35l56->asp_slot_width = (u8)slot_width; + cs35l56->asp_slot_count = (u8)slots; + + // Note: rx/tx is from point of view of the CPU end + if (tx_mask == 0) + tx_mask = 0x3; // ASPRX1/RX2 in slots 0 and 1 + + if (rx_mask == 0) + rx_mask = 0xf; // ASPTX1..TX4 in slots 0..3 + + cs35l56_set_asp_slot_positions(cs35l56, CS35L56_ASP1_FRAME_CONTROL1, rx_mask); + cs35l56_set_asp_slot_positions(cs35l56, CS35L56_ASP1_FRAME_CONTROL5, tx_mask); + + dev_dbg(cs35l56->dev, "tdm slot width: %u count: %u tx_mask: %#x rx_mask: %#x\n", + cs35l56->asp_slot_width, cs35l56->asp_slot_count, tx_mask, rx_mask); + + return 0; +} + +static int cs35l56_asp_dai_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(dai->component); + unsigned int rate = params_rate(params); + u8 asp_width, asp_wl; + + asp_wl = params_width(params); + if (cs35l56->asp_slot_width) + asp_width = cs35l56->asp_slot_width; + else + asp_width = asp_wl; + + dev_dbg(cs35l56->dev, "%s: wl=%d, width=%d, rate=%d", __func__, asp_wl, asp_width, rate); + + if (!cs35l56->sysclk_set) { + unsigned int slots = cs35l56->asp_slot_count; + unsigned int bclk_freq; + int freq_id; + + if (slots == 0) { + slots = params_channels(params); + + /* I2S always has an even number of slots */ + if (!cs35l56->tdm_mode) + slots = round_up(slots, 2); + } + + bclk_freq = asp_width * slots * rate; + freq_id = cs35l56_get_bclk_freq_id(bclk_freq); + if (freq_id < 0) { + dev_err(cs35l56->dev, "%s: Invalid BCLK %u\n", __func__, bclk_freq); + return -EINVAL; + } + + regmap_update_bits(cs35l56->regmap, CS35L56_ASP1_CONTROL1, + CS35L56_ASP_BCLK_FREQ_MASK, + freq_id << CS35L56_ASP_BCLK_FREQ_SHIFT); + } + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + regmap_update_bits(cs35l56->regmap, CS35L56_ASP1_CONTROL2, + CS35L56_ASP_RX_WIDTH_MASK, asp_width << + CS35L56_ASP_RX_WIDTH_SHIFT); + regmap_update_bits(cs35l56->regmap, CS35L56_ASP1_DATA_CONTROL5, + CS35L56_ASP_RX_WL_MASK, asp_wl); + } else { + regmap_update_bits(cs35l56->regmap, CS35L56_ASP1_CONTROL2, + CS35L56_ASP_TX_WIDTH_MASK, asp_width << + CS35L56_ASP_TX_WIDTH_SHIFT); + regmap_update_bits(cs35l56->regmap, CS35L56_ASP1_DATA_CONTROL1, + CS35L56_ASP_TX_WL_MASK, asp_wl); + } + + return 0; +} + +static int cs35l56_asp_dai_set_sysclk(struct snd_soc_dai *dai, + int clk_id, unsigned int freq, int dir) +{ + struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(dai->component); + int freq_id; + + if (freq == 0) { + cs35l56->sysclk_set = false; + return 0; + } + + freq_id = cs35l56_get_bclk_freq_id(freq); + if (freq_id < 0) + return freq_id; + + regmap_update_bits(cs35l56->regmap, CS35L56_ASP1_CONTROL1, + CS35L56_ASP_BCLK_FREQ_MASK, + freq_id << CS35L56_ASP_BCLK_FREQ_SHIFT); + cs35l56->sysclk_set = true; + + return 0; +} + +static int cs35l56_mute_stream(struct snd_soc_dai *dai, int mute, int stream) +{ + struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(dai->component); + unsigned int val; + int ret; + + dev_dbg(cs35l56->dev, "%s: %d %s\n", __func__, stream, mute ? "mute" : "unmute"); + + if (stream != SNDRV_PCM_STREAM_PLAYBACK) + return 0; + + if (mute) { + ret = cs35l56_mbox_send(cs35l56, CS35L56_MBOX_CMD_AUDIO_PAUSE); + } else { + ret = cs35l56_mbox_send(cs35l56, CS35L56_MBOX_CMD_AUDIO_PLAY); + if (ret == 0) { + /* Wait for firmware to enter PS0 power state */ + ret = regmap_read_poll_timeout(cs35l56->regmap, + CS35L56_TRANSDUCER_ACTUAL_PS, + val, (val == CS35L56_PS0), + CS35L56_PS0_POLL_US, + CS35L56_PS0_TIMEOUT_US); + if (ret) + dev_err(cs35l56->dev, "PS0 wait failed: %d\n", ret); + ret = 0; + } + } + + return ret; +} + +static const struct snd_soc_dai_ops cs35l56_ops = { + .set_fmt = cs35l56_asp_dai_set_fmt, + .set_tdm_slot = cs35l56_asp_dai_set_tdm_slot, + .hw_params = cs35l56_asp_dai_hw_params, + .set_sysclk = cs35l56_asp_dai_set_sysclk, + .mute_stream = cs35l56_mute_stream, +}; + +static void cs35l56_sdw_dai_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + snd_soc_dai_set_dma_data(dai, substream, NULL); +} + +static int cs35l56_sdw_dai_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, + unsigned int rx_mask, int slots, int slot_width) +{ + struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(dai->component); + + /* rx/tx are from point of view of the CPU end so opposite to our rx/tx */ + cs35l56->rx_mask = tx_mask; + cs35l56->tx_mask = rx_mask; + + return 0; +} + +static int cs35l56_sdw_dai_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(dai->component); + struct sdw_stream_runtime *sdw_stream = snd_soc_dai_get_dma_data(dai, substream); + struct sdw_stream_config sconfig; + struct sdw_port_config pconfig; + int ret; + + dev_dbg(cs35l56->dev, "%s: rate %d\n", __func__, params_rate(params)); + + if (!cs35l56->init_done) + return -ENODEV; + + if (!sdw_stream) + return -EINVAL; + + memset(&sconfig, 0, sizeof(sconfig)); + memset(&pconfig, 0, sizeof(pconfig)); + + sconfig.frame_rate = params_rate(params); + sconfig.bps = snd_pcm_format_width(params_format(params)); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + sconfig.direction = SDW_DATA_DIR_RX; + pconfig.num = CS35L56_SDW1_PLAYBACK_PORT; + pconfig.ch_mask = cs35l56->rx_mask; + } else { + sconfig.direction = SDW_DATA_DIR_TX; + pconfig.num = CS35L56_SDW1_CAPTURE_PORT; + pconfig.ch_mask = cs35l56->tx_mask; + } + + if (pconfig.ch_mask == 0) { + sconfig.ch_count = params_channels(params); + pconfig.ch_mask = GENMASK(sconfig.ch_count - 1, 0); + } else { + sconfig.ch_count = hweight32(pconfig.ch_mask); + } + + ret = sdw_stream_add_slave(cs35l56->sdw_peripheral, &sconfig, &pconfig, + 1, sdw_stream); + if (ret) { + dev_err(dai->dev, "Failed to add sdw stream: %d\n", ret); + return ret; + } + + return 0; +} + +static int cs35l56_sdw_dai_hw_free(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(dai->component); + struct sdw_stream_runtime *sdw_stream = snd_soc_dai_get_dma_data(dai, substream); + + if (!cs35l56->sdw_peripheral) + return -EINVAL; + + sdw_stream_remove_slave(cs35l56->sdw_peripheral, sdw_stream); + + return 0; +} + +static int cs35l56_sdw_dai_set_stream(struct snd_soc_dai *dai, + void *sdw_stream, int direction) +{ + if (!sdw_stream) + return 0; + + snd_soc_dai_dma_data_set(dai, direction, sdw_stream); + + return 0; +} + +static const struct snd_soc_dai_ops cs35l56_sdw_dai_ops = { + .set_tdm_slot = cs35l56_sdw_dai_set_tdm_slot, + .shutdown = cs35l56_sdw_dai_shutdown, + .hw_params = cs35l56_sdw_dai_hw_params, + .hw_free = cs35l56_sdw_dai_hw_free, + .mute_stream = cs35l56_mute_stream, + .set_stream = cs35l56_sdw_dai_set_stream, +}; + +static struct snd_soc_dai_driver cs35l56_dai[] = { + { + .name = "cs35l56-asp1", + .id = 0, + .playback = { + .stream_name = "ASP1 Playback", + .channels_min = 1, + .channels_max = 2, + .rates = CS35L56_RATES, + .formats = CS35L56_RX_FORMATS, + }, + .capture = { + .stream_name = "ASP1 Capture", + .channels_min = 1, + .channels_max = 4, + .rates = CS35L56_RATES, + .formats = CS35L56_TX_FORMATS, + }, + .ops = &cs35l56_ops, + .symmetric_rate = 1, + .symmetric_sample_bits = 1, + }, + { + .name = "cs35l56-sdw1", + .id = 1, + .playback = { + .stream_name = "SDW1 Playback", + .channels_min = 1, + .channels_max = 2, + .rates = CS35L56_RATES, + .formats = CS35L56_RX_FORMATS, + }, + .capture = { + .stream_name = "SDW1 Capture", + .channels_min = 1, + .channels_max = 6, + .rates = CS35L56_RATES, + .formats = CS35L56_TX_FORMATS, + }, + .symmetric_rate = 1, + .ops = &cs35l56_sdw_dai_ops, + } +}; + +static int cs35l56_wait_for_firmware_boot(struct cs35l56_private *cs35l56) +{ + unsigned int reg; + unsigned int val; + int ret; + + if (cs35l56->rev < CS35L56_REVID_B0) + reg = CS35L56_DSP1_HALO_STATE_A1; + else + reg = CS35L56_DSP1_HALO_STATE; + + ret = regmap_read_poll_timeout(cs35l56->regmap, reg, + val, + (val < 0xFFFF) && (val >= CS35L56_HALO_STATE_BOOT_DONE), + CS35L56_HALO_STATE_POLL_US, + CS35L56_HALO_STATE_TIMEOUT_US); + + if ((ret < 0) && (ret != -ETIMEDOUT)) { + dev_err(cs35l56->dev, "Failed to read HALO_STATE: %d\n", ret); + return ret; + } + + if ((ret == -ETIMEDOUT) || (val != CS35L56_HALO_STATE_BOOT_DONE)) { + dev_err(cs35l56->dev, "Firmware boot fail: HALO_STATE=%#x\n", val); + return -EIO; + } + + return 0; +} + +static const struct reg_sequence cs35l56_system_reset_seq[] = { + REG_SEQ0(CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_SYSTEM_RESET), +}; + +static void cs35l56_system_reset(struct cs35l56_private *cs35l56) +{ + cs35l56->soft_resetting = true; + + /* + * Must enter cache-only first so there can't be any more register + * accesses other than the controlled system reset sequence below. + */ + regcache_cache_only(cs35l56->regmap, true); + regmap_multi_reg_write_bypassed(cs35l56->regmap, + cs35l56_system_reset_seq, + ARRAY_SIZE(cs35l56_system_reset_seq)); + + /* On SoundWire the registers won't be accessible until it re-enumerates. */ + if (cs35l56->sdw_peripheral) + return; + + usleep_range(CS35L56_CONTROL_PORT_READY_US, CS35L56_CONTROL_PORT_READY_US + 400); + regcache_cache_only(cs35l56->regmap, false); +} + +static void cs35l56_dsp_work(struct work_struct *work) +{ + struct cs35l56_private *cs35l56 = container_of(work, + struct cs35l56_private, + dsp_work); + unsigned int reg; + unsigned int val; + int ret = 0; + + if (!wait_for_completion_timeout(&cs35l56->init_completion, + msecs_to_jiffies(5000))) { + dev_err(cs35l56->dev, "%s: init_completion timed out\n", __func__); + goto complete; + } + + if (!cs35l56->init_done || cs35l56->removing) + goto complete; + + cs35l56->dsp.part = devm_kasprintf(cs35l56->dev, GFP_KERNEL, "cs35l56%s-%02x", + cs35l56->secured ? "s" : "", cs35l56->rev); + + if (!cs35l56->dsp.part) + goto complete; + + pm_runtime_get_sync(cs35l56->dev); + + /* + * Disable SoundWire interrupts to prevent race with IRQ work. + * Setting sdw_irq_no_unmask prevents the handler re-enabling + * the SoundWire interrupt. + */ + if (cs35l56->sdw_peripheral) { + cs35l56->sdw_irq_no_unmask = true; + cancel_work_sync(&cs35l56->sdw_irq_work); + sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_MASK_1, 0); + sdw_read_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_STAT_1); + sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_STAT_1, 0xFF); + } + + ret = cs35l56_mbox_send(cs35l56, CS35L56_MBOX_CMD_SHUTDOWN); + if (ret) { + dev_dbg(cs35l56->dev, "%s: CS35L56_MBOX_CMD_SHUTDOWN ret %d\n", __func__, ret); + goto err; + } + + if (cs35l56->rev < CS35L56_REVID_B0) + reg = CS35L56_DSP1_PM_CUR_STATE_A1; + else + reg = CS35L56_DSP1_PM_CUR_STATE; + + ret = regmap_read_poll_timeout(cs35l56->regmap, reg, + val, (val == CS35L56_HALO_STATE_SHUTDOWN), + CS35L56_HALO_STATE_POLL_US, + CS35L56_HALO_STATE_TIMEOUT_US); + if (ret < 0) + dev_err(cs35l56->dev, "Failed to poll PM_CUR_STATE to 1 is %d (ret %d)\n", + val, ret); + + /* Use wm_adsp to load and apply the firmware patch and coefficient files */ + ret = wm_adsp_power_up(&cs35l56->dsp); + if (ret) { + dev_dbg(cs35l56->dev, "%s: wm_adsp_power_up ret %d\n", __func__, ret); + goto err; + } + + if (cs35l56->removing) + goto err; + + mutex_lock(&cs35l56->irq_lock); + + init_completion(&cs35l56->init_completion); + + cs35l56_system_reset(cs35l56); + + if (cs35l56->sdw_peripheral) { + /* + * The system-reset causes the CS35L56 to detach from the bus. + * Wait for the manager to re-enumerate the CS35L56 and + * cs35l56_init() to run again. + */ + if (!wait_for_completion_timeout(&cs35l56->init_completion, + msecs_to_jiffies(5000))) { + dev_err(cs35l56->dev, "%s: init_completion timed out (SDW)\n", __func__); + goto err_unlock; + } + } else if (cs35l56_init(cs35l56)) { + goto err_unlock; + } + + cs35l56->fw_patched = true; + +err_unlock: + mutex_unlock(&cs35l56->irq_lock); +err: + pm_runtime_mark_last_busy(cs35l56->dev); + pm_runtime_put_autosuspend(cs35l56->dev); + + /* Re-enable SoundWire interrupts */ + if (cs35l56->sdw_peripheral) { + cs35l56->sdw_irq_no_unmask = false; + sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_MASK_1, + CS35L56_SDW_INT_MASK_CODEC_IRQ); + } + +complete: + complete_all(&cs35l56->dsp_ready_completion); +} + +static int cs35l56_component_probe(struct snd_soc_component *component) +{ + struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component); + struct dentry *debugfs_root = component->debugfs_root; + + BUILD_BUG_ON(ARRAY_SIZE(cs35l56_tx_input_texts) != ARRAY_SIZE(cs35l56_tx_input_values)); + + cs35l56->removing = false; + cs35l56->component = component; + wm_adsp2_component_probe(&cs35l56->dsp, component); + + debugfs_create_bool("init_done", 0444, debugfs_root, &cs35l56->init_done); + debugfs_create_bool("can_hibernate", 0444, debugfs_root, &cs35l56->can_hibernate); + debugfs_create_bool("fw_patched", 0444, debugfs_root, &cs35l56->fw_patched); + + queue_work(cs35l56->dsp_wq, &cs35l56->dsp_work); + + return 0; +} + +static void cs35l56_component_remove(struct snd_soc_component *component) +{ + struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component); + + cs35l56->removing = true; + complete(&cs35l56->init_completion); + cancel_work_sync(&cs35l56->dsp_work); +} + +static int cs35l56_set_bias_level(struct snd_soc_component *component, + enum snd_soc_bias_level level) +{ + struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component); + int ret = 0; + + switch (level) { + case SND_SOC_BIAS_STANDBY: + /* + * Wait for patching to complete when transitioning from + * BIAS_OFF to BIAS_STANDBY + */ + if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) + ret = cs35l56_wait_dsp_ready(cs35l56); + + break; + default: + break; + } + + return ret; +} + +static const struct snd_soc_component_driver soc_component_dev_cs35l56 = { + .probe = cs35l56_component_probe, + .remove = cs35l56_component_remove, + + .dapm_widgets = cs35l56_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(cs35l56_dapm_widgets), + .dapm_routes = cs35l56_audio_map, + .num_dapm_routes = ARRAY_SIZE(cs35l56_audio_map), + .controls = cs35l56_controls, + .num_controls = ARRAY_SIZE(cs35l56_controls), + + .set_bias_level = cs35l56_set_bias_level, +}; + +static const struct reg_sequence cs35l56_hibernate_seq[] = { + /* This must be the last register access */ + REG_SEQ0(CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_HIBERNATE_NOW), +}; + +static const struct reg_sequence cs35l56_hibernate_wake_seq[] = { + REG_SEQ0(CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_WAKEUP), +}; + +int cs35l56_runtime_suspend(struct device *dev) +{ + struct cs35l56_private *cs35l56 = dev_get_drvdata(dev); + unsigned int val; + int ret; + + if (!cs35l56->init_done) + return 0; + + /* Firmware must have entered a power-save state */ + ret = regmap_read_poll_timeout(cs35l56->regmap, + CS35L56_TRANSDUCER_ACTUAL_PS, + val, (val >= CS35L56_PS3), + CS35L56_PS3_POLL_US, + CS35L56_PS3_TIMEOUT_US); + if (ret) + dev_warn(cs35l56->dev, "PS3 wait failed: %d\n", ret); + + /* Clear BOOT_DONE so it can be used to detect a reboot */ + regmap_write(cs35l56->regmap, CS35L56_IRQ1_EINT_4, CS35L56_OTP_BOOT_DONE_MASK); + + if (!cs35l56->can_hibernate) { + regcache_cache_only(cs35l56->regmap, true); + dev_dbg(dev, "Suspended: no hibernate"); + + return 0; + } + + /* + * Enable auto-hibernate. If it is woken by some other wake source + * it will automatically return to hibernate. + */ + ret = cs35l56_mbox_send(cs35l56, CS35L56_MBOX_CMD_ALLOW_AUTO_HIBERNATE); + if (ret) + dev_warn(cs35l56->dev, "ALLOW_HIBERNATE failed: %d\n", ret); + + /* + * Must enter cache-only first so there can't be any more register + * accesses other than the controlled hibernate sequence below. + */ + regcache_cache_only(cs35l56->regmap, true); + + regmap_multi_reg_write_bypassed(cs35l56->regmap, + cs35l56_hibernate_seq, + ARRAY_SIZE(cs35l56_hibernate_seq)); + + dev_dbg(dev, "Suspended: hibernate"); + + return 0; +} +EXPORT_SYMBOL_NS_GPL(cs35l56_runtime_suspend, SND_SOC_CS35L56_CORE); + +static int __maybe_unused cs35l56_runtime_resume_i2c_spi(struct device *dev) +{ + struct cs35l56_private *cs35l56 = dev_get_drvdata(dev); + + if (!cs35l56->init_done) + return 0; + + return cs35l56_runtime_resume_common(cs35l56); +} + +int cs35l56_runtime_resume_common(struct cs35l56_private *cs35l56) +{ + unsigned int val; + int ret; + + if (!cs35l56->can_hibernate) { + regcache_cache_only(cs35l56->regmap, false); + goto out_sync; + } + + if (!cs35l56->sdw_peripheral) { + /* + * Dummy transaction to trigger I2C/SPI auto-wake. This will NAK on I2C. + * Must be done before releasing cache-only. + */ + regmap_multi_reg_write_bypassed(cs35l56->regmap, + cs35l56_hibernate_wake_seq, + ARRAY_SIZE(cs35l56_hibernate_wake_seq)); + + usleep_range(CS35L56_CONTROL_PORT_READY_US, + CS35L56_CONTROL_PORT_READY_US + 400); + } + + regcache_cache_only(cs35l56->regmap, false); + + ret = cs35l56_wait_for_firmware_boot(cs35l56); + if (ret) { + dev_err(cs35l56->dev, "Hibernate wake failed: %d\n", ret); + goto err; + } + + ret = cs35l56_mbox_send(cs35l56, CS35L56_MBOX_CMD_PREVENT_AUTO_HIBERNATE); + if (ret) + goto err; + +out_sync: + /* BOOT_DONE will be 1 if the amp reset */ + regmap_read(cs35l56->regmap, CS35L56_IRQ1_EINT_4, &val); + if (val & CS35L56_OTP_BOOT_DONE_MASK) { + dev_dbg(cs35l56->dev, "Registers reset in suspend\n"); + regcache_mark_dirty(cs35l56->regmap); + } + + regcache_sync(cs35l56->regmap); + + dev_dbg(cs35l56->dev, "Resumed"); + + return 0; + +err: + regmap_write(cs35l56->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, + CS35L56_MBOX_CMD_HIBERNATE_NOW); + + regcache_cache_only(cs35l56->regmap, true); + + return ret; +} +EXPORT_SYMBOL_NS_GPL(cs35l56_runtime_resume_common, SND_SOC_CS35L56_CORE); + +static int cs35l56_dsp_init(struct cs35l56_private *cs35l56) +{ + struct wm_adsp *dsp; + int ret; + + cs35l56->dsp_wq = create_singlethread_workqueue("cs35l56-dsp"); + if (!cs35l56->dsp_wq) + return -ENOMEM; + + INIT_WORK(&cs35l56->dsp_work, cs35l56_dsp_work); + init_completion(&cs35l56->dsp_ready_completion); + + dsp = &cs35l56->dsp; + dsp->part = "cs35l56"; + dsp->cs_dsp.num = 1; + dsp->cs_dsp.type = WMFW_HALO; + dsp->cs_dsp.rev = 0; + dsp->fw = 12; + dsp->cs_dsp.dev = cs35l56->dev; + dsp->cs_dsp.regmap = cs35l56->regmap; + dsp->cs_dsp.base = CS35L56_DSP1_CORE_BASE; + dsp->cs_dsp.base_sysinfo = CS35L56_DSP1_SYS_INFO_ID; + dsp->cs_dsp.mem = cs35l56_dsp1_regions; + dsp->cs_dsp.num_mems = ARRAY_SIZE(cs35l56_dsp1_regions); + dsp->cs_dsp.no_core_startstop = true; + dsp->wmfw_optional = true; + + dev_dbg(cs35l56->dev, "DSP system name: '%s'\n", dsp->system_name); + + ret = wm_halo_init(dsp); + if (ret != 0) { + dev_err(cs35l56->dev, "wm_halo_init failed\n"); + return ret; + } + + return 0; +} + +static int cs35l56_acpi_get_name(struct cs35l56_private *cs35l56) +{ + acpi_handle handle = ACPI_HANDLE(cs35l56->dev); + const char *sub; + + /* If there is no ACPI_HANDLE, there is no ACPI for this system, return 0 */ + if (!handle) + return 0; + + sub = acpi_get_subsystem_id(handle); + if (IS_ERR(sub)) { + /* If bad ACPI, return 0 and fallback to legacy firmware path, otherwise fail */ + if (PTR_ERR(sub) == -ENODATA) + return 0; + else + return PTR_ERR(sub); + } + + cs35l56->dsp.system_name = sub; + dev_dbg(cs35l56->dev, "Subsystem ID: %s\n", cs35l56->dsp.system_name); + + return 0; +} + +int cs35l56_common_probe(struct cs35l56_private *cs35l56) +{ + int ret; + + init_completion(&cs35l56->init_completion); + mutex_init(&cs35l56->irq_lock); + + dev_set_drvdata(cs35l56->dev, cs35l56); + + cs35l56_fill_supply_names(cs35l56->supplies); + ret = devm_regulator_bulk_get(cs35l56->dev, ARRAY_SIZE(cs35l56->supplies), + cs35l56->supplies); + if (ret != 0) + return dev_err_probe(cs35l56->dev, ret, "Failed to request supplies\n"); + + /* Reset could be controlled by the BIOS or shared by multiple amps */ + cs35l56->reset_gpio = devm_gpiod_get_optional(cs35l56->dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(cs35l56->reset_gpio)) { + ret = PTR_ERR(cs35l56->reset_gpio); + /* + * If RESET is shared the first amp to probe will grab the reset + * line and reset all the amps + */ + if (ret != -EBUSY) + return dev_err_probe(cs35l56->dev, ret, "Failed to get reset GPIO\n"); + + dev_info(cs35l56->dev, "Reset GPIO busy, assume shared reset\n"); + cs35l56->reset_gpio = NULL; + } + + ret = regulator_bulk_enable(ARRAY_SIZE(cs35l56->supplies), cs35l56->supplies); + if (ret != 0) + return dev_err_probe(cs35l56->dev, ret, "Failed to enable supplies\n"); + + if (cs35l56->reset_gpio) { + /* satisfy minimum reset pulse width spec */ + usleep_range(CS35L56_RESET_PULSE_MIN_US, + CS35L56_RESET_PULSE_MIN_US + 400); + gpiod_set_value_cansleep(cs35l56->reset_gpio, 1); + } + + ret = cs35l56_acpi_get_name(cs35l56); + if (ret != 0) + goto err; + + ret = cs35l56_dsp_init(cs35l56); + if (ret < 0) { + dev_err_probe(cs35l56->dev, ret, "DSP init failed\n"); + goto err; + } + + ret = devm_snd_soc_register_component(cs35l56->dev, + &soc_component_dev_cs35l56, + cs35l56_dai, ARRAY_SIZE(cs35l56_dai)); + if (ret < 0) { + dev_err_probe(cs35l56->dev, ret, "Register codec failed\n"); + goto err; + } + + return 0; + +err: + gpiod_set_value_cansleep(cs35l56->reset_gpio, 0); + regulator_bulk_disable(ARRAY_SIZE(cs35l56->supplies), cs35l56->supplies); + + return ret; +} +EXPORT_SYMBOL_NS_GPL(cs35l56_common_probe, SND_SOC_CS35L56_CORE); + +int cs35l56_init(struct cs35l56_private *cs35l56) +{ + int ret; + unsigned int devid, revid, otpid, secured; + + /* + * Check whether the actions associated with soft reset or one time + * init need to be performed. + */ + if (cs35l56->soft_resetting) + goto post_soft_reset; + + if (cs35l56->init_done) + return 0; + + pm_runtime_set_autosuspend_delay(cs35l56->dev, 100); + pm_runtime_use_autosuspend(cs35l56->dev); + pm_runtime_set_active(cs35l56->dev); + pm_runtime_enable(cs35l56->dev); + + /* + * If the system is not using a reset_gpio then issue a + * dummy read to force a wakeup. + */ + if (!cs35l56->reset_gpio) + regmap_read(cs35l56->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, &devid); + + /* Wait for control port to be ready (datasheet tIRS). */ + usleep_range(CS35L56_CONTROL_PORT_READY_US, + CS35L56_CONTROL_PORT_READY_US + 400); + + /* + * The HALO_STATE register is in different locations on Ax and B0 + * devices so the REVID needs to be determined before waiting for the + * firmware to boot. + */ + ret = regmap_read(cs35l56->regmap, CS35L56_REVID, &revid); + if (ret < 0) { + dev_err(cs35l56->dev, "Get Revision ID failed\n"); + return ret; + } + cs35l56->rev = revid & (CS35L56_AREVID_MASK | CS35L56_MTLREVID_MASK); + + ret = cs35l56_wait_for_firmware_boot(cs35l56); + if (ret) + return ret; + + ret = regmap_read(cs35l56->regmap, CS35L56_DEVID, &devid); + if (ret < 0) { + dev_err(cs35l56->dev, "Get Device ID failed\n"); + return ret; + } + devid &= CS35L56_DEVID_MASK; + + switch (devid) { + case 0x35A56: + break; + default: + dev_err(cs35l56->dev, "Unknown device %x\n", devid); + return ret; + } + + ret = regmap_read(cs35l56->regmap, CS35L56_DSP_RESTRICT_STS1, &secured); + if (ret) { + dev_err(cs35l56->dev, "Get Secure status failed\n"); + return ret; + } + + /* When any bus is restricted treat the device as secured */ + if (secured & CS35L56_RESTRICTED_MASK) + cs35l56->secured = true; + + ret = regmap_read(cs35l56->regmap, CS35L56_OTPID, &otpid); + if (ret < 0) { + dev_err(cs35l56->dev, "Get OTP ID failed\n"); + return ret; + } + + dev_info(cs35l56->dev, "Cirrus Logic CS35L56%s Rev %02X OTP%d\n", + cs35l56->secured ? "s" : "", cs35l56->rev, otpid); + + cs35l56_patch(cs35l56->dev, cs35l56->regmap, cs35l56->rev); + + /* Wake source interrupts default to unmasked, so mask them */ + regmap_write(cs35l56->regmap, CS35L56_IRQ1_MASK_20, 0xffffffff); + regmap_update_bits(cs35l56->regmap, CS35L56_IRQ1_MASK_1, + CS35L56_AMP_SHORT_ERR_EINT1_MASK, + 0); + regmap_update_bits(cs35l56->regmap, CS35L56_IRQ1_MASK_8, + CS35L56_TEMP_ERR_EINT1_MASK, + 0); + + if (!cs35l56->reset_gpio) { + dev_dbg(cs35l56->dev, "No reset gpio: using soft reset\n"); + cs35l56_system_reset(cs35l56); + if (cs35l56->sdw_peripheral) { + /* Keep alive while we wait for re-enumeration */ + pm_runtime_get_noresume(cs35l56->dev); + return 0; + } + } + +post_soft_reset: + if (cs35l56->soft_resetting) { + cs35l56->soft_resetting = false; + + /* Done re-enumerating after one-time init so release the keep-alive */ + if (cs35l56->sdw_peripheral && !cs35l56->init_done) + pm_runtime_put_noidle(cs35l56->dev); + + regcache_mark_dirty(cs35l56->regmap); + ret = cs35l56_wait_for_firmware_boot(cs35l56); + if (ret) + return ret; + + dev_dbg(cs35l56->dev, "Firmware rebooted after soft reset\n"); + } + + /* Disable auto-hibernate so that runtime_pm has control */ + ret = cs35l56_mbox_send(cs35l56, CS35L56_MBOX_CMD_PREVENT_AUTO_HIBERNATE); + if (ret) + return ret; + + /* Populate soft registers in the regmap cache */ + cs35l56_reread_firmware_registers(cs35l56->dev, cs35l56->regmap); + + /* Registers could be dirty after soft reset or SoundWire enumeration */ + regcache_sync(cs35l56->regmap); + + cs35l56->init_done = true; + complete(&cs35l56->init_completion); + + return 0; +} +EXPORT_SYMBOL_NS_GPL(cs35l56_init, SND_SOC_CS35L56_CORE); + +int cs35l56_remove(struct cs35l56_private *cs35l56) +{ + cs35l56->init_done = false; + + /* + * WAKE IRQs unmask if CS35L56 hibernates so free the handler to + * prevent it racing with remove(). + */ + if (cs35l56->irq) + devm_free_irq(cs35l56->dev, cs35l56->irq, cs35l56); + + flush_workqueue(cs35l56->dsp_wq); + destroy_workqueue(cs35l56->dsp_wq); + + pm_runtime_suspend(cs35l56->dev); + pm_runtime_disable(cs35l56->dev); + + regcache_cache_only(cs35l56->regmap, true); + + kfree(cs35l56->dsp.system_name); + + gpiod_set_value_cansleep(cs35l56->reset_gpio, 0); + regulator_bulk_disable(ARRAY_SIZE(cs35l56->supplies), cs35l56->supplies); + + return 0; +} +EXPORT_SYMBOL_NS_GPL(cs35l56_remove, SND_SOC_CS35L56_CORE); + +const struct dev_pm_ops cs35l56_pm_ops_i2c_spi = { + SET_RUNTIME_PM_OPS(cs35l56_runtime_suspend, cs35l56_runtime_resume_i2c_spi, NULL) +}; +EXPORT_SYMBOL_NS_GPL(cs35l56_pm_ops_i2c_spi, SND_SOC_CS35L56_CORE); + +MODULE_DESCRIPTION("ASoC CS35L56 driver"); +MODULE_IMPORT_NS(SND_SOC_CS35L56_SHARED); +MODULE_AUTHOR("Richard Fitzgerald "); +MODULE_AUTHOR("Simon Trimmer "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/cs35l56.h b/sound/soc/codecs/cs35l56.h new file mode 100644 index 000000000000..efc4b99180f9 --- /dev/null +++ b/sound/soc/codecs/cs35l56.h @@ -0,0 +1,77 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Driver for Cirrus Logic CS35L56 smart amp + * + * Copyright (C) 2023 Cirrus Logic, Inc. and + * Cirrus Logic International Semiconductor Ltd. + */ + +#ifndef CS35L56_H +#define CS35L56_H + +#include +#include +#include +#include +#include +#include "wm_adsp.h" + +#define CS35L56_SDW_GEN_INT_STAT_1 0xc0 +#define CS35L56_SDW_GEN_INT_MASK_1 0xc1 +#define CS35L56_SDW_INT_MASK_CODEC_IRQ BIT(0) + +#define CS35L56_SDW_INVALID_BUS_SCALE 0xf + +#define CS35L56_RX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE) +#define CS35L56_TX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE \ + | SNDRV_PCM_FMTBIT_S32_LE) + +#define CS35L56_RATES (SNDRV_PCM_RATE_48000) + +struct sdw_slave; + +struct cs35l56_private { + struct wm_adsp dsp; /* must be first member */ + struct work_struct dsp_work; + struct workqueue_struct *dsp_wq; + struct completion dsp_ready_completion; + struct mutex irq_lock; + struct snd_soc_component *component; + struct device *dev; + struct regmap *regmap; + struct regulator_bulk_data supplies[CS35L56_NUM_BULK_SUPPLIES]; + int irq; + struct sdw_slave *sdw_peripheral; + u8 rev; + struct work_struct sdw_irq_work; + bool secured; + bool sdw_irq_no_unmask; + bool soft_resetting; + bool init_done; + bool sdw_attached; + bool removing; + bool fw_patched; + bool can_hibernate; + struct completion init_completion; + struct gpio_desc *reset_gpio; + + u32 rx_mask; + u32 tx_mask; + u8 asp_slot_width; + u8 asp_slot_count; + bool tdm_mode; + bool sysclk_set; + u8 old_sdw_clock_scale; +}; + +extern const struct dev_pm_ops cs35l56_pm_ops_i2c_spi; + +int cs35l56_runtime_suspend(struct device *dev); +int cs35l56_runtime_resume_common(struct cs35l56_private *cs35l56); +irqreturn_t cs35l56_irq(int irq, void *data); +int cs35l56_irq_request(struct cs35l56_private *cs35l56); +int cs35l56_common_probe(struct cs35l56_private *cs35l56); +int cs35l56_init(struct cs35l56_private *cs35l56); +int cs35l56_remove(struct cs35l56_private *cs35l56); + +#endif /* ifndef CS35L56_H */ From 3d3e223f09ed59f7a47d27cf4301b4d0d5c7fc3d Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 21 Mar 2023 11:26:52 +0200 Subject: [PATCH 576/778] ASoC: SOF: topology: Set pipeline widget before updating IPC structures Set up the IPC structure for scheduler widgets and set the pipeline widget before updating the IPC structures for all widgets. This will be needed to look up pipeline information during IPC structure set up. Signed-off-by: Ranjani Sridharan Signed-off-by: Jyri Sarha Reviewed-by: Rander Wang Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230321092654.7292-2-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/topology.c | 48 ++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index b642835e14df..bc8ca1e05b83 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -2126,7 +2126,6 @@ static int sof_complete(struct snd_soc_component *scomp) { struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); - struct snd_sof_widget *swidget, *comp_swidget; const struct sof_ipc_tplg_widget_ops *widget_ops; struct snd_sof_control *scontrol; struct snd_sof_pipeline *spipe; @@ -2145,37 +2144,38 @@ static int sof_complete(struct snd_soc_component *scomp) } } - /* - * then update all widget IPC structures. If any of the ipc_setup callbacks fail, the - * topology will be removed and all widgets will be unloaded resulting in freeing all - * associated memories. - */ - list_for_each_entry(swidget, &sdev->widget_list, list) { - if (widget_ops && widget_ops[swidget->id].ipc_setup) { - ret = widget_ops[swidget->id].ipc_setup(swidget); + /* set up the IPC structures for the pipeline widgets */ + list_for_each_entry(spipe, &sdev->pipeline_list, list) { + struct snd_sof_widget *pipe_widget = spipe->pipe_widget; + struct snd_sof_widget *swidget; + + /* Update the scheduler widget's IPC structure */ + if (widget_ops && widget_ops[pipe_widget->id].ipc_setup) { + ret = widget_ops[pipe_widget->id].ipc_setup(pipe_widget); if (ret < 0) { dev_err(sdev->dev, "failed updating IPC struct for %s\n", - swidget->widget->name); + pipe_widget->widget->name); return ret; } } - } - /* set the pipe_widget and apply the dynamic_pipeline_widget_flag */ - list_for_each_entry(spipe, &sdev->pipeline_list, list) { - struct snd_sof_widget *pipe_widget = spipe->pipe_widget; - - /* - * Apply the dynamic_pipeline_widget flag and set the pipe_widget field - * for all widgets that have the same pipeline ID as the scheduler widget. - * Skip the scheduler widgets as they have their pipeline set during widget_ready - */ - list_for_each_entry(comp_swidget, &sdev->widget_list, list) - if (comp_swidget->widget->id != snd_soc_dapm_scheduler && - comp_swidget->pipeline_id == pipe_widget->pipeline_id) { - ret = sof_set_widget_pipeline(sdev, spipe, comp_swidget); + /* set the pipeline and update the IPC structure for the non scheduler widgets */ + list_for_each_entry(swidget, &sdev->widget_list, list) + if (swidget->widget->id != snd_soc_dapm_scheduler && + swidget->pipeline_id == pipe_widget->pipeline_id) { + ret = sof_set_widget_pipeline(sdev, spipe, swidget); if (ret < 0) return ret; + + if (widget_ops && widget_ops[swidget->id].ipc_setup) { + ret = widget_ops[swidget->id].ipc_setup(swidget); + if (ret < 0) { + dev_err(sdev->dev, + "failed updating IPC struct for %s\n", + swidget->widget->name); + return ret; + } + } } } From cb3cdef33136baceada86ba2a21ba30cd53a9087 Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Tue, 21 Mar 2023 11:26:53 +0200 Subject: [PATCH 577/778] ASoC: SOF: ipc4: Add macros for chain-dma message bits In the chained DMA mode, the firmware allocates buffers for the host and link DMA, and takes care of copying data between host- and link-DMA buffers in a low-latency thread. This is different to a regular pipeline, no processing is allowed, and the connection between host- and link DMA is handled with a dedicated IPC. This patch exposes the macros needed to create the required IPC messages. Signed-off-by: Jyri Sarha Reviewed-by: Rander Wang Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230321092654.7292-3-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof/ipc4/header.h | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/include/sound/sof/ipc4/header.h b/include/sound/sof/ipc4/header.h index 49ff1558a171..78568abe2673 100644 --- a/include/sound/sof/ipc4/header.h +++ b/include/sound/sof/ipc4/header.h @@ -196,6 +196,35 @@ enum sof_ipc4_pipeline_state { #define SOF_IPC4_GLB_LOAD_LIBRARY_LIB_ID_SHIFT 16 #define SOF_IPC4_GLB_LOAD_LIBRARY_LIB_ID(x) ((x) << SOF_IPC4_GLB_LOAD_LIBRARY_LIB_ID_SHIFT) +/* chain dma ipc message */ +#define SOF_IPC4_GLB_CHAIN_DMA_HOST_ID_SHIFT 0 +#define SOF_IPC4_GLB_CHAIN_DMA_HOST_ID_MASK GENMASK(4, 0) +#define SOF_IPC4_GLB_CHAIN_DMA_HOST_ID(x) (((x) << SOF_IPC4_GLB_CHAIN_DMA_HOST_ID_SHIFT) & \ + SOF_IPC4_GLB_CHAIN_DMA_HOST_ID_MASK) + +#define SOF_IPC4_GLB_CHAIN_DMA_LINK_ID_SHIFT 8 +#define SOF_IPC4_GLB_CHAIN_DMA_LINK_ID_MASK GENMASK(12, 8) +#define SOF_IPC4_GLB_CHAIN_DMA_LINK_ID(x) (((x) << SOF_IPC4_GLB_CHAIN_DMA_LINK_ID_SHIFT) & \ + SOF_IPC4_GLB_CHAIN_DMA_LINK_ID_MASK) + +#define SOF_IPC4_GLB_CHAIN_DMA_ALLOCATE_SHIFT 16 +#define SOF_IPC4_GLB_CHAIN_DMA_ALLOCATE_MASK BIT(16) +#define SOF_IPC4_GLB_CHAIN_DMA_ALLOCATE(x) (((x) & 1) << SOF_IPC4_GLB_CHAIN_DMA_ALLOCATE_SHIFT) + +#define SOF_IPC4_GLB_CHAIN_DMA_ENABLE_SHIFT 17 +#define SOF_IPC4_GLB_CHAIN_DMA_ENABLE_MASK BIT(17) +#define SOF_IPC4_GLB_CHAIN_DMA_ENABLE(x) (((x) & 1) << SOF_IPC4_GLB_CHAIN_DMA_ENABLE_SHIFT) + +#define SOF_IPC4_GLB_CHAIN_DMA_SCS_SHIFT 18 +#define SOF_IPC4_GLB_CHAIN_DMA_SCS_MASK BIT(18) +#define SOF_IPC4_GLB_CHAIN_DMA_SCS(x) (((x) & 1) << SOF_IPC4_GLB_CHAIN_DMA_SCS_SHIFT) + +#define SOF_IPC4_GLB_EXT_CHAIN_DMA_FIFO_SIZE_SHIFT 0 +#define SOF_IPC4_GLB_EXT_CHAIN_DMA_FIFO_SIZE_MASK GENMASK(24, 0) +#define SOF_IPC4_GLB_EXT_CHAIN_DMA_FIFO_SIZE(x) (((x) << \ + SOF_IPC4_GLB_EXT_CHAIN_DMA_FIFO_SIZE_SHIFT) & \ + SOF_IPC4_GLB_EXT_CHAIN_DMA_FIFO_SIZE_MASK) + enum sof_ipc4_channel_config { /* one channel only. */ SOF_IPC4_CHANNEL_CONFIG_MONO, From ca5ce0caa67fa9eeecaa29d895c2e4c3151c159e Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Tue, 21 Mar 2023 11:26:54 +0200 Subject: [PATCH 578/778] ASoC: SOF: ipc4/intel: Add support for chained DMA Add logic for setting up and tearing down chained DMA connections. Since pipelines are not used, all the logic to set the pipeline states can be bypassed, with only the DMA programming sequences remaining. In addition the same format needs to be used for host- and link-DMA, without the usual fixup to use the S32_LE format on the link. Note however that for convenience and compatibility with existing definitions, the topology relies on the concept of pipelines with a 'USE_CHAIN_DMA' token indicating that all the logic shall be bypassed. Unlike 'normal' ALSA sequences, the chain DMA is not programmed in hw_params/hw_free. The IPC message to set-up and tear-down chained DMA are sent in sof_ipc4_trigger_pipelines(), but the contents prepared earlier. Chained DMA is only supported by the Intel HDA DAI for now, and only S16_LE and S32_LE formats are supported for now. Signed-off-by: Jyri Sarha Reviewed-by: Rander Wang Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230321092654.7292-4-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- include/uapi/sound/sof/tokens.h | 1 + sound/soc/sof/intel/hda-dai-ops.c | 18 ++++- sound/soc/sof/ipc4-pcm.c | 122 +++++++++++++++++++++++++++++- sound/soc/sof/ipc4-topology.c | 120 ++++++++++++++++++++++++++++- sound/soc/sof/ipc4-topology.h | 2 + 5 files changed, 255 insertions(+), 8 deletions(-) diff --git a/include/uapi/sound/sof/tokens.h b/include/uapi/sound/sof/tokens.h index bd02842124f9..bbc37877aaff 100644 --- a/include/uapi/sound/sof/tokens.h +++ b/include/uapi/sound/sof/tokens.h @@ -54,6 +54,7 @@ #define SOF_TKN_SCHED_DYNAMIC_PIPELINE 206 #define SOF_TKN_SCHED_LP_MODE 207 #define SOF_TKN_SCHED_MEM_USAGE 208 +#define SOF_TKN_SCHED_USE_CHAIN_DMA 209 /* volume */ #define SOF_TKN_VOLUME_RAMP_STEP_TYPE 250 diff --git a/sound/soc/sof/intel/hda-dai-ops.c b/sound/soc/sof/intel/hda-dai-ops.c index be109f33715f..de48f13259f1 100644 --- a/sound/soc/sof/intel/hda-dai-ops.c +++ b/sound/soc/sof/intel/hda-dai-ops.c @@ -277,6 +277,15 @@ static const struct hda_dai_widget_dma_ops hda_ipc4_dma_ops = { .post_trigger = hda_ipc4_post_trigger }; +static const struct hda_dai_widget_dma_ops hda_ipc4_chain_dma_ops = { + .get_hext_stream = hda_get_hext_stream, + .assign_hext_stream = hda_assign_hext_stream, + .release_hext_stream = hda_release_hext_stream, + .setup_hext_stream = hda_setup_hext_stream, + .reset_hext_stream = hda_reset_hext_stream, + .trigger = hda_trigger, +}; + static int hda_ipc3_post_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai, struct snd_pcm_substream *substream, int cmd) { @@ -331,8 +340,15 @@ hda_select_dai_widget_ops(struct snd_sof_dev *sdev, struct snd_sof_widget *swidg { struct sof_ipc4_copier *ipc4_copier = sdai->private; - if (ipc4_copier->dai_type == SOF_DAI_INTEL_HDA) + if (ipc4_copier->dai_type == SOF_DAI_INTEL_HDA) { + struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget; + struct sof_ipc4_pipeline *pipeline = pipe_widget->private; + + if (pipeline->use_chain_dma) + return &hda_ipc4_chain_dma_ops; + return &hda_ipc4_dma_ops; + } break; } default: diff --git a/sound/soc/sof/ipc4-pcm.c b/sound/soc/sof/ipc4-pcm.c index 4598057b7f28..db64200ba1e5 100644 --- a/sound/soc/sof/ipc4-pcm.c +++ b/sound/soc/sof/ipc4-pcm.c @@ -193,6 +193,88 @@ sof_ipc4_update_pipeline_state(struct snd_sof_dev *sdev, int state, int cmd, * prepare ioctl before the START trigger. */ +/* + * Chained DMA is a special case where there is no processing on + * DSP. The samples are just moved over by host side DMA to a single + * buffer on DSP and directly from there to link DMA. However, the + * model on SOF driver has two notional pipelines, one at host DAI, + * and another at link DAI. They both shall have the use_chain_dma + * attribute. + */ + +static int sof_ipc4_chain_dma_trigger(struct snd_sof_dev *sdev, + struct snd_sof_pcm_stream_pipeline_list *pipeline_list, + int state, int cmd) +{ + bool allocate, enable, set_fifo_size; + struct sof_ipc4_msg msg = {{ 0 }}; + int i; + + switch (state) { + case SOF_IPC4_PIPE_RUNNING: /* Allocate and start chained dma */ + allocate = true; + enable = true; + /* + * SOF assumes creation of a new stream from the presence of fifo_size + * in the message, so we must leave it out in pause release case. + */ + if (cmd == SNDRV_PCM_TRIGGER_PAUSE_RELEASE) + set_fifo_size = false; + else + set_fifo_size = true; + break; + case SOF_IPC4_PIPE_PAUSED: /* Disable chained DMA. */ + allocate = true; + enable = false; + set_fifo_size = false; + break; + case SOF_IPC4_PIPE_RESET: /* Disable and free chained DMA. */ + allocate = false; + enable = false; + set_fifo_size = false; + break; + default: + dev_err(sdev->dev, "Unexpected state %d", state); + return -EINVAL; + } + + msg.primary = SOF_IPC4_MSG_TYPE_SET(SOF_IPC4_GLB_CHAIN_DMA); + msg.primary |= SOF_IPC4_MSG_DIR(SOF_IPC4_MSG_REQUEST); + msg.primary |= SOF_IPC4_MSG_TARGET(SOF_IPC4_FW_GEN_MSG); + + /* + * To set-up the DMA chain, the host DMA ID and SCS setting + * are retrieved from the host pipeline configuration. Likewise + * the link DMA ID and fifo_size are retrieved from the link + * pipeline configuration. + */ + for (i = 0; i < pipeline_list->count; i++) { + struct snd_sof_pipeline *spipe = pipeline_list->pipelines[i]; + struct snd_sof_widget *pipe_widget = spipe->pipe_widget; + struct sof_ipc4_pipeline *pipeline = pipe_widget->private; + + if (!pipeline->use_chain_dma) { + dev_err(sdev->dev, + "All pipelines in chained DMA stream should have use_chain_dma attribute set."); + return -EINVAL; + } + + msg.primary |= pipeline->msg.primary; + + /* Add fifo_size (actually DMA buffer size) field to the message */ + if (set_fifo_size) + msg.extension |= pipeline->msg.extension; + } + + if (allocate) + msg.primary |= SOF_IPC4_GLB_CHAIN_DMA_ALLOCATE_MASK; + + if (enable) + msg.primary |= SOF_IPC4_GLB_CHAIN_DMA_ENABLE_MASK; + + return sof_ipc_tx_message(sdev->ipc, &msg, 0, NULL, 0); +} + static int sof_ipc4_trigger_pipelines(struct snd_soc_component *component, struct snd_pcm_substream *substream, int state, int cmd) { @@ -201,6 +283,8 @@ static int sof_ipc4_trigger_pipelines(struct snd_soc_component *component, struct snd_sof_pcm_stream_pipeline_list *pipeline_list; struct sof_ipc4_fw_data *ipc4_data = sdev->private; struct ipc4_pipeline_set_state_data *trigger_list; + struct snd_sof_widget *pipe_widget; + struct sof_ipc4_pipeline *pipeline; struct snd_sof_pipeline *spipe; struct snd_sof_pcm *spcm; int ret; @@ -218,6 +302,17 @@ static int sof_ipc4_trigger_pipelines(struct snd_soc_component *component, if (!pipeline_list->pipelines || !pipeline_list->count) return 0; + spipe = pipeline_list->pipelines[0]; + pipe_widget = spipe->pipe_widget; + pipeline = pipe_widget->private; + + /* + * If use_chain_dma attribute is set we proceed to chained DMA + * trigger function that handles the rest for the substream. + */ + if (pipeline->use_chain_dma) + return sof_ipc4_chain_dma_trigger(sdev, pipeline_list, state, cmd); + /* allocate memory for the pipeline data */ trigger_list = kzalloc(struct_size(trigger_list, pipeline_ids, pipeline_list->count), GFP_KERNEL); @@ -422,8 +517,10 @@ static int sof_ipc4_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME); struct snd_sof_dai *dai = snd_sof_find_dai(component, rtd->dai_link->name); struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct sof_ipc4_copier *ipc4_copier; - int ret; + bool use_chain_dma = false; + int dir; if (!dai) { dev_err(component->dev, "%s: No DAI found with name %s\n", __func__, @@ -438,9 +535,26 @@ static int sof_ipc4_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, return -EINVAL; } - ret = sof_ipc4_pcm_dai_link_fixup_rate(sdev, params, ipc4_copier); - if (ret) - return ret; + for_each_pcm_streams(dir) { + struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, dir); + + if (w) { + struct snd_sof_widget *swidget = w->dobj.private; + struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget; + struct sof_ipc4_pipeline *pipeline = pipe_widget->private; + + if (pipeline->use_chain_dma) + use_chain_dma = true; + } + } + + /* Chain DMA does not use copiers, so no fixup needed */ + if (!use_chain_dma) { + int ret = sof_ipc4_pcm_dai_link_fixup_rate(sdev, params, ipc4_copier); + + if (ret) + return ret; + } switch (ipc4_copier->dai_type) { case SOF_DAI_INTEL_SSP: diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index 3a4a3267017b..f1e1aed94da4 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -19,6 +19,7 @@ #define SOF_IPC4_GAIN_PARAM_ID 0 #define SOF_IPC4_TPLG_ABI_SIZE 6 +#define SOF_IPC4_CHAIN_DMA_BUF_SIZE_MS 2 static DEFINE_IDA(alh_group_ida); static DEFINE_IDA(pipeline_ida); @@ -26,6 +27,8 @@ static DEFINE_IDA(pipeline_ida); static const struct sof_topology_token ipc4_sched_tokens[] = { {SOF_TKN_SCHED_LP_MODE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, offsetof(struct sof_ipc4_pipeline, lp_mode)}, + {SOF_TKN_SCHED_USE_CHAIN_DMA, SND_SOC_TPLG_TUPLE_TYPE_BOOL, get_token_u16, + offsetof(struct sof_ipc4_pipeline, use_chain_dma)}, {SOF_TKN_SCHED_CORE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, offsetof(struct sof_ipc4_pipeline, core_id)}, }; @@ -475,6 +478,8 @@ static int sof_ipc4_widget_setup_comp_dai(struct snd_sof_widget *swidget) struct snd_soc_component *scomp = swidget->scomp; struct snd_sof_dai *dai = swidget->private; struct sof_ipc4_copier *ipc4_copier; + struct snd_sof_widget *pipe_widget; + struct sof_ipc4_pipeline *pipeline; int node_type = 0; int ret; @@ -512,6 +517,16 @@ static int sof_ipc4_widget_setup_comp_dai(struct snd_sof_widget *swidget) ipc4_copier->data.gtw_cfg.node_id = SOF_IPC4_NODE_TYPE(node_type); + pipe_widget = swidget->spipe->pipe_widget; + pipeline = pipe_widget->private; + if (pipeline->use_chain_dma && ipc4_copier->dai_type != SOF_DAI_INTEL_HDA) { + dev_err(scomp->dev, + "Bad DAI type '%d', Chained DMA is only supported by HDA DAIs (%d).\n", + ipc4_copier->dai_type, SOF_DAI_INTEL_HDA); + ret = -ENODEV; + goto free_available_fmt; + } + switch (ipc4_copier->dai_type) { case SOF_DAI_INTEL_ALH: { @@ -643,6 +658,12 @@ static int sof_ipc4_widget_setup_comp_pipeline(struct snd_sof_widget *swidget) swidget->core = pipeline->core_id; + if (pipeline->use_chain_dma) { + dev_dbg(scomp->dev, "Set up chain DMA for %s\n", swidget->widget->name); + swidget->private = pipeline; + return 0; + } + /* parse one set of pipeline tokens */ ret = sof_update_ipc_object(scomp, swidget, SOF_PIPELINE_TOKENS, swidget->tuples, swidget->num_tuples, sizeof(*swidget), 1); @@ -1103,11 +1124,21 @@ static void sof_ipc4_unprepare_copier_module(struct snd_sof_widget *swidget) pipeline->mem_usage = 0; if (WIDGET_IS_AIF(swidget->id) || swidget->id == snd_soc_dapm_buffer) { + if (pipeline->use_chain_dma) { + pipeline->msg.primary = 0; + pipeline->msg.extension = 0; + } ipc4_copier = swidget->private; } else if (WIDGET_IS_DAI(swidget->id)) { struct snd_sof_dai *dai = swidget->private; ipc4_copier = dai->private; + + if (pipeline->use_chain_dma) { + pipeline->msg.primary = 0; + pipeline->msg.extension = 0; + } + if (ipc4_copier->dai_type == SOF_DAI_INTEL_ALH) { struct sof_ipc4_copier_data *copier_data = &ipc4_copier->data; struct sof_ipc4_alh_configuration_blob *blob; @@ -1344,13 +1375,44 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, return ret; } - pipe_widget = swidget->spipe->pipe_widget; - pipeline = pipe_widget->private; ipc4_copier = (struct sof_ipc4_copier *)swidget->private; gtw_attr = ipc4_copier->gtw_attr; copier_data = &ipc4_copier->data; available_fmt = &ipc4_copier->available_fmt; + pipe_widget = swidget->spipe->pipe_widget; + pipeline = pipe_widget->private; + + if (pipeline->use_chain_dma) { + u32 host_dma_id; + u32 fifo_size; + + host_dma_id = platform_params->stream_tag - 1; + pipeline->msg.primary |= SOF_IPC4_GLB_CHAIN_DMA_HOST_ID(host_dma_id); + + /* Set SCS bit for S16_LE format only */ + if (params_format(fe_params) == SNDRV_PCM_FORMAT_S16_LE) + pipeline->msg.primary |= SOF_IPC4_GLB_CHAIN_DMA_SCS_MASK; + + /* + * Despite its name the bitfield 'fifo_size' is used to define DMA buffer + * size. The expression calculates 2ms buffer size. + */ + fifo_size = DIV_ROUND_UP((SOF_IPC4_CHAIN_DMA_BUF_SIZE_MS * + params_rate(fe_params) * + params_channels(fe_params) * + params_physical_width(fe_params)), 8000); + pipeline->msg.extension |= SOF_IPC4_GLB_EXT_CHAIN_DMA_FIFO_SIZE(fifo_size); + + /* + * Chain DMA does not support stream timestamping, set node_id to invalid + * to skip the code in sof_ipc4_get_stream_start_offset(). + */ + copier_data->gtw_cfg.node_id = SOF_IPC4_INVALID_NODE_ID; + + return 0; + } + /* * Use the input_pin_fmts to match pcm params for playback and the output_pin_fmts * for capture. @@ -1375,6 +1437,12 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, case snd_soc_dapm_dai_in: case snd_soc_dapm_dai_out: { + struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget; + struct sof_ipc4_pipeline *pipeline = pipe_widget->private; + + if (pipeline->use_chain_dma) + return 0; + dai = swidget->private; ipc4_copier = (struct sof_ipc4_copier *)dai->private; @@ -1921,6 +1989,9 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget case snd_soc_dapm_scheduler: pipeline = swidget->private; + if (pipeline->use_chain_dma) + return 0; + dev_dbg(sdev->dev, "pipeline: %d memory pages: %d\n", swidget->pipeline_id, pipeline->mem_usage); @@ -1943,6 +2014,10 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget { struct sof_ipc4_copier *ipc4_copier = swidget->private; + pipeline = pipe_widget->private; + if (pipeline->use_chain_dma) + return 0; + ipc_size = ipc4_copier->ipc_config_size; ipc_data = ipc4_copier->ipc_config_data; @@ -1955,6 +2030,10 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget struct snd_sof_dai *dai = swidget->private; struct sof_ipc4_copier *ipc4_copier = dai->private; + pipeline = pipe_widget->private; + if (pipeline->use_chain_dma) + return 0; + ipc_size = ipc4_copier->ipc_config_size; ipc_data = ipc4_copier->ipc_config_data; @@ -2066,6 +2145,9 @@ static int sof_ipc4_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget struct sof_ipc4_msg msg = {{ 0 }}; u32 header; + if (pipeline->use_chain_dma) + return 0; + header = SOF_IPC4_GLB_PIPE_INSTANCE_ID(swidget->instance_id); header |= SOF_IPC4_MSG_TYPE_SET(SOF_IPC4_GLB_DELETE_PIPELINE); header |= SOF_IPC4_MSG_DIR(SOF_IPC4_MSG_REQUEST); @@ -2082,7 +2164,11 @@ static int sof_ipc4_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget pipeline->state = SOF_IPC4_PIPE_UNINITIALIZED; ida_free(&pipeline_ida, swidget->instance_id); } else { - ida_free(&fw_module->m_ida, swidget->instance_id); + struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget; + struct sof_ipc4_pipeline *pipeline = pipe_widget->private; + + if (!pipeline->use_chain_dma) + ida_free(&fw_module->m_ida, swidget->instance_id); } mutex_unlock(&ipc4_data->pipeline_state_mutex); @@ -2234,12 +2320,27 @@ static int sof_ipc4_route_setup(struct snd_sof_dev *sdev, struct snd_sof_route * { struct snd_sof_widget *src_widget = sroute->src_widget; struct snd_sof_widget *sink_widget = sroute->sink_widget; + struct snd_sof_widget *src_pipe_widget = src_widget->spipe->pipe_widget; + struct snd_sof_widget *sink_pipe_widget = sink_widget->spipe->pipe_widget; struct sof_ipc4_fw_module *src_fw_module = src_widget->module_info; struct sof_ipc4_fw_module *sink_fw_module = sink_widget->module_info; + struct sof_ipc4_pipeline *src_pipeline = src_pipe_widget->private; + struct sof_ipc4_pipeline *sink_pipeline = sink_pipe_widget->private; struct sof_ipc4_msg msg = {{ 0 }}; u32 header, extension; int ret; + /* no route set up if chain DMA is used */ + if (src_pipeline->use_chain_dma || sink_pipeline->use_chain_dma) { + if (!src_pipeline->use_chain_dma || !sink_pipeline->use_chain_dma) { + dev_err(sdev->dev, + "use_chain_dma must be set for both src %s and sink %s pipelines\n", + src_widget->widget->name, sink_widget->widget->name); + return -EINVAL; + } + return 0; + } + sroute->src_queue_id = sof_ipc4_get_queue_id(src_widget, sink_widget, SOF_PIN_TYPE_OUTPUT); if (sroute->src_queue_id < 0) { @@ -2310,9 +2411,17 @@ static int sof_ipc4_route_free(struct snd_sof_dev *sdev, struct snd_sof_route *s struct sof_ipc4_fw_module *src_fw_module = src_widget->module_info; struct sof_ipc4_fw_module *sink_fw_module = sink_widget->module_info; struct sof_ipc4_msg msg = {{ 0 }}; + struct snd_sof_widget *src_pipe_widget = src_widget->spipe->pipe_widget; + struct snd_sof_widget *sink_pipe_widget = sink_widget->spipe->pipe_widget; + struct sof_ipc4_pipeline *src_pipeline = src_pipe_widget->private; + struct sof_ipc4_pipeline *sink_pipeline = sink_pipe_widget->private; u32 header, extension; int ret = 0; + /* no route is set up if chain DMA is used */ + if (src_pipeline->use_chain_dma || sink_pipeline->use_chain_dma) + return 0; + dev_dbg(sdev->dev, "unbind modules %s:%d -> %s:%d\n", src_widget->widget->name, sroute->src_queue_id, sink_widget->widget->name, sroute->dst_queue_id); @@ -2374,6 +2483,11 @@ static int sof_ipc4_dai_config(struct snd_sof_dev *sdev, struct snd_sof_widget * switch (ipc4_copier->dai_type) { case SOF_DAI_INTEL_HDA: + if (pipeline->use_chain_dma) { + pipeline->msg.primary &= ~SOF_IPC4_GLB_CHAIN_DMA_LINK_ID_MASK; + pipeline->msg.primary |= SOF_IPC4_GLB_CHAIN_DMA_LINK_ID(data->dai_data); + break; + } gtw_attr = ipc4_copier->gtw_attr; gtw_attr->lp_buffer_alloc = pipeline->lp_mode; pipeline->skip_during_fe_trigger = true; diff --git a/sound/soc/sof/ipc4-topology.h b/sound/soc/sof/ipc4-topology.h index 015027b23588..cf007282867b 100644 --- a/sound/soc/sof/ipc4-topology.h +++ b/sound/soc/sof/ipc4-topology.h @@ -126,6 +126,7 @@ struct sof_ipc4_copier_config_set_sink_format { * @mem_usage: Memory usage * @core_id: Target core for the pipeline * @state: Pipeline state + * @use_chain_dma: flag to indicate if the firmware shall use chained DMA * @msg: message structure for pipeline * @skip_during_fe_trigger: skip triggering this pipeline during the FE DAI trigger */ @@ -135,6 +136,7 @@ struct sof_ipc4_pipeline { uint32_t mem_usage; uint32_t core_id; int state; + bool use_chain_dma; struct sof_ipc4_msg msg; bool skip_during_fe_trigger; }; From fa8c052b4c614aa1d2d60e5c9f40e9d885bf9511 Mon Sep 17 00:00:00 2001 From: "Vlad.Karpovich" Date: Wed, 15 Mar 2023 10:47:18 -0500 Subject: [PATCH 579/778] ASoC: cs35l45: Support for GPIO pins configuration. Adds device tree configuration for cs35l45 GPIOs Signed-off-by: Vlad Karpovich Link: https://lore.kernel.org/r/20230315154722.3911463-1-vkarpovi@opensource.cirrus.com Signed-off-by: Mark Brown --- include/dt-bindings/sound/cs35l45.h | 57 +++++++++++++++++++++++++++++ sound/soc/codecs/cs35l45-tables.c | 14 +++++++ sound/soc/codecs/cs35l45.c | 56 ++++++++++++++++++++++++++++ sound/soc/codecs/cs35l45.h | 27 +++++++++++++- 4 files changed, 152 insertions(+), 2 deletions(-) diff --git a/include/dt-bindings/sound/cs35l45.h b/include/dt-bindings/sound/cs35l45.h index 076da4b2c28d..25386af18445 100644 --- a/include/dt-bindings/sound/cs35l45.h +++ b/include/dt-bindings/sound/cs35l45.h @@ -17,4 +17,61 @@ #define CS35L45_ASP_TX_HIZ_UNUSED 0x1 #define CS35L45_ASP_TX_HIZ_DISABLED 0x2 +/* + * Optional GPIOX Sub-nodes: + * The cs35l45 node can have up to three "cirrus,gpio-ctrlX" ('X' = [1,2,3]) + * sub-nodes for configuring the GPIO pins. + * + * - gpio-dir : GPIO pin direction. Valid only when 'gpio-ctrl' + * is 1. + * 0 = Output + * 1 = Input (Default) + * + * - gpio-lvl : GPIO level. Valid only when 'gpio-ctrl' is 1 and 'gpio-dir' is 0. + * + * 0 = Low (Default) + * 1 = High + * + * - gpio-op-cfg : GPIO output configuration. Valid only when 'gpio-ctrl' is 1 + * and 'gpio-dir' is 0. + * + * 0 = CMOS (Default) + * 1 = Open Drain + * + * - gpio-pol : GPIO output polarity select. Valid only when 'gpio-ctrl' is 1 + * and 'gpio-dir' is 0. + * + * 0 = Non-inverted, Active High (Default) + * 1 = Inverted, Active Low + * + * - gpio-invert : Defines the polarity of the GPIO pin if configured + * as input. + * + * 0 = Not inverted (Default) + * 1 = Inverted + * + * - gpio-ctrl : Defines the function of the GPIO pin. + * + * GPIO1: + * 0 = High impedance input (Default) + * 1 = Pin acts as a GPIO, direction controlled by 'gpio-dir' + * 2 = Pin acts as MDSYNC, direction controlled by MDSYNC + * 3-7 = Reserved + * + * GPIO2: + * 0 = High impedance input (Default) + * 1 = Pin acts as a GPIO, direction controlled by 'gpio-dir' + * 2 = Pin acts as open drain INT + * 3 = Reserved + * 4 = Pin acts as push-pull output INT. Active low. + * 5 = Pin acts as push-pull output INT. Active high. + * 6,7 = Reserved + * + * GPIO3: + * 0 = High impedance input (Default) + * 1 = Pin acts as a GPIO, direction controlled by 'gpio-dir' + * 2-7 = Reserved + */ +#define CS35L45_NUM_GPIOS 0x3 + #endif /* DT_CS35L45_H */ diff --git a/sound/soc/codecs/cs35l45-tables.c b/sound/soc/codecs/cs35l45-tables.c index 4b1320a2e6e9..997ea418a6dc 100644 --- a/sound/soc/codecs/cs35l45-tables.c +++ b/sound/soc/codecs/cs35l45-tables.c @@ -43,6 +43,9 @@ EXPORT_SYMBOL_NS_GPL(cs35l45_apply_patch, SND_SOC_CS35L45); static const struct reg_default cs35l45_defaults[] = { { CS35L45_BLOCK_ENABLES, 0x00003323 }, { CS35L45_BLOCK_ENABLES2, 0x00000010 }, + { CS35L45_SYNC_GPIO1, 0x00000007 }, + { CS35L45_INTB_GPIO2_MCLK_REF, 0x00000005 }, + { CS35L45_GPIO3, 0x00000005 }, { CS35L45_REFCLK_INPUT, 0x00000510 }, { CS35L45_GLOBAL_SAMPLE_RATE, 0x00000003 }, { CS35L45_ASP_ENABLES1, 0x00000000 }, @@ -61,6 +64,9 @@ static const struct reg_default cs35l45_defaults[] = { { CS35L45_ASPTX4_INPUT, 0x00000028 }, { CS35L45_ASPTX5_INPUT, 0x00000048 }, { CS35L45_AMP_PCM_CONTROL, 0x00100000 }, + { CS35L45_GPIO1_CTRL1, 0x81000001 }, + { CS35L45_GPIO2_CTRL1, 0x81000001 }, + { CS35L45_GPIO3_CTRL1, 0x81000001 }, }; static bool cs35l45_readable_reg(struct device *dev, unsigned int reg) @@ -72,6 +78,9 @@ static bool cs35l45_readable_reg(struct device *dev, unsigned int reg) case CS35L45_BLOCK_ENABLES: case CS35L45_BLOCK_ENABLES2: case CS35L45_ERROR_RELEASE: + case CS35L45_SYNC_GPIO1: + case CS35L45_INTB_GPIO2_MCLK_REF: + case CS35L45_GPIO3: case CS35L45_REFCLK_INPUT: case CS35L45_GLOBAL_SAMPLE_RATE: case CS35L45_ASP_ENABLES1: @@ -92,6 +101,10 @@ static bool cs35l45_readable_reg(struct device *dev, unsigned int reg) case CS35L45_AMP_PCM_CONTROL: case CS35L45_AMP_PCM_HPF_TST: case CS35L45_IRQ1_EINT_4: + case CS35L45_GPIO_STATUS1: + case CS35L45_GPIO1_CTRL1: + case CS35L45_GPIO2_CTRL1: + case CS35L45_GPIO3_CTRL1: return true; default: return false; @@ -107,6 +120,7 @@ static bool cs35l45_volatile_reg(struct device *dev, unsigned int reg) case CS35L45_ERROR_RELEASE: case CS35L45_AMP_PCM_HPF_TST: /* not cachable */ case CS35L45_IRQ1_EINT_4: + case CS35L45_GPIO_STATUS1: return true; default: return false; diff --git a/sound/soc/codecs/cs35l45.c b/sound/soc/codecs/cs35l45.c index 855d9f13e6ff..c87dccb3382e 100644 --- a/sound/soc/codecs/cs35l45.c +++ b/sound/soc/codecs/cs35l45.c @@ -536,7 +536,63 @@ static int __maybe_unused cs35l45_runtime_resume(struct device *dev) static int cs35l45_apply_property_config(struct cs35l45_private *cs35l45) { + struct device_node *node = cs35l45->dev->of_node; + unsigned int gpio_regs[] = {CS35L45_GPIO1_CTRL1, CS35L45_GPIO2_CTRL1, + CS35L45_GPIO3_CTRL1}; + unsigned int pad_regs[] = {CS35L45_SYNC_GPIO1, + CS35L45_INTB_GPIO2_MCLK_REF, CS35L45_GPIO3}; + struct device_node *child; unsigned int val; + char of_name[32]; + int ret, i; + + if (!node) + return 0; + + for (i = 0; i < CS35L45_NUM_GPIOS; i++) { + sprintf(of_name, "cirrus,gpio-ctrl%d", i + 1); + child = of_get_child_by_name(node, of_name); + if (!child) + continue; + + ret = of_property_read_u32(child, "gpio-dir", &val); + if (!ret) + regmap_update_bits(cs35l45->regmap, gpio_regs[i], + CS35L45_GPIO_DIR_MASK, + val << CS35L45_GPIO_DIR_SHIFT); + + ret = of_property_read_u32(child, "gpio-lvl", &val); + if (!ret) + regmap_update_bits(cs35l45->regmap, gpio_regs[i], + CS35L45_GPIO_LVL_MASK, + val << CS35L45_GPIO_LVL_SHIFT); + + ret = of_property_read_u32(child, "gpio-op-cfg", &val); + if (!ret) + regmap_update_bits(cs35l45->regmap, gpio_regs[i], + CS35L45_GPIO_OP_CFG_MASK, + val << CS35L45_GPIO_OP_CFG_SHIFT); + + ret = of_property_read_u32(child, "gpio-pol", &val); + if (!ret) + regmap_update_bits(cs35l45->regmap, gpio_regs[i], + CS35L45_GPIO_POL_MASK, + val << CS35L45_GPIO_POL_SHIFT); + + ret = of_property_read_u32(child, "gpio-ctrl", &val); + if (!ret) + regmap_update_bits(cs35l45->regmap, pad_regs[i], + CS35L45_GPIO_CTRL_MASK, + val << CS35L45_GPIO_CTRL_SHIFT); + + ret = of_property_read_u32(child, "gpio-invert", &val); + if (!ret) + regmap_update_bits(cs35l45->regmap, pad_regs[i], + CS35L45_GPIO_INVERT_MASK, + val << CS35L45_GPIO_INVERT_SHIFT); + + of_node_put(child); + } if (device_property_read_u32(cs35l45->dev, "cirrus,asp-sdout-hiz-ctrl", &val) == 0) { diff --git a/sound/soc/codecs/cs35l45.h b/sound/soc/codecs/cs35l45.h index 53fe9d2b7b15..f3a54fc57d53 100644 --- a/sound/soc/codecs/cs35l45.h +++ b/sound/soc/codecs/cs35l45.h @@ -14,6 +14,7 @@ #include #include #include +#include #define CS35L45_DEVID 0x00000000 #define CS35L45_REVID 0x00000004 @@ -24,6 +25,9 @@ #define CS35L45_BLOCK_ENABLES 0x00002018 #define CS35L45_BLOCK_ENABLES2 0x0000201C #define CS35L45_ERROR_RELEASE 0x00002034 +#define CS35L45_SYNC_GPIO1 0x00002430 +#define CS35L45_INTB_GPIO2_MCLK_REF 0x00002434 +#define CS35L45_GPIO3 0x00002438 #define CS35L45_REFCLK_INPUT 0x00002C04 #define CS35L45_GLOBAL_SAMPLE_RATE 0x00002C0C #define CS35L45_BOOST_CCM_CFG 0x00003808 @@ -48,8 +52,11 @@ #define CS35L45_AMP_PCM_CONTROL 0x00007000 #define CS35L45_AMP_PCM_HPF_TST 0x00007004 #define CS35L45_IRQ1_EINT_4 0x0000E01C -#define CS35L45_LASTREG 0x0000E01C - +#define CS35L45_GPIO_STATUS1 0x0000F000 +#define CS35L45_GPIO1_CTRL1 0x0000F008 +#define CS35L45_GPIO2_CTRL1 0x0000F00C +#define CS35L45_GPIO3_CTRL1 0x0000F010 +#define CS35L45_LASTREG 0x0000F010 /* SFT_RESET */ #define CS35L45_SOFT_RESET_TRIGGER 0x5A000000 @@ -165,6 +172,22 @@ #define CS35L45_OTP_BOOT_DONE_STS_MASK BIT(1) #define CS35L45_OTP_BUSY_MASK BIT(0) +/* GPIOX_CTRL1 */ +#define CS35L45_GPIO_DIR_SHIFT 31 +#define CS35L45_GPIO_DIR_MASK BIT(31) +#define CS35L45_GPIO_LVL_SHIFT 15 +#define CS35L45_GPIO_LVL_MASK BIT(15) +#define CS35L45_GPIO_OP_CFG_SHIFT 14 +#define CS35L45_GPIO_OP_CFG_MASK BIT(14) +#define CS35L45_GPIO_POL_SHIFT 12 +#define CS35L45_GPIO_POL_MASK BIT(12) + +/* SYNC_GPIO1, INTB_GPIO2_MCLK_REF, GPIO3 */ +#define CS35L45_GPIO_CTRL_SHIFT 20 +#define CS35L45_GPIO_CTRL_MASK GENMASK(22, 20) +#define CS35L45_GPIO_INVERT_SHIFT 19 +#define CS35L45_GPIO_INVERT_MASK BIT(19) + /* Mixer sources */ #define CS35L45_PCM_SRC_MASK 0x7F #define CS35L45_PCM_SRC_ZERO 0x00 From c6cec088ab037b57e08e0694e2b150b1b034826c Mon Sep 17 00:00:00 2001 From: "Vlad.Karpovich" Date: Wed, 15 Mar 2023 10:47:19 -0500 Subject: [PATCH 580/778] ASoC: dt-bindings: cs35l45: GPIOs configuration This adds description of CS35L45 GPIOs configuration. Signed-off-by: Vlad Karpovich Link: https://lore.kernel.org/r/20230315154722.3911463-2-vkarpovi@opensource.cirrus.com Signed-off-by: Mark Brown --- .../bindings/sound/cirrus,cs35l45.yaml | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/cirrus,cs35l45.yaml b/Documentation/devicetree/bindings/sound/cirrus,cs35l45.yaml index b79990cf4f9f..2ab74f995685 100644 --- a/Documentation/devicetree/bindings/sound/cirrus,cs35l45.yaml +++ b/Documentation/devicetree/bindings/sound/cirrus,cs35l45.yaml @@ -50,6 +50,74 @@ properties: maximum: 3 default: 2 +patternProperties: + "^cirrus,gpio-ctrl[1-3]$": + description: + GPIO pins configuration. + type: object + additionalProperties: false + properties: + gpio-dir: + description: + GPIO pin direction. Valid only when 'gpio-ctrl' is 1 + 0 = Output + 1 = Input + $ref: "/schemas/types.yaml#/definitions/uint32" + minimum: 0 + maximum: 1 + default: 1 + gpio-lvl: + description: + GPIO level. Valid only when 'gpio-ctrl' is 1 and 'gpio-dir' is 0 + 0 = Low + 1 = High + $ref: "/schemas/types.yaml#/definitions/uint32" + minimum: 0 + maximum: 1 + default: 0 + gpio-op-cfg: + description: + GPIO level. Valid only when 'gpio-ctrl' is 1 and 'gpio-dir' is 0 + 0 = CMOS + 1 = Open Drain + $ref: "/schemas/types.yaml#/definitions/uint32" + minimum: 0 + maximum: 1 + default: 0 + gpio-pol: + description: + GPIO output polarity select. Valid only when 'gpio-ctrl' is 1 + and 'gpio-dir' is 0 + 0 = Non-inverted, Active High + 1 = Inverted, Active Low + $ref: "/schemas/types.yaml#/definitions/uint32" + minimum: 0 + maximum: 1 + default: 0 + gpio-ctrl: + description: + Defines the function of the GPIO pin. + GPIO1 + 0 = High impedance input + 1 = Pin acts as a GPIO, direction controlled by 'gpio-dir' + 2 = Pin acts as MDSYNC, direction controlled by MDSYNC + 3-7 = Reserved + GPIO2 + 0 = High impedance input + 1 = Pin acts as a GPIO, direction controlled by 'gpio-dir' + 2 = Pin acts as open drain INT + 3 = Reserved + 4 = Pin acts as push-pull output INT. Active low. + 5 = Pin acts as push-pull output INT. Active high. + 6,7 = Reserved + GPIO3 + 0 = High impedance input + 1 = Pin acts as a GPIO, direction controlled by 'gpio-dir' + 2-7 = Reserved + $ref: "/schemas/types.yaml#/definitions/uint32" + minimum: 0 + maximum: 7 + default: 0 required: - compatible - reg @@ -74,5 +142,15 @@ examples: reset-gpios = <&gpio 110 0>; cirrus,asp-sdout-hiz-ctrl = <(CS35L45_ASP_TX_HIZ_UNUSED | CS35L45_ASP_TX_HIZ_DISABLED)>; + cirrus,gpio-ctrl1 { + gpio-ctrl = <0x2>; + }; + cirrus,gpio-ctrl2 { + gpio-ctrl = <0x2>; + }; + cirrus,gpio-ctrl3 { + gpio-ctrl = <0x1>; + gpio-dir = <0x1>; + }; }; }; From 6085f9e6dc1973cf98ee7f5dcf629939e50f1b84 Mon Sep 17 00:00:00 2001 From: "Vlad.Karpovich" Date: Wed, 15 Mar 2023 10:47:20 -0500 Subject: [PATCH 581/778] ASoC: cs35l45: IRQ support Adds IRQ handlers Signed-off-by: Vlad Karpovich Link: https://lore.kernel.org/r/167933510218.26.11092784685990338045@mailman-core.alsa-project.org Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l45-i2c.c | 1 + sound/soc/codecs/cs35l45-spi.c | 1 + sound/soc/codecs/cs35l45-tables.c | 29 +++++++- sound/soc/codecs/cs35l45.c | 111 +++++++++++++++++++++++++++++- sound/soc/codecs/cs35l45.h | 107 ++++++++++++++++++++++++++++ 5 files changed, 245 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/cs35l45-i2c.c b/sound/soc/codecs/cs35l45-i2c.c index 1117df4b2f11..33fa6d59e9a4 100644 --- a/sound/soc/codecs/cs35l45-i2c.c +++ b/sound/soc/codecs/cs35l45-i2c.c @@ -32,6 +32,7 @@ static int cs35l45_i2c_probe(struct i2c_client *client) } cs35l45->dev = dev; + cs35l45->irq = client->irq; return cs35l45_probe(cs35l45); } diff --git a/sound/soc/codecs/cs35l45-spi.c b/sound/soc/codecs/cs35l45-spi.c index ffaca07fb267..6166cff417be 100644 --- a/sound/soc/codecs/cs35l45-spi.c +++ b/sound/soc/codecs/cs35l45-spi.c @@ -32,6 +32,7 @@ static int cs35l45_spi_probe(struct spi_device *spi) } cs35l45->dev = dev; + cs35l45->irq = spi->irq; return cs35l45_probe(cs35l45); } diff --git a/sound/soc/codecs/cs35l45-tables.c b/sound/soc/codecs/cs35l45-tables.c index 997ea418a6dc..eb9fb075c134 100644 --- a/sound/soc/codecs/cs35l45-tables.c +++ b/sound/soc/codecs/cs35l45-tables.c @@ -64,6 +64,25 @@ static const struct reg_default cs35l45_defaults[] = { { CS35L45_ASPTX4_INPUT, 0x00000028 }, { CS35L45_ASPTX5_INPUT, 0x00000048 }, { CS35L45_AMP_PCM_CONTROL, 0x00100000 }, + { CS35L45_IRQ1_CFG, 0x00000000 }, + { CS35L45_IRQ1_MASK_1, 0xBFEFFFBF }, + { CS35L45_IRQ1_MASK_2, 0xFFFFFFFF }, + { CS35L45_IRQ1_MASK_3, 0xFFFF87FF }, + { CS35L45_IRQ1_MASK_4, 0xF8FFFFFF }, + { CS35L45_IRQ1_MASK_5, 0x0EF80000 }, + { CS35L45_IRQ1_MASK_6, 0x00000000 }, + { CS35L45_IRQ1_MASK_7, 0xFFFFFF78 }, + { CS35L45_IRQ1_MASK_8, 0x00003FFF }, + { CS35L45_IRQ1_MASK_9, 0x00000000 }, + { CS35L45_IRQ1_MASK_10, 0x00000000 }, + { CS35L45_IRQ1_MASK_11, 0x00000000 }, + { CS35L45_IRQ1_MASK_12, 0x00000000 }, + { CS35L45_IRQ1_MASK_13, 0x00000000 }, + { CS35L45_IRQ1_MASK_14, 0x00000001 }, + { CS35L45_IRQ1_MASK_15, 0x00000000 }, + { CS35L45_IRQ1_MASK_16, 0x00000000 }, + { CS35L45_IRQ1_MASK_17, 0x00000000 }, + { CS35L45_IRQ1_MASK_18, 0x3FE5D0FF }, { CS35L45_GPIO1_CTRL1, 0x81000001 }, { CS35L45_GPIO2_CTRL1, 0x81000001 }, { CS35L45_GPIO3_CTRL1, 0x81000001 }, @@ -100,7 +119,11 @@ static bool cs35l45_readable_reg(struct device *dev, unsigned int reg) case CS35L45_ASPTX5_INPUT: case CS35L45_AMP_PCM_CONTROL: case CS35L45_AMP_PCM_HPF_TST: - case CS35L45_IRQ1_EINT_4: + case CS35L45_IRQ1_CFG: + case CS35L45_IRQ1_STATUS: + case CS35L45_IRQ1_EINT_1 ... CS35L45_IRQ1_EINT_18: + case CS35L45_IRQ1_STS_1 ... CS35L45_IRQ1_STS_18: + case CS35L45_IRQ1_MASK_1 ... CS35L45_IRQ1_MASK_18: case CS35L45_GPIO_STATUS1: case CS35L45_GPIO1_CTRL1: case CS35L45_GPIO2_CTRL1: @@ -119,7 +142,9 @@ static bool cs35l45_volatile_reg(struct device *dev, unsigned int reg) case CS35L45_GLOBAL_ENABLES: case CS35L45_ERROR_RELEASE: case CS35L45_AMP_PCM_HPF_TST: /* not cachable */ - case CS35L45_IRQ1_EINT_4: + case CS35L45_IRQ1_STATUS: + case CS35L45_IRQ1_EINT_1 ... CS35L45_IRQ1_EINT_18: + case CS35L45_IRQ1_STS_1 ... CS35L45_IRQ1_STS_18: case CS35L45_GPIO_STATUS1: return true; default: diff --git a/sound/soc/codecs/cs35l45.c b/sound/soc/codecs/cs35l45.c index c87dccb3382e..a7095da34f5a 100644 --- a/sound/soc/codecs/cs35l45.c +++ b/sound/soc/codecs/cs35l45.c @@ -586,10 +586,13 @@ static int cs35l45_apply_property_config(struct cs35l45_private *cs35l45) val << CS35L45_GPIO_CTRL_SHIFT); ret = of_property_read_u32(child, "gpio-invert", &val); - if (!ret) + if (!ret) { regmap_update_bits(cs35l45->regmap, pad_regs[i], CS35L45_GPIO_INVERT_MASK, val << CS35L45_GPIO_INVERT_SHIFT); + if (i == 1) + cs35l45->irq_invert = val; + } of_node_put(child); } @@ -604,6 +607,78 @@ static int cs35l45_apply_property_config(struct cs35l45_private *cs35l45) return 0; } +static irqreturn_t cs35l45_pll_unlock(int irq, void *data) +{ + struct cs35l45_private *cs35l45 = data; + + dev_dbg(cs35l45->dev, "PLL unlock detected!"); + + return IRQ_HANDLED; +} + +static irqreturn_t cs35l45_pll_lock(int irq, void *data) +{ + struct cs35l45_private *cs35l45 = data; + + dev_dbg(cs35l45->dev, "PLL lock detected!"); + + return IRQ_HANDLED; +} + +static irqreturn_t cs35l45_spk_safe_err(int irq, void *data); + +static const struct cs35l45_irq cs35l45_irqs[] = { + CS35L45_IRQ(AMP_SHORT_ERR, "Amplifier short error", cs35l45_spk_safe_err), + CS35L45_IRQ(UVLO_VDDBATT_ERR, "VDDBATT undervoltage error", cs35l45_spk_safe_err), + CS35L45_IRQ(BST_SHORT_ERR, "Boost inductor error", cs35l45_spk_safe_err), + CS35L45_IRQ(BST_UVP_ERR, "Boost undervoltage error", cs35l45_spk_safe_err), + CS35L45_IRQ(TEMP_ERR, "Overtemperature error", cs35l45_spk_safe_err), + CS35L45_IRQ(AMP_CAL_ERR, "Amplifier calibration error", cs35l45_spk_safe_err), + CS35L45_IRQ(UVLO_VDDLV_ERR, "LV threshold detector error", cs35l45_spk_safe_err), + CS35L45_IRQ(GLOBAL_ERROR, "Global error", cs35l45_spk_safe_err), + CS35L45_IRQ(DSP_WDT_EXPIRE, "DSP Watchdog Timer", cs35l45_spk_safe_err), + CS35L45_IRQ(PLL_UNLOCK_FLAG_RISE, "PLL unlock", cs35l45_pll_unlock), + CS35L45_IRQ(PLL_LOCK_FLAG, "PLL lock", cs35l45_pll_lock), +}; + +static irqreturn_t cs35l45_spk_safe_err(int irq, void *data) +{ + struct cs35l45_private *cs35l45 = data; + int i; + + i = irq - regmap_irq_get_virq(cs35l45->irq_data, 0); + + dev_err(cs35l45->dev, "%s condition detected!\n", cs35l45_irqs[i].name); + + return IRQ_HANDLED; +} + +static const struct regmap_irq cs35l45_reg_irqs[] = { + CS35L45_REG_IRQ(IRQ1_EINT_1, AMP_SHORT_ERR), + CS35L45_REG_IRQ(IRQ1_EINT_1, UVLO_VDDBATT_ERR), + CS35L45_REG_IRQ(IRQ1_EINT_1, BST_SHORT_ERR), + CS35L45_REG_IRQ(IRQ1_EINT_1, BST_UVP_ERR), + CS35L45_REG_IRQ(IRQ1_EINT_1, TEMP_ERR), + CS35L45_REG_IRQ(IRQ1_EINT_3, AMP_CAL_ERR), + CS35L45_REG_IRQ(IRQ1_EINT_18, UVLO_VDDLV_ERR), + CS35L45_REG_IRQ(IRQ1_EINT_18, GLOBAL_ERROR), + CS35L45_REG_IRQ(IRQ1_EINT_2, DSP_WDT_EXPIRE), + CS35L45_REG_IRQ(IRQ1_EINT_3, PLL_UNLOCK_FLAG_RISE), + CS35L45_REG_IRQ(IRQ1_EINT_3, PLL_LOCK_FLAG), +}; + +static const struct regmap_irq_chip cs35l45_regmap_irq_chip = { + .name = "cs35l45 IRQ1 Controller", + .main_status = CS35L45_IRQ1_STATUS, + .status_base = CS35L45_IRQ1_EINT_1, + .mask_base = CS35L45_IRQ1_MASK_1, + .ack_base = CS35L45_IRQ1_EINT_1, + .num_regs = 18, + .irqs = cs35l45_reg_irqs, + .num_irqs = ARRAY_SIZE(cs35l45_reg_irqs), + .runtime_pm = true, +}; + static int cs35l45_initialize(struct cs35l45_private *cs35l45) { struct device *dev = cs35l45->dev; @@ -660,7 +735,8 @@ static int cs35l45_initialize(struct cs35l45_private *cs35l45) int cs35l45_probe(struct cs35l45_private *cs35l45) { struct device *dev = cs35l45->dev; - int ret; + unsigned long irq_pol = IRQF_ONESHOT | IRQF_SHARED; + int ret, i, irq; cs35l45->vdd_batt = devm_regulator_get(dev, "vdd-batt"); if (IS_ERR(cs35l45->vdd_batt)) @@ -705,6 +781,37 @@ int cs35l45_probe(struct cs35l45_private *cs35l45) if (ret < 0) goto err_reset; + if (cs35l45->irq) { + if (cs35l45->irq_invert) + irq_pol |= IRQF_TRIGGER_HIGH; + else + irq_pol |= IRQF_TRIGGER_LOW; + + ret = devm_regmap_add_irq_chip(dev, cs35l45->regmap, cs35l45->irq, irq_pol, 0, + &cs35l45_regmap_irq_chip, &cs35l45->irq_data); + if (ret) { + dev_err(dev, "Failed to register IRQ chip: %d\n", ret); + goto err_reset; + } + + for (i = 0; i < ARRAY_SIZE(cs35l45_irqs); i++) { + irq = regmap_irq_get_virq(cs35l45->irq_data, cs35l45_irqs[i].irq); + if (irq < 0) { + dev_err(dev, "Failed to get %s\n", cs35l45_irqs[i].name); + ret = irq; + goto err_reset; + } + + ret = devm_request_threaded_irq(dev, irq, NULL, cs35l45_irqs[i].handler, + irq_pol, cs35l45_irqs[i].name, cs35l45); + if (ret) { + dev_err(dev, "Failed to request IRQ %s: %d\n", + cs35l45_irqs[i].name, ret); + goto err_reset; + } + } + } + ret = devm_snd_soc_register_component(dev, &cs35l45_component, cs35l45_dai, ARRAY_SIZE(cs35l45_dai)); diff --git a/sound/soc/codecs/cs35l45.h b/sound/soc/codecs/cs35l45.h index f3a54fc57d53..ce92f5068ac5 100644 --- a/sound/soc/codecs/cs35l45.h +++ b/sound/soc/codecs/cs35l45.h @@ -51,7 +51,42 @@ #define CS35L45_LDPM_CONFIG 0x00006404 #define CS35L45_AMP_PCM_CONTROL 0x00007000 #define CS35L45_AMP_PCM_HPF_TST 0x00007004 +#define CS35L45_IRQ1_CFG 0x0000E000 +#define CS35L45_IRQ1_STATUS 0x0000E004 +#define CS35L45_IRQ1_EINT_1 0x0000E010 +#define CS35L45_IRQ1_EINT_2 0x0000E014 +#define CS35L45_IRQ1_EINT_3 0x0000E018 #define CS35L45_IRQ1_EINT_4 0x0000E01C +#define CS35L45_IRQ1_EINT_5 0x0000E020 +#define CS35L45_IRQ1_EINT_7 0x0000E028 +#define CS35L45_IRQ1_EINT_8 0x0000E02C +#define CS35L45_IRQ1_EINT_18 0x0000E054 +#define CS35L45_IRQ1_STS_1 0x0000E090 +#define CS35L45_IRQ1_STS_2 0x0000E094 +#define CS35L45_IRQ1_STS_3 0x0000E098 +#define CS35L45_IRQ1_STS_4 0x0000E09C +#define CS35L45_IRQ1_STS_5 0x0000E0A0 +#define CS35L45_IRQ1_STS_7 0x0000E0A8 +#define CS35L45_IRQ1_STS_8 0x0000E0AC +#define CS35L45_IRQ1_STS_18 0x0000E0D4 +#define CS35L45_IRQ1_MASK_1 0x0000E110 +#define CS35L45_IRQ1_MASK_2 0x0000E114 +#define CS35L45_IRQ1_MASK_3 0x0000E118 +#define CS35L45_IRQ1_MASK_4 0x0000E11C +#define CS35L45_IRQ1_MASK_5 0x0000E120 +#define CS35L45_IRQ1_MASK_6 0x0000E124 +#define CS35L45_IRQ1_MASK_7 0x0000E128 +#define CS35L45_IRQ1_MASK_8 0x0000E12C +#define CS35L45_IRQ1_MASK_9 0x0000E130 +#define CS35L45_IRQ1_MASK_10 0x0000E134 +#define CS35L45_IRQ1_MASK_11 0x0000E138 +#define CS35L45_IRQ1_MASK_12 0x0000E13C +#define CS35L45_IRQ1_MASK_13 0x0000E140 +#define CS35L45_IRQ1_MASK_14 0x0000E144 +#define CS35L45_IRQ1_MASK_15 0x0000E148 +#define CS35L45_IRQ1_MASK_16 0x0000E14C +#define CS35L45_IRQ1_MASK_17 0x0000E150 +#define CS35L45_IRQ1_MASK_18 0x0000E154 #define CS35L45_GPIO_STATUS1 0x0000F000 #define CS35L45_GPIO1_CTRL1 0x0000F008 #define CS35L45_GPIO2_CTRL1 0x0000F00C @@ -188,6 +223,38 @@ #define CS35L45_GPIO_INVERT_SHIFT 19 #define CS35L45_GPIO_INVERT_MASK BIT(19) +/* CS35L45_IRQ1_EINT_1 */ +#define CS35L45_BST_UVP_ERR_SHIFT 7 +#define CS35L45_BST_UVP_ERR_MASK BIT(7) +#define CS35L45_BST_SHORT_ERR_SHIFT 8 +#define CS35L45_BST_SHORT_ERR_MASK BIT(8) +#define CS35L45_TEMP_ERR_SHIFT 17 +#define CS35L45_TEMP_ERR_MASK BIT(17) +#define CS35L45_MSM_GLOBAL_EN_ASSERT_SHIFT 22 +#define CS35L45_MSM_GLOBAL_EN_ASSERT_MASK BIT(22) +#define CS35L45_UVLO_VDDBATT_ERR_SHIFT 29 +#define CS35L45_UVLO_VDDBATT_ERR_MASK BIT(29) +#define CS35L45_AMP_SHORT_ERR_SHIFT 31 +#define CS35L45_AMP_SHORT_ERR_MASK BIT(31) + +/* CS35L45_IRQ1_EINT_2 */ +#define CS35L45_DSP_WDT_EXPIRE_SHIFT 4 +#define CS35L45_DSP_WDT_EXPIRE_MASK BIT(4) + +/* CS35L45_IRQ1_EINT_3 */ +#define CS35L45_PLL_LOCK_FLAG_SHIFT 1 +#define CS35L45_PLL_LOCK_FLAG_MASK BIT(1) +#define CS35L45_PLL_UNLOCK_FLAG_RISE_SHIFT 4 +#define CS35L45_PLL_UNLOCK_FLAG_RISE_MASK BIT(4) +#define CS35L45_AMP_CAL_ERR_SHIFT 25 +#define CS35L45_AMP_CAL_ERR_MASK BIT(25) + +/* CS35L45_IRQ1_EINT_18 */ +#define CS35L45_GLOBAL_ERROR_SHIFT 15 +#define CS35L45_GLOBAL_ERROR_MASK BIT(15) +#define CS35L45_UVLO_VDDLV_ERR_SHIFT 16 +#define CS35L45_UVLO_VDDLV_ERR_MASK BIT(16) + /* Mixer sources */ #define CS35L45_PCM_SRC_MASK 0x7F #define CS35L45_PCM_SRC_ZERO 0x00 @@ -217,6 +284,43 @@ SNDRV_PCM_RATE_88200 | \ SNDRV_PCM_RATE_96000) +/* + * IRQs + */ +#define CS35L45_IRQ(_irq, _name, _hand) \ + { \ + .irq = CS35L45_ ## _irq ## _IRQ,\ + .name = _name, \ + .handler = _hand, \ + } + +struct cs35l45_irq { + int irq; + const char *name; + irqreturn_t (*handler)(int irq, void *data); +}; + +#define CS35L45_REG_IRQ(_reg, _irq) \ + [CS35L45_ ## _irq ## _IRQ] = { \ + .reg_offset = (CS35L45_ ## _reg) - CS35L45_IRQ1_EINT_1, \ + .mask = CS35L45_ ## _irq ## _MASK \ + } + +enum cs35l45_irq_list { + CS35L45_AMP_SHORT_ERR_IRQ, + CS35L45_UVLO_VDDBATT_ERR_IRQ, + CS35L45_BST_SHORT_ERR_IRQ, + CS35L45_BST_UVP_ERR_IRQ, + CS35L45_TEMP_ERR_IRQ, + CS35L45_AMP_CAL_ERR_IRQ, + CS35L45_UVLO_VDDLV_ERR_IRQ, + CS35L45_GLOBAL_ERROR_IRQ, + CS35L45_DSP_WDT_EXPIRE_IRQ, + CS35L45_PLL_UNLOCK_FLAG_RISE_IRQ, + CS35L45_PLL_LOCK_FLAG_IRQ, + CS35L45_NUM_IRQ +}; + struct cs35l45_private { struct device *dev; struct regmap *regmap; @@ -227,6 +331,9 @@ struct cs35l45_private { bool sysclk_set; u8 slot_width; u8 slot_count; + int irq_invert; + int irq; + struct regmap_irq_chip_data *irq_data; }; extern const struct dev_pm_ops cs35l45_pm_ops; From 74b14e2850a34740c121cf2758d4181063d4c77c Mon Sep 17 00:00:00 2001 From: "Vlad.Karpovich" Date: Wed, 15 Mar 2023 10:47:21 -0500 Subject: [PATCH 582/778] ASoC: cs35l45: DSP Support The CS35L45 digital core incorporates one programmable DSP block, capable of running a wide range of audio enhancement and speaker and battery protection functions. Signed-off-by: Vlad Karpovich Link: https://lore.kernel.org/r/167933510679.26.5992985447093367768@mailman-core.alsa-project.org Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 4 + sound/soc/codecs/cs35l45-spi.c | 3 + sound/soc/codecs/cs35l45-tables.c | 86 +++++++ sound/soc/codecs/cs35l45.c | 391 +++++++++++++++++++++++++++++- sound/soc/codecs/cs35l45.h | 108 ++++++++- 5 files changed, 579 insertions(+), 13 deletions(-) diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 07747565c3b5..090f296e6857 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -364,6 +364,8 @@ config SND_SOC_WM_ADSP default y if SND_SOC_WM2200=y default y if SND_SOC_CS35L41_SPI=y default y if SND_SOC_CS35L41_I2C=y + default y if SND_SOC_CS35L45_SPI=y + default y if SND_SOC_CS35L45_I2C=y default m if SND_SOC_MADERA=m default m if SND_SOC_CS47L24=m default m if SND_SOC_WM5102=m @@ -371,6 +373,8 @@ config SND_SOC_WM_ADSP default m if SND_SOC_WM2200=m default m if SND_SOC_CS35L41_SPI=m default m if SND_SOC_CS35L41_I2C=m + default m if SND_SOC_CS35L45_SPI=m + default m if SND_SOC_CS35L45_I2C=m config SND_SOC_AB8500_CODEC tristate diff --git a/sound/soc/codecs/cs35l45-spi.c b/sound/soc/codecs/cs35l45-spi.c index 6166cff417be..99657325a281 100644 --- a/sound/soc/codecs/cs35l45-spi.c +++ b/sound/soc/codecs/cs35l45-spi.c @@ -23,6 +23,9 @@ static int cs35l45_spi_probe(struct spi_device *spi) if (cs35l45 == NULL) return -ENOMEM; + spi->max_speed_hz = CS35L45_SPI_MAX_FREQ; + spi_setup(spi); + spi_set_drvdata(spi, cs35l45); cs35l45->regmap = devm_regmap_init_spi(spi, &cs35l45_spi_regmap); if (IS_ERR(cs35l45->regmap)) { diff --git a/sound/soc/codecs/cs35l45-tables.c b/sound/soc/codecs/cs35l45-tables.c index eb9fb075c134..434a6473070e 100644 --- a/sound/soc/codecs/cs35l45-tables.c +++ b/sound/soc/codecs/cs35l45-tables.c @@ -46,6 +46,7 @@ static const struct reg_default cs35l45_defaults[] = { { CS35L45_SYNC_GPIO1, 0x00000007 }, { CS35L45_INTB_GPIO2_MCLK_REF, 0x00000005 }, { CS35L45_GPIO3, 0x00000005 }, + { CS35L45_PWRMGT_CTL, 0x00000000 }, { CS35L45_REFCLK_INPUT, 0x00000510 }, { CS35L45_GLOBAL_SAMPLE_RATE, 0x00000003 }, { CS35L45_ASP_ENABLES1, 0x00000000 }, @@ -63,6 +64,30 @@ static const struct reg_default cs35l45_defaults[] = { { CS35L45_ASPTX3_INPUT, 0x00000020 }, { CS35L45_ASPTX4_INPUT, 0x00000028 }, { CS35L45_ASPTX5_INPUT, 0x00000048 }, + { CS35L45_DSP1_RX1_RATE, 0x00000001 }, + { CS35L45_DSP1_RX2_RATE, 0x00000001 }, + { CS35L45_DSP1_RX3_RATE, 0x00000001 }, + { CS35L45_DSP1_RX4_RATE, 0x00000001 }, + { CS35L45_DSP1_RX5_RATE, 0x00000001 }, + { CS35L45_DSP1_RX6_RATE, 0x00000001 }, + { CS35L45_DSP1_RX7_RATE, 0x00000001 }, + { CS35L45_DSP1_RX8_RATE, 0x00000001 }, + { CS35L45_DSP1_TX1_RATE, 0x00000001 }, + { CS35L45_DSP1_TX2_RATE, 0x00000001 }, + { CS35L45_DSP1_TX3_RATE, 0x00000001 }, + { CS35L45_DSP1_TX4_RATE, 0x00000001 }, + { CS35L45_DSP1_TX5_RATE, 0x00000001 }, + { CS35L45_DSP1_TX6_RATE, 0x00000001 }, + { CS35L45_DSP1_TX7_RATE, 0x00000001 }, + { CS35L45_DSP1_TX8_RATE, 0x00000001 }, + { CS35L45_DSP1RX1_INPUT, 0x00000008 }, + { CS35L45_DSP1RX2_INPUT, 0x00000009 }, + { CS35L45_DSP1RX3_INPUT, 0x00000018 }, + { CS35L45_DSP1RX4_INPUT, 0x00000019 }, + { CS35L45_DSP1RX5_INPUT, 0x00000020 }, + { CS35L45_DSP1RX6_INPUT, 0x00000028 }, + { CS35L45_DSP1RX7_INPUT, 0x0000003A }, + { CS35L45_DSP1RX8_INPUT, 0x00000028 }, { CS35L45_AMP_PCM_CONTROL, 0x00100000 }, { CS35L45_IRQ1_CFG, 0x00000000 }, { CS35L45_IRQ1_MASK_1, 0xBFEFFFBF }, @@ -100,6 +125,7 @@ static bool cs35l45_readable_reg(struct device *dev, unsigned int reg) case CS35L45_SYNC_GPIO1: case CS35L45_INTB_GPIO2_MCLK_REF: case CS35L45_GPIO3: + case CS35L45_PWRMGT_CTL: case CS35L45_REFCLK_INPUT: case CS35L45_GLOBAL_SAMPLE_RATE: case CS35L45_ASP_ENABLES1: @@ -117,6 +143,14 @@ static bool cs35l45_readable_reg(struct device *dev, unsigned int reg) case CS35L45_ASPTX3_INPUT: case CS35L45_ASPTX4_INPUT: case CS35L45_ASPTX5_INPUT: + case CS35L45_DSP1RX1_INPUT: + case CS35L45_DSP1RX2_INPUT: + case CS35L45_DSP1RX3_INPUT: + case CS35L45_DSP1RX4_INPUT: + case CS35L45_DSP1RX5_INPUT: + case CS35L45_DSP1RX6_INPUT: + case CS35L45_DSP1RX7_INPUT: + case CS35L45_DSP1RX8_INPUT: case CS35L45_AMP_PCM_CONTROL: case CS35L45_AMP_PCM_HPF_TST: case CS35L45_IRQ1_CFG: @@ -128,6 +162,40 @@ static bool cs35l45_readable_reg(struct device *dev, unsigned int reg) case CS35L45_GPIO1_CTRL1: case CS35L45_GPIO2_CTRL1: case CS35L45_GPIO3_CTRL1: + case CS35L45_DSP_MBOX_1: + case CS35L45_DSP_MBOX_2: + case CS35L45_DSP_VIRT1_MBOX_1 ... CS35L45_DSP_VIRT1_MBOX_4: + case CS35L45_DSP_VIRT2_MBOX_1 ... CS35L45_DSP_VIRT2_MBOX_4: + case CS35L45_DSP1_SYS_ID: + case CS35L45_DSP1_CLOCK_FREQ: + case CS35L45_DSP1_RX1_RATE: + case CS35L45_DSP1_RX2_RATE: + case CS35L45_DSP1_RX3_RATE: + case CS35L45_DSP1_RX4_RATE: + case CS35L45_DSP1_RX5_RATE: + case CS35L45_DSP1_RX6_RATE: + case CS35L45_DSP1_RX7_RATE: + case CS35L45_DSP1_RX8_RATE: + case CS35L45_DSP1_TX1_RATE: + case CS35L45_DSP1_TX2_RATE: + case CS35L45_DSP1_TX3_RATE: + case CS35L45_DSP1_TX4_RATE: + case CS35L45_DSP1_TX5_RATE: + case CS35L45_DSP1_TX6_RATE: + case CS35L45_DSP1_TX7_RATE: + case CS35L45_DSP1_TX8_RATE: + case CS35L45_DSP1_SCRATCH1: + case CS35L45_DSP1_SCRATCH2: + case CS35L45_DSP1_SCRATCH3: + case CS35L45_DSP1_SCRATCH4: + case CS35L45_DSP1_CCM_CORE_CONTROL: + case CS35L45_DSP1_XMEM_PACK_0 ... CS35L45_DSP1_XMEM_PACK_4607: + case CS35L45_DSP1_XMEM_UNPACK32_0 ... CS35L45_DSP1_XMEM_UNPACK32_3071: + case CS35L45_DSP1_XMEM_UNPACK24_0 ... CS35L45_DSP1_XMEM_UNPACK24_6143: + case CS35L45_DSP1_YMEM_PACK_0 ... CS35L45_DSP1_YMEM_PACK_1532: + case CS35L45_DSP1_YMEM_UNPACK32_0 ... CS35L45_DSP1_YMEM_UNPACK32_1022: + case CS35L45_DSP1_YMEM_UNPACK24_0 ... CS35L45_DSP1_YMEM_UNPACK24_2043: + case CS35L45_DSP1_PMEM_0 ... CS35L45_DSP1_PMEM_3834: return true; default: return false; @@ -146,6 +214,24 @@ static bool cs35l45_volatile_reg(struct device *dev, unsigned int reg) case CS35L45_IRQ1_EINT_1 ... CS35L45_IRQ1_EINT_18: case CS35L45_IRQ1_STS_1 ... CS35L45_IRQ1_STS_18: case CS35L45_GPIO_STATUS1: + case CS35L45_DSP_MBOX_1: + case CS35L45_DSP_MBOX_2: + case CS35L45_DSP_VIRT1_MBOX_1 ... CS35L45_DSP_VIRT1_MBOX_4: + case CS35L45_DSP_VIRT2_MBOX_1 ... CS35L45_DSP_VIRT2_MBOX_4: + case CS35L45_DSP1_SYS_ID: + case CS35L45_DSP1_CLOCK_FREQ: + case CS35L45_DSP1_SCRATCH1: + case CS35L45_DSP1_SCRATCH2: + case CS35L45_DSP1_SCRATCH3: + case CS35L45_DSP1_SCRATCH4: + case CS35L45_DSP1_CCM_CORE_CONTROL: + case CS35L45_DSP1_XMEM_PACK_0 ... CS35L45_DSP1_XMEM_PACK_4607: + case CS35L45_DSP1_XMEM_UNPACK32_0 ... CS35L45_DSP1_XMEM_UNPACK32_3071: + case CS35L45_DSP1_XMEM_UNPACK24_0 ... CS35L45_DSP1_XMEM_UNPACK24_6143: + case CS35L45_DSP1_YMEM_PACK_0 ... CS35L45_DSP1_YMEM_PACK_1532: + case CS35L45_DSP1_YMEM_UNPACK32_0 ... CS35L45_DSP1_YMEM_UNPACK32_1022: + case CS35L45_DSP1_YMEM_UNPACK24_0 ... CS35L45_DSP1_YMEM_UNPACK24_2043: + case CS35L45_DSP1_PMEM_0 ... CS35L45_DSP1_PMEM_3834: return true; default: return false; diff --git a/sound/soc/codecs/cs35l45.c b/sound/soc/codecs/cs35l45.c index a7095da34f5a..97f6819fa2ad 100644 --- a/sound/soc/codecs/cs35l45.c +++ b/sound/soc/codecs/cs35l45.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -19,6 +20,69 @@ #include "cs35l45.h" +static bool cs35l45_check_cspl_mbox_sts(const enum cs35l45_cspl_mboxcmd cmd, + enum cs35l45_cspl_mboxstate sts) +{ + switch (cmd) { + case CSPL_MBOX_CMD_NONE: + case CSPL_MBOX_CMD_UNKNOWN_CMD: + return true; + case CSPL_MBOX_CMD_PAUSE: + case CSPL_MBOX_CMD_OUT_OF_HIBERNATE: + return (sts == CSPL_MBOX_STS_PAUSED); + case CSPL_MBOX_CMD_RESUME: + return (sts == CSPL_MBOX_STS_RUNNING); + case CSPL_MBOX_CMD_REINIT: + return (sts == CSPL_MBOX_STS_RUNNING); + case CSPL_MBOX_CMD_STOP_PRE_REINIT: + return (sts == CSPL_MBOX_STS_RDY_FOR_REINIT); + default: + return false; + } +} + +static int cs35l45_set_cspl_mbox_cmd(struct cs35l45_private *cs35l45, + struct regmap *regmap, + const enum cs35l45_cspl_mboxcmd cmd) +{ + unsigned int sts = 0, i; + int ret; + + if (!cs35l45->dsp.cs_dsp.running) { + dev_err(cs35l45->dev, "DSP not running\n"); + return -EPERM; + } + + // Set mailbox cmd + ret = regmap_write(regmap, CS35L45_DSP_VIRT1_MBOX_1, cmd); + if (ret < 0) { + if (cmd != CSPL_MBOX_CMD_OUT_OF_HIBERNATE) + dev_err(cs35l45->dev, "Failed to write MBOX: %d\n", ret); + return ret; + } + + // Read mailbox status and verify it is appropriate for the given cmd + for (i = 0; i < 5; i++) { + usleep_range(1000, 1100); + + ret = regmap_read(regmap, CS35L45_DSP_MBOX_2, &sts); + if (ret < 0) { + dev_err(cs35l45->dev, "Failed to read MBOX STS: %d\n", ret); + continue; + } + + if (!cs35l45_check_cspl_mbox_sts(cmd, sts)) + dev_dbg(cs35l45->dev, "[%u] cmd %u returned invalid sts %u", i, cmd, sts); + else + return 0; + } + + if (cmd != CSPL_MBOX_CMD_OUT_OF_HIBERNATE) + dev_err(cs35l45->dev, "Failed to set mailbox cmd %u (status %u)\n", cmd, sts); + + return -ENOMSG; +} + static int cs35l45_global_en_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { @@ -46,10 +110,68 @@ static int cs35l45_global_en_ev(struct snd_soc_dapm_widget *w, return 0; } +static int cs35l45_dsp_preload_ev(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + struct cs35l45_private *cs35l45 = snd_soc_component_get_drvdata(component); + int ret; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + if (cs35l45->dsp.cs_dsp.booted) + return 0; + + return wm_adsp_early_event(w, kcontrol, event); + case SND_SOC_DAPM_POST_PMU: + if (cs35l45->dsp.cs_dsp.running) + return 0; + + regmap_set_bits(cs35l45->regmap, CS35L45_PWRMGT_CTL, + CS35L45_MEM_RDY_MASK); + + return wm_adsp_event(w, kcontrol, event); + case SND_SOC_DAPM_PRE_PMD: + if (cs35l45->dsp.preloaded) + return 0; + + if (cs35l45->dsp.cs_dsp.running) { + ret = wm_adsp_event(w, kcontrol, event); + if (ret) + return ret; + } + + return wm_adsp_early_event(w, kcontrol, event); + default: + return 0; + } +} + +static int cs35l45_dsp_audio_ev(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + struct cs35l45_private *cs35l45 = snd_soc_component_get_drvdata(component); + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + return cs35l45_set_cspl_mbox_cmd(cs35l45, cs35l45->regmap, + CSPL_MBOX_CMD_RESUME); + case SND_SOC_DAPM_PRE_PMD: + return cs35l45_set_cspl_mbox_cmd(cs35l45, cs35l45->regmap, + CSPL_MBOX_CMD_PAUSE); + default: + return 0; + } + + return 0; +} + static const char * const cs35l45_asp_tx_txt[] = { "Zero", "ASP_RX1", "ASP_RX2", "VMON", "IMON", "ERR_VOL", "VDD_BATTMON", "VDD_BSTMON", + "DSP_TX1", "DSP_TX2", "Interpolator", "IL_TARGET", }; @@ -57,6 +179,7 @@ static const unsigned int cs35l45_asp_tx_val[] = { CS35L45_PCM_SRC_ZERO, CS35L45_PCM_SRC_ASP_RX1, CS35L45_PCM_SRC_ASP_RX2, CS35L45_PCM_SRC_VMON, CS35L45_PCM_SRC_IMON, CS35L45_PCM_SRC_ERR_VOL, CS35L45_PCM_SRC_VDD_BATTMON, CS35L45_PCM_SRC_VDD_BSTMON, + CS35L45_PCM_SRC_DSP_TX1, CS35L45_PCM_SRC_DSP_TX2, CS35L45_PCM_SRC_INTERPOLATOR, CS35L45_PCM_SRC_IL_TARGET, }; @@ -78,12 +201,54 @@ static const struct soc_enum cs35l45_asp_tx_enums[] = { cs35l45_asp_tx_val), }; +static const char * const cs35l45_dsp_rx_txt[] = { + "Zero", "ASP_RX1", "ASP_RX2", + "VMON", "IMON", "ERR_VOL", + "CLASSH_TGT", "VDD_BATTMON", + "VDD_BSTMON", "TEMPMON", +}; + +static const unsigned int cs35l45_dsp_rx_val[] = { + CS35L45_PCM_SRC_ZERO, CS35L45_PCM_SRC_ASP_RX1, CS35L45_PCM_SRC_ASP_RX2, + CS35L45_PCM_SRC_VMON, CS35L45_PCM_SRC_IMON, CS35L45_PCM_SRC_ERR_VOL, + CS35L45_PCM_SRC_CLASSH_TGT, CS35L45_PCM_SRC_VDD_BATTMON, + CS35L45_PCM_SRC_VDD_BSTMON, CS35L45_PCM_SRC_TEMPMON, +}; + +static const struct soc_enum cs35l45_dsp_rx_enums[] = { + SOC_VALUE_ENUM_SINGLE(CS35L45_DSP1RX1_INPUT, 0, CS35L45_PCM_SRC_MASK, + ARRAY_SIZE(cs35l45_dsp_rx_txt), cs35l45_dsp_rx_txt, + cs35l45_dsp_rx_val), + SOC_VALUE_ENUM_SINGLE(CS35L45_DSP1RX2_INPUT, 0, CS35L45_PCM_SRC_MASK, + ARRAY_SIZE(cs35l45_dsp_rx_txt), cs35l45_dsp_rx_txt, + cs35l45_dsp_rx_val), + SOC_VALUE_ENUM_SINGLE(CS35L45_DSP1RX3_INPUT, 0, CS35L45_PCM_SRC_MASK, + ARRAY_SIZE(cs35l45_dsp_rx_txt), cs35l45_dsp_rx_txt, + cs35l45_dsp_rx_val), + SOC_VALUE_ENUM_SINGLE(CS35L45_DSP1RX4_INPUT, 0, CS35L45_PCM_SRC_MASK, + ARRAY_SIZE(cs35l45_dsp_rx_txt), cs35l45_dsp_rx_txt, + cs35l45_dsp_rx_val), + SOC_VALUE_ENUM_SINGLE(CS35L45_DSP1RX5_INPUT, 0, CS35L45_PCM_SRC_MASK, + ARRAY_SIZE(cs35l45_dsp_rx_txt), cs35l45_dsp_rx_txt, + cs35l45_dsp_rx_val), + SOC_VALUE_ENUM_SINGLE(CS35L45_DSP1RX6_INPUT, 0, CS35L45_PCM_SRC_MASK, + ARRAY_SIZE(cs35l45_dsp_rx_txt), cs35l45_dsp_rx_txt, + cs35l45_dsp_rx_val), + SOC_VALUE_ENUM_SINGLE(CS35L45_DSP1RX7_INPUT, 0, CS35L45_PCM_SRC_MASK, + ARRAY_SIZE(cs35l45_dsp_rx_txt), cs35l45_dsp_rx_txt, + cs35l45_dsp_rx_val), + SOC_VALUE_ENUM_SINGLE(CS35L45_DSP1RX8_INPUT, 0, CS35L45_PCM_SRC_MASK, + ARRAY_SIZE(cs35l45_dsp_rx_txt), cs35l45_dsp_rx_txt, + cs35l45_dsp_rx_val), +}; + static const char * const cs35l45_dac_txt[] = { - "Zero", "ASP_RX1", "ASP_RX2" + "Zero", "ASP_RX1", "ASP_RX2", "DSP_TX1", "DSP_TX2" }; static const unsigned int cs35l45_dac_val[] = { - CS35L45_PCM_SRC_ZERO, CS35L45_PCM_SRC_ASP_RX1, CS35L45_PCM_SRC_ASP_RX2 + CS35L45_PCM_SRC_ZERO, CS35L45_PCM_SRC_ASP_RX1, CS35L45_PCM_SRC_ASP_RX2, + CS35L45_PCM_SRC_DSP_TX1, CS35L45_PCM_SRC_DSP_TX2 }; static const struct soc_enum cs35l45_dacpcm_enums[] = { @@ -100,11 +265,29 @@ static const struct snd_kcontrol_new cs35l45_asp_muxes[] = { SOC_DAPM_ENUM("ASP_TX5 Source", cs35l45_asp_tx_enums[4]), }; +static const struct snd_kcontrol_new cs35l45_dsp_muxes[] = { + SOC_DAPM_ENUM("DSP_RX1 Source", cs35l45_dsp_rx_enums[0]), + SOC_DAPM_ENUM("DSP_RX2 Source", cs35l45_dsp_rx_enums[1]), + SOC_DAPM_ENUM("DSP_RX3 Source", cs35l45_dsp_rx_enums[2]), + SOC_DAPM_ENUM("DSP_RX4 Source", cs35l45_dsp_rx_enums[3]), + SOC_DAPM_ENUM("DSP_RX5 Source", cs35l45_dsp_rx_enums[4]), + SOC_DAPM_ENUM("DSP_RX6 Source", cs35l45_dsp_rx_enums[5]), + SOC_DAPM_ENUM("DSP_RX7 Source", cs35l45_dsp_rx_enums[6]), + SOC_DAPM_ENUM("DSP_RX8 Source", cs35l45_dsp_rx_enums[7]), +}; + static const struct snd_kcontrol_new cs35l45_dac_muxes[] = { SOC_DAPM_ENUM("DACPCM1 Source", cs35l45_dacpcm_enums[0]), }; static const struct snd_soc_dapm_widget cs35l45_dapm_widgets[] = { + SND_SOC_DAPM_SPK("DSP1 Preload", NULL), + SND_SOC_DAPM_SUPPLY_S("DSP1 Preloader", 100, SND_SOC_NOPM, 0, 0, + cs35l45_dsp_preload_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_OUT_DRV_E("DSP1", SND_SOC_NOPM, 0, 0, NULL, 0, + cs35l45_dsp_audio_ev, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), SND_SOC_DAPM_SUPPLY("GLOBAL_EN", SND_SOC_NOPM, 0, 0, cs35l45_global_en_ev, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), @@ -139,6 +322,15 @@ static const struct snd_soc_dapm_widget cs35l45_dapm_widgets[] = { SND_SOC_DAPM_MUX("ASP_TX4 Source", SND_SOC_NOPM, 0, 0, &cs35l45_asp_muxes[3]), SND_SOC_DAPM_MUX("ASP_TX5 Source", SND_SOC_NOPM, 0, 0, &cs35l45_asp_muxes[4]), + SND_SOC_DAPM_MUX("DSP_RX1 Source", SND_SOC_NOPM, 0, 0, &cs35l45_dsp_muxes[0]), + SND_SOC_DAPM_MUX("DSP_RX2 Source", SND_SOC_NOPM, 0, 0, &cs35l45_dsp_muxes[1]), + SND_SOC_DAPM_MUX("DSP_RX3 Source", SND_SOC_NOPM, 0, 0, &cs35l45_dsp_muxes[2]), + SND_SOC_DAPM_MUX("DSP_RX4 Source", SND_SOC_NOPM, 0, 0, &cs35l45_dsp_muxes[3]), + SND_SOC_DAPM_MUX("DSP_RX5 Source", SND_SOC_NOPM, 0, 0, &cs35l45_dsp_muxes[4]), + SND_SOC_DAPM_MUX("DSP_RX6 Source", SND_SOC_NOPM, 0, 0, &cs35l45_dsp_muxes[5]), + SND_SOC_DAPM_MUX("DSP_RX7 Source", SND_SOC_NOPM, 0, 0, &cs35l45_dsp_muxes[6]), + SND_SOC_DAPM_MUX("DSP_RX8 Source", SND_SOC_NOPM, 0, 0, &cs35l45_dsp_muxes[7]), + SND_SOC_DAPM_MUX("DACPCM1 Source", SND_SOC_NOPM, 0, 0, &cs35l45_dac_muxes[0]), SND_SOC_DAPM_OUT_DRV("AMP", SND_SOC_NOPM, 0, 0, NULL, 0), @@ -149,6 +341,8 @@ static const struct snd_soc_dapm_widget cs35l45_dapm_widgets[] = { #define CS35L45_ASP_MUX_ROUTE(name) \ { name" Source", "ASP_RX1", "ASP_RX1" }, \ { name" Source", "ASP_RX2", "ASP_RX2" }, \ + { name" Source", "DSP_TX1", "DSP1" }, \ + { name" Source", "DSP_TX2", "DSP1" }, \ { name" Source", "VMON", "VMON" }, \ { name" Source", "IMON", "IMON" }, \ { name" Source", "ERR_VOL", "ERR_VOL" }, \ @@ -157,10 +351,16 @@ static const struct snd_soc_dapm_widget cs35l45_dapm_widgets[] = { { name" Source", "Interpolator", "AMP_INTP" }, \ { name" Source", "IL_TARGET", "IL_TARGET" } -#define CS35L45_DAC_MUX_ROUTE(name) \ +#define CS35L45_DSP_MUX_ROUTE(name) \ { name" Source", "ASP_RX1", "ASP_RX1" }, \ { name" Source", "ASP_RX2", "ASP_RX2" } +#define CS35L45_DAC_MUX_ROUTE(name) \ + { name" Source", "ASP_RX1", "ASP_RX1" }, \ + { name" Source", "ASP_RX2", "ASP_RX2" }, \ + { name" Source", "DSP_TX1", "DSP1" }, \ + { name" Source", "DSP_TX2", "DSP1" } + static const struct snd_soc_dapm_route cs35l45_dapm_routes[] = { /* Feedback */ { "VMON", NULL, "VMON_SRC" }, @@ -204,6 +404,27 @@ static const struct snd_soc_dapm_route cs35l45_dapm_routes[] = { { "AMP", NULL, "DACPCM1 Source"}, { "AMP", NULL, "GLOBAL_EN"}, + CS35L45_DSP_MUX_ROUTE("DSP_RX1"), + CS35L45_DSP_MUX_ROUTE("DSP_RX2"), + CS35L45_DSP_MUX_ROUTE("DSP_RX3"), + CS35L45_DSP_MUX_ROUTE("DSP_RX4"), + CS35L45_DSP_MUX_ROUTE("DSP_RX5"), + CS35L45_DSP_MUX_ROUTE("DSP_RX6"), + CS35L45_DSP_MUX_ROUTE("DSP_RX7"), + CS35L45_DSP_MUX_ROUTE("DSP_RX8"), + + {"DSP1", NULL, "DSP_RX1 Source"}, + {"DSP1", NULL, "DSP_RX2 Source"}, + {"DSP1", NULL, "DSP_RX3 Source"}, + {"DSP1", NULL, "DSP_RX4 Source"}, + {"DSP1", NULL, "DSP_RX5 Source"}, + {"DSP1", NULL, "DSP_RX6 Source"}, + {"DSP1", NULL, "DSP_RX7 Source"}, + {"DSP1", NULL, "DSP_RX8 Source"}, + + {"DSP1 Preload", NULL, "DSP1 Preloader"}, + {"DSP1", NULL, "DSP1 Preloader"}, + CS35L45_DAC_MUX_ROUTE("DACPCM1"), { "SPK", NULL, "AMP"}, @@ -219,6 +440,8 @@ static const struct snd_kcontrol_new cs35l45_controls[] = { -409, 48, (CS35L45_AMP_VOL_PCM_WIDTH - 1) - 1, 0, cs35l45_dig_pcm_vol_tlv), + WM_ADSP2_PRELOAD_SWITCH("DSP1", 1), + WM_ADSP_FW_CONTROL("DSP1", 0), }; static int cs35l45_set_pll(struct cs35l45_private *cs35l45, unsigned int freq) @@ -489,7 +712,24 @@ static struct snd_soc_dai_driver cs35l45_dai[] = { }, }; +static int cs35l45_component_probe(struct snd_soc_component *component) +{ + struct cs35l45_private *cs35l45 = snd_soc_component_get_drvdata(component); + + return wm_adsp2_component_probe(&cs35l45->dsp, component); +} + +static void cs35l45_component_remove(struct snd_soc_component *component) +{ + struct cs35l45_private *cs35l45 = snd_soc_component_get_drvdata(component); + + wm_adsp2_component_remove(&cs35l45->dsp, component); +} + static const struct snd_soc_component_driver cs35l45_component = { + .probe = cs35l45_component_probe, + .remove = cs35l45_component_remove, + .dapm_widgets = cs35l45_dapm_widgets, .num_dapm_widgets = ARRAY_SIZE(cs35l45_dapm_widgets), @@ -607,6 +847,60 @@ static int cs35l45_apply_property_config(struct cs35l45_private *cs35l45) return 0; } +static int cs35l45_dsp_virt2_mbox3_irq_handle(struct cs35l45_private *cs35l45, + const unsigned int cmd, + unsigned int data) +{ + static char *speak_status = "Unknown"; + + switch (cmd) { + case EVENT_SPEAKER_STATUS: + switch (data) { + case 1: + speak_status = "All Clear"; + break; + case 2: + speak_status = "Open Circuit"; + break; + case 4: + speak_status = "Short Circuit"; + break; + } + + dev_info(cs35l45->dev, "MBOX event (SPEAKER_STATUS): %s\n", + speak_status); + break; + case EVENT_BOOT_DONE: + dev_dbg(cs35l45->dev, "MBOX event (BOOT_DONE)\n"); + break; + default: + dev_err(cs35l45->dev, "MBOX event not supported %u\n", cmd); + return -EINVAL; + } + + return 0; +} + +static irqreturn_t cs35l45_dsp_virt2_mbox_cb(int irq, void *data) +{ + struct cs35l45_private *cs35l45 = data; + unsigned int mbox_val; + int ret = 0; + + ret = regmap_read(cs35l45->regmap, CS35L45_DSP_VIRT2_MBOX_3, &mbox_val); + if (!ret && mbox_val) + ret = cs35l45_dsp_virt2_mbox3_irq_handle(cs35l45, mbox_val & CS35L45_MBOX3_CMD_MASK, + (mbox_val & CS35L45_MBOX3_DATA_MASK) >> CS35L45_MBOX3_DATA_SHIFT); + + /* Handle DSP trace log IRQ */ + ret = regmap_read(cs35l45->regmap, CS35L45_DSP_VIRT2_MBOX_4, &mbox_val); + if (!ret && mbox_val != 0) { + dev_err(cs35l45->dev, "Spurious DSP MBOX4 IRQ\n"); + } + + return IRQ_RETVAL(ret); +} + static irqreturn_t cs35l45_pll_unlock(int irq, void *data) { struct cs35l45_private *cs35l45 = data; @@ -639,6 +933,7 @@ static const struct cs35l45_irq cs35l45_irqs[] = { CS35L45_IRQ(DSP_WDT_EXPIRE, "DSP Watchdog Timer", cs35l45_spk_safe_err), CS35L45_IRQ(PLL_UNLOCK_FLAG_RISE, "PLL unlock", cs35l45_pll_unlock), CS35L45_IRQ(PLL_LOCK_FLAG, "PLL lock", cs35l45_pll_lock), + CS35L45_IRQ(DSP_VIRT2_MBOX, "DSP virtual MBOX 2 write flag", cs35l45_dsp_virt2_mbox_cb), }; static irqreturn_t cs35l45_spk_safe_err(int irq, void *data) @@ -665,6 +960,7 @@ static const struct regmap_irq cs35l45_reg_irqs[] = { CS35L45_REG_IRQ(IRQ1_EINT_2, DSP_WDT_EXPIRE), CS35L45_REG_IRQ(IRQ1_EINT_3, PLL_UNLOCK_FLAG_RISE), CS35L45_REG_IRQ(IRQ1_EINT_3, PLL_LOCK_FLAG), + CS35L45_REG_IRQ(IRQ1_EINT_2, DSP_VIRT2_MBOX), }; static const struct regmap_irq_chip cs35l45_regmap_irq_chip = { @@ -724,14 +1020,63 @@ static int cs35l45_initialize(struct cs35l45_private *cs35l45) if (ret < 0) return ret; - pm_runtime_set_autosuspend_delay(cs35l45->dev, 3000); - pm_runtime_use_autosuspend(cs35l45->dev); - pm_runtime_set_active(cs35l45->dev); - pm_runtime_enable(cs35l45->dev); - return 0; } +static const struct reg_sequence cs35l45_fs_errata_patch[] = { + {0x02B80080, 0x00000001}, + {0x02B80088, 0x00000001}, + {0x02B80090, 0x00000001}, + {0x02B80098, 0x00000001}, + {0x02B800A0, 0x00000001}, + {0x02B800A8, 0x00000001}, + {0x02B800B0, 0x00000001}, + {0x02B800B8, 0x00000001}, + {0x02B80280, 0x00000001}, + {0x02B80288, 0x00000001}, + {0x02B80290, 0x00000001}, + {0x02B80298, 0x00000001}, + {0x02B802A0, 0x00000001}, + {0x02B802A8, 0x00000001}, + {0x02B802B0, 0x00000001}, + {0x02B802B8, 0x00000001}, +}; + +static const struct cs_dsp_region cs35l45_dsp1_regions[] = { + { .type = WMFW_HALO_PM_PACKED, .base = CS35L45_DSP1_PMEM_0 }, + { .type = WMFW_HALO_XM_PACKED, .base = CS35L45_DSP1_XMEM_PACK_0 }, + { .type = WMFW_HALO_YM_PACKED, .base = CS35L45_DSP1_YMEM_PACK_0 }, + {. type = WMFW_ADSP2_XM, .base = CS35L45_DSP1_XMEM_UNPACK24_0}, + {. type = WMFW_ADSP2_YM, .base = CS35L45_DSP1_YMEM_UNPACK24_0}, +}; + +static int cs35l45_dsp_init(struct cs35l45_private *cs35l45) +{ + struct wm_adsp *dsp = &cs35l45->dsp; + int ret; + + dsp->part = "cs35l45"; + dsp->fw = 9; /* 9 is WM_ADSP_FW_SPK_PROT in wm_adsp.c */ + dsp->toggle_preload = true; + dsp->cs_dsp.num = 1; + dsp->cs_dsp.type = WMFW_HALO; + dsp->cs_dsp.rev = 0; + dsp->cs_dsp.dev = cs35l45->dev; + dsp->cs_dsp.regmap = cs35l45->regmap; + dsp->cs_dsp.base = CS35L45_DSP1_CLOCK_FREQ; + dsp->cs_dsp.base_sysinfo = CS35L45_DSP1_SYS_ID; + dsp->cs_dsp.mem = cs35l45_dsp1_regions; + dsp->cs_dsp.num_mems = ARRAY_SIZE(cs35l45_dsp1_regions); + dsp->cs_dsp.lock_regions = 0xFFFFFFFF; + + ret = wm_halo_init(dsp); + + regmap_multi_reg_write(cs35l45->regmap, cs35l45_fs_errata_patch, + ARRAY_SIZE(cs35l45_fs_errata_patch)); + + return ret; +} + int cs35l45_probe(struct cs35l45_private *cs35l45) { struct device *dev = cs35l45->dev; @@ -781,6 +1126,17 @@ int cs35l45_probe(struct cs35l45_private *cs35l45) if (ret < 0) goto err_reset; + ret = cs35l45_dsp_init(cs35l45); + if (ret < 0) + goto err_reset; + + pm_runtime_set_autosuspend_delay(cs35l45->dev, 3000); + pm_runtime_use_autosuspend(cs35l45->dev); + pm_runtime_mark_last_busy(cs35l45->dev); + pm_runtime_set_active(cs35l45->dev); + pm_runtime_get_noresume(cs35l45->dev); + pm_runtime_enable(cs35l45->dev); + if (cs35l45->irq) { if (cs35l45->irq_invert) irq_pol |= IRQF_TRIGGER_HIGH; @@ -791,7 +1147,7 @@ int cs35l45_probe(struct cs35l45_private *cs35l45) &cs35l45_regmap_irq_chip, &cs35l45->irq_data); if (ret) { dev_err(dev, "Failed to register IRQ chip: %d\n", ret); - goto err_reset; + goto err_dsp; } for (i = 0; i < ARRAY_SIZE(cs35l45_irqs); i++) { @@ -799,7 +1155,7 @@ int cs35l45_probe(struct cs35l45_private *cs35l45) if (irq < 0) { dev_err(dev, "Failed to get %s\n", cs35l45_irqs[i].name); ret = irq; - goto err_reset; + goto err_dsp; } ret = devm_request_threaded_irq(dev, irq, NULL, cs35l45_irqs[i].handler, @@ -807,7 +1163,7 @@ int cs35l45_probe(struct cs35l45_private *cs35l45) if (ret) { dev_err(dev, "Failed to request IRQ %s: %d\n", cs35l45_irqs[i].name, ret); - goto err_reset; + goto err_dsp; } } } @@ -816,10 +1172,17 @@ int cs35l45_probe(struct cs35l45_private *cs35l45) cs35l45_dai, ARRAY_SIZE(cs35l45_dai)); if (ret < 0) - goto err_reset; + goto err_dsp; + + pm_runtime_put_autosuspend(cs35l45->dev); return 0; +err_dsp: + pm_runtime_disable(cs35l45->dev); + pm_runtime_put_noidle(cs35l45->dev); + wm_adsp2_remove(&cs35l45->dsp); + err_reset: gpiod_set_value_cansleep(cs35l45->reset_gpio, 0); err: @@ -832,9 +1195,13 @@ EXPORT_SYMBOL_NS_GPL(cs35l45_probe, SND_SOC_CS35L45); void cs35l45_remove(struct cs35l45_private *cs35l45) { + pm_runtime_get_sync(cs35l45->dev); pm_runtime_disable(cs35l45->dev); + wm_adsp2_remove(&cs35l45->dsp); gpiod_set_value_cansleep(cs35l45->reset_gpio, 0); + + pm_runtime_put_noidle(cs35l45->dev); regulator_disable(cs35l45->vdd_a); /* VDD_BATT must be the last to power-off */ regulator_disable(cs35l45->vdd_batt); diff --git a/sound/soc/codecs/cs35l45.h b/sound/soc/codecs/cs35l45.h index ce92f5068ac5..87032619b341 100644 --- a/sound/soc/codecs/cs35l45.h +++ b/sound/soc/codecs/cs35l45.h @@ -15,6 +15,7 @@ #include #include #include +#include "wm_adsp.h" #define CS35L45_DEVID 0x00000000 #define CS35L45_REVID 0x00000004 @@ -28,6 +29,7 @@ #define CS35L45_SYNC_GPIO1 0x00002430 #define CS35L45_INTB_GPIO2_MCLK_REF 0x00002434 #define CS35L45_GPIO3 0x00002438 +#define CS35L45_PWRMGT_CTL 0x00002900 #define CS35L45_REFCLK_INPUT 0x00002C04 #define CS35L45_GLOBAL_SAMPLE_RATE 0x00002C0C #define CS35L45_BOOST_CCM_CFG 0x00003808 @@ -48,6 +50,14 @@ #define CS35L45_ASPTX3_INPUT 0x00004C28 #define CS35L45_ASPTX4_INPUT 0x00004C2C #define CS35L45_ASPTX5_INPUT 0x00004C30 +#define CS35L45_DSP1RX1_INPUT 0x00004C40 +#define CS35L45_DSP1RX2_INPUT 0x00004C44 +#define CS35L45_DSP1RX3_INPUT 0x00004C48 +#define CS35L45_DSP1RX4_INPUT 0x00004C4C +#define CS35L45_DSP1RX5_INPUT 0x00004C50 +#define CS35L45_DSP1RX6_INPUT 0x00004C54 +#define CS35L45_DSP1RX7_INPUT 0x00004C58 +#define CS35L45_DSP1RX8_INPUT 0x00004C5C #define CS35L45_LDPM_CONFIG 0x00006404 #define CS35L45_AMP_PCM_CONTROL 0x00007000 #define CS35L45_AMP_PCM_HPF_TST 0x00007004 @@ -91,7 +101,55 @@ #define CS35L45_GPIO1_CTRL1 0x0000F008 #define CS35L45_GPIO2_CTRL1 0x0000F00C #define CS35L45_GPIO3_CTRL1 0x0000F010 -#define CS35L45_LASTREG 0x0000F010 +#define CS35L45_DSP_MBOX_1 0x00011000 +#define CS35L45_DSP_MBOX_2 0x00011004 +#define CS35L45_DSP_VIRT1_MBOX_1 0x00011020 +#define CS35L45_DSP_VIRT1_MBOX_2 0x00011024 +#define CS35L45_DSP_VIRT1_MBOX_3 0x00011028 +#define CS35L45_DSP_VIRT1_MBOX_4 0x0001102C +#define CS35L45_DSP_VIRT2_MBOX_1 0x00011040 +#define CS35L45_DSP_VIRT2_MBOX_2 0x00011044 +#define CS35L45_DSP_VIRT2_MBOX_3 0x00011048 +#define CS35L45_DSP_VIRT2_MBOX_4 0x0001104C +#define CS35L45_DSP1_XMEM_PACK_0 0x02000000 +#define CS35L45_DSP1_XMEM_PACK_4607 0x020047FC +#define CS35L45_DSP1_XMEM_UNPACK32_0 0x02400000 +#define CS35L45_DSP1_XMEM_UNPACK32_3071 0x02402FFC +#define CS35L45_DSP1_SYS_ID 0x025E0000 +#define CS35L45_DSP1_XMEM_UNPACK24_0 0x02800000 +#define CS35L45_DSP1_XMEM_UNPACK24_6143 0x02805FFC +#define CS35L45_DSP1_CLOCK_FREQ 0x02B80000 +#define CS35L45_DSP1_RX1_RATE 0x02B80080 +#define CS35L45_DSP1_RX2_RATE 0x02B80088 +#define CS35L45_DSP1_RX3_RATE 0x02B80090 +#define CS35L45_DSP1_RX4_RATE 0x02B80098 +#define CS35L45_DSP1_RX5_RATE 0x02B800A0 +#define CS35L45_DSP1_RX6_RATE 0x02B800A8 +#define CS35L45_DSP1_RX7_RATE 0x02B800B0 +#define CS35L45_DSP1_RX8_RATE 0x02B800B8 +#define CS35L45_DSP1_TX1_RATE 0x02B80280 +#define CS35L45_DSP1_TX2_RATE 0x02B80288 +#define CS35L45_DSP1_TX3_RATE 0x02B80290 +#define CS35L45_DSP1_TX4_RATE 0x02B80298 +#define CS35L45_DSP1_TX5_RATE 0x02B802A0 +#define CS35L45_DSP1_TX6_RATE 0x02B802A8 +#define CS35L45_DSP1_TX7_RATE 0x02B802B0 +#define CS35L45_DSP1_TX8_RATE 0x02B802B8 +#define CS35L45_DSP1_SCRATCH1 0x02B805C0 +#define CS35L45_DSP1_SCRATCH2 0x02B805C8 +#define CS35L45_DSP1_SCRATCH3 0x02B805D0 +#define CS35L45_DSP1_SCRATCH4 0x02B805D8 +#define CS35L45_DSP1_CCM_CORE_CONTROL 0x02BC1000 +#define CS35L45_DSP1_YMEM_PACK_0 0x02C00000 +#define CS35L45_DSP1_YMEM_PACK_1532 0x02C017F0 +#define CS35L45_DSP1_YMEM_UNPACK32_0 0x03000000 +#define CS35L45_DSP1_YMEM_UNPACK32_1022 0x03000FF8 +#define CS35L45_DSP1_YMEM_UNPACK24_0 0x03400000 +#define CS35L45_DSP1_YMEM_UNPACK24_2043 0x03401FEC +#define CS35L45_DSP1_PMEM_0 0x03800000 +#define CS35L45_DSP1_PMEM_3834 0x03803BE8 +#define CS35L45_LASTREG 0x03C6EFE8 + /* SFT_RESET */ #define CS35L45_SOFT_RESET_TRIGGER 0x5A000000 @@ -112,9 +170,20 @@ /* BLOCK_ENABLES2 */ #define CS35L45_ASP_EN_SHIFT 27 +#define CS35L45_MEM_RDY_SHIFT 1 +#define CS35L45_MEM_RDY_MASK BIT(1) + /* ERROR_RELEASE */ #define CS35L45_GLOBAL_ERR_RLS_MASK BIT(11) +/* CCM_CORE */ +#define CS35L45_CCM_CORE_RESET_SHIFT 9 +#define CS35L45_CCM_CORE_RESET_MASK BIT(9) +#define CS35L45_CCM_PM_REMAP_SHIFT 7 +#define CS35L45_CCM_PM_REMAP_MASK BIT(7) +#define CS35L45_CCM_CORE_EN_SHIFT 0 +#define CS35L45_CCM_CORE_EN_MASK BIT(0) + /* REFCLK_INPUT */ #define CS35L45_PLL_FORCE_EN_SHIFT 16 #define CS35L45_PLL_FORCE_EN_MASK BIT(16) @@ -240,6 +309,8 @@ /* CS35L45_IRQ1_EINT_2 */ #define CS35L45_DSP_WDT_EXPIRE_SHIFT 4 #define CS35L45_DSP_WDT_EXPIRE_MASK BIT(4) +#define CS35L45_DSP_VIRT2_MBOX_SHIFT 21 +#define CS35L45_DSP_VIRT2_MBOX_MASK BIT(21) /* CS35L45_IRQ1_EINT_3 */ #define CS35L45_PLL_LOCK_FLAG_SHIFT 1 @@ -266,6 +337,8 @@ #define CS35L45_PCM_SRC_CLASSH_TGT 0x21 #define CS35L45_PCM_SRC_VDD_BATTMON 0x28 #define CS35L45_PCM_SRC_VDD_BSTMON 0x29 +#define CS35L45_PCM_SRC_DSP_TX1 0x32 +#define CS35L45_PCM_SRC_DSP_TX2 0x33 #define CS35L45_PCM_SRC_TEMPMON 0x3A #define CS35L45_PCM_SRC_INTERPOLATOR 0x40 #define CS35L45_PCM_SRC_IL_TARGET 0x48 @@ -275,6 +348,27 @@ #define CS35L45_POST_GLOBAL_EN_US 5000 #define CS35L45_PRE_GLOBAL_DIS_US 3000 +#define CS35L45_SPI_MAX_FREQ 4000000 + +enum cs35l45_cspl_mboxstate { + CSPL_MBOX_STS_RUNNING = 0, + CSPL_MBOX_STS_PAUSED = 1, + CSPL_MBOX_STS_RDY_FOR_REINIT = 2, + CSPL_MBOX_STS_HIBERNATE = 3, +}; + +enum cs35l45_cspl_mboxcmd { + CSPL_MBOX_CMD_NONE = 0, + CSPL_MBOX_CMD_PAUSE = 1, + CSPL_MBOX_CMD_RESUME = 2, + CSPL_MBOX_CMD_REINIT = 3, + CSPL_MBOX_CMD_STOP_PRE_REINIT = 4, + CSPL_MBOX_CMD_HIBERNATE = 5, + CSPL_MBOX_CMD_OUT_OF_HIBERNATE = 6, + CSPL_MBOX_CMD_UNKNOWN_CMD = -1, + CSPL_MBOX_CMD_INVALID_SEQUENCE = -2, +}; + #define CS35L45_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ SNDRV_PCM_FMTBIT_S24_3LE| \ SNDRV_PCM_FMTBIT_S24_LE) @@ -318,10 +412,22 @@ enum cs35l45_irq_list { CS35L45_DSP_WDT_EXPIRE_IRQ, CS35L45_PLL_UNLOCK_FLAG_RISE_IRQ, CS35L45_PLL_LOCK_FLAG_IRQ, + CS35L45_DSP_VIRT2_MBOX_IRQ, CS35L45_NUM_IRQ }; +#define CS35L45_MBOX3_CMD_MASK 0xFF +#define CS35L45_MBOX3_CMD_SHIFT 0 +#define CS35L45_MBOX3_DATA_MASK 0xFFFFFF00 +#define CS35L45_MBOX3_DATA_SHIFT 8 + +enum mbox3_events { + EVENT_SPEAKER_STATUS = 0x66, + EVENT_BOOT_DONE = 0x67, +}; + struct cs35l45_private { + struct wm_adsp dsp; /* needs to be first member */ struct device *dev; struct regmap *regmap; struct gpio_desc *reset_gpio; From 6c07be8fe92c6b0c24ee1c599601dce3506b83c7 Mon Sep 17 00:00:00 2001 From: "Vlad.Karpovich" Date: Wed, 15 Mar 2023 10:47:22 -0500 Subject: [PATCH 583/778] ASoC: cs35l45: Hibernation support Adds support for a low-power Hibernation State. Add support for a low-power hibernation state for the DSP. In this state the DSP RAM contents are maintained, such that firmware does not need to be re-downloaded, but the rest of the chip's register state is lost. Entry to this state is achieved via the register interface (either by an external driver using the control port, or the programmable DSP). Exit from this state is triggered by activity on device GPIO pins, intended SPI transaction, or I2C transaction with intended slave address. Signed-off-by: Vlad Karpovich Link: https://lore.kernel.org/r/167933511185.26.10641185496218226278@mailman-core.alsa-project.org Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l45-i2c.c | 2 + sound/soc/codecs/cs35l45-spi.c | 1 + sound/soc/codecs/cs35l45-tables.c | 6 +++ sound/soc/codecs/cs35l45.c | 80 +++++++++++++++++++++++++++++++ sound/soc/codecs/cs35l45.h | 29 +++++++++++ 5 files changed, 118 insertions(+) diff --git a/sound/soc/codecs/cs35l45-i2c.c b/sound/soc/codecs/cs35l45-i2c.c index 33fa6d59e9a4..562f73df7afa 100644 --- a/sound/soc/codecs/cs35l45-i2c.c +++ b/sound/soc/codecs/cs35l45-i2c.c @@ -33,6 +33,8 @@ static int cs35l45_i2c_probe(struct i2c_client *client) cs35l45->dev = dev; cs35l45->irq = client->irq; + cs35l45->bus_type = CONTROL_BUS_I2C; + cs35l45->i2c_addr = client->addr; return cs35l45_probe(cs35l45); } diff --git a/sound/soc/codecs/cs35l45-spi.c b/sound/soc/codecs/cs35l45-spi.c index 99657325a281..a00b23b4180c 100644 --- a/sound/soc/codecs/cs35l45-spi.c +++ b/sound/soc/codecs/cs35l45-spi.c @@ -36,6 +36,7 @@ static int cs35l45_spi_probe(struct spi_device *spi) cs35l45->dev = dev; cs35l45->irq = spi->irq; + cs35l45->bus_type = CONTROL_BUS_SPI; return cs35l45_probe(cs35l45); } diff --git a/sound/soc/codecs/cs35l45-tables.c b/sound/soc/codecs/cs35l45-tables.c index 434a6473070e..46610e64e818 100644 --- a/sound/soc/codecs/cs35l45-tables.c +++ b/sound/soc/codecs/cs35l45-tables.c @@ -47,6 +47,8 @@ static const struct reg_default cs35l45_defaults[] = { { CS35L45_INTB_GPIO2_MCLK_REF, 0x00000005 }, { CS35L45_GPIO3, 0x00000005 }, { CS35L45_PWRMGT_CTL, 0x00000000 }, + { CS35L45_WAKESRC_CTL, 0x00000008 }, + { CS35L45_WKI2C_CTL, 0x00000030 }, { CS35L45_REFCLK_INPUT, 0x00000510 }, { CS35L45_GLOBAL_SAMPLE_RATE, 0x00000003 }, { CS35L45_ASP_ENABLES1, 0x00000000 }, @@ -126,6 +128,9 @@ static bool cs35l45_readable_reg(struct device *dev, unsigned int reg) case CS35L45_INTB_GPIO2_MCLK_REF: case CS35L45_GPIO3: case CS35L45_PWRMGT_CTL: + case CS35L45_WAKESRC_CTL: + case CS35L45_WKI2C_CTL: + case CS35L45_PWRMGT_STS: case CS35L45_REFCLK_INPUT: case CS35L45_GLOBAL_SAMPLE_RATE: case CS35L45_ASP_ENABLES1: @@ -210,6 +215,7 @@ static bool cs35l45_volatile_reg(struct device *dev, unsigned int reg) case CS35L45_GLOBAL_ENABLES: case CS35L45_ERROR_RELEASE: case CS35L45_AMP_PCM_HPF_TST: /* not cachable */ + case CS35L45_PWRMGT_STS: case CS35L45_IRQ1_STATUS: case CS35L45_IRQ1_EINT_1 ... CS35L45_IRQ1_EINT_18: case CS35L45_IRQ1_STS_1 ... CS35L45_IRQ1_STS_18: diff --git a/sound/soc/codecs/cs35l45.c b/sound/soc/codecs/cs35l45.c index 97f6819fa2ad..c31597f6bfae 100644 --- a/sound/soc/codecs/cs35l45.c +++ b/sound/soc/codecs/cs35l45.c @@ -36,6 +36,8 @@ static bool cs35l45_check_cspl_mbox_sts(const enum cs35l45_cspl_mboxcmd cmd, return (sts == CSPL_MBOX_STS_RUNNING); case CSPL_MBOX_CMD_STOP_PRE_REINIT: return (sts == CSPL_MBOX_STS_RDY_FOR_REINIT); + case CSPL_MBOX_CMD_HIBERNATE: + return (sts == CSPL_MBOX_STS_HIBERNATE); default: return false; } @@ -744,11 +746,81 @@ static const struct snd_soc_component_driver cs35l45_component = { .endianness = 1, }; +static void cs35l45_setup_hibernate(struct cs35l45_private *cs35l45) +{ + unsigned int wksrc; + + if (cs35l45->bus_type == CONTROL_BUS_I2C) + wksrc = CS35L45_WKSRC_I2C; + else + wksrc = CS35L45_WKSRC_SPI; + + regmap_update_bits(cs35l45->regmap, CS35L45_WAKESRC_CTL, + CS35L45_WKSRC_EN_MASK, + wksrc << CS35L45_WKSRC_EN_SHIFT); + + regmap_set_bits(cs35l45->regmap, CS35L45_WAKESRC_CTL, + CS35L45_UPDT_WKCTL_MASK); + + regmap_update_bits(cs35l45->regmap, CS35L45_WKI2C_CTL, + CS35L45_WKI2C_ADDR_MASK, cs35l45->i2c_addr); + + regmap_set_bits(cs35l45->regmap, CS35L45_WKI2C_CTL, + CS35L45_UPDT_WKI2C_MASK); +} + +static int cs35l45_enter_hibernate(struct cs35l45_private *cs35l45) +{ + dev_dbg(cs35l45->dev, "Enter hibernate\n"); + + cs35l45_setup_hibernate(cs35l45); + + // Don't wait for ACK since bus activity would wake the device + regmap_write(cs35l45->regmap, CS35L45_DSP_VIRT1_MBOX_1, CSPL_MBOX_CMD_HIBERNATE); + + return 0; +} + +static int cs35l45_exit_hibernate(struct cs35l45_private *cs35l45) +{ + const int wake_retries = 20; + const int sleep_retries = 5; + int ret, i, j; + + for (i = 0; i < sleep_retries; i++) { + dev_dbg(cs35l45->dev, "Exit hibernate\n"); + + for (j = 0; j < wake_retries; j++) { + ret = cs35l45_set_cspl_mbox_cmd(cs35l45, cs35l45->regmap, + CSPL_MBOX_CMD_OUT_OF_HIBERNATE); + if (!ret) { + dev_dbg(cs35l45->dev, "Wake success at cycle: %d\n", j); + return 0; + } + usleep_range(100, 200); + } + + dev_err(cs35l45->dev, "Wake failed, re-enter hibernate: %d\n", ret); + + cs35l45_setup_hibernate(cs35l45); + } + + dev_err(cs35l45->dev, "Timed out waking device\n"); + + return -ETIMEDOUT; +} + static int __maybe_unused cs35l45_runtime_suspend(struct device *dev) { struct cs35l45_private *cs35l45 = dev_get_drvdata(dev); + if (!cs35l45->dsp.preloaded || !cs35l45->dsp.cs_dsp.running) + return 0; + + cs35l45_enter_hibernate(cs35l45); + regcache_cache_only(cs35l45->regmap, true); + regcache_mark_dirty(cs35l45->regmap); dev_dbg(cs35l45->dev, "Runtime suspended\n"); @@ -760,9 +832,17 @@ static int __maybe_unused cs35l45_runtime_resume(struct device *dev) struct cs35l45_private *cs35l45 = dev_get_drvdata(dev); int ret; + if (!cs35l45->dsp.preloaded || !cs35l45->dsp.cs_dsp.running) + return 0; + dev_dbg(cs35l45->dev, "Runtime resume\n"); regcache_cache_only(cs35l45->regmap, false); + + ret = cs35l45_exit_hibernate(cs35l45); + if (ret) + return ret; + ret = regcache_sync(cs35l45->regmap); if (ret != 0) dev_warn(cs35l45->dev, "regcache_sync failed: %d\n", ret); diff --git a/sound/soc/codecs/cs35l45.h b/sound/soc/codecs/cs35l45.h index 87032619b341..0da28439f628 100644 --- a/sound/soc/codecs/cs35l45.h +++ b/sound/soc/codecs/cs35l45.h @@ -30,6 +30,9 @@ #define CS35L45_INTB_GPIO2_MCLK_REF 0x00002434 #define CS35L45_GPIO3 0x00002438 #define CS35L45_PWRMGT_CTL 0x00002900 +#define CS35L45_WAKESRC_CTL 0x00002904 +#define CS35L45_WKI2C_CTL 0x00002908 +#define CS35L45_PWRMGT_STS 0x0000290C #define CS35L45_REFCLK_INPUT 0x00002C04 #define CS35L45_GLOBAL_SAMPLE_RATE 0x00002C0C #define CS35L45_BOOST_CCM_CFG 0x00003808 @@ -348,6 +351,25 @@ #define CS35L45_POST_GLOBAL_EN_US 5000 #define CS35L45_PRE_GLOBAL_DIS_US 3000 +/* WAKESRC_CTL */ +#define CS35L45_WKSRC_SYNC_GPIO1 BIT(0) +#define CS35L45_WKSRC_INT_GPIO2 BIT(1) +#define CS35L45_WKSRC_GPIO3 BIT(2) +#define CS35L45_WKSRC_SPI BIT(3) +#define CS35L45_WKSRC_I2C BIT(4) +#define CS35L45_UPDT_WKCTL_SHIFT 15 +#define CS35L45_UPDT_WKCTL_MASK BIT(15) +#define CS35L45_WKSRC_EN_SHIFT 8 +#define CS35L45_WKSRC_EN_MASK GENMASK(12, 8) +#define CS35L45_WKSRC_POL_SHIFT 0 +#define CS35L45_WKSRC_POL_MASK GENMASK(3, 0) + +/* WAKEI2C_CTL */ +#define CS35L45_UPDT_WKI2C_SHIFT 15 +#define CS35L45_UPDT_WKI2C_MASK BIT(15) +#define CS35L45_WKI2C_ADDR_SHIFT 0 +#define CS35L45_WKI2C_ADDR_MASK GENMASK(6, 0) + #define CS35L45_SPI_MAX_FREQ 4000000 enum cs35l45_cspl_mboxstate { @@ -369,6 +391,11 @@ enum cs35l45_cspl_mboxcmd { CSPL_MBOX_CMD_INVALID_SEQUENCE = -2, }; +enum control_bus_type { + CONTROL_BUS_I2C = 0, + CONTROL_BUS_SPI = 1, +}; + #define CS35L45_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ SNDRV_PCM_FMTBIT_S24_3LE| \ SNDRV_PCM_FMTBIT_S24_LE) @@ -439,6 +466,8 @@ struct cs35l45_private { u8 slot_count; int irq_invert; int irq; + unsigned int i2c_addr; + enum control_bus_type bus_type; struct regmap_irq_chip_data *irq_data; }; From 1c12e032cc43256d75fdd22e60a7df85e8df4549 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 21 Mar 2023 16:56:51 +0200 Subject: [PATCH 584/778] ASoC: SOF: ipc4-control: Return on error in sof_ipc4_widget_kcontrol_setup() The patch adding the bytes control support moved the error check outside of the list_for_each_entry() which was not correct as at the end of the list_for_each_entry() the scontrol will no longer point where the error happened, but it to the list head. Restore the original logic and return on the first error with the error code. Fixes: a062c8899fed ("ASoC: SOF: ipc4-control: Add support for bytes control get and put") Reported-by: Dan Carpenter Link: https://lore.kernel.org/alsa-devel/6be945d2-40cb-46fb-67ba-ed3a19cddfa4@linux.intel.com/T/#t Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230321145651.9118-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-control.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/sound/soc/sof/ipc4-control.c b/sound/soc/sof/ipc4-control.c index d26ed2a6029f..6f0698be9451 100644 --- a/sound/soc/sof/ipc4-control.c +++ b/sound/soc/sof/ipc4-control.c @@ -429,14 +429,17 @@ static int sof_ipc4_widget_kcontrol_setup(struct snd_sof_dev *sdev, struct snd_s default: break; } + + if (ret < 0) { + dev_err(sdev->dev, + "kcontrol %d set up failed for widget %s\n", + scontrol->comp_id, swidget->widget->name); + return ret; + } } } - if (ret < 0) - dev_err(sdev->dev, "kcontrol %d set up failed for widget %s\n", - scontrol->comp_id, swidget->widget->name); - - return ret; + return 0; } static int From e51f49512d98783b90799c9cc2002895ec3aa0eb Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Wed, 22 Mar 2023 10:55:38 +0200 Subject: [PATCH 585/778] ASoC: SOF: ipc4: Ensure DSP is in D0I0 during sof_ipc4_set_get_data() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The set_get_data() IPC op bypasses the check for the no_pm flag as done with the regular IPC tx_msg op. Since set_get_data should be performed when the DSP is in D0I0, set the DSP power state to D0I0 before sending the IPC's in sof_ipc4_set_get_data(). Fixes: ceb89acc4dc8 ("ASoC: SOF: ipc4: Add support for mandatory message handling functionality") Signed-off-by: Ranjani Sridharan Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230322085538.10214-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sound/soc/sof/ipc4.c b/sound/soc/sof/ipc4.c index 8ede4b952997..246b56d24a6f 100644 --- a/sound/soc/sof/ipc4.c +++ b/sound/soc/sof/ipc4.c @@ -405,6 +405,9 @@ static int sof_ipc4_tx_msg(struct snd_sof_dev *sdev, void *msg_data, size_t msg_ static int sof_ipc4_set_get_data(struct snd_sof_dev *sdev, void *data, size_t payload_bytes, bool set) { + const struct sof_dsp_power_state target_state = { + .state = SOF_DSP_PM_D0, + }; size_t payload_limit = sdev->ipc->max_payload_size; struct sof_ipc4_msg *ipc4_msg = data; struct sof_ipc4_msg tx = {{ 0 }}; @@ -435,6 +438,11 @@ static int sof_ipc4_set_get_data(struct snd_sof_dev *sdev, void *data, tx.extension |= SOF_IPC4_MOD_EXT_MSG_FIRST_BLOCK(1); + /* ensure the DSP is in D0i0 before sending IPC */ + ret = snd_sof_dsp_set_power_state(sdev, &target_state); + if (ret < 0) + return ret; + /* Serialise IPC TX */ mutex_lock(&sdev->ipc->tx_mutex); From 1bf83fa6654ce8959948878aad14a6db586125b8 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Wed, 22 Mar 2023 11:43:44 +0200 Subject: [PATCH 586/778] ASoC: SOF: Intel: hda-dai: Do not perform DMA cleanup during stop In the case of repeated start/stop without involving hw_free, the stream tag needs to be preserved for the subsequent starts. So, skip performing the DMA clean up during stop and handle it only during suspend or hw_free. Signed-off-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Bard Liao Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230322094346.6019-2-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index 9637f0f44b01..46a17afdd1ea 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -305,7 +305,6 @@ static int hda_dai_trigger(struct snd_pcm_substream *substream, int cmd, struct switch (cmd) { case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_STOP: ret = hda_link_dma_cleanup(substream, hext_stream, dai, codec_dai); if (ret < 0) { dev_err(sdev->dev, "%s: failed to clean up link DMA\n", __func__); From 7d6f623c6a9d05195d1b19120383d4f42a1747db Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Wed, 22 Mar 2023 11:43:45 +0200 Subject: [PATCH 587/778] ASoC: SOF: pcm: Make hw_params reset conditional for IPC3 In the case of IPC4, since there is no PCM_PARAMS IPC to send the new stream tag when restarting a stream without a hw_free, the original stream tag needs to be preserved. So, add new a flag as part of struct sof_ipc_pcm_ops, reset_hw_params_during_stop and set it only for IPC3. This will ensure that the host DMA stream tag will not be given up during the STOP trigger for IPC4. Signed-off-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Bard Liao Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230322094346.6019-3-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc3-pcm.c | 1 + sound/soc/sof/pcm.c | 3 ++- sound/soc/sof/sof-audio.h | 3 +++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/sound/soc/sof/ipc3-pcm.c b/sound/soc/sof/ipc3-pcm.c index b29d93e0d216..b7f1eb21ca26 100644 --- a/sound/soc/sof/ipc3-pcm.c +++ b/sound/soc/sof/ipc3-pcm.c @@ -382,4 +382,5 @@ const struct sof_ipc_pcm_ops ipc3_pcm_ops = { .hw_free = sof_ipc3_pcm_hw_free, .trigger = sof_ipc3_pcm_trigger, .dai_link_fixup = sof_ipc3_pcm_dai_link_fixup, + .reset_hw_params_during_stop = true, }; diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index 445acb5c3a21..f75b161125fa 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -328,7 +328,8 @@ static int sof_pcm_trigger(struct snd_soc_component *component, fallthrough; case SNDRV_PCM_TRIGGER_STOP: ipc_first = true; - reset_hw_params = true; + if (pcm_ops && pcm_ops->reset_hw_params_during_stop) + reset_hw_params = true; break; default: dev_err(component->dev, "Unhandled trigger cmd %d\n", cmd); diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h index d220af5f08fb..81685e778ad6 100644 --- a/sound/soc/sof/sof-audio.h +++ b/sound/soc/sof/sof-audio.h @@ -104,6 +104,8 @@ struct snd_sof_dai_config_data { * @pcm_free: Function pointer for PCM free that can be used for freeing any * additional memory in the SOF PCM stream structure * @delay: Function pointer for pcm delay calculation + * @reset_hw_params_during_stop: Flag indicating whether the hw_params should be reset during the + * STOP pcm trigger */ struct sof_ipc_pcm_ops { int (*hw_params)(struct snd_soc_component *component, struct snd_pcm_substream *substream, @@ -117,6 +119,7 @@ struct sof_ipc_pcm_ops { void (*pcm_free)(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm); snd_pcm_sframes_t (*delay)(struct snd_soc_component *component, struct snd_pcm_substream *substream); + bool reset_hw_params_during_stop; }; /** From 51ce3e6effab4fd4e13a3f187f4e256259f6e5a4 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Wed, 22 Mar 2023 11:43:46 +0200 Subject: [PATCH 588/778] ASoC: SOF: pcm: Improve the pcm trigger sequence MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The recommended sequence for triggering the host DMA is to first program the DMA in the FW before setting the RUN bit to start the stream in the host. With IPC3, this sequence is honored because the FW programs the DMA when the HW_PARAMS IPC is sent during PCM hw_params and then the host sets the RUN bit during sof_pcm_trigger(). But with IPC4, sof_pcm_trigger() sends the SET_PIPELINE_STATE IPC to program the DMA in the FW after the DMA RUN bit is set. In order to minimize the impact for IPC3, introduce a new flag as part of struct sof_ipc_pcm_ops, ipc_first_on_start, which will be set for IPC4 only. With this flag set, the SET_PIPELINE_STATE IPC will be sent before the DMA RUN bit is set by the host during the START/PAUSE_RELEASE triggers. Signed-off-by: Ranjani Sridharan Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230322094346.6019-4-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-pcm.c | 3 ++- sound/soc/sof/pcm.c | 26 ++++++++++++++++++++------ sound/soc/sof/sof-audio.h | 3 +++ 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/sound/soc/sof/ipc4-pcm.c b/sound/soc/sof/ipc4-pcm.c index db64200ba1e5..a2cd21256e44 100644 --- a/sound/soc/sof/ipc4-pcm.c +++ b/sound/soc/sof/ipc4-pcm.c @@ -835,5 +835,6 @@ const struct sof_ipc_pcm_ops ipc4_pcm_ops = { .dai_link_fixup = sof_ipc4_pcm_dai_link_fixup, .pcm_setup = sof_ipc4_pcm_setup, .pcm_free = sof_ipc4_pcm_free, - .delay = sof_ipc4_pcm_delay + .delay = sof_ipc4_pcm_delay, + .ipc_first_on_start = true }; diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index f75b161125fa..d9b4633bba7a 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -301,6 +301,8 @@ static int sof_pcm_trigger(struct snd_soc_component *component, ipc_first = true; break; case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + if (pcm_ops && pcm_ops->ipc_first_on_start) + ipc_first = true; break; case SNDRV_PCM_TRIGGER_START: if (spcm->stream[substream->stream].suspend_ignored) { @@ -312,6 +314,9 @@ static int sof_pcm_trigger(struct snd_soc_component *component, spcm->stream[substream->stream].suspend_ignored = false; return 0; } + + if (pcm_ops && pcm_ops->ipc_first_on_start) + ipc_first = true; break; case SNDRV_PCM_TRIGGER_SUSPEND: if (sdev->system_suspend_target == SOF_SUSPEND_S0IX && @@ -336,19 +341,28 @@ static int sof_pcm_trigger(struct snd_soc_component *component, return -EINVAL; } - /* - * DMA and IPC sequence is different for start and stop. Need to send - * STOP IPC before stop DMA - */ if (!ipc_first) snd_sof_pcm_platform_trigger(sdev, substream, cmd); if (pcm_ops && pcm_ops->trigger) ret = pcm_ops->trigger(component, substream, cmd); - /* need to STOP DMA even if trigger IPC failed */ - if (ipc_first) + switch (cmd) { + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + case SNDRV_PCM_TRIGGER_START: + /* invoke platform trigger to start DMA only if pcm_ops is successful */ + if (ipc_first && !ret) + snd_sof_pcm_platform_trigger(sdev, substream, cmd); + break; + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + case SNDRV_PCM_TRIGGER_STOP: + /* invoke platform trigger to stop DMA even if pcm_ops failed */ snd_sof_pcm_platform_trigger(sdev, substream, cmd); + break; + default: + break; + } /* free PCM if reset_hw_params is set and the STOP IPC is successful */ if (!ret && reset_hw_params) diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h index 81685e778ad6..6c64376858b3 100644 --- a/sound/soc/sof/sof-audio.h +++ b/sound/soc/sof/sof-audio.h @@ -106,6 +106,8 @@ struct snd_sof_dai_config_data { * @delay: Function pointer for pcm delay calculation * @reset_hw_params_during_stop: Flag indicating whether the hw_params should be reset during the * STOP pcm trigger + * @ipc_first_on_start: Send IPC before invoking platform trigger during + * START/PAUSE_RELEASE triggers */ struct sof_ipc_pcm_ops { int (*hw_params)(struct snd_soc_component *component, struct snd_pcm_substream *substream, @@ -120,6 +122,7 @@ struct sof_ipc_pcm_ops { snd_pcm_sframes_t (*delay)(struct snd_soc_component *component, struct snd_pcm_substream *substream); bool reset_hw_params_during_stop; + bool ipc_first_on_start; }; /** From 54e288766906569a9e5ca2ff3a09fb4e4cc25a37 Mon Sep 17 00:00:00 2001 From: Uday M Bhat Date: Wed, 22 Mar 2023 09:49:15 +0200 Subject: [PATCH 589/778] ASoC: Intel: sof_rt5682: Update BT offload config for Rex For Rex, SSP1 is used for BT offload. This is enabled in the sof_rt5682_quirk_table Signed-off-by: Uday M Bhat Reviewed-by: Kai Vehmanen Reviewed-by: Pierre-Louis Bossart Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230322074916.23225-2-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_rt5682.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index 2eec32846078..01a2a4db498c 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -234,7 +234,9 @@ static const struct dmi_system_id sof_rt5682_quirk_table[] = { SOF_SPEAKER_AMP_PRESENT | SOF_MAX98360A_SPEAKER_AMP_PRESENT | SOF_RT5682_SSP_AMP(0) | - SOF_RT5682_NUM_HDMIDEV(4) + SOF_RT5682_NUM_HDMIDEV(4) | + SOF_BT_OFFLOAD_SSP(1) | + SOF_SSP_BT_OFFLOAD_PRESENT ), }, { @@ -246,7 +248,9 @@ static const struct dmi_system_id sof_rt5682_quirk_table[] = { SOF_RT5682_SSP_CODEC(2) | SOF_SPEAKER_AMP_PRESENT | SOF_RT5682_SSP_AMP(0) | - SOF_RT5682_NUM_HDMIDEV(4) + SOF_RT5682_NUM_HDMIDEV(4) | + SOF_BT_OFFLOAD_SSP(1) | + SOF_SSP_BT_OFFLOAD_PRESENT ), }, {} From f19f24d47900656962cafa51426660c8aa32744d Mon Sep 17 00:00:00 2001 From: Uday M Bhat Date: Wed, 22 Mar 2023 09:49:16 +0200 Subject: [PATCH 590/778] ASoC: Intel: sof_rt5682: Update BT offload config for MTL RVP For MTL RVP, SSP2 is used for BT offload. This is enabled in the sof_rt5682_quirk_table Signed-off-by: Uday M Bhat Reviewed-by: Kai Vehmanen Reviewed-by: Pierre-Louis Bossart Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230322074916.23225-3-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_rt5682.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index 01a2a4db498c..c6c82e89b754 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -1123,7 +1123,9 @@ static const struct platform_device_id board_ids[] = { SOF_RT5682_SSP_CODEC(0) | SOF_SPEAKER_AMP_PRESENT | SOF_RT5682_SSP_AMP(1) | - SOF_RT5682_NUM_HDMIDEV(4)), + SOF_RT5682_NUM_HDMIDEV(4) | + SOF_BT_OFFLOAD_SSP(2) | + SOF_SSP_BT_OFFLOAD_PRESENT), }, { .name = "mtl_mx98360_rt5682", From 3e1a334ad5b6e1aee25fd7f09400000f9b7b1f82 Mon Sep 17 00:00:00 2001 From: Yong Zhi Date: Wed, 22 Mar 2023 09:50:12 +0200 Subject: [PATCH 591/778] ASoC: Intel: sof_rt5682: Remove conditional dpcm_capture setting The dpcm_capture is set unconditionally, we can drop the conditional setting of it. Signed-off-by: Yong Zhi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230322075012.23463-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_rt5682.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index 2eec32846078..76ee2e35e1ef 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -793,7 +793,6 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev, } links[id].init = max_98390_spk_codec_init; links[id].ops = &max_98390_ops; - links[id].dpcm_capture = 1; } else { max_98357a_dai_link(&links[id]); From dcf084247e376b35c139c922d30917f4ff716a4c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 22 Mar 2023 01:12:24 +0000 Subject: [PATCH 592/778] ASoC: simple-card: add comment to indicate don't remove platforms Basically CPU and Platform are different Component, but if CPU is using soc-generic-dmaengine-pcm, same dev will be shared between CPU and Platform, and Simple Card had been supporting it. When we focus to clean up Simple Card driver, we tend to remove platforms if no Platform was selected, but it is wrong because of above reasons. This patch adds comment why we shouldn't remove platforms. In case of CPU is not using soc-generic-dmaengine-pcm, CPU and Platform will be duplicated, but it will be ignored by snd_soc_rtd_add_component(). Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/875yattwqv.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/generic/audio-graph-card.c | 13 ++++++++++++- sound/soc/generic/audio-graph-card2.c | 17 +++++++++++++++++ sound/soc/generic/simple-card-utils.c | 11 ++++++++++- sound/soc/generic/simple-card.c | 22 +++++++++++++++++++++- 4 files changed, 60 insertions(+), 3 deletions(-) diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index d788f5f23a8a..4e85536a1b26 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -613,10 +613,16 @@ static int graph_count_noml(struct asoc_simple_priv *priv, return -EINVAL; } + /* + * DON'T REMOVE platforms + * see + * simple-card.c :: simple_count_noml() + */ li->num[li->link].cpus = 1; - li->num[li->link].codecs = 1; li->num[li->link].platforms = 1; + li->num[li->link].codecs = 1; + li->link += 1; /* 1xCPU-Codec */ dev_dbg(dev, "Count As Normal\n"); @@ -637,6 +643,11 @@ static int graph_count_dpcm(struct asoc_simple_priv *priv, } if (li->cpu) { + /* + * DON'T REMOVE platforms + * see + * simple-card.c :: simple_count_noml() + */ li->num[li->link].cpus = 1; li->num[li->link].platforms = 1; diff --git a/sound/soc/generic/audio-graph-card2.c b/sound/soc/generic/audio-graph-card2.c index 259544f64df9..d145b74d41e4 100644 --- a/sound/soc/generic/audio-graph-card2.c +++ b/sound/soc/generic/audio-graph-card2.c @@ -1046,8 +1046,14 @@ static int graph_count_normal(struct asoc_simple_priv *priv, * => lnk: port { endpoint { .. }; }; * }; */ + /* + * DON'T REMOVE platforms + * see + * simple-card.c :: simple_count_noml() + */ li->num[li->link].cpus = li->num[li->link].platforms = graph_counter(cpu_port); + li->num[li->link].codecs = graph_counter(codec_port); of_node_put(cpu_ep); @@ -1079,6 +1085,11 @@ static int graph_count_dpcm(struct asoc_simple_priv *priv, */ if (asoc_graph_is_ports0(lnk)) { + /* + * DON'T REMOVE platforms + * see + * simple-card.c :: simple_count_noml() + */ li->num[li->link].cpus = graph_counter(rport); /* FE */ li->num[li->link].platforms = graph_counter(rport); } else { @@ -1113,8 +1124,14 @@ static int graph_count_c2c(struct asoc_simple_priv *priv, * }; * }; */ + /* + * DON'T REMOVE platforms + * see + * simple-card.c :: simple_count_noml() + */ li->num[li->link].cpus = li->num[li->link].platforms = graph_counter(codec0); + li->num[li->link].codecs = graph_counter(codec1); of_node_put(ports); diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index 56552a616f21..34a9b91e676f 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -638,7 +638,16 @@ EXPORT_SYMBOL_GPL(asoc_simple_dai_init); void asoc_simple_canonicalize_platform(struct snd_soc_dai_link_component *platforms, struct snd_soc_dai_link_component *cpus) { - /* Assumes platform == cpu */ + /* + * Assumes Platform == CPU + * + * Some CPU might be using soc-generic-dmaengine-pcm. This means CPU and Platform + * are different Component, but are sharing same component->dev. + * + * Let's assume Platform is same as CPU if it doesn't identify Platform on DT. + * see + * simple-card.c :: simple_count_noml() + */ if (!platforms->of_node) platforms->of_node = cpus->of_node; } diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index e98932c16754..fcd6c44f89f6 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -509,10 +509,25 @@ static int simple_count_noml(struct asoc_simple_priv *priv, return -EINVAL; } + /* + * DON'T REMOVE platforms + * + * Some CPU might be using soc-generic-dmaengine-pcm. This means CPU and Platform + * are different Component, but are sharing same component->dev. + * Simple Card had been supported it without special Platform selection. + * We need platforms here. + * + * In case of no Platform, it will be Platform == CPU, but Platform will be + * ignored by snd_soc_rtd_add_component(). + * + * see + * simple-card-utils.c :: asoc_simple_canonicalize_platform() + */ li->num[li->link].cpus = 1; - li->num[li->link].codecs = 1; li->num[li->link].platforms = 1; + li->num[li->link].codecs = 1; + li->link += 1; return 0; @@ -531,6 +546,11 @@ static int simple_count_dpcm(struct asoc_simple_priv *priv, } if (li->cpu) { + /* + * DON'T REMOVE platforms + * see + * simple_count_noml() + */ li->num[li->link].cpus = 1; li->num[li->link].platforms = 1; From 59385ed41c37b609c70a1ebb46003e4cc6685ec0 Mon Sep 17 00:00:00 2001 From: Jiapeng Chong Date: Wed, 22 Mar 2023 09:43:30 +0800 Subject: [PATCH 593/778] ASoC: tegra: remove unneeded semicolon ./sound/soc/tegra/tegra_asoc_machine.c:206:3-4: Unneeded semicolon. Reported-by: Abaci Robot Link: https://bugzilla.openanolis.cn/show_bug.cgi?id=4583 Signed-off-by: Jiapeng Chong Link: https://lore.kernel.org/r/20230322014330.97079-1-jiapeng.chong@linux.alibaba.com Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_asoc_machine.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/tegra/tegra_asoc_machine.c b/sound/soc/tegra/tegra_asoc_machine.c index c2aaa496468c..f5092b410926 100644 --- a/sound/soc/tegra/tegra_asoc_machine.c +++ b/sound/soc/tegra/tegra_asoc_machine.c @@ -203,7 +203,7 @@ int tegra_asoc_machine_init(struct snd_soc_pcm_runtime *rtd) "nvidia,coupled-mic-hp-det")) { tegra_machine_mic_jack_gpio.desc = machine->gpiod_hp_det; tegra_machine_mic_jack_gpio.jack_status_check = coupled_mic_hp_check; - }; + } err = snd_soc_jack_add_gpios(&tegra_machine_mic_jack, 1, &tegra_machine_mic_jack_gpio); From 935d31fdda2c69324b3eeb648a73fdedf4131474 Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Wed, 22 Mar 2023 20:18:30 +0200 Subject: [PATCH 594/778] ASoC: SOF: ipc4/intel: Add missing mutex_unlock() There was a missing mutex_unlock() in sof_ipc4_widget_free() use_chain_dma if-branch that caused a static analysis error. The branch should not be used in a normal working configuration and if its used its an indication of a bad topology. Add missing mutex_unlock() and a warning print if the if-branch is taken, and another warning print to a symmetric place in sof_ipc4_widget_setup(). Fixes: ca5ce0caa67fa9 ("ASoC: SOF: ipc4/intel: Add support for chained DMA") Reported-by: kernel test robot Reported-by: Dan Carpenter Link: https://lore.kernel.org/r/202303222050.dCw0fPCW-lkp@intel.com/ Signed-off-by: Jyri Sarha Link: https://lore.kernel.org/r/20230322181830.574635-1-jyri.sarha@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index f1e1aed94da4..12775fcb6b54 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -1989,8 +1989,11 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget case snd_soc_dapm_scheduler: pipeline = swidget->private; - if (pipeline->use_chain_dma) + if (pipeline->use_chain_dma) { + dev_warn(sdev->dev, "use_chain_dma set for schduler %s", + swidget->widget->name); return 0; + } dev_dbg(sdev->dev, "pipeline: %d memory pages: %d\n", swidget->pipeline_id, pipeline->mem_usage); @@ -2145,8 +2148,12 @@ static int sof_ipc4_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget struct sof_ipc4_msg msg = {{ 0 }}; u32 header; - if (pipeline->use_chain_dma) + if (pipeline->use_chain_dma) { + dev_warn(sdev->dev, "use_chain_dma set for schduler %s", + swidget->widget->name); + mutex_unlock(&ipc4_data->pipeline_state_mutex); return 0; + } header = SOF_IPC4_GLB_PIPE_INSTANCE_ID(swidget->instance_id); header |= SOF_IPC4_MSG_TYPE_SET(SOF_IPC4_GLB_DELETE_PIPELINE); From e38c5e80c3d293a883c6f1d553f2146ec0bda35e Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 22 Mar 2023 15:53:32 +0100 Subject: [PATCH 595/778] ASoC: Intel: bytcr_rt5640: Add quirk for the Acer Iconia One 7 B1-750 The Acer Iconia One 7 B1-750 tablet mostly works fine with the defaults for an Bay Trail CR tablet. Except for the internal mic, instead of an analog mic on IN3 a digital mic on DMIC1 is uses. Add a quirk with these settings for this tablet. Acked-by: Pierre-Louis Bossart Signed-off-by: Hans de Goede Link: https://lore.kernel.org/r/20230322145332.131525-1-hdegoede@redhat.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/bytcr_rt5640.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index 79e0039c79a3..5a12940ef907 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -533,6 +533,18 @@ static int byt_rt5640_aif1_hw_params(struct snd_pcm_substream *substream, /* Please keep this list alphabetically sorted */ static const struct dmi_system_id byt_rt5640_quirk_table[] = { + { /* Acer Iconia One 7 B1-750 */ + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Insyde"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "VESPA2"), + }, + .driver_data = (void *)(BYT_RT5640_DMIC1_MAP | + BYT_RT5640_JD_SRC_JD1_IN4P | + BYT_RT5640_OVCD_TH_1500UA | + BYT_RT5640_OVCD_SF_0P75 | + BYT_RT5640_SSP0_AIF1 | + BYT_RT5640_MCLK_EN), + }, { /* Acer Iconia Tab 8 W1-810 */ .matches = { DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Acer"), From 056db840115653659d86a3931a78b3c504edb2cc Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 23 Mar 2023 09:05:31 +0000 Subject: [PATCH 596/778] ASoC: SOF: ipc4/intel: Fix spelling mistake "schduler" -> "scheduler" There are two spelling mistakes in dev_warn messages. Fix them. Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20230323090531.67679-1-colin.i.king@gmail.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index 12775fcb6b54..de7213237b27 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -1990,7 +1990,7 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget pipeline = swidget->private; if (pipeline->use_chain_dma) { - dev_warn(sdev->dev, "use_chain_dma set for schduler %s", + dev_warn(sdev->dev, "use_chain_dma set for scheduler %s", swidget->widget->name); return 0; } @@ -2149,7 +2149,7 @@ static int sof_ipc4_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget u32 header; if (pipeline->use_chain_dma) { - dev_warn(sdev->dev, "use_chain_dma set for schduler %s", + dev_warn(sdev->dev, "use_chain_dma set for scheduler %s", swidget->widget->name); mutex_unlock(&ipc4_data->pipeline_state_mutex); return 0; From 80404e4e13882cf3037577e4a3451a61d54f58db Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 22 Mar 2023 20:35:41 +0100 Subject: [PATCH 597/778] ASoC: dt-bindings: wlf,wm8994: Convert to dtschema Convert the Wolfson WM1811/WM8994/WM8958 audio codecs bindings to DT schema. Changes against original binding: 1. Add missing LDO1VDD-supply and LDO2VDD-supply. 2. Use "gpios" suffix for wlf,ldo1ena and wlf,ldo2ena (Linux kernel's gpiolib already looks for both variants). 3. Do not require AVDD1-supply and DCVDD-supply, because at least on Arndale board with Exynos5250 these are being supplied by internal LDOs. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Rob Herring Acked-by: Charles Keepax Link: https://lore.kernel.org/r/20230322193541.827291-1-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/wlf,wm8994.yaml | 194 ++++++++++++++++++ .../devicetree/bindings/sound/wm8994.txt | 112 ---------- 2 files changed, 194 insertions(+), 112 deletions(-) create mode 100644 Documentation/devicetree/bindings/sound/wlf,wm8994.yaml delete mode 100644 Documentation/devicetree/bindings/sound/wm8994.txt diff --git a/Documentation/devicetree/bindings/sound/wlf,wm8994.yaml b/Documentation/devicetree/bindings/sound/wlf,wm8994.yaml new file mode 100644 index 000000000000..8f045de02850 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/wlf,wm8994.yaml @@ -0,0 +1,194 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/wlf,wm8994.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Wolfson WM1811/WM8994/WM8958 audio codecs + +maintainers: + - Krzysztof Kozlowski + - patches@opensource.cirrus.com + +description: | + These devices support both I2C and SPI (configured with pin strapping on the + board). + + Pins on the device (for linking into audio routes): + IN1LN, IN1LP, IN2LN, IN2LP:VXRN, IN1RN, IN1RP, IN2RN, IN2RP:VXRP, SPKOUTLP, + SPKOUTLN, SPKOUTRP, SPKOUTRN, HPOUT1L, HPOUT1R, HPOUT2P, HPOUT2N, LINEOUT1P, + LINEOUT1N, LINEOUT2P, LINEOUT2N. + +properties: + compatible: + enum: + - wlf,wm1811 + - wlf,wm8994 + - wlf,wm8958 + + reg: + maxItems: 1 + + clocks: + minItems: 1 + maxItems: 2 + + clock-names: + minItems: 1 + items: + - const: MCLK1 + - const: MCLK2 + + gpio-controller: true + + '#gpio-cells': + const: 2 + + interrupts: + maxItems: 1 + + interrupt-controller: true + + '#interrupt-cells': + const: 2 + description: + The first cell is the IRQ number. The second cell is the flags, encoded + as the trigger masks. + + AVDD1-supply: true + AVDD2-supply: true + CPVDD-supply: true + DBVDD-supply: true + DBVDD1-supply: true + DBVDD2-supply: true + DBVDD3-supply: true + DCVDD-supply: true + LDO1VDD-supply: true + LDO2VDD-supply: true + SPKVDD1-supply: true + SPKVDD2-supply: true + + '#sound-dai-cells': + const: 0 + + wlf,gpio-cfg: + $ref: /schemas/types.yaml#/definitions/uint32-array + maxItems: 11 + description: + A list of GPIO configuration register values. If absent, no configuration + of these registers is performed. If any value is over 0xffff then the + register will be left as default. If present 11 values must be supplied. + + wlf,micbias-cfg: + $ref: /schemas/types.yaml#/definitions/uint32-array + maxItems: 2 + description: + Two MICBIAS register values for WM1811 or WM8958. If absent the register + defaults will be used. + + wlf,ldo1ena-gpios: + maxItems: 1 + description: + Control of LDO1ENA input to device. + + wlf,ldo2ena-gpios: + maxItems: 1 + description: + Control of LDO2ENA input to device. + + wlf,lineout1-se: + type: boolean + description: + LINEOUT1 is in single ended mode. + + wlf,lineout2-se: + type: boolean + description: + INEOUT2 is in single ended mode. + + wlf,lineout1-feedback: + type: boolean + description: + LINEOUT1 has common mode feedback connected. + + wlf,lineout2-feedback: + type: boolean + description: + LINEOUT2 has common mode feedback connected. + + wlf,ldoena-always-driven: + type: boolean + description: + LDOENA is always driven. + + wlf,spkmode-pu: + type: boolean + description: + Enable the internal pull-up resistor on the SPKMODE pin. + + wlf,csnaddr-pd: + type: boolean + description: + Enable the internal pull-down resistor on the CS/ADDR pin. + +required: + - compatible + - reg + - AVDD2-supply + - CPVDD-supply + - SPKVDD1-supply + - SPKVDD2-supply + +allOf: + - $ref: dai-common.yaml# + - if: + properties: + compatible: + enum: + - wlf,wm1811 + - wlf,wm8958 + then: + properties: + DBVDD-supply: false + LDO2VDD-supply: false + required: + - DBVDD1-supply + - DBVDD2-supply + - DBVDD3-supply + else: + properties: + DBVDD1-supply: false + DBVDD2-supply: false + DBVDD3-supply: false + required: + - DBVDD-supply + +unevaluatedProperties: false + +examples: + - | + #include + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + audio-codec@1a { + compatible = "wlf,wm1811"; + reg = <0x1a>; + clocks = <&i2s0 0>; + clock-names = "MCLK1"; + + AVDD2-supply = <&main_dc_reg>; + CPVDD-supply = <&main_dc_reg>; + DBVDD1-supply = <&main_dc_reg>; + DBVDD2-supply = <&main_dc_reg>; + DBVDD3-supply = <&main_dc_reg>; + LDO1VDD-supply = <&main_dc_reg>; + SPKVDD1-supply = <&main_dc_reg>; + SPKVDD2-supply = <&main_dc_reg>; + + wlf,ldo1ena-gpios = <&gpb0 0 GPIO_ACTIVE_HIGH>; + wlf,ldo2ena-gpios = <&gpb0 1 GPIO_ACTIVE_HIGH>; + }; + }; diff --git a/Documentation/devicetree/bindings/sound/wm8994.txt b/Documentation/devicetree/bindings/sound/wm8994.txt deleted file mode 100644 index 8fa947509c10..000000000000 --- a/Documentation/devicetree/bindings/sound/wm8994.txt +++ /dev/null @@ -1,112 +0,0 @@ -WM1811/WM8994/WM8958 audio CODEC - -These devices support both I2C and SPI (configured with pin strapping -on the board). - -Required properties: - - - compatible : One of "wlf,wm1811", "wlf,wm8994" or "wlf,wm8958". - - - reg : the I2C address of the device for I2C, the chip select - number for SPI. - - - gpio-controller : Indicates this device is a GPIO controller. - - #gpio-cells : Must be 2. The first cell is the pin number and the - second cell is used to specify optional parameters (currently unused). - - - power supplies for the device, as covered in - Documentation/devicetree/bindings/regulator/regulator.txt, depending - on compatible: - - for wlf,wm1811 and wlf,wm8958: - AVDD1-supply, AVDD2-supply, DBVDD1-supply, DBVDD2-supply, DBVDD3-supply, - DCVDD-supply, CPVDD-supply, SPKVDD1-supply, SPKVDD2-supply - - for wlf,wm8994: - AVDD1-supply, AVDD2-supply, DBVDD-supply, DCVDD-supply, CPVDD-supply, - SPKVDD1-supply, SPKVDD2-supply - -Optional properties: - - - interrupts : The interrupt line the IRQ signal for the device is - connected to. This is optional, if it is not connected then none - of the interrupt related properties should be specified. - - interrupt-controller : These devices contain interrupt controllers - and may provide interrupt services to other devices if they have an - interrupt line connected. - - #interrupt-cells: the number of cells to describe an IRQ, this should be 2. - The first cell is the IRQ number. - The second cell is the flags, encoded as the trigger masks from - Documentation/devicetree/bindings/interrupt-controller/interrupts.txt - - - clocks : A list of up to two phandle and clock specifier pairs - - clock-names : A list of clock names sorted in the same order as clocks. - Valid clock names are "MCLK1" and "MCLK2". - - - wlf,gpio-cfg : A list of GPIO configuration register values. If absent, - no configuration of these registers is performed. If any value is - over 0xffff then the register will be left as default. If present 11 - values must be supplied. - - - wlf,micbias-cfg : Two MICBIAS register values for WM1811 or - WM8958. If absent the register defaults will be used. - - - wlf,ldo1ena : GPIO specifier for control of LDO1ENA input to device. - - wlf,ldo2ena : GPIO specifier for control of LDO2ENA input to device. - - - wlf,lineout1-se : If present LINEOUT1 is in single ended mode. - - wlf,lineout2-se : If present LINEOUT2 is in single ended mode. - - - wlf,lineout1-feedback : If present LINEOUT1 has common mode feedback - connected. - - wlf,lineout2-feedback : If present LINEOUT2 has common mode feedback - connected. - - - wlf,ldoena-always-driven : If present LDOENA is always driven. - - - wlf,spkmode-pu : If present enable the internal pull-up resistor on - the SPKMODE pin. - - - wlf,csnaddr-pd : If present enable the internal pull-down resistor on - the CS/ADDR pin. - -Pins on the device (for linking into audio routes): - - * IN1LN - * IN1LP - * IN2LN - * IN2LP:VXRN - * IN1RN - * IN1RP - * IN2RN - * IN2RP:VXRP - * SPKOUTLP - * SPKOUTLN - * SPKOUTRP - * SPKOUTRN - * HPOUT1L - * HPOUT1R - * HPOUT2P - * HPOUT2N - * LINEOUT1P - * LINEOUT1N - * LINEOUT2P - * LINEOUT2N - -Example: - -wm8994: codec@1a { - compatible = "wlf,wm8994"; - reg = <0x1a>; - - gpio-controller; - #gpio-cells = <2>; - - lineout1-se; - - AVDD1-supply = <®ulator>; - AVDD2-supply = <®ulator>; - CPVDD-supply = <®ulator>; - DBVDD-supply = <®ulator>; - DCVDD-supply = <®ulator>; - SPKVDD1-supply = <®ulator>; - SPKVDD2-supply = <®ulator>; -}; From a4a3203426f4b67535d6442ddc5dca8878a0678f Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Thu, 23 Mar 2023 11:01:25 +0000 Subject: [PATCH 598/778] ASoC: codecs: lpass: fix the order or clks turn off during suspend The order in which clocks are stopped matters as some of the clock like NPL are derived from MCLK. Without this patch, Dragonboard RB5 DSP would crash with below error: qcom_q6v5_pas 17300000.remoteproc: fatal error received: ABT_dal.c:278:ABTimeout: AHB Bus hang is detected, Number of bus hang detected := 2 , addr0 = 0x3370000 , addr1 = 0x0!!! Turn off fsgen first, followed by npl and then finally mclk, which is exactly the opposite order of enable sequence. Fixes: 1dc3459009c3 ("ASoC: codecs: lpass: register mclk after runtime pm") Reported-by: Amit Pundir Signed-off-by: Srinivas Kandagatla Tested-by: Amit Pundir Link: https://lore.kernel.org/r/20230323110125.23790-1-srinivas.kandagatla@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/lpass-rx-macro.c | 4 ++-- sound/soc/codecs/lpass-tx-macro.c | 4 ++-- sound/soc/codecs/lpass-wsa-macro.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/sound/soc/codecs/lpass-rx-macro.c b/sound/soc/codecs/lpass-rx-macro.c index a73a7d7a1c0a..faba4237bd3d 100644 --- a/sound/soc/codecs/lpass-rx-macro.c +++ b/sound/soc/codecs/lpass-rx-macro.c @@ -3670,9 +3670,9 @@ static int __maybe_unused rx_macro_runtime_suspend(struct device *dev) regcache_cache_only(rx->regmap, true); regcache_mark_dirty(rx->regmap); - clk_disable_unprepare(rx->mclk); - clk_disable_unprepare(rx->npl); clk_disable_unprepare(rx->fsgen); + clk_disable_unprepare(rx->npl); + clk_disable_unprepare(rx->mclk); return 0; } diff --git a/sound/soc/codecs/lpass-tx-macro.c b/sound/soc/codecs/lpass-tx-macro.c index 473d3cd39554..589c490a8c48 100644 --- a/sound/soc/codecs/lpass-tx-macro.c +++ b/sound/soc/codecs/lpass-tx-macro.c @@ -2098,9 +2098,9 @@ static int __maybe_unused tx_macro_runtime_suspend(struct device *dev) regcache_cache_only(tx->regmap, true); regcache_mark_dirty(tx->regmap); - clk_disable_unprepare(tx->mclk); - clk_disable_unprepare(tx->npl); clk_disable_unprepare(tx->fsgen); + clk_disable_unprepare(tx->npl); + clk_disable_unprepare(tx->mclk); return 0; } diff --git a/sound/soc/codecs/lpass-wsa-macro.c b/sound/soc/codecs/lpass-wsa-macro.c index ba7480f3831e..3f6f1bdd4e03 100644 --- a/sound/soc/codecs/lpass-wsa-macro.c +++ b/sound/soc/codecs/lpass-wsa-macro.c @@ -2506,9 +2506,9 @@ static int __maybe_unused wsa_macro_runtime_suspend(struct device *dev) regcache_cache_only(wsa->regmap, true); regcache_mark_dirty(wsa->regmap); - clk_disable_unprepare(wsa->mclk); - clk_disable_unprepare(wsa->npl); clk_disable_unprepare(wsa->fsgen); + clk_disable_unprepare(wsa->npl); + clk_disable_unprepare(wsa->mclk); return 0; } From 829d78e3ea321eb4f4e93bc7b162b8cc6ed91ec7 Mon Sep 17 00:00:00 2001 From: Saalim Quadri Date: Thu, 23 Mar 2023 01:39:49 +0530 Subject: [PATCH 599/778] ASoC: dt-bindings: ak5558: Convert to dtschema Convert the AK5558 ADC audio codec bindings to DT schema. Signed-off-by: Saalim Quadri Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230322200949.8986-1-danascape@gmail.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/ak5558.txt | 24 ---------- .../bindings/sound/asahi-kasei,ak5558.yaml | 48 +++++++++++++++++++ 2 files changed, 48 insertions(+), 24 deletions(-) delete mode 100644 Documentation/devicetree/bindings/sound/ak5558.txt create mode 100644 Documentation/devicetree/bindings/sound/asahi-kasei,ak5558.yaml diff --git a/Documentation/devicetree/bindings/sound/ak5558.txt b/Documentation/devicetree/bindings/sound/ak5558.txt deleted file mode 100644 index e28708db6686..000000000000 --- a/Documentation/devicetree/bindings/sound/ak5558.txt +++ /dev/null @@ -1,24 +0,0 @@ -AK5558 8 channel differential 32-bit delta-sigma ADC - -This device supports I2C mode only. - -Required properties: - -- compatible : "asahi-kasei,ak5558" or "asahi-kasei,ak5552". -- reg : The I2C address of the device. - -Optional properties: - -- reset-gpios: A GPIO specifier for the power down & reset pin. -- AVDD-supply: Analog power supply -- DVDD-supply: Digital power supply - -Example: - -&i2c { - ak5558: adc@10 { - compatible = "asahi-kasei,ak5558"; - reg = <0x10>; - reset-gpios = <&gpio1 10 GPIO_ACTIVE_LOW>; - }; -}; diff --git a/Documentation/devicetree/bindings/sound/asahi-kasei,ak5558.yaml b/Documentation/devicetree/bindings/sound/asahi-kasei,ak5558.yaml new file mode 100644 index 000000000000..d3d494ae8abf --- /dev/null +++ b/Documentation/devicetree/bindings/sound/asahi-kasei,ak5558.yaml @@ -0,0 +1,48 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/asahi-kasei,ak5558.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: AK5558 8 channel differential 32-bit delta-sigma ADC + +maintainers: + - Junichi Wakasugi + - Mihai Serban + +properties: + compatible: + enum: + - asahi-kasei,ak5552 + - asahi-kasei,ak5558 + + reg: + maxItems: 1 + + avdd-supply: + description: A 1.8V supply that powers up the AVDD pin. + + dvdd-supply: + description: A 1.2V supply that powers up the DVDD pin. + + reset-gpios: + maxItems: 1 + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + #include + i2c { + #address-cells = <1>; + #size-cells = <0>; + ak5558: codec@10 { + compatible = "asahi-kasei,ak5558"; + reg = <0x10>; + reset-gpios = <&gpio1 10 GPIO_ACTIVE_LOW>; + }; + }; From 33683cbf49b5412061cb1e4c876063fdef86def4 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Mar 2023 22:53:29 +0000 Subject: [PATCH 600/778] ASoC: fsl: remove unnecessary dai_link->platform dai_link->platform is no longer needed if CPU and Platform are same Component. This patch removes unnecessary dai_link->platform. Dummy Platform is also not necessary. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87o7ojjd06.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/fsl/imx-audmix.c | 14 ++++---------- sound/soc/fsl/imx-spdif.c | 5 +---- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/sound/soc/fsl/imx-audmix.c b/sound/soc/fsl/imx-audmix.c index 1292a845c424..2c57fe9d2d08 100644 --- a/sound/soc/fsl/imx-audmix.c +++ b/sound/soc/fsl/imx-audmix.c @@ -207,8 +207,8 @@ static int imx_audmix_probe(struct platform_device *pdev) for (i = 0; i < num_dai; i++) { struct snd_soc_dai_link_component *dlc; - /* for CPU/Codec/Platform x 2 */ - dlc = devm_kcalloc(&pdev->dev, 6, sizeof(*dlc), GFP_KERNEL); + /* for CPU/Codec x 2 */ + dlc = devm_kcalloc(&pdev->dev, 4, sizeof(*dlc), GFP_KERNEL); if (!dlc) return -ENOMEM; @@ -240,11 +240,9 @@ static int imx_audmix_probe(struct platform_device *pdev) priv->dai[i].cpus = &dlc[0]; priv->dai[i].codecs = &dlc[1]; - priv->dai[i].platforms = &dlc[2]; priv->dai[i].num_cpus = 1; priv->dai[i].num_codecs = 1; - priv->dai[i].num_platforms = 1; priv->dai[i].name = dai_name; priv->dai[i].stream_name = "HiFi-AUDMIX-FE"; @@ -252,7 +250,6 @@ static int imx_audmix_probe(struct platform_device *pdev) priv->dai[i].codecs->name = "snd-soc-dummy"; priv->dai[i].cpus->of_node = args.np; priv->dai[i].cpus->dai_name = dev_name(&cpu_pdev->dev); - priv->dai[i].platforms->of_node = args.np; priv->dai[i].dynamic = 1; priv->dai[i].dpcm_playback = 1; priv->dai[i].dpcm_capture = (i == 0 ? 1 : 0); @@ -267,20 +264,17 @@ static int imx_audmix_probe(struct platform_device *pdev) be_cp = devm_kasprintf(&pdev->dev, GFP_KERNEL, "AUDMIX-Capture-%d", i); - priv->dai[num_dai + i].cpus = &dlc[3]; - priv->dai[num_dai + i].codecs = &dlc[4]; - priv->dai[num_dai + i].platforms = &dlc[5]; + priv->dai[num_dai + i].cpus = &dlc[2]; + priv->dai[num_dai + i].codecs = &dlc[3]; priv->dai[num_dai + i].num_cpus = 1; priv->dai[num_dai + i].num_codecs = 1; - priv->dai[num_dai + i].num_platforms = 1; priv->dai[num_dai + i].name = be_name; priv->dai[num_dai + i].codecs->dai_name = "snd-soc-dummy-dai"; priv->dai[num_dai + i].codecs->name = "snd-soc-dummy"; priv->dai[num_dai + i].cpus->of_node = audmix_np; priv->dai[num_dai + i].cpus->dai_name = be_name; - priv->dai[num_dai + i].platforms->name = "snd-soc-dummy"; priv->dai[num_dai + i].no_pcm = 1; priv->dai[num_dai + i].dpcm_playback = 1; priv->dai[num_dai + i].dpcm_capture = 1; diff --git a/sound/soc/fsl/imx-spdif.c b/sound/soc/fsl/imx-spdif.c index 4446fba755b9..114b49660193 100644 --- a/sound/soc/fsl/imx-spdif.c +++ b/sound/soc/fsl/imx-spdif.c @@ -26,7 +26,7 @@ static int imx_spdif_audio_probe(struct platform_device *pdev) } data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); - comp = devm_kzalloc(&pdev->dev, 3 * sizeof(*comp), GFP_KERNEL); + comp = devm_kzalloc(&pdev->dev, 2 * sizeof(*comp), GFP_KERNEL); if (!data || !comp) { ret = -ENOMEM; goto end; @@ -34,18 +34,15 @@ static int imx_spdif_audio_probe(struct platform_device *pdev) data->dai.cpus = &comp[0]; data->dai.codecs = &comp[1]; - data->dai.platforms = &comp[2]; data->dai.num_cpus = 1; data->dai.num_codecs = 1; - data->dai.num_platforms = 1; data->dai.name = "S/PDIF PCM"; data->dai.stream_name = "S/PDIF PCM"; data->dai.codecs->dai_name = "snd-soc-dummy-dai"; data->dai.codecs->name = "snd-soc-dummy"; data->dai.cpus->of_node = spdif_np; - data->dai.platforms->of_node = spdif_np; data->dai.playback_only = true; data->dai.capture_only = true; From 2f650f87c03cab72e751fc739f42a1e257bdc6b9 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Mar 2023 22:53:35 +0000 Subject: [PATCH 601/778] ASoC: atmel: remove unnecessary dai_link->platform dai_link->platform is no longer needed if CPU and Platform are same Component. This patch removes unnecessary dai_link->platform. Signed-off-by: Kuninori Morimoto Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/87mt43jd00.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/atmel/atmel-classd.c | 5 +---- sound/soc/atmel/atmel-pdmic.c | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/sound/soc/atmel/atmel-classd.c b/sound/soc/atmel/atmel-classd.c index 9883e6867fd1..007ab746973d 100644 --- a/sound/soc/atmel/atmel-classd.c +++ b/sound/soc/atmel/atmel-classd.c @@ -473,24 +473,21 @@ static int atmel_classd_asoc_card_init(struct device *dev, if (!dai_link) return -ENOMEM; - comp = devm_kzalloc(dev, 3 * sizeof(*comp), GFP_KERNEL); + comp = devm_kzalloc(dev, 2 * sizeof(*comp), GFP_KERNEL); if (!comp) return -ENOMEM; dai_link->cpus = &comp[0]; dai_link->codecs = &comp[1]; - dai_link->platforms = &comp[2]; dai_link->num_cpus = 1; dai_link->num_codecs = 1; - dai_link->num_platforms = 1; dai_link->name = "CLASSD"; dai_link->stream_name = "CLASSD PCM"; dai_link->codecs->dai_name = "snd-soc-dummy-dai"; dai_link->cpus->dai_name = dev_name(dev); dai_link->codecs->name = "snd-soc-dummy"; - dai_link->platforms->name = dev_name(dev); card->dai_link = dai_link; card->num_links = 1; diff --git a/sound/soc/atmel/atmel-pdmic.c b/sound/soc/atmel/atmel-pdmic.c index 12cd40b15644..00c7b3a34ef5 100644 --- a/sound/soc/atmel/atmel-pdmic.c +++ b/sound/soc/atmel/atmel-pdmic.c @@ -496,24 +496,21 @@ static int atmel_pdmic_asoc_card_init(struct device *dev, if (!dai_link) return -ENOMEM; - comp = devm_kzalloc(dev, 3 * sizeof(*comp), GFP_KERNEL); + comp = devm_kzalloc(dev, 2 * sizeof(*comp), GFP_KERNEL); if (!comp) return -ENOMEM; dai_link->cpus = &comp[0]; dai_link->codecs = &comp[1]; - dai_link->platforms = &comp[2]; dai_link->num_cpus = 1; dai_link->num_codecs = 1; - dai_link->num_platforms = 1; dai_link->name = "PDMIC"; dai_link->stream_name = "PDMIC PCM"; dai_link->codecs->dai_name = "snd-soc-dummy-dai"; dai_link->cpus->dai_name = dev_name(dev); dai_link->codecs->name = "snd-soc-dummy"; - dai_link->platforms->name = dev_name(dev); card->dai_link = dai_link; card->num_links = 1; From 3b0db249cf8fe0027e2a4161d27a8566d82fcd80 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Mar 2023 22:53:41 +0000 Subject: [PATCH 602/778] ASoC: ti: remove unnecessary dai_link->platform dai_link->platform is no longer needed if CPU and Platform are same Component. This patch removes unnecessary dai_link->platform. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87lejnjczu.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/ti/omap-hdmi.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sound/soc/ti/omap-hdmi.c b/sound/soc/ti/omap-hdmi.c index ad37785e05d8..96c3569d7643 100644 --- a/sound/soc/ti/omap-hdmi.c +++ b/sound/soc/ti/omap-hdmi.c @@ -365,20 +365,17 @@ static int omap_hdmi_audio_probe(struct platform_device *pdev) if (!card->dai_link) return -ENOMEM; - compnent = devm_kzalloc(dev, 3 * sizeof(*compnent), GFP_KERNEL); + compnent = devm_kzalloc(dev, 2 * sizeof(*compnent), GFP_KERNEL); if (!compnent) return -ENOMEM; card->dai_link->cpus = &compnent[0]; card->dai_link->num_cpus = 1; card->dai_link->codecs = &compnent[1]; card->dai_link->num_codecs = 1; - card->dai_link->platforms = &compnent[2]; - card->dai_link->num_platforms = 1; card->dai_link->name = card->name; card->dai_link->stream_name = card->name; card->dai_link->cpus->dai_name = dev_name(ad->dssdev); - card->dai_link->platforms->name = dev_name(ad->dssdev); card->dai_link->codecs->name = "snd-soc-dummy"; card->dai_link->codecs->dai_name = "snd-soc-dummy-dai"; card->num_links = 1; From e7098ba9b3785d626326040d300f95fec79aa765 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Mar 2023 22:53:46 +0000 Subject: [PATCH 603/778] ASoC: soc-topology.c: remove unnecessary dai_link->platform dai_link->platform is no longer needed if CPU and Platform are same Component. This patch removes unnecessary dai_link->platform. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87jzz7jczp.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-topology.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 07421f5d4ebd..7f6424fa59ab 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -1685,8 +1685,8 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg, struct snd_soc_dai_link_component *dlc; int ret; - /* link + cpu + codec + platform */ - link = devm_kzalloc(tplg->dev, sizeof(*link) + (3 * sizeof(*dlc)), GFP_KERNEL); + /* link + cpu + codec */ + link = devm_kzalloc(tplg->dev, sizeof(*link) + (2 * sizeof(*dlc)), GFP_KERNEL); if (link == NULL) return -ENOMEM; @@ -1694,11 +1694,9 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg, link->cpus = &dlc[0]; link->codecs = &dlc[1]; - link->platforms = &dlc[2]; link->num_cpus = 1; link->num_codecs = 1; - link->num_platforms = 1; link->dobj.index = tplg->index; link->dobj.type = SND_SOC_DOBJ_DAI_LINK; @@ -1726,8 +1724,6 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg, link->codecs->name = "snd-soc-dummy"; link->codecs->dai_name = "snd-soc-dummy-dai"; - link->platforms->name = "snd-soc-dummy"; - /* enable DPCM */ link->dynamic = 1; link->ignore_pmdown_time = 1; From 92405802a7d6aa1953915af869192296d1792d18 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Mar 2023 22:56:08 +0000 Subject: [PATCH 604/778] ASoC: simple-card.c: add missing of_node_put() It is missing of_node_put() for platform. This patch fixup it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87ilerjcvr.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/generic/simple-card.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index fcd6c44f89f6..6f044cc8357e 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -422,6 +422,7 @@ static int __simple_for_each_link(struct asoc_simple_priv *priv, } of_node_put(codec); + of_node_put(plat); node = of_get_next_child(top, node); } while (!is_top && node); From ab76c891a687ae871f7e76dbf9bc3a0e32b53423 Mon Sep 17 00:00:00 2001 From: Jiapeng Chong Date: Fri, 24 Mar 2023 10:23:03 +0800 Subject: [PATCH 605/778] ASoC: cs35l56: Fix an unsigned comparison which can never be negative The variable 'rv' is defined as unsigned type, so the following if statement is invalid, we can modify the type of rv to int. if (rv < 0) { dev_err(cs35l56->dev, "irq: failed to get pm_runtime: %d\n", rv); goto err_unlock; } ./sound/soc/codecs/cs35l56.c:333:5-7: WARNING: Unsigned expression compared with zero: rv < 0. Reported-by: Abaci Robot Link: https://bugzilla.openanolis.cn/show_bug.cgi?id=4599 Signed-off-by: Jiapeng Chong Reviewed-by: Richard Fitzgerald Link: https://lore.kernel.org/r/20230324022303.121485-1-jiapeng.chong@linux.alibaba.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l56.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c index 90fc79b5666d..d97b465f0d3c 100644 --- a/sound/soc/codecs/cs35l56.c +++ b/sound/soc/codecs/cs35l56.c @@ -321,7 +321,9 @@ irqreturn_t cs35l56_irq(int irq, void *data) struct cs35l56_private *cs35l56 = data; unsigned int status1 = 0, status8 = 0, status20 = 0; unsigned int mask1, mask8, mask20; - unsigned int rv, val; + unsigned int val; + int rv; + irqreturn_t ret = IRQ_NONE; if (!cs35l56->init_done) From 37b58becc1cee4d591024f2056d7ffa99c6089e0 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Fri, 24 Mar 2023 14:40:19 +0200 Subject: [PATCH 606/778] ASoC: soc-compress: Inherit atomicity from DAI link for Compress FE After commit bbf7d3b1c4f40 ("ASoC: soc-pcm: align BE 'atomicity' with that of the FE") BE and FE atomicity must match. In the case of Compress PCM there is a mismatch in atomicity between FE and BE and we get errors like this: [ 36.434566] sai1-wm8960-hifi: dpcm_be_connect: FE is atomic but BE is nonatomic, invalid configuration [ 36.444278] PCM Deep Buffer: ASoC: can't connect SAI1.OUT In order to fix this we must inherit the atomicity from DAI link associated with current PCM Compress FE. Fixes: bbf7d3b1c4f4 ("ASoC: soc-pcm: align BE 'atomicity' with that of the FE") Signed-off-by: Daniel Baluta Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20230324124019.30826-1-daniel.baluta@oss.nxp.com Signed-off-by: Mark Brown --- sound/soc/soc-compress.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 554c329ec87f..6e74a6c48986 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -615,6 +615,9 @@ int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) return ret; } + /* inherit atomicity from DAI link */ + be_pcm->nonatomic = rtd->dai_link->nonatomic; + rtd->pcm = be_pcm; rtd->fe_compr = 1; if (rtd->dai_link->dpcm_playback) From 283771e8eefcbe4a0a84c6a00a0b7a210bbc5846 Mon Sep 17 00:00:00 2001 From: Harshit Mogalapalli Date: Fri, 24 Mar 2023 07:55:35 -0700 Subject: [PATCH 607/778] ASoC: cs35l56: Remove redundant return statement in cs35l56_spi_probe() We have unreachable 'return ret' statement in cs35l56_spi_probe(), delete it as its dead code.. This is found by static analysis with smatch. Fixes: e49611252900 ("ASoC: cs35l56: Add driver for Cirrus Logic CS35L56") Signed-off-by: Harshit Mogalapalli Reviewed-by: Richard Fitzgerald Link: https://lore.kernel.org/r/20230324145535.3951689-1-harshit.m.mogalapalli@oracle.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l56-spi.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/codecs/cs35l56-spi.c b/sound/soc/codecs/cs35l56-spi.c index 80dcf37daae2..4b2084e85f29 100644 --- a/sound/soc/codecs/cs35l56-spi.c +++ b/sound/soc/codecs/cs35l56-spi.c @@ -29,7 +29,6 @@ static int cs35l56_spi_probe(struct spi_device *spi) if (IS_ERR(cs35l56->regmap)) { ret = PTR_ERR(cs35l56->regmap); return dev_err_probe(&spi->dev, ret, "Failed to allocate register map\n"); - return ret; } cs35l56->dev = &spi->dev; From f6887a71bdd2f0dcba9b8180dd2223cfa8637e85 Mon Sep 17 00:00:00 2001 From: Jason Montleon Date: Fri, 24 Mar 2023 13:07:11 -0400 Subject: [PATCH 608/778] ASoC: hdac_hdmi: use set_stream() instead of set_tdm_slots() hdac_hdmi was not updated to use set_stream() instead of set_tdm_slots() in the original commit so HDMI no longer produces audio. Cc: stable@vger.kernel.org Link: https://lore.kernel.org/regressions/CAJD_bPKQdtaExvVEKxhQ47G-ZXDA=k+gzhMJRHLBe=mysPnuKA@mail.gmail.com/ Fixes: 636110411ca7 ("ASoC: Intel/SOF: use set_stream() instead of set_tdm_slots() for HDAudio") Signed-off-by: Jason Montleon Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20230324170711.2526-1-jmontleo@redhat.com Signed-off-by: Mark Brown --- sound/soc/codecs/hdac_hdmi.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index ed4f7cdda04f..8b6b76029694 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c @@ -436,23 +436,28 @@ static int hdac_hdmi_setup_audio_infoframe(struct hdac_device *hdev, return 0; } -static int hdac_hdmi_set_tdm_slot(struct snd_soc_dai *dai, - unsigned int tx_mask, unsigned int rx_mask, - int slots, int slot_width) +static int hdac_hdmi_set_stream(struct snd_soc_dai *dai, + void *stream, int direction) { struct hdac_hdmi_priv *hdmi = snd_soc_dai_get_drvdata(dai); struct hdac_device *hdev = hdmi->hdev; struct hdac_hdmi_dai_port_map *dai_map; struct hdac_hdmi_pcm *pcm; + struct hdac_stream *hstream; - dev_dbg(&hdev->dev, "%s: strm_tag: %d\n", __func__, tx_mask); + if (!stream) + return -EINVAL; + + hstream = (struct hdac_stream *)stream; + + dev_dbg(&hdev->dev, "%s: strm_tag: %d\n", __func__, hstream->stream_tag); dai_map = &hdmi->dai_map[dai->id]; pcm = hdac_hdmi_get_pcm_from_cvt(hdmi, dai_map->cvt); if (pcm) - pcm->stream_tag = (tx_mask << 4); + pcm->stream_tag = (hstream->stream_tag << 4); return 0; } @@ -1544,7 +1549,7 @@ static const struct snd_soc_dai_ops hdmi_dai_ops = { .startup = hdac_hdmi_pcm_open, .shutdown = hdac_hdmi_pcm_close, .hw_params = hdac_hdmi_set_hw_params, - .set_tdm_slot = hdac_hdmi_set_tdm_slot, + .set_stream = hdac_hdmi_set_stream, }; /* From 65d4d7259bfec376b6b1483b4fe4058a5ba2259b Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sun, 26 Mar 2023 14:43:38 +0200 Subject: [PATCH 609/778] ASoC: meson: Use the devm_clk_get_optional() helper Use devm_clk_get_optional() instead of hand writing it. This saves some loC and improves the semantic. Signed-off-by: Christophe JAILLET Reviewed-by: Jerome Brunet Link: https://lore.kernel.org/r/8dab942d6ce47657a9c038295959be80bb2ee09e.1679834598.git.christophe.jaillet@wanadoo.fr Signed-off-by: Mark Brown --- sound/soc/meson/axg-tdm-interface.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/sound/soc/meson/axg-tdm-interface.c b/sound/soc/meson/axg-tdm-interface.c index 7624aafe9009..5e5e4c56d505 100644 --- a/sound/soc/meson/axg-tdm-interface.c +++ b/sound/soc/meson/axg-tdm-interface.c @@ -496,7 +496,7 @@ static int axg_tdm_iface_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct snd_soc_dai_driver *dai_drv; struct axg_tdm_iface *iface; - int ret, i; + int i; iface = devm_kzalloc(dev, sizeof(*iface), GFP_KERNEL); if (!iface) @@ -533,14 +533,9 @@ static int axg_tdm_iface_probe(struct platform_device *pdev) * At this point, ignore the error if mclk is missing. We'll * throw an error if the cpu dai is master and mclk is missing */ - iface->mclk = devm_clk_get(dev, "mclk"); - if (IS_ERR(iface->mclk)) { - ret = PTR_ERR(iface->mclk); - if (ret == -ENOENT) - iface->mclk = NULL; - else - return dev_err_probe(dev, ret, "failed to get mclk\n"); - } + iface->mclk = devm_clk_get_optional(dev, "mclk"); + if (IS_ERR(iface->mclk)) + return dev_err_probe(dev, PTR_ERR(iface->mclk), "failed to get mclk\n"); return devm_snd_soc_register_component(dev, &axg_tdm_iface_component_drv, dai_drv, From ad58151fa04280a938c173bcba05ba42a4073d92 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 27 Mar 2023 04:33:41 +0000 Subject: [PATCH 610/778] ASoC: audio-graph-card2-custom-sample.dtsi: use card->name to avoid long name Current Card2 Custom Sample will be too long Card name, and be error audio-graph-card2-custom-sample audio-graph-card2-custom-sample \ ASoC: driver name too long \ audio-graph-card2-custom-sample' -> 'audio-graph-car' This patch uses short name to avoid it Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87bkke7qzf.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/generic/audio-graph-card2-custom-sample.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/generic/audio-graph-card2-custom-sample.c b/sound/soc/generic/audio-graph-card2-custom-sample.c index 4a2c743e286c..a3142be9323e 100644 --- a/sound/soc/generic/audio-graph-card2-custom-sample.c +++ b/sound/soc/generic/audio-graph-card2-custom-sample.c @@ -151,6 +151,9 @@ static int custom_probe(struct platform_device *pdev) simple_priv = &custom_priv->simple_priv; simple_priv->ops = &custom_ops; /* customize dai_link ops */ + /* "audio-graph-card2-custom-sample" is too long */ + simple_priv->snd_card.name = "card2-custom"; + /* use audio-graph-card2 parsing with own custom hooks */ ret = audio_graph2_parse_of(simple_priv, dev, &custom_hooks); if (ret < 0) From 8908c36dabad7dd52872034f9f42c6c077bc7270 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 27 Mar 2023 16:55:55 +0200 Subject: [PATCH 611/778] ASoC: qcom: audioreach: drop stray 'get' from error message Drop the stray 'get', which appears to be a copy-paste error, from the registration-failure error message. Signed-off-by: Johan Hovold Link: https://lore.kernel.org/r/20230327145555.19351-1-johan+linaro@kernel.org Signed-off-by: Mark Brown --- sound/soc/qcom/qdsp6/q6apm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/qcom/qdsp6/q6apm.c b/sound/soc/qcom/qdsp6/q6apm.c index 994c9e823a88..a7a3f973eb6d 100644 --- a/sound/soc/qcom/qdsp6/q6apm.c +++ b/sound/soc/qcom/qdsp6/q6apm.c @@ -676,7 +676,7 @@ static int apm_probe(gpr_device_t *gdev) ret = devm_snd_soc_register_component(dev, &q6apm_audio_component, NULL, 0); if (ret < 0) { - dev_err(dev, "failed to get register q6apm: %d\n", ret); + dev_err(dev, "failed to register q6apm: %d\n", ret); return ret; } From ffaf886e249ee269f9084c21fbd8617ce9b83817 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 27 Mar 2023 00:34:26 +0000 Subject: [PATCH 612/778] ASoC: soc-core.c: add snd_soc_add_pcm_runtimes() Current ASoC supports snd_soc_add_pcm_runtime(), but user need to call it one-by-one if it has multi dai_links. This patch adds snd_soc_add_pcm_runtimes() which supports multi dai_links. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87h6u76nhq.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc.h | 5 +++-- sound/soc/intel/avs/boards/hdaudio.c | 10 ++++----- sound/soc/soc-core.c | 31 +++++++++++++++++++--------- sound/soc/soc-topology.c | 2 +- 4 files changed, 29 insertions(+), 19 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index e58b43b5da7c..57c5786a625b 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1302,8 +1302,9 @@ int snd_soc_of_get_dai_link_cpus(struct device *dev, struct snd_soc_dai_link *dai_link); void snd_soc_of_put_dai_link_cpus(struct snd_soc_dai_link *dai_link); -int snd_soc_add_pcm_runtime(struct snd_soc_card *card, - struct snd_soc_dai_link *dai_link); +int snd_soc_add_pcm_runtimes(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_link, + int num_dai_link); void snd_soc_remove_pcm_runtime(struct snd_soc_card *card, struct snd_soc_pcm_runtime *rtd); diff --git a/sound/soc/intel/avs/boards/hdaudio.c b/sound/soc/intel/avs/boards/hdaudio.c index e68c4c7aa2ba..a542a67e21d0 100644 --- a/sound/soc/intel/avs/boards/hdaudio.c +++ b/sound/soc/intel/avs/boards/hdaudio.c @@ -194,12 +194,10 @@ static int avs_probing_link_init(struct snd_soc_pcm_runtime *rtm) return ret; } - for (n = 0; n < pcm_count; n++) { - ret = snd_soc_add_pcm_runtime(card, &links[n]); - if (ret < 0) { - dev_err(card->dev, "add links failed: %d\n", ret); - return ret; - } + ret = snd_soc_add_pcm_runtimes(card, links, pcm_count); + if (ret < 0) { + dev_err(card->dev, "add links failed: %d\n", ret); + return ret; } ret = avs_create_dapm_routes(card->dev, codec, pcm_count, &routes, &n); diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 2faa0d8d0d8e..9bbcff492c1e 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -959,8 +959,8 @@ EXPORT_SYMBOL_GPL(snd_soc_remove_pcm_runtime); * topology component. And machine drivers can still define static * DAI links in dai_link array. */ -int snd_soc_add_pcm_runtime(struct snd_soc_card *card, - struct snd_soc_dai_link *dai_link) +static int snd_soc_add_pcm_runtime(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_link) { struct snd_soc_pcm_runtime *rtd; struct snd_soc_dai_link_component *codec, *platform, *cpu; @@ -1027,7 +1027,21 @@ _err_defer: snd_soc_remove_pcm_runtime(card, rtd); return -EPROBE_DEFER; } -EXPORT_SYMBOL_GPL(snd_soc_add_pcm_runtime); + +int snd_soc_add_pcm_runtimes(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_link, + int num_dai_link) +{ + for (int i = 0; i < num_dai_link; i++) { + int ret = snd_soc_add_pcm_runtime(card, dai_link + i); + + if (ret < 0) + return ret; + } + + return 0; +} +EXPORT_SYMBOL_GPL(snd_soc_add_pcm_runtimes); static void snd_soc_runtime_get_dai_fmt(struct snd_soc_pcm_runtime *rtd) { @@ -1921,8 +1935,7 @@ static int snd_soc_bind_card(struct snd_soc_card *card) { struct snd_soc_pcm_runtime *rtd; struct snd_soc_component *component; - struct snd_soc_dai_link *dai_link; - int ret, i; + int ret; mutex_lock(&client_mutex); mutex_lock_nested(&card->mutex, SND_SOC_CARD_CLASS_INIT); @@ -1939,11 +1952,9 @@ static int snd_soc_bind_card(struct snd_soc_card *card) /* add predefined DAI links to the list */ card->num_rtd = 0; - for_each_card_prelinks(card, i, dai_link) { - ret = snd_soc_add_pcm_runtime(card, dai_link); - if (ret < 0) - goto probe_end; - } + ret = snd_soc_add_pcm_runtimes(card, card->dai_link, card->num_links); + if (ret < 0) + goto probe_end; /* card bind complete so register a sound card */ ret = snd_card_new(card->dev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 7f6424fa59ab..be9849749713 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -1741,7 +1741,7 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg, goto err; } - ret = snd_soc_add_pcm_runtime(tplg->comp->card, link); + ret = snd_soc_add_pcm_runtimes(tplg->comp->card, link, 1); if (ret < 0) { dev_err(tplg->dev, "ASoC: adding FE link failed\n"); goto err; From 44378cd113e5f15bb0a89f5ac5a0e687b52feb90 Mon Sep 17 00:00:00 2001 From: Duy Nguyen Date: Tue, 28 Mar 2023 00:03:03 +0000 Subject: [PATCH 613/778] ASoC: da7213.c: add missing pm_runtime_disable() da7213.c is missing pm_runtime_disable(), thus we will get below error when rmmod -> insmod. $ rmmod snd-soc-da7213.ko $ insmod snd-soc-da7213.ko da7213 0-001a: Unbalanced pm_runtime_enable!" [Kuninori adjusted to latest upstream] Signed-off-by: Duy Nguyen Signed-off-by: Kuninori Morimoto Tested-by: Khanh Le Link: https://lore.kernel.org/r/87mt3xg2tk.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/da7213.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sound/soc/codecs/da7213.c b/sound/soc/codecs/da7213.c index 0068780fe0a7..1c1f211a8e2e 100644 --- a/sound/soc/codecs/da7213.c +++ b/sound/soc/codecs/da7213.c @@ -2022,6 +2022,11 @@ static int da7213_i2c_probe(struct i2c_client *i2c) return ret; } +static void da7213_i2c_remove(struct i2c_client *i2c) +{ + pm_runtime_disable(&i2c->dev); +} + static int __maybe_unused da7213_runtime_suspend(struct device *dev) { struct da7213_priv *da7213 = dev_get_drvdata(dev); @@ -2065,6 +2070,7 @@ static struct i2c_driver da7213_i2c_driver = { .pm = &da7213_pm, }, .probe_new = da7213_i2c_probe, + .remove = da7213_i2c_remove, .id_table = da7213_i2c_id, }; From e4cf7805f084772cccf2094b634a16bccf2f444f Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 13 Mar 2023 08:54:37 +0100 Subject: [PATCH 614/778] ASoC: dt-bindings: qcom,lpass-rx-macro: narrow clocks per variants Currently the Qualcomm RX macro codec binding allows two different clock setups - with (for ADSP) and without macro/dcodec entries (for ADSP bypassed). With more devices coming soon, this will keep growing, thus rework the clocks/clock-names to be specific for each binding. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20230313075445.17160-1-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- .../bindings/sound/qcom,lpass-rx-macro.yaml | 58 ++++++++++++++----- 1 file changed, 44 insertions(+), 14 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml b/Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml index 79c6f8da1319..705e34f999fc 100644 --- a/Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml @@ -9,9 +9,6 @@ title: LPASS(Low Power Audio Subsystem) RX Macro audio codec maintainers: - Srinivas Kandagatla -allOf: - - $ref: dai-common.yaml# - properties: compatible: enum: @@ -33,17 +30,8 @@ properties: maxItems: 5 clock-names: - oneOf: - - items: #for ADSP based platforms - - const: mclk - - const: npl - - const: macro - - const: dcodec - - const: fsgen - - items: #for ADSP bypass based platforms - - const: mclk - - const: npl - - const: fsgen + minItems: 3 + maxItems: 5 clock-output-names: maxItems: 1 @@ -61,6 +49,48 @@ required: - reg - "#sound-dai-cells" +allOf: + - $ref: dai-common.yaml# + - if: + properties: + compatible: + enum: + - qcom,sc7280-lpass-rx-macro + then: + properties: + clock-names: + oneOf: + - items: #for ADSP based platforms + - const: mclk + - const: npl + - const: macro + - const: dcodec + - const: fsgen + - items: #for ADSP bypass based platforms + - const: mclk + - const: npl + - const: fsgen + + - if: + properties: + compatible: + enum: + - qcom,sc8280xp-lpass-rx-macro + - qcom,sm8250-lpass-rx-macro + - qcom,sm8450-lpass-rx-macro + then: + properties: + clocks: + minItems: 5 + maxItems: 5 + clock-names: + items: + - const: mclk + - const: npl + - const: macro + - const: dcodec + - const: fsgen + unevaluatedProperties: false examples: From 0fc109f875721f9cef29bb68095f50d67343b4b7 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 13 Mar 2023 08:54:38 +0100 Subject: [PATCH 615/778] ASoC: dt-bindings: qcom,lpass-rx-macro: Add SM8550 RX macro Add the RX macro codec on Qualcomm SM8550, which comes without NPL clock exposed. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20230313075445.17160-2-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- .../bindings/sound/qcom,lpass-rx-macro.yaml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml b/Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml index 705e34f999fc..78e462e2cdcf 100644 --- a/Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml @@ -15,6 +15,7 @@ properties: - qcom,sc7280-lpass-rx-macro - qcom,sm8250-lpass-rx-macro - qcom,sm8450-lpass-rx-macro + - qcom,sm8550-lpass-rx-macro - qcom,sc8280xp-lpass-rx-macro reg: @@ -91,6 +92,23 @@ allOf: - const: dcodec - const: fsgen + - if: + properties: + compatible: + enum: + - qcom,sm8550-lpass-rx-macro + then: + properties: + clocks: + minItems: 4 + maxItems: 4 + clock-names: + items: + - const: mclk + - const: macro + - const: dcodec + - const: fsgen + unevaluatedProperties: false examples: From 492fe974fed0754f7076580e069e1e182e7b3603 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 13 Mar 2023 08:54:39 +0100 Subject: [PATCH 616/778] ASoC: codecs: lpass-rx-macro: add support for SM8550 Add support for the RX macro codec on Qualcomm SM8550. SM8550 does not use NPL clock, thus add flags allowing to skip it. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20230313075445.17160-3-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/lpass-macro-common.h | 3 +++ sound/soc/codecs/lpass-rx-macro.c | 36 +++++++++++++++++++++------ 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/sound/soc/codecs/lpass-macro-common.h b/sound/soc/codecs/lpass-macro-common.h index f2cbf9fe2c6e..4eb886565ea3 100644 --- a/sound/soc/codecs/lpass-macro-common.h +++ b/sound/soc/codecs/lpass-macro-common.h @@ -6,6 +6,9 @@ #ifndef __LPASS_MACRO_COMMON_H__ #define __LPASS_MACRO_COMMON_H__ +/* NPL clock is expected */ +#define LPASS_MACRO_FLAG_HAS_NPL_CLOCK BIT(0) + struct lpass_macro { struct device *macro_pd; struct device *dcodec_pd; diff --git a/sound/soc/codecs/lpass-rx-macro.c b/sound/soc/codecs/lpass-rx-macro.c index 9e0a4e8a46c3..532b19b1980d 100644 --- a/sound/soc/codecs/lpass-rx-macro.c +++ b/sound/soc/codecs/lpass-rx-macro.c @@ -3491,7 +3491,10 @@ static int rx_macro_register_mclk_output(struct rx_macro *rx) struct clk_init_data init; int ret; - parent_clk_name = __clk_get_name(rx->npl); + if (rx->npl) + parent_clk_name = __clk_get_name(rx->npl); + else + parent_clk_name = __clk_get_name(rx->mclk); init.name = clk_name; init.ops = &swclk_gate_ops; @@ -3521,10 +3524,13 @@ static const struct snd_soc_component_driver rx_macro_component_drv = { static int rx_macro_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; + kernel_ulong_t flags; struct rx_macro *rx; void __iomem *base; int ret; + flags = (kernel_ulong_t)device_get_match_data(dev); + rx = devm_kzalloc(dev, sizeof(*rx), GFP_KERNEL); if (!rx) return -ENOMEM; @@ -3541,9 +3547,11 @@ static int rx_macro_probe(struct platform_device *pdev) if (IS_ERR(rx->mclk)) return PTR_ERR(rx->mclk); - rx->npl = devm_clk_get(dev, "npl"); - if (IS_ERR(rx->npl)) - return PTR_ERR(rx->npl); + if (flags & LPASS_MACRO_FLAG_HAS_NPL_CLOCK) { + rx->npl = devm_clk_get(dev, "npl"); + if (IS_ERR(rx->npl)) + return PTR_ERR(rx->npl); + } rx->fsgen = devm_clk_get(dev, "fsgen"); if (IS_ERR(rx->fsgen)) @@ -3653,10 +3661,22 @@ static void rx_macro_remove(struct platform_device *pdev) } static const struct of_device_id rx_macro_dt_match[] = { - { .compatible = "qcom,sc7280-lpass-rx-macro" }, - { .compatible = "qcom,sm8250-lpass-rx-macro" }, - { .compatible = "qcom,sm8450-lpass-rx-macro" }, - { .compatible = "qcom,sc8280xp-lpass-rx-macro" }, + { + .compatible = "qcom,sc7280-lpass-rx-macro", + .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, + + }, { + .compatible = "qcom,sm8250-lpass-rx-macro", + .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, + }, { + .compatible = "qcom,sm8450-lpass-rx-macro", + .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, + }, { + .compatible = "qcom,sm8550-lpass-rx-macro", + }, { + .compatible = "qcom,sc8280xp-lpass-rx-macro", + .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, + }, { } }; MODULE_DEVICE_TABLE(of, rx_macro_dt_match); From bf4afbf950938d42cf0df1ecd915affeb26f4d76 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 13 Mar 2023 08:54:40 +0100 Subject: [PATCH 617/778] ASoC: dt-bindings: qcom,lpass-tx-macro: narrow clocks per variants Currently the Qualcomm TX macro codec binding allows two different clock setups - with (for ADSP) and without macro/dcodec entries (for ADSP bypassed). With more devices coming soon, this will keep growing, thus rework the clocks/clock-names to be specific for each binding. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20230313075445.17160-4-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- .../bindings/sound/qcom,lpass-tx-macro.yaml | 63 ++++++++++++++----- 1 file changed, 46 insertions(+), 17 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-tx-macro.yaml b/Documentation/devicetree/bindings/sound/qcom,lpass-tx-macro.yaml index da5f70910da5..559da2509d8d 100644 --- a/Documentation/devicetree/bindings/sound/qcom,lpass-tx-macro.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,lpass-tx-macro.yaml @@ -9,9 +9,6 @@ title: LPASS(Low Power Audio Subsystem) TX Macro audio codec maintainers: - Srinivas Kandagatla -allOf: - - $ref: dai-common.yaml# - properties: compatible: enum: @@ -30,22 +27,12 @@ properties: const: 0 clocks: - oneOf: - - maxItems: 3 - - maxItems: 5 + minItems: 3 + maxItems: 5 clock-names: - oneOf: - - items: #for ADSP based platforms - - const: mclk - - const: npl - - const: macro - - const: dcodec - - const: fsgen - - items: #for ADSP bypass based platforms - - const: mclk - - const: npl - - const: fsgen + minItems: 3 + maxItems: 5 clock-output-names: maxItems: 1 @@ -67,6 +54,48 @@ required: - reg - "#sound-dai-cells" +allOf: + - $ref: dai-common.yaml# + - if: + properties: + compatible: + enum: + - qcom,sc7280-lpass-tx-macro + then: + properties: + clock-names: + oneOf: + - items: #for ADSP based platforms + - const: mclk + - const: npl + - const: macro + - const: dcodec + - const: fsgen + - items: #for ADSP bypass based platforms + - const: mclk + - const: npl + - const: fsgen + + - if: + properties: + compatible: + enum: + - qcom,sc8280xp-lpass-tx-macro + - qcom,sm8250-lpass-tx-macro + - qcom,sm8450-lpass-tx-macro + then: + properties: + clocks: + minItems: 5 + maxItems: 5 + clock-names: + items: + - const: mclk + - const: npl + - const: macro + - const: dcodec + - const: fsgen + unevaluatedProperties: false examples: From 050578c6f18c28e95f9659493a52a67b68b4b667 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 13 Mar 2023 08:54:41 +0100 Subject: [PATCH 618/778] ASoC: dt-bindings: qcom,lpass-tx-macro: Add SM8550 TX macro Add the TX macro codec on Qualcomm SM8550, which comes without NPL clock exposed. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20230313075445.17160-5-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- .../bindings/sound/qcom,lpass-tx-macro.yaml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-tx-macro.yaml b/Documentation/devicetree/bindings/sound/qcom,lpass-tx-macro.yaml index 559da2509d8d..9d6e67524daf 100644 --- a/Documentation/devicetree/bindings/sound/qcom,lpass-tx-macro.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,lpass-tx-macro.yaml @@ -15,6 +15,7 @@ properties: - qcom,sc7280-lpass-tx-macro - qcom,sm8250-lpass-tx-macro - qcom,sm8450-lpass-tx-macro + - qcom,sm8550-lpass-tx-macro - qcom,sc8280xp-lpass-tx-macro reg: @@ -96,6 +97,23 @@ allOf: - const: dcodec - const: fsgen + - if: + properties: + compatible: + enum: + - qcom,sm8550-lpass-tx-macro + then: + properties: + clocks: + minItems: 4 + maxItems: 4 + clock-names: + items: + - const: mclk + - const: macro + - const: dcodec + - const: fsgen + unevaluatedProperties: false examples: From 5faf6a1c5256559af98c998b7416e4db8fb09b75 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 13 Mar 2023 08:54:42 +0100 Subject: [PATCH 619/778] ASoC: codecs: lpass-tx-macro: add support for SM8550 Add support for the TX macro codec on Qualcomm SM8550. SM8550 does not use NPL clock, thus add flags allowing to skip it. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20230313075445.17160-6-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/lpass-tx-macro.c | 35 ++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/sound/soc/codecs/lpass-tx-macro.c b/sound/soc/codecs/lpass-tx-macro.c index b044c9c6f89b..ae01e464502c 100644 --- a/sound/soc/codecs/lpass-tx-macro.c +++ b/sound/soc/codecs/lpass-tx-macro.c @@ -1915,7 +1915,10 @@ static int tx_macro_register_mclk_output(struct tx_macro *tx) struct clk_init_data init; int ret; - parent_clk_name = __clk_get_name(tx->npl); + if (tx->npl) + parent_clk_name = __clk_get_name(tx->npl); + else + parent_clk_name = __clk_get_name(tx->mclk); init.name = clk_name; init.ops = &swclk_gate_ops; @@ -1946,10 +1949,13 @@ static int tx_macro_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; + kernel_ulong_t flags; struct tx_macro *tx; void __iomem *base; int ret, reg; + flags = (kernel_ulong_t)device_get_match_data(dev); + tx = devm_kzalloc(dev, sizeof(*tx), GFP_KERNEL); if (!tx) return -ENOMEM; @@ -1966,9 +1972,11 @@ static int tx_macro_probe(struct platform_device *pdev) if (IS_ERR(tx->mclk)) return PTR_ERR(tx->mclk); - tx->npl = devm_clk_get(dev, "npl"); - if (IS_ERR(tx->npl)) - return PTR_ERR(tx->npl); + if (flags & LPASS_MACRO_FLAG_HAS_NPL_CLOCK) { + tx->npl = devm_clk_get(dev, "npl"); + if (IS_ERR(tx->npl)) + return PTR_ERR(tx->npl); + } tx->fsgen = devm_clk_get(dev, "fsgen"); if (IS_ERR(tx->fsgen)) @@ -2143,10 +2151,21 @@ static const struct dev_pm_ops tx_macro_pm_ops = { }; static const struct of_device_id tx_macro_dt_match[] = { - { .compatible = "qcom,sc7280-lpass-tx-macro" }, - { .compatible = "qcom,sm8250-lpass-tx-macro" }, - { .compatible = "qcom,sm8450-lpass-tx-macro" }, - { .compatible = "qcom,sc8280xp-lpass-tx-macro" }, + { + .compatible = "qcom,sc7280-lpass-tx-macro", + .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, + }, { + .compatible = "qcom,sm8250-lpass-tx-macro", + .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, + }, { + .compatible = "qcom,sm8450-lpass-tx-macro", + .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, + }, { + .compatible = "qcom,sm8550-lpass-tx-macro", + }, { + .compatible = "qcom,sc8280xp-lpass-tx-macro", + .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, + }, { } }; MODULE_DEVICE_TABLE(of, tx_macro_dt_match); From c1bda22bd2f382f9c3b27fb7a899f8804d92f897 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 13 Mar 2023 08:54:44 +0100 Subject: [PATCH 620/778] ASoC: dt-bindings: qcom,lpass-wsa-macro: Add SM8550 WSA macro Add the WSA macro codec on Qualcomm SM8550, which comes without NPL clock exposed. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20230313075445.17160-8-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- .../bindings/sound/qcom,lpass-wsa-macro.yaml | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-wsa-macro.yaml b/Documentation/devicetree/bindings/sound/qcom,lpass-wsa-macro.yaml index 66cbb1f5e31a..eea7609d1b33 100644 --- a/Documentation/devicetree/bindings/sound/qcom,lpass-wsa-macro.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,lpass-wsa-macro.yaml @@ -15,6 +15,7 @@ properties: - qcom,sc7280-lpass-wsa-macro - qcom,sm8250-lpass-wsa-macro - qcom,sm8450-lpass-wsa-macro + - qcom,sm8550-lpass-wsa-macro - qcom,sc8280xp-lpass-wsa-macro reg: @@ -27,11 +28,11 @@ properties: const: 0 clocks: - minItems: 5 + minItems: 4 maxItems: 6 clock-names: - minItems: 5 + minItems: 4 maxItems: 6 clock-output-names: @@ -62,6 +63,7 @@ allOf: then: properties: clocks: + minItems: 5 maxItems: 5 clock-names: items: @@ -89,6 +91,23 @@ allOf: - const: va - const: fsgen + - if: + properties: + compatible: + enum: + - qcom,sm8550-lpass-wsa-macro + then: + properties: + clocks: + minItems: 4 + maxItems: 4 + clock-names: + items: + - const: mclk + - const: macro + - const: dcodec + - const: fsgen + unevaluatedProperties: false examples: From 6b004b836ced4d9ce655b5f1c810833c1a880369 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 13 Mar 2023 08:54:45 +0100 Subject: [PATCH 621/778] ASoC: codecs: lpass-wsa-macro: add support for SM8550 Add support for the WSA macro codec on Qualcomm SM8550. SM8550 does not use NPL clock, thus add flags allowing to skip it. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20230313075445.17160-9-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/lpass-wsa-macro.c | 37 +++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/sound/soc/codecs/lpass-wsa-macro.c b/sound/soc/codecs/lpass-wsa-macro.c index 728f26d12ab0..3cbcbfc219b2 100644 --- a/sound/soc/codecs/lpass-wsa-macro.c +++ b/sound/soc/codecs/lpass-wsa-macro.c @@ -14,6 +14,8 @@ #include #include #include + +#include "lpass-macro-common.h" #include "lpass-wsa-macro.h" #define CDC_WSA_CLK_RST_CTRL_MCLK_CONTROL (0x0000) @@ -2346,7 +2348,10 @@ static int wsa_macro_register_mclk_output(struct wsa_macro *wsa) struct clk_init_data init; int ret; - parent_clk_name = __clk_get_name(wsa->npl); + if (wsa->npl) + parent_clk_name = __clk_get_name(wsa->npl); + else + parent_clk_name = __clk_get_name(wsa->mclk); init.name = "mclk"; of_property_read_string(dev_of_node(dev), "clock-output-names", @@ -2379,9 +2384,12 @@ static int wsa_macro_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct wsa_macro *wsa; + kernel_ulong_t flags; void __iomem *base; int ret; + flags = (kernel_ulong_t)device_get_match_data(dev); + wsa = devm_kzalloc(dev, sizeof(*wsa), GFP_KERNEL); if (!wsa) return -ENOMEM; @@ -2398,9 +2406,11 @@ static int wsa_macro_probe(struct platform_device *pdev) if (IS_ERR(wsa->mclk)) return PTR_ERR(wsa->mclk); - wsa->npl = devm_clk_get(dev, "npl"); - if (IS_ERR(wsa->npl)) - return PTR_ERR(wsa->npl); + if (flags & LPASS_MACRO_FLAG_HAS_NPL_CLOCK) { + wsa->npl = devm_clk_get(dev, "npl"); + if (IS_ERR(wsa->npl)) + return PTR_ERR(wsa->npl); + } wsa->fsgen = devm_clk_get(dev, "fsgen"); if (IS_ERR(wsa->fsgen)) @@ -2551,10 +2561,21 @@ static const struct dev_pm_ops wsa_macro_pm_ops = { }; static const struct of_device_id wsa_macro_dt_match[] = { - {.compatible = "qcom,sc7280-lpass-wsa-macro"}, - {.compatible = "qcom,sm8250-lpass-wsa-macro"}, - {.compatible = "qcom,sm8450-lpass-wsa-macro"}, - {.compatible = "qcom,sc8280xp-lpass-wsa-macro" }, + { + .compatible = "qcom,sc7280-lpass-wsa-macro", + .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, + }, { + .compatible = "qcom,sm8250-lpass-wsa-macro", + .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, + }, { + .compatible = "qcom,sm8450-lpass-wsa-macro", + .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, + }, { + .compatible = "qcom,sm8550-lpass-wsa-macro", + }, { + .compatible = "qcom,sc8280xp-lpass-wsa-macro", + .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, + }, {} }; MODULE_DEVICE_TABLE(of, wsa_macro_dt_match); From d23d50de4ad9a960b752b8b7f4ffce32e05a8971 Mon Sep 17 00:00:00 2001 From: Richard Leitner Date: Tue, 28 Mar 2023 13:25:14 +0200 Subject: [PATCH 622/778] ASoC: dt-bindings: maxim,max9867: fix example Remove the common clock node from the example as suggested by Krzysztof Kozlowski in [1]. [1] https://lore.kernel.org/lkml/45d306d3-8efb-12ac-0a83-f01ca2982b0a@linaro.org/ Signed-off-by: Richard Leitner Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230328-max9867_dt_example_fix-v1-1-cdf31c3fdfc8@linux.dev Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/maxim,max9867.yaml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/maxim,max9867.yaml b/Documentation/devicetree/bindings/sound/maxim,max9867.yaml index 6f27029b137d..0b9a84d33b6c 100644 --- a/Documentation/devicetree/bindings/sound/maxim,max9867.yaml +++ b/Documentation/devicetree/bindings/sound/maxim,max9867.yaml @@ -57,10 +57,4 @@ examples: clocks = <&codec_clk>; }; }; - - codec_clk: clock { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <12288000>; - }; ... From 39db65a0a17b54915b269d3685f253a4731f344c Mon Sep 17 00:00:00 2001 From: Cristian Ciocaltea Date: Tue, 28 Mar 2023 12:49:01 +0300 Subject: [PATCH 623/778] ASoC: es8316: Handle optional IRQ assignment The driver is able to work fine without relying on a mandatory interrupt being assigned to the I2C device. This is only needed when making use of the jack-detect support. However, the following warning message is always emitted when there is no such interrupt available: es8316 0-0011: Failed to get IRQ 0: -22 Do not attempt to request an IRQ if it is not available/valid. This also ensures the rather misleading message is not displayed anymore. Also note the IRQ validation relies on commit dab472eb931bc291 ("i2c / ACPI: Use 0 to indicate that device does not have interrupt assigned"). Fixes: 822257661031 ("ASoC: es8316: Add jack-detect support") Signed-off-by: Cristian Ciocaltea Reviewed-by: Hans de Goede Link: https://lore.kernel.org/r/20230328094901.50763-1-cristian.ciocaltea@collabora.com Signed-off-by: Mark Brown --- sound/soc/codecs/es8316.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c index 056c3082fe02..f7d7a9c91e04 100644 --- a/sound/soc/codecs/es8316.c +++ b/sound/soc/codecs/es8316.c @@ -842,12 +842,14 @@ static int es8316_i2c_probe(struct i2c_client *i2c_client) es8316->irq = i2c_client->irq; mutex_init(&es8316->lock); - ret = devm_request_threaded_irq(dev, es8316->irq, NULL, es8316_irq, - IRQF_TRIGGER_HIGH | IRQF_ONESHOT | IRQF_NO_AUTOEN, - "es8316", es8316); - if (ret) { - dev_warn(dev, "Failed to get IRQ %d: %d\n", es8316->irq, ret); - es8316->irq = -ENXIO; + if (es8316->irq > 0) { + ret = devm_request_threaded_irq(dev, es8316->irq, NULL, es8316_irq, + IRQF_TRIGGER_HIGH | IRQF_ONESHOT | IRQF_NO_AUTOEN, + "es8316", es8316); + if (ret) { + dev_warn(dev, "Failed to get IRQ %d: %d\n", es8316->irq, ret); + es8316->irq = -ENXIO; + } } return devm_snd_soc_register_component(&i2c_client->dev, From 7739b152776655a86568103afded77aa240f3ad4 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 28 Mar 2023 10:58:19 +0100 Subject: [PATCH 624/778] ASoC: wm8903: Remove outdated DMIC comment Support for DMICs was added in commit 97945c46a23d ("ASoC: WM8903: Implement DMIC support"). Remove them from the TODO list at the top of the driver. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20230328095819.1632802-1-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8903.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index 41346e5ec5ad..1dc8e20bdace 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c @@ -9,7 +9,6 @@ * * TODO: * - TDM mode configuration. - * - Digital microphone support. */ #include From ef36ca92754b4e50289aee99453e69c6ff13edad Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 29 Mar 2023 00:21:03 +0000 Subject: [PATCH 625/778] ASoC: soc-topology.c: dai_link->platform again On SOF, many topology is assuming dai_link->platform exists, and is allowed to be overwritten on each link_load(). This patch restore the removed dai_link->platform for SOF, and add the comment. Fixes: e7098ba9b378 ("ASoC: soc-topology.c: remove unnecessary dai_link->platform") Reported-by: Peter Ujfalusi Link: https://lore.kernel.org/r/87jzz7jczp.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Kuninori Morimoto Tested-by: Peter Ujfalusi Link: https://lore.kernel.org/r/87v8ikcsr5.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-topology.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index be9849749713..d0aca6b9058b 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -1685,8 +1685,8 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg, struct snd_soc_dai_link_component *dlc; int ret; - /* link + cpu + codec */ - link = devm_kzalloc(tplg->dev, sizeof(*link) + (2 * sizeof(*dlc)), GFP_KERNEL); + /* link + cpu + codec + platform */ + link = devm_kzalloc(tplg->dev, sizeof(*link) + (3 * sizeof(*dlc)), GFP_KERNEL); if (link == NULL) return -ENOMEM; @@ -1724,6 +1724,14 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg, link->codecs->name = "snd-soc-dummy"; link->codecs->dai_name = "snd-soc-dummy-dai"; + /* + * Many topology is assuming link has Platform. + * This might be overwritten at soc_tplg_dai_link_load(). + */ + link->platforms = &dlc[2]; + link->platforms->name = "snd-soc-dummy"; + link->num_platforms = 1; + /* enable DPCM */ link->dynamic = 1; link->ignore_pmdown_time = 1; From 3e226b4db21fc339423c318ec7d238424c884d11 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 27 Mar 2023 15:22:47 +0200 Subject: [PATCH 626/778] ASoC: codecs: lpass-rx-macro: add support for SM8550 Add support for the RX macro codec on Qualcomm SM8550. SM8550 does not use NPL clock, thus add flags allowing to skip it. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20230327132254.147975-4-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/lpass-macro-common.h | 3 +++ sound/soc/codecs/lpass-rx-macro.c | 36 +++++++++++++++++++++------ 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/sound/soc/codecs/lpass-macro-common.h b/sound/soc/codecs/lpass-macro-common.h index f2cbf9fe2c6e..4eb886565ea3 100644 --- a/sound/soc/codecs/lpass-macro-common.h +++ b/sound/soc/codecs/lpass-macro-common.h @@ -6,6 +6,9 @@ #ifndef __LPASS_MACRO_COMMON_H__ #define __LPASS_MACRO_COMMON_H__ +/* NPL clock is expected */ +#define LPASS_MACRO_FLAG_HAS_NPL_CLOCK BIT(0) + struct lpass_macro { struct device *macro_pd; struct device *dcodec_pd; diff --git a/sound/soc/codecs/lpass-rx-macro.c b/sound/soc/codecs/lpass-rx-macro.c index 9e0a4e8a46c3..532b19b1980d 100644 --- a/sound/soc/codecs/lpass-rx-macro.c +++ b/sound/soc/codecs/lpass-rx-macro.c @@ -3491,7 +3491,10 @@ static int rx_macro_register_mclk_output(struct rx_macro *rx) struct clk_init_data init; int ret; - parent_clk_name = __clk_get_name(rx->npl); + if (rx->npl) + parent_clk_name = __clk_get_name(rx->npl); + else + parent_clk_name = __clk_get_name(rx->mclk); init.name = clk_name; init.ops = &swclk_gate_ops; @@ -3521,10 +3524,13 @@ static const struct snd_soc_component_driver rx_macro_component_drv = { static int rx_macro_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; + kernel_ulong_t flags; struct rx_macro *rx; void __iomem *base; int ret; + flags = (kernel_ulong_t)device_get_match_data(dev); + rx = devm_kzalloc(dev, sizeof(*rx), GFP_KERNEL); if (!rx) return -ENOMEM; @@ -3541,9 +3547,11 @@ static int rx_macro_probe(struct platform_device *pdev) if (IS_ERR(rx->mclk)) return PTR_ERR(rx->mclk); - rx->npl = devm_clk_get(dev, "npl"); - if (IS_ERR(rx->npl)) - return PTR_ERR(rx->npl); + if (flags & LPASS_MACRO_FLAG_HAS_NPL_CLOCK) { + rx->npl = devm_clk_get(dev, "npl"); + if (IS_ERR(rx->npl)) + return PTR_ERR(rx->npl); + } rx->fsgen = devm_clk_get(dev, "fsgen"); if (IS_ERR(rx->fsgen)) @@ -3653,10 +3661,22 @@ static void rx_macro_remove(struct platform_device *pdev) } static const struct of_device_id rx_macro_dt_match[] = { - { .compatible = "qcom,sc7280-lpass-rx-macro" }, - { .compatible = "qcom,sm8250-lpass-rx-macro" }, - { .compatible = "qcom,sm8450-lpass-rx-macro" }, - { .compatible = "qcom,sc8280xp-lpass-rx-macro" }, + { + .compatible = "qcom,sc7280-lpass-rx-macro", + .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, + + }, { + .compatible = "qcom,sm8250-lpass-rx-macro", + .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, + }, { + .compatible = "qcom,sm8450-lpass-rx-macro", + .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, + }, { + .compatible = "qcom,sm8550-lpass-rx-macro", + }, { + .compatible = "qcom,sc8280xp-lpass-rx-macro", + .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, + }, { } }; MODULE_DEVICE_TABLE(of, rx_macro_dt_match); From f03038baacb8e1d8a16556215807ac9ee2dbeada Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 27 Mar 2023 15:22:50 +0200 Subject: [PATCH 627/778] ASoC: codecs: lpass-tx-macro: add support for SM8550 Add support for the TX macro codec on Qualcomm SM8550. SM8550 does not use NPL clock, thus add flags allowing to skip it. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20230327132254.147975-7-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/lpass-tx-macro.c | 35 ++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/sound/soc/codecs/lpass-tx-macro.c b/sound/soc/codecs/lpass-tx-macro.c index b044c9c6f89b..ae01e464502c 100644 --- a/sound/soc/codecs/lpass-tx-macro.c +++ b/sound/soc/codecs/lpass-tx-macro.c @@ -1915,7 +1915,10 @@ static int tx_macro_register_mclk_output(struct tx_macro *tx) struct clk_init_data init; int ret; - parent_clk_name = __clk_get_name(tx->npl); + if (tx->npl) + parent_clk_name = __clk_get_name(tx->npl); + else + parent_clk_name = __clk_get_name(tx->mclk); init.name = clk_name; init.ops = &swclk_gate_ops; @@ -1946,10 +1949,13 @@ static int tx_macro_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; + kernel_ulong_t flags; struct tx_macro *tx; void __iomem *base; int ret, reg; + flags = (kernel_ulong_t)device_get_match_data(dev); + tx = devm_kzalloc(dev, sizeof(*tx), GFP_KERNEL); if (!tx) return -ENOMEM; @@ -1966,9 +1972,11 @@ static int tx_macro_probe(struct platform_device *pdev) if (IS_ERR(tx->mclk)) return PTR_ERR(tx->mclk); - tx->npl = devm_clk_get(dev, "npl"); - if (IS_ERR(tx->npl)) - return PTR_ERR(tx->npl); + if (flags & LPASS_MACRO_FLAG_HAS_NPL_CLOCK) { + tx->npl = devm_clk_get(dev, "npl"); + if (IS_ERR(tx->npl)) + return PTR_ERR(tx->npl); + } tx->fsgen = devm_clk_get(dev, "fsgen"); if (IS_ERR(tx->fsgen)) @@ -2143,10 +2151,21 @@ static const struct dev_pm_ops tx_macro_pm_ops = { }; static const struct of_device_id tx_macro_dt_match[] = { - { .compatible = "qcom,sc7280-lpass-tx-macro" }, - { .compatible = "qcom,sm8250-lpass-tx-macro" }, - { .compatible = "qcom,sm8450-lpass-tx-macro" }, - { .compatible = "qcom,sc8280xp-lpass-tx-macro" }, + { + .compatible = "qcom,sc7280-lpass-tx-macro", + .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, + }, { + .compatible = "qcom,sm8250-lpass-tx-macro", + .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, + }, { + .compatible = "qcom,sm8450-lpass-tx-macro", + .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, + }, { + .compatible = "qcom,sm8550-lpass-tx-macro", + }, { + .compatible = "qcom,sc8280xp-lpass-tx-macro", + .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, + }, { } }; MODULE_DEVICE_TABLE(of, tx_macro_dt_match); From 84054a8d0d8db7670142c5f74ee82d369ef5bc75 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 27 Mar 2023 15:22:52 +0200 Subject: [PATCH 628/778] ASoC: dt-bindings: qcom,lpass-va-macro: Add SM8550 VA macro Add the VA macro codec on Qualcomm SM8550, which comes without NPL clock exposed. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20230327132254.147975-9-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- .../bindings/sound/qcom,lpass-va-macro.yaml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-va-macro.yaml b/Documentation/devicetree/bindings/sound/qcom,lpass-va-macro.yaml index 0a3c688ef1ec..4cf778e3afdd 100644 --- a/Documentation/devicetree/bindings/sound/qcom,lpass-va-macro.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,lpass-va-macro.yaml @@ -18,6 +18,7 @@ properties: - qcom,sc7280-lpass-va-macro - qcom,sm8250-lpass-va-macro - qcom,sm8450-lpass-va-macro + - qcom,sm8550-lpass-va-macro - qcom,sc8280xp-lpass-va-macro reg: @@ -64,6 +65,23 @@ required: - reg - "#sound-dai-cells" + - if: + properties: + compatible: + contains: + enum: + - qcom,sm8550-lpass-va-macro + then: + properties: + clocks: + minItems: 3 + maxItems: 3 + clock-names: + items: + - const: mclk + - const: macro + - const: dcodec + unevaluatedProperties: false examples: From 5d83b5ce86624e3cf3802fbcb41d9dbfbd0fe964 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 27 Mar 2023 15:22:53 +0200 Subject: [PATCH 629/778] ASoC: dt-bindings: qcom,lpass-wsa-macro: Add SM8550 WSA macro Add the WSA macro codec on Qualcomm SM8550, which comes without NPL clock exposed. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20230327132254.147975-10-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- .../bindings/sound/qcom,lpass-wsa-macro.yaml | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-wsa-macro.yaml b/Documentation/devicetree/bindings/sound/qcom,lpass-wsa-macro.yaml index 66cbb1f5e31a..eea7609d1b33 100644 --- a/Documentation/devicetree/bindings/sound/qcom,lpass-wsa-macro.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,lpass-wsa-macro.yaml @@ -15,6 +15,7 @@ properties: - qcom,sc7280-lpass-wsa-macro - qcom,sm8250-lpass-wsa-macro - qcom,sm8450-lpass-wsa-macro + - qcom,sm8550-lpass-wsa-macro - qcom,sc8280xp-lpass-wsa-macro reg: @@ -27,11 +28,11 @@ properties: const: 0 clocks: - minItems: 5 + minItems: 4 maxItems: 6 clock-names: - minItems: 5 + minItems: 4 maxItems: 6 clock-output-names: @@ -62,6 +63,7 @@ allOf: then: properties: clocks: + minItems: 5 maxItems: 5 clock-names: items: @@ -89,6 +91,23 @@ allOf: - const: va - const: fsgen + - if: + properties: + compatible: + enum: + - qcom,sm8550-lpass-wsa-macro + then: + properties: + clocks: + minItems: 4 + maxItems: 4 + clock-names: + items: + - const: mclk + - const: macro + - const: dcodec + - const: fsgen + unevaluatedProperties: false examples: From 63e280a549140d0c162e5b958ddf02840bf35f0f Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 27 Mar 2023 15:22:54 +0200 Subject: [PATCH 630/778] ASoC: codecs: lpass-wsa-macro: add support for SM8550 Add support for the WSA macro codec on Qualcomm SM8550. SM8550 does not use NPL clock, thus add flags allowing to skip it. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20230327132254.147975-11-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/lpass-wsa-macro.c | 37 +++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/sound/soc/codecs/lpass-wsa-macro.c b/sound/soc/codecs/lpass-wsa-macro.c index 728f26d12ab0..3cbcbfc219b2 100644 --- a/sound/soc/codecs/lpass-wsa-macro.c +++ b/sound/soc/codecs/lpass-wsa-macro.c @@ -14,6 +14,8 @@ #include #include #include + +#include "lpass-macro-common.h" #include "lpass-wsa-macro.h" #define CDC_WSA_CLK_RST_CTRL_MCLK_CONTROL (0x0000) @@ -2346,7 +2348,10 @@ static int wsa_macro_register_mclk_output(struct wsa_macro *wsa) struct clk_init_data init; int ret; - parent_clk_name = __clk_get_name(wsa->npl); + if (wsa->npl) + parent_clk_name = __clk_get_name(wsa->npl); + else + parent_clk_name = __clk_get_name(wsa->mclk); init.name = "mclk"; of_property_read_string(dev_of_node(dev), "clock-output-names", @@ -2379,9 +2384,12 @@ static int wsa_macro_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct wsa_macro *wsa; + kernel_ulong_t flags; void __iomem *base; int ret; + flags = (kernel_ulong_t)device_get_match_data(dev); + wsa = devm_kzalloc(dev, sizeof(*wsa), GFP_KERNEL); if (!wsa) return -ENOMEM; @@ -2398,9 +2406,11 @@ static int wsa_macro_probe(struct platform_device *pdev) if (IS_ERR(wsa->mclk)) return PTR_ERR(wsa->mclk); - wsa->npl = devm_clk_get(dev, "npl"); - if (IS_ERR(wsa->npl)) - return PTR_ERR(wsa->npl); + if (flags & LPASS_MACRO_FLAG_HAS_NPL_CLOCK) { + wsa->npl = devm_clk_get(dev, "npl"); + if (IS_ERR(wsa->npl)) + return PTR_ERR(wsa->npl); + } wsa->fsgen = devm_clk_get(dev, "fsgen"); if (IS_ERR(wsa->fsgen)) @@ -2551,10 +2561,21 @@ static const struct dev_pm_ops wsa_macro_pm_ops = { }; static const struct of_device_id wsa_macro_dt_match[] = { - {.compatible = "qcom,sc7280-lpass-wsa-macro"}, - {.compatible = "qcom,sm8250-lpass-wsa-macro"}, - {.compatible = "qcom,sm8450-lpass-wsa-macro"}, - {.compatible = "qcom,sc8280xp-lpass-wsa-macro" }, + { + .compatible = "qcom,sc7280-lpass-wsa-macro", + .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, + }, { + .compatible = "qcom,sm8250-lpass-wsa-macro", + .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, + }, { + .compatible = "qcom,sm8450-lpass-wsa-macro", + .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, + }, { + .compatible = "qcom,sm8550-lpass-wsa-macro", + }, { + .compatible = "qcom,sc8280xp-lpass-wsa-macro", + .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, + }, {} }; MODULE_DEVICE_TABLE(of, wsa_macro_dt_match); From e3720f92e0237921da537e47a0b24e27899203f8 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 29 Mar 2023 14:38:28 +0300 Subject: [PATCH 631/778] ASoC: SOF: avoid a NULL dereference with unsupported widgets If an IPC4 topology contains an unsupported widget, its .module_info field won't be set, then sof_ipc4_route_setup() will cause a kernel Oops trying to dereference it. Add a check for such cases. Cc: stable@vger.kernel.org # 6.2 Signed-off-by: Guennadi Liakhovetski Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230329113828.28562-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index a623707c8ffc..669b99a4f76e 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -1805,6 +1805,14 @@ static int sof_ipc4_route_setup(struct snd_sof_dev *sdev, struct snd_sof_route * u32 header, extension; int ret; + if (!src_fw_module || !sink_fw_module) { + /* The NULL module will print as "(efault)" */ + dev_err(sdev->dev, "source %s or sink %s widget weren't set up properly\n", + src_fw_module->man4_module_entry.name, + sink_fw_module->man4_module_entry.name); + return -ENODEV; + } + sroute->src_queue_id = sof_ipc4_get_queue_id(src_widget, sink_widget, SOF_PIN_TYPE_SOURCE); if (sroute->src_queue_id < 0) { From 892855d57c47c32f475e9efa36c1a3452cc19918 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 24 Mar 2023 09:43:56 +0800 Subject: [PATCH 632/778] ASoC: codecs: cs42l42-sdw: clear stream MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The API requires the stream info to be cleared when the argument is NULL. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Rander Wang Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20230324014408.1677505-2-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs42l42-sdw.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/sound/soc/codecs/cs42l42-sdw.c b/sound/soc/codecs/cs42l42-sdw.c index 7b539ee55499..eeab07c850f9 100644 --- a/sound/soc/codecs/cs42l42-sdw.c +++ b/sound/soc/codecs/cs42l42-sdw.c @@ -152,9 +152,6 @@ static int cs42l42_sdw_port_prep(struct sdw_slave *slave, static int cs42l42_sdw_dai_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, int direction) { - if (!sdw_stream) - return 0; - snd_soc_dai_dma_data_set(dai, direction, sdw_stream); return 0; From f3def177876450df07fab6f28ad24a70397dc94d Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 24 Mar 2023 09:43:57 +0800 Subject: [PATCH 633/778] ASoC: codecs: sdw-mockup: simplify set_stream MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using a dynamic allocation to store a single pointer is not very efficient/useful. Worse, the memory is released in the SoundWire stream.c file, but still accessed in the DAI shutdown, leading to kmemleak reports. And last the API requires the previous stream information to be cleared when the argument is NULL. Simplify the code to address all 3 problems. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Rander Wang Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20230324014408.1677505-3-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/sdw-mockup.c | 34 ++++++---------------------------- 1 file changed, 6 insertions(+), 28 deletions(-) diff --git a/sound/soc/codecs/sdw-mockup.c b/sound/soc/codecs/sdw-mockup.c index 62b02d764f09..5498ff027c58 100644 --- a/sound/soc/codecs/sdw-mockup.c +++ b/sound/soc/codecs/sdw-mockup.c @@ -23,10 +23,6 @@ struct sdw_mockup_priv { struct sdw_slave *slave; }; -struct sdw_stream_data { - struct sdw_stream_runtime *sdw_stream; -}; - static int sdw_mockup_component_probe(struct snd_soc_component *component) { return 0; @@ -45,19 +41,7 @@ static const struct snd_soc_component_driver snd_soc_sdw_mockup_component = { static int sdw_mockup_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, int direction) { - struct sdw_stream_data *stream; - - if (!sdw_stream) - return 0; - - stream = kzalloc(sizeof(*stream), GFP_KERNEL); - if (!stream) - return -ENOMEM; - - stream->sdw_stream = sdw_stream; - - /* Use tx_mask or rx_mask to configure stream tag and set dma_data */ - snd_soc_dai_dma_data_set(dai, direction, stream); + snd_soc_dai_dma_data_set(dai, direction, sdw_stream); return 0; } @@ -65,11 +49,7 @@ static int sdw_mockup_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, static void sdw_mockup_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct sdw_stream_data *stream; - - stream = snd_soc_dai_get_dma_data(dai, substream); snd_soc_dai_set_dma_data(dai, substream, NULL); - kfree(stream); } static int sdw_mockup_pcm_hw_params(struct snd_pcm_substream *substream, @@ -80,11 +60,10 @@ static int sdw_mockup_pcm_hw_params(struct snd_pcm_substream *substream, struct sdw_mockup_priv *sdw_mockup = snd_soc_component_get_drvdata(component); struct sdw_stream_config stream_config = {0}; struct sdw_port_config port_config = {0}; - struct sdw_stream_data *stream; + struct sdw_stream_runtime *sdw_stream = snd_soc_dai_get_dma_data(dai, substream); int ret; - stream = snd_soc_dai_get_dma_data(dai, substream); - if (!stream) + if (!sdw_stream) return -EINVAL; if (!sdw_mockup->slave) @@ -99,7 +78,7 @@ static int sdw_mockup_pcm_hw_params(struct snd_pcm_substream *substream, port_config.num = 8; ret = sdw_stream_add_slave(sdw_mockup->slave, &stream_config, - &port_config, 1, stream->sdw_stream); + &port_config, 1, sdw_stream); if (ret) dev_err(dai->dev, "Unable to configure port\n"); @@ -111,13 +90,12 @@ static int sdw_mockup_pcm_hw_free(struct snd_pcm_substream *substream, { struct snd_soc_component *component = dai->component; struct sdw_mockup_priv *sdw_mockup = snd_soc_component_get_drvdata(component); - struct sdw_stream_data *stream = - snd_soc_dai_get_dma_data(dai, substream); + struct sdw_stream_runtime *sdw_stream = snd_soc_dai_get_dma_data(dai, substream); if (!sdw_mockup->slave) return -EINVAL; - sdw_stream_remove_slave(sdw_mockup->slave, stream->sdw_stream); + sdw_stream_remove_slave(sdw_mockup->slave, sdw_stream); return 0; } From 658d6f7381b1be5a6fec7d90c865fb593b8c78b6 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 24 Mar 2023 09:43:58 +0800 Subject: [PATCH 634/778] ASoC: codecs: max98373-sdw: simplify set_stream MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using a dynamic allocation to store a single pointer is not very efficient/useful. Worse, the memory is released in the SoundWire stream.c file, but still accessed in the DAI shutdown, leading to kmemleak reports. And last the API requires the previous stream information to be cleared when the argument is NULL. Simplify the code to address all 3 problems. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Rander Wang Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20230324014408.1677505-4-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/max98373-sdw.c | 34 +++++++-------------------------- 1 file changed, 7 insertions(+), 27 deletions(-) diff --git a/sound/soc/codecs/max98373-sdw.c b/sound/soc/codecs/max98373-sdw.c index c9a2d4dabd3c..df92242af960 100644 --- a/sound/soc/codecs/max98373-sdw.c +++ b/sound/soc/codecs/max98373-sdw.c @@ -20,10 +20,6 @@ #include "max98373.h" #include "max98373-sdw.h" -struct sdw_stream_data { - struct sdw_stream_runtime *sdw_stream; -}; - static const u32 max98373_sdw_cache_reg[] = { MAX98373_R2054_MEAS_ADC_PVDD_CH_READBACK, MAX98373_R2055_MEAS_ADC_THERM_CH_READBACK, @@ -536,12 +532,12 @@ static int max98373_sdw_dai_hw_params(struct snd_pcm_substream *substream, snd_soc_component_get_drvdata(component); struct sdw_stream_config stream_config = {0}; struct sdw_port_config port_config = {0}; - struct sdw_stream_data *stream; + struct sdw_stream_runtime *sdw_stream; int ret, chan_sz, sampling_rate; - stream = snd_soc_dai_get_dma_data(dai, substream); + sdw_stream = snd_soc_dai_get_dma_data(dai, substream); - if (!stream) + if (!sdw_stream) return -EINVAL; if (!max98373->slave) @@ -565,7 +561,7 @@ static int max98373_sdw_dai_hw_params(struct snd_pcm_substream *substream, } ret = sdw_stream_add_slave(max98373->slave, &stream_config, - &port_config, 1, stream->sdw_stream); + &port_config, 1, sdw_stream); if (ret) { dev_err(dai->dev, "Unable to configure port\n"); return ret; @@ -664,32 +660,20 @@ static int max98373_pcm_hw_free(struct snd_pcm_substream *substream, struct snd_soc_component *component = dai->component; struct max98373_priv *max98373 = snd_soc_component_get_drvdata(component); - struct sdw_stream_data *stream = + struct sdw_stream_runtime *sdw_stream = snd_soc_dai_get_dma_data(dai, substream); if (!max98373->slave) return -EINVAL; - sdw_stream_remove_slave(max98373->slave, stream->sdw_stream); + sdw_stream_remove_slave(max98373->slave, sdw_stream); return 0; } static int max98373_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, int direction) { - struct sdw_stream_data *stream; - - if (!sdw_stream) - return 0; - - stream = kzalloc(sizeof(*stream), GFP_KERNEL); - if (!stream) - return -ENOMEM; - - stream->sdw_stream = sdw_stream; - - /* Use tx_mask or rx_mask to configure stream tag and set dma_data */ - snd_soc_dai_dma_data_set(dai, direction, stream); + snd_soc_dai_dma_data_set(dai, direction, sdw_stream); return 0; } @@ -697,11 +681,7 @@ static int max98373_set_sdw_stream(struct snd_soc_dai *dai, static void max98373_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct sdw_stream_data *stream; - - stream = snd_soc_dai_get_dma_data(dai, substream); snd_soc_dai_set_dma_data(dai, substream, NULL); - kfree(stream); } static int max98373_sdw_set_tdm_slot(struct snd_soc_dai *dai, From ce8ffc1bac7bee5015eb68faf214b39fcbd65d15 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 24 Mar 2023 09:43:59 +0800 Subject: [PATCH 635/778] ASoC: codecs: rt1308-sdw: simplify set_stream MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using a dynamic allocation to store a single pointer is not very efficient/useful. Worse, the memory is released in the SoundWire stream.c file, but still accessed in the DAI shutdown, leading to kmemleak reports. And last the API requires the previous stream information to be cleared when the argument is NULL. Simplify the code to address all 3 problems. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Rander Wang Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20230324014408.1677505-5-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1308-sdw.c | 30 +++++++----------------------- sound/soc/codecs/rt1308-sdw.h | 4 ---- 2 files changed, 7 insertions(+), 27 deletions(-) diff --git a/sound/soc/codecs/rt1308-sdw.c b/sound/soc/codecs/rt1308-sdw.c index 45544b530d3d..1797af824f60 100644 --- a/sound/soc/codecs/rt1308-sdw.c +++ b/sound/soc/codecs/rt1308-sdw.c @@ -496,19 +496,7 @@ static const struct snd_soc_dapm_route rt1308_dapm_routes[] = { static int rt1308_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, int direction) { - struct sdw_stream_data *stream; - - if (!sdw_stream) - return 0; - - stream = kzalloc(sizeof(*stream), GFP_KERNEL); - if (!stream) - return -ENOMEM; - - stream->sdw_stream = sdw_stream; - - /* Use tx_mask or rx_mask to configure stream tag and set dma_data */ - snd_soc_dai_dma_data_set(dai, direction, stream); + snd_soc_dai_dma_data_set(dai, direction, sdw_stream); return 0; } @@ -516,11 +504,7 @@ static int rt1308_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, static void rt1308_sdw_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct sdw_stream_data *stream; - - stream = snd_soc_dai_get_dma_data(dai, substream); snd_soc_dai_set_dma_data(dai, substream, NULL); - kfree(stream); } static int rt1308_sdw_set_tdm_slot(struct snd_soc_dai *dai, @@ -553,13 +537,13 @@ static int rt1308_sdw_hw_params(struct snd_pcm_substream *substream, snd_soc_component_get_drvdata(component); struct sdw_stream_config stream_config = {0}; struct sdw_port_config port_config = {0}; - struct sdw_stream_data *stream; + struct sdw_stream_runtime *sdw_stream; int retval; dev_dbg(dai->dev, "%s %s", __func__, dai->name); - stream = snd_soc_dai_get_dma_data(dai, substream); + sdw_stream = snd_soc_dai_get_dma_data(dai, substream); - if (!stream) + if (!sdw_stream) return -EINVAL; if (!rt1308->sdw_slave) @@ -580,7 +564,7 @@ static int rt1308_sdw_hw_params(struct snd_pcm_substream *substream, } retval = sdw_stream_add_slave(rt1308->sdw_slave, &stream_config, - &port_config, 1, stream->sdw_stream); + &port_config, 1, sdw_stream); if (retval) { dev_err(dai->dev, "Unable to configure port\n"); return retval; @@ -595,13 +579,13 @@ static int rt1308_sdw_pcm_hw_free(struct snd_pcm_substream *substream, struct snd_soc_component *component = dai->component; struct rt1308_sdw_priv *rt1308 = snd_soc_component_get_drvdata(component); - struct sdw_stream_data *stream = + struct sdw_stream_runtime *sdw_stream = snd_soc_dai_get_dma_data(dai, substream); if (!rt1308->sdw_slave) return -EINVAL; - sdw_stream_remove_slave(rt1308->sdw_slave, stream->sdw_stream); + sdw_stream_remove_slave(rt1308->sdw_slave, sdw_stream); return 0; } diff --git a/sound/soc/codecs/rt1308-sdw.h b/sound/soc/codecs/rt1308-sdw.h index 1eaaef9f351b..04ff18fa18e2 100644 --- a/sound/soc/codecs/rt1308-sdw.h +++ b/sound/soc/codecs/rt1308-sdw.h @@ -170,8 +170,4 @@ struct rt1308_sdw_priv { unsigned int bq_params_cnt; }; -struct sdw_stream_data { - struct sdw_stream_runtime *sdw_stream; -}; - #endif /* __RT1308_SDW_H__ */ From 1294d7d71f6abad6299a12cf6911f8e5622c7865 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 24 Mar 2023 09:44:00 +0800 Subject: [PATCH 636/778] ASoC: codecs: rt1316-sdw: simplify set_stream MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using a dynamic allocation to store a single pointer is not very efficient/useful. Worse, the memory is released in the SoundWire stream.c file, but still accessed in the DAI shutdown, leading to kmemleak reports. And last the API requires the previous stream information to be cleared when the argument is NULL. Simplify the code to address all 3 problems. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Rander Wang Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20230324014408.1677505-6-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1316-sdw.c | 30 +++++++----------------------- sound/soc/codecs/rt1316-sdw.h | 4 ---- 2 files changed, 7 insertions(+), 27 deletions(-) diff --git a/sound/soc/codecs/rt1316-sdw.c b/sound/soc/codecs/rt1316-sdw.c index b45121ee7533..2ee5e763e345 100644 --- a/sound/soc/codecs/rt1316-sdw.c +++ b/sound/soc/codecs/rt1316-sdw.c @@ -494,19 +494,7 @@ static const struct snd_soc_dapm_route rt1316_dapm_routes[] = { static int rt1316_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, int direction) { - struct sdw_stream_data *stream; - - if (!sdw_stream) - return 0; - - stream = kzalloc(sizeof(*stream), GFP_KERNEL); - if (!stream) - return -ENOMEM; - - stream->sdw_stream = sdw_stream; - - /* Use tx_mask or rx_mask to configure stream tag and set dma_data */ - snd_soc_dai_dma_data_set(dai, direction, stream); + snd_soc_dai_dma_data_set(dai, direction, sdw_stream); return 0; } @@ -514,11 +502,7 @@ static int rt1316_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, static void rt1316_sdw_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct sdw_stream_data *stream; - - stream = snd_soc_dai_get_dma_data(dai, substream); snd_soc_dai_set_dma_data(dai, substream, NULL); - kfree(stream); } static int rt1316_sdw_hw_params(struct snd_pcm_substream *substream, @@ -529,13 +513,13 @@ static int rt1316_sdw_hw_params(struct snd_pcm_substream *substream, snd_soc_component_get_drvdata(component); struct sdw_stream_config stream_config = {0}; struct sdw_port_config port_config = {0}; - struct sdw_stream_data *stream; + struct sdw_stream_runtime *sdw_stream; int retval; dev_dbg(dai->dev, "%s %s", __func__, dai->name); - stream = snd_soc_dai_get_dma_data(dai, substream); + sdw_stream = snd_soc_dai_get_dma_data(dai, substream); - if (!stream) + if (!sdw_stream) return -EINVAL; if (!rt1316->sdw_slave) @@ -551,7 +535,7 @@ static int rt1316_sdw_hw_params(struct snd_pcm_substream *substream, port_config.num = 2; retval = sdw_stream_add_slave(rt1316->sdw_slave, &stream_config, - &port_config, 1, stream->sdw_stream); + &port_config, 1, sdw_stream); if (retval) { dev_err(dai->dev, "Unable to configure port\n"); return retval; @@ -566,13 +550,13 @@ static int rt1316_sdw_pcm_hw_free(struct snd_pcm_substream *substream, struct snd_soc_component *component = dai->component; struct rt1316_sdw_priv *rt1316 = snd_soc_component_get_drvdata(component); - struct sdw_stream_data *stream = + struct sdw_stream_runtime *sdw_stream = snd_soc_dai_get_dma_data(dai, substream); if (!rt1316->sdw_slave) return -EINVAL; - sdw_stream_remove_slave(rt1316->sdw_slave, stream->sdw_stream); + sdw_stream_remove_slave(rt1316->sdw_slave, sdw_stream); return 0; } diff --git a/sound/soc/codecs/rt1316-sdw.h b/sound/soc/codecs/rt1316-sdw.h index 57dbd49993b0..e37121655bc1 100644 --- a/sound/soc/codecs/rt1316-sdw.h +++ b/sound/soc/codecs/rt1316-sdw.h @@ -50,8 +50,4 @@ struct rt1316_sdw_priv { unsigned int bq_params_cnt; }; -struct sdw_stream_data { - struct sdw_stream_runtime *sdw_stream; -}; - #endif /* __RT1316_SDW_H__ */ From be8e5a850eb1780bae360b9b48b6d2ab70e5fb03 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 24 Mar 2023 09:44:01 +0800 Subject: [PATCH 637/778] ASoC: codecs: rt1318-sdw: simplify set_stream MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using a dynamic allocation to store a single pointer is not very efficient/useful. Worse, the memory is released in the SoundWire stream.c file, but still accessed in the DAI shutdown, leading to kmemleak reports. And last the API requires the previous stream information to be cleared when the argument is NULL. Simplify the code to address all 3 problems. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Rander Wang Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20230324014408.1677505-7-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1318-sdw.c | 30 +++++++----------------------- sound/soc/codecs/rt1318-sdw.h | 4 ---- 2 files changed, 7 insertions(+), 27 deletions(-) diff --git a/sound/soc/codecs/rt1318-sdw.c b/sound/soc/codecs/rt1318-sdw.c index c32d8ae77981..795accedc22c 100644 --- a/sound/soc/codecs/rt1318-sdw.c +++ b/sound/soc/codecs/rt1318-sdw.c @@ -562,19 +562,7 @@ static const struct snd_soc_dapm_route rt1318_dapm_routes[] = { static int rt1318_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, int direction) { - struct sdw_stream_data *stream; - - if (!sdw_stream) - return 0; - - stream = kzalloc(sizeof(*stream), GFP_KERNEL); - if (!stream) - return -ENOMEM; - - stream->sdw_stream = sdw_stream; - - /* Use tx_mask or rx_mask to configure stream tag and set dma_data */ - snd_soc_dai_dma_data_set(dai, direction, stream); + snd_soc_dai_dma_data_set(dai, direction, sdw_stream); return 0; } @@ -582,11 +570,7 @@ static int rt1318_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, static void rt1318_sdw_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct sdw_stream_data *stream; - - stream = snd_soc_dai_get_dma_data(dai, substream); snd_soc_dai_set_dma_data(dai, substream, NULL); - kfree(stream); } static int rt1318_sdw_hw_params(struct snd_pcm_substream *substream, @@ -598,14 +582,14 @@ static int rt1318_sdw_hw_params(struct snd_pcm_substream *substream, struct sdw_stream_config stream_config; struct sdw_port_config port_config; enum sdw_data_direction direction; - struct sdw_stream_data *stream; + struct sdw_stream_runtime *sdw_stream; int retval, port, num_channels, ch_mask; unsigned int sampling_rate; dev_dbg(dai->dev, "%s %s", __func__, dai->name); - stream = snd_soc_dai_get_dma_data(dai, substream); + sdw_stream = snd_soc_dai_get_dma_data(dai, substream); - if (!stream) + if (!sdw_stream) return -EINVAL; if (!rt1318->sdw_slave) @@ -633,7 +617,7 @@ static int rt1318_sdw_hw_params(struct snd_pcm_substream *substream, port_config.num = port; retval = sdw_stream_add_slave(rt1318->sdw_slave, &stream_config, - &port_config, 1, stream->sdw_stream); + &port_config, 1, sdw_stream); if (retval) { dev_err(dai->dev, "Unable to configure port\n"); return retval; @@ -679,13 +663,13 @@ static int rt1318_sdw_pcm_hw_free(struct snd_pcm_substream *substream, struct snd_soc_component *component = dai->component; struct rt1318_sdw_priv *rt1318 = snd_soc_component_get_drvdata(component); - struct sdw_stream_data *stream = + struct sdw_stream_runtime *sdw_stream = snd_soc_dai_get_dma_data(dai, substream); if (!rt1318->sdw_slave) return -EINVAL; - sdw_stream_remove_slave(rt1318->sdw_slave, stream->sdw_stream); + sdw_stream_remove_slave(rt1318->sdw_slave, sdw_stream); return 0; } diff --git a/sound/soc/codecs/rt1318-sdw.h b/sound/soc/codecs/rt1318-sdw.h index 4d7ac9c4bd8d..85918c184f16 100644 --- a/sound/soc/codecs/rt1318-sdw.h +++ b/sound/soc/codecs/rt1318-sdw.h @@ -94,8 +94,4 @@ struct rt1318_sdw_priv { bool first_hw_init; }; -struct sdw_stream_data { - struct sdw_stream_runtime *sdw_stream; -}; - #endif /* __RT1318_SDW_H__ */ From 3bcced019eb266e91b7eecc1f8fd3da5f55ca4cd Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 24 Mar 2023 09:44:02 +0800 Subject: [PATCH 638/778] ASoC: codecs: rt700-sdw: simplify set_stream MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using a dynamic allocation to store a single pointer is not very efficient/useful. Worse, the memory is released in the SoundWire stream.c file, but still accessed in the DAI shutdown, leading to kmemleak reports. And last the API requires the previous stream information to be cleared when the argument is NULL. Simplify the code to address all 3 problems. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Rander Wang Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20230324014408.1677505-8-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt700.c | 30 +++++++----------------------- sound/soc/codecs/rt700.h | 4 ---- 2 files changed, 7 insertions(+), 27 deletions(-) diff --git a/sound/soc/codecs/rt700.c b/sound/soc/codecs/rt700.c index 659ce26e9f3b..a04b9246256b 100644 --- a/sound/soc/codecs/rt700.c +++ b/sound/soc/codecs/rt700.c @@ -875,19 +875,7 @@ static const struct snd_soc_component_driver soc_codec_dev_rt700 = { static int rt700_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, int direction) { - struct sdw_stream_data *stream; - - if (!sdw_stream) - return 0; - - stream = kzalloc(sizeof(*stream), GFP_KERNEL); - if (!stream) - return -ENOMEM; - - stream->sdw_stream = sdw_stream; - - /* Use tx_mask or rx_mask to configure stream tag and set dma_data */ - snd_soc_dai_dma_data_set(dai, direction, stream); + snd_soc_dai_dma_data_set(dai, direction, sdw_stream); return 0; } @@ -895,11 +883,7 @@ static int rt700_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, static void rt700_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct sdw_stream_data *stream; - - stream = snd_soc_dai_get_dma_data(dai, substream); snd_soc_dai_set_dma_data(dai, substream, NULL); - kfree(stream); } static int rt700_pcm_hw_params(struct snd_pcm_substream *substream, @@ -910,14 +894,14 @@ static int rt700_pcm_hw_params(struct snd_pcm_substream *substream, struct rt700_priv *rt700 = snd_soc_component_get_drvdata(component); struct sdw_stream_config stream_config = {0}; struct sdw_port_config port_config = {0}; - struct sdw_stream_data *stream; + struct sdw_stream_runtime *sdw_stream; int retval; unsigned int val = 0; dev_dbg(dai->dev, "%s %s", __func__, dai->name); - stream = snd_soc_dai_get_dma_data(dai, substream); + sdw_stream = snd_soc_dai_get_dma_data(dai, substream); - if (!stream) + if (!sdw_stream) return -EINVAL; if (!rt700->slave) @@ -944,7 +928,7 @@ static int rt700_pcm_hw_params(struct snd_pcm_substream *substream, } retval = sdw_stream_add_slave(rt700->slave, &stream_config, - &port_config, 1, stream->sdw_stream); + &port_config, 1, sdw_stream); if (retval) { dev_err(dai->dev, "Unable to configure port\n"); return retval; @@ -991,13 +975,13 @@ static int rt700_pcm_hw_free(struct snd_pcm_substream *substream, { struct snd_soc_component *component = dai->component; struct rt700_priv *rt700 = snd_soc_component_get_drvdata(component); - struct sdw_stream_data *stream = + struct sdw_stream_runtime *sdw_stream = snd_soc_dai_get_dma_data(dai, substream); if (!rt700->slave) return -EINVAL; - sdw_stream_remove_slave(rt700->slave, stream->sdw_stream); + sdw_stream_remove_slave(rt700->slave, sdw_stream); return 0; } diff --git a/sound/soc/codecs/rt700.h b/sound/soc/codecs/rt700.h index bed9d1de6d5b..93c44005d38c 100644 --- a/sound/soc/codecs/rt700.h +++ b/sound/soc/codecs/rt700.h @@ -27,10 +27,6 @@ struct rt700_priv { bool disable_irq; }; -struct sdw_stream_data { - struct sdw_stream_runtime *sdw_stream; -}; - /* NID */ #define RT700_AUDIO_FUNCTION_GROUP 0x01 #define RT700_DAC_OUT1 0x02 From fa55b31fb65347ceab617af7541f0a31b53901f1 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 24 Mar 2023 09:44:03 +0800 Subject: [PATCH 639/778] ASoC: codecs: rt711-sdw: simplify set_stream MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using a dynamic allocation to store a single pointer is not very efficient/useful. Worse, the memory is released in the SoundWire stream.c file, but still accessed in the DAI shutdown, leading to kmemleak reports. And last the API requires the previous stream information to be cleared when the argument is NULL. Simplify the code to address all 3 problems. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Rander Wang Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20230324014408.1677505-9-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt711.c | 30 +++++++----------------------- sound/soc/codecs/rt711.h | 4 ---- 2 files changed, 7 insertions(+), 27 deletions(-) diff --git a/sound/soc/codecs/rt711.c b/sound/soc/codecs/rt711.c index 862f50950565..af53cbcc7bf2 100644 --- a/sound/soc/codecs/rt711.c +++ b/sound/soc/codecs/rt711.c @@ -964,19 +964,7 @@ static const struct snd_soc_component_driver soc_codec_dev_rt711 = { static int rt711_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, int direction) { - struct sdw_stream_data *stream; - - if (!sdw_stream) - return 0; - - stream = kzalloc(sizeof(*stream), GFP_KERNEL); - if (!stream) - return -ENOMEM; - - stream->sdw_stream = sdw_stream; - - /* Use tx_mask or rx_mask to configure stream tag and set dma_data */ - snd_soc_dai_dma_data_set(dai, direction, stream); + snd_soc_dai_dma_data_set(dai, direction, sdw_stream); return 0; } @@ -984,11 +972,7 @@ static int rt711_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, static void rt711_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct sdw_stream_data *stream; - - stream = snd_soc_dai_get_dma_data(dai, substream); snd_soc_dai_set_dma_data(dai, substream, NULL); - kfree(stream); } static int rt711_pcm_hw_params(struct snd_pcm_substream *substream, @@ -999,14 +983,14 @@ static int rt711_pcm_hw_params(struct snd_pcm_substream *substream, struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component); struct sdw_stream_config stream_config = {0}; struct sdw_port_config port_config = {0}; - struct sdw_stream_data *stream; + struct sdw_stream_runtime *sdw_stream; int retval; unsigned int val = 0; dev_dbg(dai->dev, "%s %s", __func__, dai->name); - stream = snd_soc_dai_get_dma_data(dai, substream); + sdw_stream = snd_soc_dai_get_dma_data(dai, substream); - if (!stream) + if (!sdw_stream) return -EINVAL; if (!rt711->slave) @@ -1027,7 +1011,7 @@ static int rt711_pcm_hw_params(struct snd_pcm_substream *substream, } retval = sdw_stream_add_slave(rt711->slave, &stream_config, - &port_config, 1, stream->sdw_stream); + &port_config, 1, sdw_stream); if (retval) { dev_err(dai->dev, "Unable to configure port\n"); return retval; @@ -1075,13 +1059,13 @@ static int rt711_pcm_hw_free(struct snd_pcm_substream *substream, { struct snd_soc_component *component = dai->component; struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component); - struct sdw_stream_data *stream = + struct sdw_stream_runtime *sdw_stream = snd_soc_dai_get_dma_data(dai, substream); if (!rt711->slave) return -EINVAL; - sdw_stream_remove_slave(rt711->slave, stream->sdw_stream); + sdw_stream_remove_slave(rt711->slave, sdw_stream); return 0; } diff --git a/sound/soc/codecs/rt711.h b/sound/soc/codecs/rt711.h index f50f8c8d0934..b31351f11df9 100644 --- a/sound/soc/codecs/rt711.h +++ b/sound/soc/codecs/rt711.h @@ -29,10 +29,6 @@ struct rt711_priv { bool disable_irq; }; -struct sdw_stream_data { - struct sdw_stream_runtime *sdw_stream; -}; - /* NID */ #define RT711_AUDIO_FUNCTION_GROUP 0x01 #define RT711_DAC_OUT2 0x03 From b2790eccc0bc755d37ed5cd8d225cec0d72798c8 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 24 Mar 2023 09:44:04 +0800 Subject: [PATCH 640/778] ASoC: codecs: rt711-sdca: simplify set_stream MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using a dynamic allocation to store a single pointer is not very efficient/useful. Worse, the memory is released in the SoundWire stream.c file, but still accessed in the DAI shutdown, leading to kmemleak reports. And last the API requires the previous stream information to be cleared when the argument is NULL. Simplify the code to address all 3 problems. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Rander Wang Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20230324014408.1677505-10-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt711-sdca.c | 30 +++++++----------------------- sound/soc/codecs/rt711-sdca.h | 4 ---- 2 files changed, 7 insertions(+), 27 deletions(-) diff --git a/sound/soc/codecs/rt711-sdca.c b/sound/soc/codecs/rt711-sdca.c index c65abe812a4c..07640d2f6e56 100644 --- a/sound/soc/codecs/rt711-sdca.c +++ b/sound/soc/codecs/rt711-sdca.c @@ -1237,19 +1237,7 @@ static const struct snd_soc_component_driver soc_sdca_dev_rt711 = { static int rt711_sdca_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, int direction) { - struct sdw_stream_data *stream; - - if (!sdw_stream) - return 0; - - stream = kzalloc(sizeof(*stream), GFP_KERNEL); - if (!stream) - return -ENOMEM; - - stream->sdw_stream = sdw_stream; - - /* Use tx_mask or rx_mask to configure stream tag and set dma_data */ - snd_soc_dai_dma_data_set(dai, direction, stream); + snd_soc_dai_dma_data_set(dai, direction, sdw_stream); return 0; } @@ -1257,11 +1245,7 @@ static int rt711_sdca_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, static void rt711_sdca_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct sdw_stream_data *stream; - - stream = snd_soc_dai_get_dma_data(dai, substream); snd_soc_dai_set_dma_data(dai, substream, NULL); - kfree(stream); } static int rt711_sdca_pcm_hw_params(struct snd_pcm_substream *substream, @@ -1272,14 +1256,14 @@ static int rt711_sdca_pcm_hw_params(struct snd_pcm_substream *substream, struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); struct sdw_stream_config stream_config = {0}; struct sdw_port_config port_config = {0}; - struct sdw_stream_data *stream; + struct sdw_stream_runtime *sdw_stream; int retval; unsigned int sampling_rate; dev_dbg(dai->dev, "%s %s", __func__, dai->name); - stream = snd_soc_dai_get_dma_data(dai, substream); + sdw_stream = snd_soc_dai_get_dma_data(dai, substream); - if (!stream) + if (!sdw_stream) return -EINVAL; if (!rt711->slave) @@ -1300,7 +1284,7 @@ static int rt711_sdca_pcm_hw_params(struct snd_pcm_substream *substream, } retval = sdw_stream_add_slave(rt711->slave, &stream_config, - &port_config, 1, stream->sdw_stream); + &port_config, 1, sdw_stream); if (retval) { dev_err(dai->dev, "Unable to configure port\n"); return retval; @@ -1351,13 +1335,13 @@ static int rt711_sdca_pcm_hw_free(struct snd_pcm_substream *substream, { struct snd_soc_component *component = dai->component; struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); - struct sdw_stream_data *stream = + struct sdw_stream_runtime *sdw_stream = snd_soc_dai_get_dma_data(dai, substream); if (!rt711->slave) return -EINVAL; - sdw_stream_remove_slave(rt711->slave, stream->sdw_stream); + sdw_stream_remove_slave(rt711->slave, sdw_stream); return 0; } diff --git a/sound/soc/codecs/rt711-sdca.h b/sound/soc/codecs/rt711-sdca.h index 10e3c801b813..22076f268577 100644 --- a/sound/soc/codecs/rt711-sdca.h +++ b/sound/soc/codecs/rt711-sdca.h @@ -36,10 +36,6 @@ struct rt711_sdca_priv { bool fu1e_dapm_mute, fu1e_mixer_l_mute, fu1e_mixer_r_mute; }; -struct sdw_stream_data { - struct sdw_stream_runtime *sdw_stream; -}; - /* NID */ #define RT711_AUDIO_FUNCTION_GROUP 0x01 #define RT711_DAC_OUT2 0x03 From 278432084b093f7257cf96c75bb33f155e4a8232 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 24 Mar 2023 09:44:05 +0800 Subject: [PATCH 641/778] ASoC: codecs: rt712-sdca: simplify set_stream MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using a dynamic allocation to store a single pointer is not very efficient/useful. Worse, the memory is released in the SoundWire stream.c file, but still accessed in the DAI shutdown, leading to kmemleak reports. And last the API requires the previous stream information to be cleared when the argument is NULL. Simplify the code to address all 3 problems. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Rander Wang Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20230324014408.1677505-11-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt712-sdca.c | 30 +++++++----------------------- sound/soc/codecs/rt712-sdca.h | 4 ---- 2 files changed, 7 insertions(+), 27 deletions(-) diff --git a/sound/soc/codecs/rt712-sdca.c b/sound/soc/codecs/rt712-sdca.c index 8d2fa769bb2e..89d245655ca4 100644 --- a/sound/soc/codecs/rt712-sdca.c +++ b/sound/soc/codecs/rt712-sdca.c @@ -992,19 +992,7 @@ static const struct snd_soc_component_driver soc_sdca_dev_rt712 = { static int rt712_sdca_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, int direction) { - struct sdw_stream_data *stream; - - if (!sdw_stream) - return 0; - - stream = kzalloc(sizeof(*stream), GFP_KERNEL); - if (!stream) - return -ENOMEM; - - stream->sdw_stream = sdw_stream; - - /* Use tx_mask or rx_mask to configure stream tag and set dma_data */ - snd_soc_dai_dma_data_set(dai, direction, stream); + snd_soc_dai_dma_data_set(dai, direction, sdw_stream); return 0; } @@ -1012,11 +1000,7 @@ static int rt712_sdca_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, static void rt712_sdca_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct sdw_stream_data *stream; - - stream = snd_soc_dai_get_dma_data(dai, substream); snd_soc_dai_set_dma_data(dai, substream, NULL); - kfree(stream); } static int rt712_sdca_pcm_hw_params(struct snd_pcm_substream *substream, @@ -1028,14 +1012,14 @@ static int rt712_sdca_pcm_hw_params(struct snd_pcm_substream *substream, struct sdw_stream_config stream_config; struct sdw_port_config port_config; enum sdw_data_direction direction; - struct sdw_stream_data *stream; + struct sdw_stream_runtime *sdw_stream; int retval, port, num_channels; unsigned int sampling_rate; dev_dbg(dai->dev, "%s %s", __func__, dai->name); - stream = snd_soc_dai_get_dma_data(dai, substream); + sdw_stream = snd_soc_dai_get_dma_data(dai, substream); - if (!stream) + if (!sdw_stream) return -EINVAL; if (!rt712->slave) @@ -1068,7 +1052,7 @@ static int rt712_sdca_pcm_hw_params(struct snd_pcm_substream *substream, port_config.num = port; retval = sdw_stream_add_slave(rt712->slave, &stream_config, - &port_config, 1, stream->sdw_stream); + &port_config, 1, sdw_stream); if (retval) { dev_err(dai->dev, "Unable to configure port\n"); return retval; @@ -1128,13 +1112,13 @@ static int rt712_sdca_pcm_hw_free(struct snd_pcm_substream *substream, { struct snd_soc_component *component = dai->component; struct rt712_sdca_priv *rt712 = snd_soc_component_get_drvdata(component); - struct sdw_stream_data *stream = + struct sdw_stream_runtime *sdw_stream = snd_soc_dai_get_dma_data(dai, substream); if (!rt712->slave) return -EINVAL; - sdw_stream_remove_slave(rt712->slave, stream->sdw_stream); + sdw_stream_remove_slave(rt712->slave, sdw_stream); return 0; } diff --git a/sound/soc/codecs/rt712-sdca.h b/sound/soc/codecs/rt712-sdca.h index cf647162f9da..c6a94a23f46e 100644 --- a/sound/soc/codecs/rt712-sdca.h +++ b/sound/soc/codecs/rt712-sdca.h @@ -40,10 +40,6 @@ struct rt712_sdca_priv { bool fu0f_mixer_r_mute; }; -struct sdw_stream_data { - struct sdw_stream_runtime *sdw_stream; -}; - /* NID */ #define RT712_VENDOR_REG 0x20 #define RT712_VENDOR_CALI 0x58 From e506b2bd1d2e9daaedd1db2ef9868f7b8c4c86c3 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 24 Mar 2023 09:44:06 +0800 Subject: [PATCH 642/778] ASoC: codecs: rt715: simplify set_stream MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using a dynamic allocation to store a single pointer is not very efficient/useful. Worse, the memory is released in the SoundWire stream.c file, but still accessed in the DAI shutdown, leading to kmemleak reports. And last the API requires the previous stream information to be cleared when the argument is NULL. Simplify the code to address all 3 problems. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Rander Wang Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20230324014408.1677505-12-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt715.c | 30 +++++++----------------------- sound/soc/codecs/rt715.h | 4 ---- 2 files changed, 7 insertions(+), 27 deletions(-) diff --git a/sound/soc/codecs/rt715.c b/sound/soc/codecs/rt715.c index c6dd9df7be45..6c2e165dd621 100644 --- a/sound/soc/codecs/rt715.c +++ b/sound/soc/codecs/rt715.c @@ -765,19 +765,7 @@ static int rt715_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, int direction) { - struct sdw_stream_data *stream; - - if (!sdw_stream) - return 0; - - stream = kzalloc(sizeof(*stream), GFP_KERNEL); - if (!stream) - return -ENOMEM; - - stream->sdw_stream = sdw_stream; - - /* Use tx_mask or rx_mask to configure stream tag and set dma_data */ - snd_soc_dai_dma_data_set(dai, direction, stream); + snd_soc_dai_dma_data_set(dai, direction, sdw_stream); return 0; } @@ -786,11 +774,7 @@ static void rt715_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct sdw_stream_data *stream; - - stream = snd_soc_dai_get_dma_data(dai, substream); snd_soc_dai_set_dma_data(dai, substream, NULL); - kfree(stream); } static int rt715_pcm_hw_params(struct snd_pcm_substream *substream, @@ -801,13 +785,13 @@ static int rt715_pcm_hw_params(struct snd_pcm_substream *substream, struct rt715_priv *rt715 = snd_soc_component_get_drvdata(component); struct sdw_stream_config stream_config = {0}; struct sdw_port_config port_config = {0}; - struct sdw_stream_data *stream; + struct sdw_stream_runtime *sdw_stream; int retval; unsigned int val = 0; - stream = snd_soc_dai_get_dma_data(dai, substream); + sdw_stream = snd_soc_dai_get_dma_data(dai, substream); - if (!stream) + if (!sdw_stream) return -EINVAL; if (!rt715->slave) @@ -830,7 +814,7 @@ static int rt715_pcm_hw_params(struct snd_pcm_substream *substream, } retval = sdw_stream_add_slave(rt715->slave, &stream_config, - &port_config, 1, stream->sdw_stream); + &port_config, 1, sdw_stream); if (retval) { dev_err(dai->dev, "Unable to configure port\n"); return retval; @@ -893,13 +877,13 @@ static int rt715_pcm_hw_free(struct snd_pcm_substream *substream, { struct snd_soc_component *component = dai->component; struct rt715_priv *rt715 = snd_soc_component_get_drvdata(component); - struct sdw_stream_data *stream = + struct sdw_stream_runtime *sdw_stream = snd_soc_dai_get_dma_data(dai, substream); if (!rt715->slave) return -EINVAL; - sdw_stream_remove_slave(rt715->slave, stream->sdw_stream); + sdw_stream_remove_slave(rt715->slave, sdw_stream); return 0; } diff --git a/sound/soc/codecs/rt715.h b/sound/soc/codecs/rt715.h index 25dba61f1760..17a8d041c1c3 100644 --- a/sound/soc/codecs/rt715.h +++ b/sound/soc/codecs/rt715.h @@ -27,10 +27,6 @@ struct rt715_priv { unsigned int kctl_8ch_vol_ori[8]; }; -struct sdw_stream_data { - struct sdw_stream_runtime *sdw_stream; -}; - /* NID */ #define RT715_AUDIO_FUNCTION_GROUP 0x01 #define RT715_MIC_ADC 0x07 From cf1d6a3ad07c982a09455bf8720dc75754909932 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 24 Mar 2023 09:44:07 +0800 Subject: [PATCH 643/778] ASoC: codecs: rt715-sdca: simplify set_stream MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using a dynamic allocation to store a single pointer is not very efficient/useful. Worse, the memory is released in the SoundWire stream.c file, but still accessed in the DAI shutdown, leading to kmemleak reports. And last the API requires the previous stream information to be cleared when the argument is NULL. Simplify the code to address all 3 problems. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Rander Wang Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20230324014408.1677505-13-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt715-sdca.c | 30 +++++++----------------------- sound/soc/codecs/rt715-sdca.h | 4 ---- 2 files changed, 7 insertions(+), 27 deletions(-) diff --git a/sound/soc/codecs/rt715-sdca.c b/sound/soc/codecs/rt715-sdca.c index 920510365fd7..b989f907784b 100644 --- a/sound/soc/codecs/rt715-sdca.c +++ b/sound/soc/codecs/rt715-sdca.c @@ -784,16 +784,7 @@ static const struct snd_soc_component_driver soc_codec_dev_rt715_sdca = { static int rt715_sdca_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, int direction) { - struct rt715_sdw_stream_data *stream; - - stream = kzalloc(sizeof(*stream), GFP_KERNEL); - if (!stream) - return -ENOMEM; - - stream->sdw_stream = sdw_stream; - - /* Use tx_mask or rx_mask to configure stream tag and set dma_data */ - snd_soc_dai_dma_data_set(dai, direction, stream); + snd_soc_dai_dma_data_set(dai, direction, sdw_stream); return 0; } @@ -802,14 +793,7 @@ static void rt715_sdca_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct rt715_sdw_stream_data *stream; - - stream = snd_soc_dai_get_dma_data(dai, substream); - if (!stream) - return; - snd_soc_dai_set_dma_data(dai, substream, NULL); - kfree(stream); } static int rt715_sdca_pcm_hw_params(struct snd_pcm_substream *substream, @@ -820,13 +804,13 @@ static int rt715_sdca_pcm_hw_params(struct snd_pcm_substream *substream, struct rt715_sdca_priv *rt715 = snd_soc_component_get_drvdata(component); struct sdw_stream_config stream_config = {0}; struct sdw_port_config port_config = {0}; - struct rt715_sdw_stream_data *stream; + struct sdw_stream_runtime *sdw_stream; int retval; unsigned int val; - stream = snd_soc_dai_get_dma_data(dai, substream); + sdw_stream = snd_soc_dai_get_dma_data(dai, substream); - if (!stream) + if (!sdw_stream) return -EINVAL; if (!rt715->slave) @@ -851,7 +835,7 @@ static int rt715_sdca_pcm_hw_params(struct snd_pcm_substream *substream, } retval = sdw_stream_add_slave(rt715->slave, &stream_config, - &port_config, 1, stream->sdw_stream); + &port_config, 1, sdw_stream); if (retval) { dev_err(component->dev, "Unable to configure port, retval:%d\n", retval); @@ -922,13 +906,13 @@ static int rt715_sdca_pcm_hw_free(struct snd_pcm_substream *substream, { struct snd_soc_component *component = dai->component; struct rt715_sdca_priv *rt715 = snd_soc_component_get_drvdata(component); - struct rt715_sdw_stream_data *stream = + struct sdw_stream_runtime *sdw_stream = snd_soc_dai_get_dma_data(dai, substream); if (!rt715->slave) return -EINVAL; - sdw_stream_remove_slave(rt715->slave, stream->sdw_stream); + sdw_stream_remove_slave(rt715->slave, sdw_stream); return 0; } diff --git a/sound/soc/codecs/rt715-sdca.h b/sound/soc/codecs/rt715-sdca.h index 90881b455ece..7577f3151934 100644 --- a/sound/soc/codecs/rt715-sdca.h +++ b/sound/soc/codecs/rt715-sdca.h @@ -37,10 +37,6 @@ struct rt715_sdca_priv { int kctl_8ch_orig[8]; }; -struct rt715_sdw_stream_data { - struct sdw_stream_runtime *sdw_stream; -}; - struct rt715_sdca_kcontrol_private { unsigned int reg_base; unsigned int count; From b3a2e00e20671091f7175f8f36b7f9c9ea2e77bb Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 24 Mar 2023 09:44:08 +0800 Subject: [PATCH 644/778] ASoC: codecs: rt5682-sdw: simplify set_stream MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using a dynamic allocation to store a single pointer is not very efficient/useful. Worse, the memory is released in the SoundWire stream.c file, but still accessed in the DAI shutdown, leading to kmemleak reports. And last the API requires the previous stream information to be cleared when the argument is NULL. Simplify the code to address all 3 problems. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Rander Wang Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20230324014408.1677505-14-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5682-sdw.c | 34 +++++++--------------------------- 1 file changed, 7 insertions(+), 27 deletions(-) diff --git a/sound/soc/codecs/rt5682-sdw.c b/sound/soc/codecs/rt5682-sdw.c index 5f80a5d59b65..23f17f70d7e9 100644 --- a/sound/soc/codecs/rt5682-sdw.c +++ b/sound/soc/codecs/rt5682-sdw.c @@ -88,26 +88,10 @@ static const struct regmap_config rt5682_sdw_indirect_regmap = { .reg_write = rt5682_sdw_write, }; -struct sdw_stream_data { - struct sdw_stream_runtime *sdw_stream; -}; - static int rt5682_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, int direction) { - struct sdw_stream_data *stream; - - if (!sdw_stream) - return 0; - - stream = kzalloc(sizeof(*stream), GFP_KERNEL); - if (!stream) - return -ENOMEM; - - stream->sdw_stream = sdw_stream; - - /* Use tx_mask or rx_mask to configure stream tag and set dma_data */ - snd_soc_dai_dma_data_set(dai, direction, stream); + snd_soc_dai_dma_data_set(dai, direction, sdw_stream); return 0; } @@ -115,11 +99,7 @@ static int rt5682_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, static void rt5682_sdw_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct sdw_stream_data *stream; - - stream = snd_soc_dai_get_dma_data(dai, substream); snd_soc_dai_set_dma_data(dai, substream, NULL); - kfree(stream); } static int rt5682_sdw_hw_params(struct snd_pcm_substream *substream, @@ -130,14 +110,14 @@ static int rt5682_sdw_hw_params(struct snd_pcm_substream *substream, struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); struct sdw_stream_config stream_config = {0}; struct sdw_port_config port_config = {0}; - struct sdw_stream_data *stream; + struct sdw_stream_runtime *sdw_stream; int retval; unsigned int val_p = 0, val_c = 0, osr_p = 0, osr_c = 0; dev_dbg(dai->dev, "%s %s", __func__, dai->name); - stream = snd_soc_dai_get_dma_data(dai, substream); - if (!stream) + sdw_stream = snd_soc_dai_get_dma_data(dai, substream); + if (!sdw_stream) return -ENOMEM; if (!rt5682->slave) @@ -152,7 +132,7 @@ static int rt5682_sdw_hw_params(struct snd_pcm_substream *substream, port_config.num = 2; retval = sdw_stream_add_slave(rt5682->slave, &stream_config, - &port_config, 1, stream->sdw_stream); + &port_config, 1, sdw_stream); if (retval) { dev_err(dai->dev, "Unable to configure port\n"); return retval; @@ -246,13 +226,13 @@ static int rt5682_sdw_hw_free(struct snd_pcm_substream *substream, { struct snd_soc_component *component = dai->component; struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); - struct sdw_stream_data *stream = + struct sdw_stream_runtime *sdw_stream = snd_soc_dai_get_dma_data(dai, substream); if (!rt5682->slave) return -EINVAL; - sdw_stream_remove_slave(rt5682->slave, stream->sdw_stream); + sdw_stream_remove_slave(rt5682->slave, sdw_stream); return 0; } From 6a7c51b4d91b5d73aae2647356990573643b2ae4 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 29 Mar 2023 00:21:03 +0000 Subject: [PATCH 645/778] ASoC: soc-topology.c: dai_link->platform again On SOF, many topology is assuming dai_link->platform exists, and is allowed to be overwritten on each link_load(). This patch restore the removed dai_link->platform for SOF, and add the comment. Fixes: e7098ba9b378 ("ASoC: soc-topology.c: remove unnecessary dai_link->platform") Reported-by: Peter Ujfalusi Link: https://lore.kernel.org/r/87jzz7jczp.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Kuninori Morimoto Tested-by: Peter Ujfalusi Link: https://lore.kernel.org/r/87v8ikcsr5.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-topology.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index be9849749713..d0aca6b9058b 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -1685,8 +1685,8 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg, struct snd_soc_dai_link_component *dlc; int ret; - /* link + cpu + codec */ - link = devm_kzalloc(tplg->dev, sizeof(*link) + (2 * sizeof(*dlc)), GFP_KERNEL); + /* link + cpu + codec + platform */ + link = devm_kzalloc(tplg->dev, sizeof(*link) + (3 * sizeof(*dlc)), GFP_KERNEL); if (link == NULL) return -ENOMEM; @@ -1724,6 +1724,14 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg, link->codecs->name = "snd-soc-dummy"; link->codecs->dai_name = "snd-soc-dummy-dai"; + /* + * Many topology is assuming link has Platform. + * This might be overwritten at soc_tplg_dai_link_load(). + */ + link->platforms = &dlc[2]; + link->platforms->name = "snd-soc-dummy"; + link->num_platforms = 1; + /* enable DPCM */ link->dynamic = 1; link->ignore_pmdown_time = 1; From f769fcefa683e150456555e2a280668509d834df Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 27 Mar 2023 15:22:52 +0200 Subject: [PATCH 646/778] ASoC: dt-bindings: qcom,lpass-va-macro: Add SM8550 VA macro Add the VA macro codec on Qualcomm SM8550, which comes without NPL clock exposed. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20230327132254.147975-9-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- .../bindings/sound/qcom,lpass-va-macro.yaml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-va-macro.yaml b/Documentation/devicetree/bindings/sound/qcom,lpass-va-macro.yaml index 0a3c688ef1ec..4cf778e3afdd 100644 --- a/Documentation/devicetree/bindings/sound/qcom,lpass-va-macro.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,lpass-va-macro.yaml @@ -18,6 +18,7 @@ properties: - qcom,sc7280-lpass-va-macro - qcom,sm8250-lpass-va-macro - qcom,sm8450-lpass-va-macro + - qcom,sm8550-lpass-va-macro - qcom,sc8280xp-lpass-va-macro reg: @@ -64,6 +65,23 @@ required: - reg - "#sound-dai-cells" + - if: + properties: + compatible: + contains: + enum: + - qcom,sm8550-lpass-va-macro + then: + properties: + clocks: + minItems: 3 + maxItems: 3 + clock-names: + items: + - const: mclk + - const: macro + - const: dcodec + unevaluatedProperties: false examples: From 24e9e57f581dd3e90c4b63f066dab96c6ba4e05f Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 24 Mar 2023 16:33:28 +0000 Subject: [PATCH 647/778] ASoC: dapm: Sort speakers after other outputs Currently we sequence speakers with line and headphone outputs in DAPM. This works well when speakers are integrate into a CODEC but when there is an external speaker driver connected to a line or headphone output it can mean that the speaker driver ends up getting sequenced such that it picks up pops and clicks from the CODEC. Mask this by moving speakers after the other outputs in DAPM. We may want to consider doing this for headphones too but separate drivers are less common there and headphone drivers often also function as line outputs so the situation is less clear. Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20230324-asoc-dapm-spk-v1-1-e1f27f766505@kernel.org Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 74 ++++++++++++++++++++++---------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 5d9a671e50f1..34fdcb7ee079 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -99,52 +99,52 @@ static int dapm_up_seq[] = { [snd_soc_dapm_adc] = 11, [snd_soc_dapm_out_drv] = 12, [snd_soc_dapm_hp] = 12, - [snd_soc_dapm_spk] = 12, [snd_soc_dapm_line] = 12, [snd_soc_dapm_sink] = 12, - [snd_soc_dapm_kcontrol] = 13, - [snd_soc_dapm_post] = 14, + [snd_soc_dapm_spk] = 13, + [snd_soc_dapm_kcontrol] = 14, + [snd_soc_dapm_post] = 15, }; static int dapm_down_seq[] = { [snd_soc_dapm_pre] = 1, [snd_soc_dapm_kcontrol] = 2, [snd_soc_dapm_adc] = 3, - [snd_soc_dapm_hp] = 4, [snd_soc_dapm_spk] = 4, - [snd_soc_dapm_line] = 4, - [snd_soc_dapm_out_drv] = 4, - [snd_soc_dapm_sink] = 4, - [snd_soc_dapm_pga] = 5, - [snd_soc_dapm_buffer] = 5, - [snd_soc_dapm_scheduler] = 5, - [snd_soc_dapm_effect] = 5, - [snd_soc_dapm_src] = 5, - [snd_soc_dapm_asrc] = 5, - [snd_soc_dapm_encoder] = 5, - [snd_soc_dapm_decoder] = 5, - [snd_soc_dapm_switch] = 6, - [snd_soc_dapm_mixer_named_ctl] = 6, - [snd_soc_dapm_mixer] = 6, - [snd_soc_dapm_dac] = 7, - [snd_soc_dapm_mic] = 8, - [snd_soc_dapm_siggen] = 8, - [snd_soc_dapm_input] = 8, - [snd_soc_dapm_output] = 8, - [snd_soc_dapm_micbias] = 9, - [snd_soc_dapm_vmid] = 9, - [snd_soc_dapm_mux] = 10, - [snd_soc_dapm_demux] = 10, - [snd_soc_dapm_aif_in] = 11, - [snd_soc_dapm_aif_out] = 11, - [snd_soc_dapm_dai_in] = 11, - [snd_soc_dapm_dai_out] = 11, - [snd_soc_dapm_dai_link] = 12, - [snd_soc_dapm_supply] = 13, - [snd_soc_dapm_clock_supply] = 14, - [snd_soc_dapm_pinctrl] = 14, - [snd_soc_dapm_regulator_supply] = 14, - [snd_soc_dapm_post] = 15, + [snd_soc_dapm_hp] = 5, + [snd_soc_dapm_line] = 5, + [snd_soc_dapm_out_drv] = 5, + [snd_soc_dapm_sink] = 6, + [snd_soc_dapm_pga] = 6, + [snd_soc_dapm_buffer] = 6, + [snd_soc_dapm_scheduler] = 6, + [snd_soc_dapm_effect] = 6, + [snd_soc_dapm_src] = 6, + [snd_soc_dapm_asrc] = 6, + [snd_soc_dapm_encoder] = 6, + [snd_soc_dapm_decoder] = 6, + [snd_soc_dapm_switch] = 7, + [snd_soc_dapm_mixer_named_ctl] = 7, + [snd_soc_dapm_mixer] = 7, + [snd_soc_dapm_dac] = 8, + [snd_soc_dapm_mic] = 9, + [snd_soc_dapm_siggen] = 9, + [snd_soc_dapm_input] = 9, + [snd_soc_dapm_output] = 9, + [snd_soc_dapm_micbias] = 10, + [snd_soc_dapm_vmid] = 10, + [snd_soc_dapm_mux] = 11, + [snd_soc_dapm_demux] = 11, + [snd_soc_dapm_aif_in] = 12, + [snd_soc_dapm_aif_out] = 12, + [snd_soc_dapm_dai_in] = 12, + [snd_soc_dapm_dai_out] = 12, + [snd_soc_dapm_dai_link] = 13, + [snd_soc_dapm_supply] = 14, + [snd_soc_dapm_clock_supply] = 15, + [snd_soc_dapm_pinctrl] = 15, + [snd_soc_dapm_regulator_supply] = 15, + [snd_soc_dapm_post] = 16, }; static void dapm_assert_locked(struct snd_soc_dapm_context *dapm) From 0b57a2d87b4de2a1f01edaf3b00b3d1939792948 Mon Sep 17 00:00:00 2001 From: Saalim Quadri Date: Tue, 28 Mar 2023 02:46:29 +0530 Subject: [PATCH 648/778] ASoC: dt-bindings: alc5632: Convert to dtschema Convert the ALC5632 audio codec bindings to DT schema. Signed-off-by: Saalim Quadri Link: https://lore.kernel.org/r/20230327211629.28643-1-danascape@gmail.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/alc5632.txt | 43 ------------- .../bindings/sound/realtek,alc5632.yaml | 63 +++++++++++++++++++ 2 files changed, 63 insertions(+), 43 deletions(-) delete mode 100644 Documentation/devicetree/bindings/sound/alc5632.txt create mode 100644 Documentation/devicetree/bindings/sound/realtek,alc5632.yaml diff --git a/Documentation/devicetree/bindings/sound/alc5632.txt b/Documentation/devicetree/bindings/sound/alc5632.txt deleted file mode 100644 index ffd886d110bd..000000000000 --- a/Documentation/devicetree/bindings/sound/alc5632.txt +++ /dev/null @@ -1,43 +0,0 @@ -ALC5632 audio CODEC - -This device supports I2C only. - -Required properties: - - - compatible : "realtek,alc5632" - - - reg : the I2C address of the device. - - - gpio-controller : Indicates this device is a GPIO controller. - - - #gpio-cells : Should be two. The first cell is the pin number and the - second cell is used to specify optional parameters (currently unused). - -Pins on the device (for linking into audio routes): - - * SPK_OUTP - * SPK_OUTN - * HP_OUT_L - * HP_OUT_R - * AUX_OUT_P - * AUX_OUT_N - * LINE_IN_L - * LINE_IN_R - * PHONE_P - * PHONE_N - * MIC1_P - * MIC1_N - * MIC2_P - * MIC2_N - * MICBIAS1 - * DMICDAT - -Example: - -alc5632: alc5632@1e { - compatible = "realtek,alc5632"; - reg = <0x1a>; - - gpio-controller; - #gpio-cells = <2>; -}; diff --git a/Documentation/devicetree/bindings/sound/realtek,alc5632.yaml b/Documentation/devicetree/bindings/sound/realtek,alc5632.yaml new file mode 100644 index 000000000000..fb05988ff7ea --- /dev/null +++ b/Documentation/devicetree/bindings/sound/realtek,alc5632.yaml @@ -0,0 +1,63 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/realtek,alc5632.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: ALC5632 audio CODEC + +description: | + Pins on the device (for linking into audio routes): + * SPK_OUTP + * SPK_OUTN + * HP_OUT_L + * HP_OUT_R + * AUX_OUT_P + * AUX_OUT_N + * LINE_IN_L + * LINE_IN_R + * PHONE_P + * PHONE_N + * MIC1_P + * MIC1_N + * MIC2_P + * MIC2_N + * MICBIAS1 + * DMICDAT + +maintainers: + - Leon Romanovsky + +properties: + compatible: + const: realtek,alc5632 + + reg: + maxItems: 1 + + '#gpio-cells': + const: 2 + + gpio-controller: true + +required: + - compatible + - reg + - '#gpio-cells' + - gpio-controller + +additionalProperties: false + +examples: + - | + #include + i2c { + #address-cells = <1>; + #size-cells = <0>; + codec@1a { + compatible = "realtek,alc5632"; + reg = <0x1a>; + gpio-controller; + #gpio-cells = <2>; + }; + }; From 59257015ac8813d2430988aa01c2f4609a60e8e7 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 30 Mar 2023 09:13:33 +0200 Subject: [PATCH 649/778] ASoC: dt-bindings: qcom,lpass-rx-macro: correct minItems for clocks The RX macro codec comes on some platforms in two variants - ADSP and ADSP bypassed - thus the clock-names varies from 3 to 5. The clocks must vary as well: sc7280-idp.dtb: codec@3200000: clocks: [[202, 8], [202, 7], [203]] is too short Fixes: 852fda58d99a ("ASoC: qcom: dt-bindings: Update bindings for clocks in lpass digital codes") Cc: Acked-by: Rob Herring Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230330071333.24308-1-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml b/Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml index 78e462e2cdcf..0ae3c81abdf8 100644 --- a/Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml @@ -28,6 +28,7 @@ properties: const: 0 clocks: + minItems: 3 maxItems: 5 clock-names: From cfad817095e111b640c7d538b9f182d2535ee065 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 30 Mar 2023 13:34:05 +0200 Subject: [PATCH 650/778] ASoC: dt-bindings: qcom,lpass-va-macro: Add missing NPL clock Several devices (e.g. SC8280XP and SM8450) expect a NPL (Near Pad Logic) clock. Add the clock and customize allowed clocks per each variant. The clocks are also required by ADSP in all variants. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230330113405.55722-1-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- .../bindings/sound/qcom,lpass-va-macro.yaml | 68 ++++++++++++++++--- 1 file changed, 57 insertions(+), 11 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-va-macro.yaml b/Documentation/devicetree/bindings/sound/qcom,lpass-va-macro.yaml index 4cf778e3afdd..4a56108c444b 100644 --- a/Documentation/devicetree/bindings/sound/qcom,lpass-va-macro.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,lpass-va-macro.yaml @@ -9,9 +9,6 @@ title: LPASS(Low Power Audio Subsystem) VA Macro audio codec maintainers: - Srinivas Kandagatla -allOf: - - $ref: dai-common.yaml# - properties: compatible: enum: @@ -31,16 +28,12 @@ properties: const: 0 clocks: - maxItems: 3 + minItems: 1 + maxItems: 4 clock-names: - oneOf: - - items: #for ADSP based platforms - - const: mclk - - const: macro - - const: dcodec - - items: #for ADSP bypass based platforms - - const: mclk + minItems: 1 + maxItems: 4 clock-output-names: maxItems: 1 @@ -64,6 +57,59 @@ required: - compatible - reg - "#sound-dai-cells" + - clock-names + - clocks + +allOf: + - $ref: dai-common.yaml# + + - if: + properties: + compatible: + contains: + const: qcom,sc7280-lpass-va-macro + then: + properties: + clocks: + maxItems: 1 + clock-names: + items: + - const: mclk + + - if: + properties: + compatible: + contains: + const: qcom,sm8250-lpass-va-macro + then: + properties: + clocks: + minItems: 3 + maxItems: 3 + clock-names: + items: + - const: mclk + - const: macro + - const: dcodec + + - if: + properties: + compatible: + contains: + enum: + - qcom,sc8280xp-lpass-va-macro + - qcom,sm8450-lpass-va-macro + then: + properties: + clocks: + minItems: 4 + maxItems: 4 + clock-names: + items: + - const: mclk + - const: macro + - const: dcodec + - const: npl - if: properties: From 18c0af945fa35766730d3f729adcf417a3d1ad5d Mon Sep 17 00:00:00 2001 From: Ryan Lee Date: Thu, 30 Mar 2023 16:43:18 -0700 Subject: [PATCH 651/778] ASoC: max98363: add soundwire amplifier driver Added Analog Devices MAX98363 SoundWire Amplifier Driver. The MAX98363 is a SoundWire peripheral device that supports MIPI SoundWire v1.2-compatible digital interface for audio and control data. Signed-off-by: Ryan Lee Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20230330234319.6841-1-ryan.lee.analog@gmail.com Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 11 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/max98363.c | 464 ++++++++++++++++++++++++++++++++++++ sound/soc/codecs/max98363.h | 36 +++ 4 files changed, 513 insertions(+) create mode 100644 sound/soc/codecs/max98363.c create mode 100644 sound/soc/codecs/max98363.h diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 03630d13d35f..4062fe3fbb1c 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -133,6 +133,7 @@ config SND_SOC_ALL_CODECS imply SND_SOC_MAX98925 imply SND_SOC_MAX98926 imply SND_SOC_MAX98927 + imply SND_SOC_MAX98363 imply SND_SOC_MAX98373_I2C imply SND_SOC_MAX98373_SDW imply SND_SOC_MAX98390 @@ -1133,6 +1134,16 @@ config SND_SOC_MAX98520 To compile this driver as a module, choose M here. +config SND_SOC_MAX98363 + tristate "Analog Devices MAX98363 Soundwire Speaker Amplifier" + depends on SOUNDWIRE + select REGMAP_SOUNDWIRE + help + Enable support for Analog Devices MAX98363 Soundwire + amplifier. MAX98363 supports the MIPI SoundWire v1.2 + compatible interface for audio and control data. + This amplifier does not support I2C and I2S. + config SND_SOC_MAX98373 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 25ebce58a0ba..44ea747579fd 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -148,6 +148,7 @@ snd-soc-max98925-objs := max98925.o snd-soc-max98926-objs := max98926.o snd-soc-max98927-objs := max98927.o snd-soc-max98520-objs := max98520.o +snd-soc-max98363-objs := max98363.o snd-soc-max98373-objs := max98373.o snd-soc-max98373-i2c-objs := max98373-i2c.o snd-soc-max98373-sdw-objs := max98373-sdw.o @@ -515,6 +516,7 @@ obj-$(CONFIG_SND_SOC_MAX98925) += snd-soc-max98925.o obj-$(CONFIG_SND_SOC_MAX98926) += snd-soc-max98926.o obj-$(CONFIG_SND_SOC_MAX98927) += snd-soc-max98927.o obj-$(CONFIG_SND_SOC_MAX98520) += snd-soc-max98520.o +obj-$(CONFIG_SND_SOC_MAX98363) += snd-soc-max98363.o obj-$(CONFIG_SND_SOC_MAX98373) += snd-soc-max98373.o obj-$(CONFIG_SND_SOC_MAX98373_I2C) += snd-soc-max98373-i2c.o obj-$(CONFIG_SND_SOC_MAX98373_SDW) += snd-soc-max98373-sdw.o diff --git a/sound/soc/codecs/max98363.c b/sound/soc/codecs/max98363.c new file mode 100644 index 000000000000..4585ebb1e82c --- /dev/null +++ b/sound/soc/codecs/max98363.c @@ -0,0 +1,464 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (c) 2022, Analog Devices Inc. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "max98363.h" + +static struct reg_default max98363_reg[] = { + {MAX98363_R2001_INTR_RAW, 0x0}, + {MAX98363_R2003_INTR_STATE, 0x0}, + {MAX98363_R2005_INTR_FALG, 0x0}, + {MAX98363_R2007_INTR_EN, 0x0}, + {MAX98363_R2009_INTR_CLR, 0x0}, + {MAX98363_R2021_ERR_MON_CTRL, 0x0}, + {MAX98363_R2022_SPK_MON_THRESH, 0x0}, + {MAX98363_R2023_SPK_MON_DURATION, 0x0}, + {MAX98363_R2030_TONE_GEN_CFG, 0x0}, + {MAX98363_R203F_TONE_GEN_EN, 0x0}, + {MAX98363_R2040_AMP_VOL, 0x0}, + {MAX98363_R2041_AMP_GAIN, 0x5}, + {MAX98363_R2042_DSP_CFG, 0x0}, + {MAX98363_R21FF_REV_ID, 0x0}, +}; + +static bool max98363_readable_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case MAX98363_R2001_INTR_RAW: + case MAX98363_R2003_INTR_STATE: + case MAX98363_R2005_INTR_FALG: + case MAX98363_R2007_INTR_EN: + case MAX98363_R2009_INTR_CLR: + case MAX98363_R2021_ERR_MON_CTRL ... MAX98363_R2023_SPK_MON_DURATION: + case MAX98363_R2030_TONE_GEN_CFG: + case MAX98363_R203F_TONE_GEN_EN: + case MAX98363_R2040_AMP_VOL: + case MAX98363_R2041_AMP_GAIN: + case MAX98363_R2042_DSP_CFG: + case MAX98363_R21FF_REV_ID: + return true; + default: + return false; + } +}; + +static bool max98363_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case MAX98363_R2001_INTR_RAW: + case MAX98363_R2003_INTR_STATE: + case MAX98363_R2005_INTR_FALG: + case MAX98363_R2007_INTR_EN: + case MAX98363_R2009_INTR_CLR: + case MAX98363_R21FF_REV_ID: + return true; + default: + return false; + } +} + +static const struct regmap_config max98363_sdw_regmap = { + .reg_bits = 32, + .val_bits = 8, + .max_register = MAX98363_R21FF_REV_ID, + .reg_defaults = max98363_reg, + .num_reg_defaults = ARRAY_SIZE(max98363_reg), + .readable_reg = max98363_readable_register, + .volatile_reg = max98363_volatile_reg, + .cache_type = REGCACHE_RBTREE, + .use_single_read = true, + .use_single_write = true, +}; + +static int max98363_suspend(struct device *dev) +{ + struct max98363_priv *max98363 = dev_get_drvdata(dev); + + regcache_cache_only(max98363->regmap, true); + regcache_mark_dirty(max98363->regmap); + + return 0; +} + +#define MAX98363_PROBE_TIMEOUT 5000 + +static int max98363_resume(struct device *dev) +{ + struct sdw_slave *slave = dev_to_sdw_dev(dev); + struct max98363_priv *max98363 = dev_get_drvdata(dev); + unsigned long time; + + if (!max98363->first_hw_init) + return 0; + + if (!slave->unattach_request) + goto regmap_sync; + + time = wait_for_completion_timeout(&slave->initialization_complete, + msecs_to_jiffies(MAX98363_PROBE_TIMEOUT)); + if (!time) { + dev_err(dev, "Initialization not complete, timed out\n"); + return -ETIMEDOUT; + } + +regmap_sync: + + slave->unattach_request = 0; + regcache_cache_only(max98363->regmap, false); + regcache_sync(max98363->regmap); + + return 0; +} + +static DEFINE_RUNTIME_DEV_PM_OPS(max98363_pm, max98363_suspend, max98363_resume, NULL); + +static int max98363_read_prop(struct sdw_slave *slave) +{ + struct sdw_slave_prop *prop = &slave->prop; + int nval, i; + u32 bit; + unsigned long addr; + struct sdw_dpn_prop *dpn; + + prop->scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY; + + /* BITMAP: 00000010 Dataport 1 is active */ + prop->sink_ports = BIT(1); + prop->paging_support = true; + prop->clk_stop_timeout = 20; + prop->simple_clk_stop_capable = true; + prop->clock_reg_supported = true; + + nval = hweight32(prop->sink_ports); + prop->sink_dpn_prop = devm_kcalloc(&slave->dev, nval, + sizeof(*prop->sink_dpn_prop), + GFP_KERNEL); + if (!prop->sink_dpn_prop) + return -ENOMEM; + + i = 0; + dpn = prop->sink_dpn_prop; + addr = prop->sink_ports; + for_each_set_bit(bit, &addr, 32) { + dpn[i].num = bit; + dpn[i].type = SDW_DPN_FULL; + dpn[i].simple_ch_prep_sm = true; + dpn[i].ch_prep_timeout = 10; + i++; + } + + return 0; +} + +static int max98363_io_init(struct sdw_slave *slave) +{ + struct device *dev = &slave->dev; + struct max98363_priv *max98363 = dev_get_drvdata(dev); + int ret, reg; + + if (max98363->first_hw_init) { + regcache_cache_only(max98363->regmap, false); + regcache_cache_bypass(max98363->regmap, true); + } + + /* + * PM runtime is only enabled when a Slave reports as Attached + */ + if (!max98363->first_hw_init) { + /* set autosuspend parameters */ + pm_runtime_set_autosuspend_delay(dev, 3000); + pm_runtime_use_autosuspend(dev); + + /* update count of parent 'active' children */ + pm_runtime_set_active(dev); + + /* make sure the device does not suspend immediately */ + pm_runtime_mark_last_busy(dev); + + pm_runtime_enable(dev); + } + + pm_runtime_get_noresume(dev); + + ret = regmap_read(max98363->regmap, MAX98363_R21FF_REV_ID, ®); + if (!ret) { + dev_info(dev, "Revision ID: %X\n", reg); + return ret; + } + + if (max98363->first_hw_init) { + regcache_cache_bypass(max98363->regmap, false); + regcache_mark_dirty(max98363->regmap); + } + + max98363->first_hw_init = true; + max98363->hw_init = true; + + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + + return 0; +} + +#define MAX98363_RATES SNDRV_PCM_RATE_8000_192000 +#define MAX98363_FORMATS (SNDRV_PCM_FMTBIT_S32_LE) + +static int max98363_sdw_dai_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct max98363_priv *max98363 = + snd_soc_component_get_drvdata(component); + + struct sdw_stream_config stream_config; + struct sdw_port_config port_config; + enum sdw_data_direction direction; + struct sdw_stream_runtime *stream; + struct snd_pcm_runtime *runtime = substream->runtime; + + int ret; + + stream = snd_soc_dai_get_dma_data(dai, substream); + + if (!stream) + return -EINVAL; + + if (!max98363->slave) + return -EINVAL; + + if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) + return -EINVAL; + + direction = SDW_DATA_DIR_RX; + port_config.num = 1; + + stream_config.frame_rate = params_rate(params); + stream_config.bps = snd_pcm_format_width(params_format(params)); + stream_config.direction = direction; + stream_config.ch_count = params_channels(params); + + if (stream_config.ch_count > runtime->hw.channels_max) { + stream_config.ch_count = runtime->hw.channels_max; + dev_info(dai->dev, "Number of channels: %d (requested: %d)\n", + stream_config.ch_count, params_channels(params)); + } + port_config.ch_mask = GENMASK((int)stream_config.ch_count - 1, 0); + + ret = sdw_stream_add_slave(max98363->slave, &stream_config, + &port_config, 1, stream); + if (ret) { + dev_err(dai->dev, "Unable to configure port\n"); + return ret; + } + + dev_dbg(component->dev, "Format supported %d", params_format(params)); + + return 0; +} + +static int max98363_pcm_hw_free(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct max98363_priv *max98363 = + snd_soc_component_get_drvdata(component); + struct sdw_stream_runtime *stream = + snd_soc_dai_get_dma_data(dai, substream); + + if (!max98363->slave) + return -EINVAL; + + sdw_stream_remove_slave(max98363->slave, stream); + + return 0; +} + +static int max98363_set_sdw_stream(struct snd_soc_dai *dai, + void *sdw_stream, int direction) +{ + snd_soc_dai_dma_data_set(dai, direction, sdw_stream); + + return 0; +} + +static const struct snd_soc_dai_ops max98363_dai_sdw_ops = { + .hw_params = max98363_sdw_dai_hw_params, + .hw_free = max98363_pcm_hw_free, + .set_stream = max98363_set_sdw_stream, +}; + +static struct snd_soc_dai_driver max98363_dai[] = { + { + .name = "max98363-aif1", + .playback = { + .stream_name = "HiFi Playback", + .channels_min = 1, + .channels_max = 1, + .rates = MAX98363_RATES, + .formats = MAX98363_FORMATS, + }, + .ops = &max98363_dai_sdw_ops, + } +}; + +static int max98363_update_status(struct sdw_slave *slave, + enum sdw_slave_status status) +{ + struct max98363_priv *max98363 = dev_get_drvdata(&slave->dev); + + if (status == SDW_SLAVE_UNATTACHED) + max98363->hw_init = false; + + /* + * Perform initialization only if slave status is SDW_SLAVE_ATTACHED + */ + if (max98363->hw_init || status != SDW_SLAVE_ATTACHED) + return 0; + + /* perform I/O transfers required for Slave initialization */ + return max98363_io_init(slave); +} + +static struct sdw_slave_ops max98363_slave_ops = { + .read_prop = max98363_read_prop, + .update_status = max98363_update_status, +}; + +static DECLARE_TLV_DB_SCALE(max98363_digital_tlv, -6350, 50, 1); +static const DECLARE_TLV_DB_RANGE(max98363_spk_tlv, + 0, 5, TLV_DB_SCALE_ITEM(-300, 300, 0), +); + +static const char * const max98363_tone_cfg_text[] = { + "Reserved", "0", "+FS/2", "-FS/2", "1KHz", + "12KHz", "8KHz", "6KHz", "4KHz", "3KHz", + "2KHz", "1.5KHz", "Reserved", "500Hz", "250Hz" +}; + +static SOC_ENUM_SINGLE_DECL(max98363_tone_cfg_enum, + MAX98363_R2030_TONE_GEN_CFG, 0, + max98363_tone_cfg_text); + +static const char * const max98363_spkmon_duration_text[] = { + "8ms", "20ms", "40ms", "60ms", + "80ms", "160ms", "240ms", "320ms", + "400ms", "480ms", "560ms", "640ms", + "720ms", "800ms", "880ms", "960ms" +}; + +static SOC_ENUM_SINGLE_DECL(max98363_spkmon_duration_enum, + MAX98363_R2023_SPK_MON_DURATION, 0, + max98363_spkmon_duration_text); + +static const struct snd_kcontrol_new max98363_snd_controls[] = { + SOC_SINGLE_TLV("Digital Volume", MAX98363_R2040_AMP_VOL, + 0, 0x7F, 1, max98363_digital_tlv), + SOC_SINGLE_TLV("Speaker Volume", MAX98363_R2041_AMP_GAIN, + 0, 10, 0, max98363_spk_tlv), + SOC_SINGLE("Tone Generator Switch", MAX98363_R203F_TONE_GEN_EN, + 0, 1, 0), + SOC_ENUM("Tone Config", max98363_tone_cfg_enum), + SOC_SINGLE("Ramp Switch", MAX98363_R2042_DSP_CFG, + MAX98363_AMP_DSP_CFG_RMP_SHIFT, 1, 0), + SOC_SINGLE("CLK Monitor Switch", MAX98363_R2021_ERR_MON_CTRL, + MAX98363_CLOCK_MON_SHIFT, 1, 0), + SOC_SINGLE("SPKMON Monitor Switch", MAX98363_R2021_ERR_MON_CTRL, + MAX98363_SPKMON_SHIFT, 1, 0), + SOC_SINGLE("SPKMON Thresh", MAX98363_R2022_SPK_MON_THRESH, 0, 0xFF, 0), + SOC_ENUM("SPKMON Duration", max98363_spkmon_duration_enum), +}; + +static const struct snd_soc_dapm_widget max98363_dapm_widgets[] = { + SND_SOC_DAPM_AIF_IN("AIFIN", "HiFi Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_OUTPUT("BE_OUT"), +}; + +static const struct snd_soc_dapm_route max98363_audio_map[] = { + /* Plabyack */ + {"BE_OUT", NULL, "AIFIN"}, +}; + +const struct snd_soc_component_driver soc_codec_dev_max98363 = { + .controls = max98363_snd_controls, + .num_controls = ARRAY_SIZE(max98363_snd_controls), + .dapm_widgets = max98363_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(max98363_dapm_widgets), + .dapm_routes = max98363_audio_map, + .num_dapm_routes = ARRAY_SIZE(max98363_audio_map), + .use_pmdown_time = 1, + .endianness = 1, +}; + +static int max98363_init(struct sdw_slave *slave, struct regmap *regmap) +{ + struct max98363_priv *max98363; + int ret; + struct device *dev = &slave->dev; + + /* Allocate and assign private driver data structure */ + max98363 = devm_kzalloc(dev, sizeof(*max98363), GFP_KERNEL); + if (!max98363) + return -ENOMEM; + + dev_set_drvdata(dev, max98363); + max98363->regmap = regmap; + max98363->slave = slave; + + max98363->hw_init = false; + max98363->first_hw_init = false; + + /* codec registration */ + ret = devm_snd_soc_register_component(dev, &soc_codec_dev_max98363, + max98363_dai, + ARRAY_SIZE(max98363_dai)); + if (ret < 0) + dev_err(dev, "Failed to register codec: %d\n", ret); + + return ret; +} + +static int max98363_sdw_probe(struct sdw_slave *slave, + const struct sdw_device_id *id) +{ + struct regmap *regmap; + + /* Regmap Initialization */ + regmap = devm_regmap_init_sdw(slave, &max98363_sdw_regmap); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + return max98363_init(slave, regmap); +} + +static const struct sdw_device_id max98363_id[] = { + SDW_SLAVE_ENTRY(0x019F, 0x8363, 0), + {}, +}; +MODULE_DEVICE_TABLE(sdw, max98363_id); + +static struct sdw_driver max98363_sdw_driver = { + .driver = { + .name = "max98363", + .pm = pm_ptr(&max98363_pm), + }, + .probe = max98363_sdw_probe, + .ops = &max98363_slave_ops, + .id_table = max98363_id, +}; + +module_sdw_driver(max98363_sdw_driver); + +MODULE_DESCRIPTION("ASoC MAX98363 driver SDW"); +MODULE_AUTHOR("Ryan Lee "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/max98363.h b/sound/soc/codecs/max98363.h new file mode 100644 index 000000000000..2b6743d3a2cf --- /dev/null +++ b/sound/soc/codecs/max98363.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright (c) 2022 Analog Devices Inc. */ + +#ifndef _MAX98363_H +#define _MAX98363_H + +#define MAX98363_R2000_SW_RESET 0x2000 +#define MAX98363_R2001_INTR_RAW 0x2001 +#define MAX98363_R2003_INTR_STATE 0x2003 +#define MAX98363_R2005_INTR_FALG 0x2005 +#define MAX98363_R2007_INTR_EN 0x2007 +#define MAX98363_R2009_INTR_CLR 0x2009 +#define MAX98363_R2021_ERR_MON_CTRL 0x2021 +#define MAX98363_R2022_SPK_MON_THRESH 0x2022 +#define MAX98363_R2023_SPK_MON_DURATION 0x2023 +#define MAX98363_R2030_TONE_GEN_CFG 0x2030 +#define MAX98363_R203F_TONE_GEN_EN 0x203F +#define MAX98363_R2040_AMP_VOL 0x2040 +#define MAX98363_R2041_AMP_GAIN 0x2041 +#define MAX98363_R2042_DSP_CFG 0x2042 +#define MAX98363_R21FF_REV_ID 0x21FF + +/* MAX98363_R2021_ERR_MON_CTRL */ +#define MAX98363_SPKMON_SHIFT (3) +#define MAX98363_CLOCK_MON_SHIFT (0) + +/* MAX98363_R2042_DSP_CFG */ +#define MAX98363_AMP_DSP_CFG_RMP_SHIFT (3) + +struct max98363_priv { + struct regmap *regmap; + struct sdw_slave *slave; + bool hw_init; + bool first_hw_init; +}; +#endif From 276d8c08e82b9f6062f6febc7bc63913829bde27 Mon Sep 17 00:00:00 2001 From: Ryan Lee Date: Thu, 30 Mar 2023 16:43:19 -0700 Subject: [PATCH 652/778] ASoC: dt-bindings: max98363: add soundwire amplifier Add dt-bindings information for Analog Devices MAX98363 SoundWire Amplifier Signed-off-by: Ryan Lee Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230330234319.6841-2-ryan.lee.analog@gmail.com Signed-off-by: Mark Brown --- .../bindings/sound/adi,max98363.yaml | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/adi,max98363.yaml diff --git a/Documentation/devicetree/bindings/sound/adi,max98363.yaml b/Documentation/devicetree/bindings/sound/adi,max98363.yaml new file mode 100644 index 000000000000..a844b63f3930 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/adi,max98363.yaml @@ -0,0 +1,60 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/adi,max98363.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Analog Devices MAX98363 SoundWire Amplifier + +maintainers: + - Ryan Lee + +description: + The MAX98363 is a SoundWire input Class D mono amplifier that + supports MIPI SoundWire v1.2-compatible digital interface for + audio and control data. + SoundWire peripheral device ID of MAX98363 is 0x3*019f836300 + where * is the peripheral device unique ID decoded from pin. + It supports up to 10 peripheral devices(0x0 to 0x9). + +allOf: + - $ref: dai-common.yaml# + +properties: + compatible: + const: sdw3019f836300 + + reg: + maxItems: 1 + + '#sound-dai-cells': + const: 0 + +required: + - compatible + - reg + - "#sound-dai-cells" + +unevaluatedProperties: false + +examples: + - | + soundwire-controller@3250000 { + #address-cells = <2>; + #size-cells = <0>; + reg = <0x3250000 0x2000>; + + speaker@0,0 { + compatible = "sdw3019f836300"; + reg = <0 0>; + #sound-dai-cells = <0>; + sound-name-prefix = "Speaker Left"; + }; + + speaker@0,1 { + compatible = "sdw3019f836300"; + reg = <0 1>; + #sound-dai-cells = <0>; + sound-name-prefix = "Speaker Right"; + }; + }; From a4d432e9132c0b29d857b09ca2ec4c1f455b5948 Mon Sep 17 00:00:00 2001 From: Syed Saba Kareem Date: Fri, 31 Mar 2023 10:50:23 +0530 Subject: [PATCH 653/778] ASoC: amd: ps: update the acp clock source. Updating the clock source from ACLK to default clock Signed-off-by: Syed Saba Kareem Link: https://lore.kernel.org/r/20230331052102.2211115-1-Syed.SabaKareem@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/ps/pci-ps.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c index e86f23d97584..688a1d4643d9 100644 --- a/sound/soc/amd/ps/pci-ps.c +++ b/sound/soc/amd/ps/pci-ps.c @@ -91,7 +91,6 @@ static int acp63_init(void __iomem *acp_base, struct device *dev) dev_err(dev, "ACP reset failed\n"); return ret; } - acp63_writel(0x03, acp_base + ACP_CLKMUX_SEL); acp63_enable_interrupts(acp_base); return 0; } @@ -106,7 +105,6 @@ static int acp63_deinit(void __iomem *acp_base, struct device *dev) dev_err(dev, "ACP reset failed\n"); return ret; } - acp63_writel(0, acp_base + ACP_CLKMUX_SEL); acp63_writel(0, acp_base + ACP_CONTROL); return 0; } From 7a3f924cee4bdfe85eda4e636213e79d3fda6182 Mon Sep 17 00:00:00 2001 From: Simon Trimmer Date: Tue, 28 Mar 2023 14:10:18 +0100 Subject: [PATCH 654/778] firmware: cs_dsp: Add a debugfs entry containing control details The file named 'controls' in the DSP's debugfs root contains a formatted table describing the controls defined within the loaded DSP firmware, it is of the form name: len region:offset addr fwname algid ctltype flags en dirty Where flags is represented as a character for each flag if set, or '-', enabled is whether the control is enabled or disabled and dirty is whether the control value is set in the cache but not the hardware. Signed-off-by: Simon Trimmer Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/20230328131018.6820-1-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- drivers/firmware/cirrus/cs_dsp.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/drivers/firmware/cirrus/cs_dsp.c b/drivers/firmware/cirrus/cs_dsp.c index 513136a924cf..e4ccfb6a8fa5 100644 --- a/drivers/firmware/cirrus/cs_dsp.c +++ b/drivers/firmware/cirrus/cs_dsp.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -457,6 +458,33 @@ static const struct { }, }; +static int cs_dsp_coeff_base_reg(struct cs_dsp_coeff_ctl *ctl, unsigned int *reg, + unsigned int off); + +static int cs_dsp_debugfs_read_controls_show(struct seq_file *s, void *ignored) +{ + struct cs_dsp *dsp = s->private; + struct cs_dsp_coeff_ctl *ctl; + unsigned int reg; + + list_for_each_entry(ctl, &dsp->ctl_list, list) { + cs_dsp_coeff_base_reg(ctl, ®, 0); + seq_printf(s, "%22.*s: %#8zx %s:%08x %#8x %s %#8x %#4x %c%c%c%c %s %s\n", + ctl->subname_len, ctl->subname, ctl->len, + cs_dsp_mem_region_name(ctl->alg_region.type), + ctl->offset, reg, ctl->fw_name, ctl->alg_region.alg, ctl->type, + ctl->flags & WMFW_CTL_FLAG_VOLATILE ? 'V' : '-', + ctl->flags & WMFW_CTL_FLAG_SYS ? 'S' : '-', + ctl->flags & WMFW_CTL_FLAG_READABLE ? 'R' : '-', + ctl->flags & WMFW_CTL_FLAG_WRITEABLE ? 'W' : '-', + ctl->enabled ? "enabled" : "disabled", + ctl->set ? "dirty" : "clean"); + } + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(cs_dsp_debugfs_read_controls); + /** * cs_dsp_init_debugfs() - Create and populate DSP representation in debugfs * @dsp: pointer to DSP structure @@ -479,6 +507,9 @@ void cs_dsp_init_debugfs(struct cs_dsp *dsp, struct dentry *debugfs_root) debugfs_create_file(cs_dsp_debugfs_fops[i].name, 0444, root, dsp, &cs_dsp_debugfs_fops[i].fops); + debugfs_create_file("controls", 0444, root, dsp, + &cs_dsp_debugfs_read_controls_fops); + dsp->debugfs_root = root; } EXPORT_SYMBOL_NS_GPL(cs_dsp_init_debugfs, FW_CS_DSP); From ee4281de4d60288b9c802bb0906061ec355ecef2 Mon Sep 17 00:00:00 2001 From: Prajna Sariputra Date: Sun, 2 Apr 2023 02:21:30 +1100 Subject: [PATCH 655/778] ASoC: amd: yc: Add DMI entries to support HP OMEN 16-n0xxx (8A42) This model requires an additional detection quirk to enable the internal microphone. Signed-off-by: Prajna Sariputra Link: https://lore.kernel.org/r/2283110.ElGaqSPkdT@n0067ax-linux62 Signed-off-by: Mark Brown --- sound/soc/amd/yc/acp6x-mach.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sound/soc/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c index 0acdf0156f07..a428e17f0325 100644 --- a/sound/soc/amd/yc/acp6x-mach.c +++ b/sound/soc/amd/yc/acp6x-mach.c @@ -262,6 +262,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "OMEN by HP Gaming Laptop 16z-n000"), } }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "HP"), + DMI_MATCH(DMI_BOARD_NAME, "8A42"), + } + }, { .driver_data = &acp6x_card, .matches = { From 5781c22ea87700cd1da8f8de8a82fc10ef2f14d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Morishita?= Date: Sat, 1 Apr 2023 15:19:29 -0300 Subject: [PATCH 656/778] ASoC: dt-bindings: maxim,max98371: Convert to DT schema MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Convert the Maxim Integrated MAX98371 audio codec bindings to DT schema. Signed-off-by: André Morishita Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230401181930.533067-1-andremorishita@gmail.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/max98371.txt | 17 -------- .../bindings/sound/maxim,max98371.yaml | 42 +++++++++++++++++++ 2 files changed, 42 insertions(+), 17 deletions(-) delete mode 100644 Documentation/devicetree/bindings/sound/max98371.txt create mode 100644 Documentation/devicetree/bindings/sound/maxim,max98371.yaml diff --git a/Documentation/devicetree/bindings/sound/max98371.txt b/Documentation/devicetree/bindings/sound/max98371.txt deleted file mode 100644 index 8b2b2704b574..000000000000 --- a/Documentation/devicetree/bindings/sound/max98371.txt +++ /dev/null @@ -1,17 +0,0 @@ -max98371 codec - -This device supports I2C mode only. - -Required properties: - -- compatible : "maxim,max98371" -- reg : The chip select number on the I2C bus - -Example: - -&i2c { - max98371: max98371@31 { - compatible = "maxim,max98371"; - reg = <0x31>; - }; -}; diff --git a/Documentation/devicetree/bindings/sound/maxim,max98371.yaml b/Documentation/devicetree/bindings/sound/maxim,max98371.yaml new file mode 100644 index 000000000000..14fba34ef81a --- /dev/null +++ b/Documentation/devicetree/bindings/sound/maxim,max98371.yaml @@ -0,0 +1,42 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/maxim,max98371.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Maxim MAX98371 audio codec + +maintainers: + - anish kumar + +allOf: + - $ref: dai-common.yaml# + +properties: + compatible: + const: maxim,max98371 + + '#sound-dai-cells': + const: 0 + + reg: + maxItems: 1 + +required: + - compatible + - reg + +unevaluatedProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + + codec@31 { + compatible = "maxim,max98371"; + reg = <0x31>; + #sound-dai-cells = <0>; + }; + }; From 56e008146e5b46059c5469a8b47478ab78f5b895 Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Mon, 3 Apr 2023 12:46:41 +0530 Subject: [PATCH 657/778] ASoC: SOF: amd: remove unused code During initial SOF driver bring up on AMD platforms, only DMIC support was added. As of today, we have a complete SOF solution for I2S endpoints along with DMIC endpoint. This code is no longer required. Remove unused code from RMB and RN platform ACP PCI driver. Signed-off-by: Vijendar Mukunda Link: https://lore.kernel.org/r/20230403071651.919027-1-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/sof/amd/pci-rmb.c | 70 +------------------------------------ sound/soc/sof/amd/pci-rn.c | 70 +------------------------------------ 2 files changed, 2 insertions(+), 138 deletions(-) diff --git a/sound/soc/sof/amd/pci-rmb.c b/sound/soc/sof/amd/pci-rmb.c index 4e1de462b431..d0a56e8f09c0 100644 --- a/sound/soc/sof/amd/pci-rmb.c +++ b/sound/soc/sof/amd/pci-rmb.c @@ -27,22 +27,6 @@ #define ACP6x_REG_END 0x125C000 static struct platform_device *dmic_dev; -static struct platform_device *pdev; - -static const struct resource rembrandt_res[] = { - { - .start = 0, - .end = ACP6x_REG_END - ACP6x_REG_START, - .name = "acp_mem", - .flags = IORESOURCE_MEM, - }, - { - .start = 0, - .end = 0, - .name = "acp_dai_irq", - .flags = IORESOURCE_IRQ, - }, -}; static const struct sof_amd_acp_desc rembrandt_chip_info = { .rev = 6, @@ -83,11 +67,8 @@ static const struct sof_dev_desc rembrandt_desc = { static int acp_pci_rmb_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { - struct platform_device_info pdevinfo; struct device *dev = &pci->dev; - const struct resource *res_i2s; - struct resource *res; - unsigned int flag, i, addr; + unsigned int flag; int ret; flag = snd_amd_acp_find_config(pci); @@ -104,53 +85,6 @@ static int acp_pci_rmb_probe(struct pci_dev *pci, const struct pci_device_id *pc sof_pci_remove(pci); return PTR_ERR(dmic_dev); } - - /* Register platform device only if flag set to FLAG_AMD_SOF_ONLY_DMIC */ - if (flag != FLAG_AMD_SOF_ONLY_DMIC) - return 0; - - addr = pci_resource_start(pci, 0); - res = devm_kzalloc(&pci->dev, sizeof(struct resource) * ARRAY_SIZE(rembrandt_res), - GFP_KERNEL); - if (!res) { - platform_device_unregister(dmic_dev); - sof_pci_remove(pci); - return -ENOMEM; - } - - res_i2s = rembrandt_res; - for (i = 0; i < ARRAY_SIZE(rembrandt_res); i++, res_i2s++) { - res[i].name = res_i2s->name; - res[i].flags = res_i2s->flags; - res[i].start = addr + res_i2s->start; - res[i].end = addr + res_i2s->end; - if (res_i2s->flags == IORESOURCE_IRQ) { - res[i].start = pci->irq; - res[i].end = res[i].start; - } - } - - memset(&pdevinfo, 0, sizeof(pdevinfo)); - - /* - * We have common PCI driver probe for ACP device but we have to support I2S without SOF - * for some distributions. Register platform device that will be used to support non dsp - * ACP's audio ends points on some machines. - */ - pdevinfo.name = "acp_asoc_rembrandt"; - pdevinfo.id = 0; - pdevinfo.parent = &pci->dev; - pdevinfo.num_res = ARRAY_SIZE(rembrandt_res); - pdevinfo.res = &res[0]; - - pdev = platform_device_register_full(&pdevinfo); - if (IS_ERR(pdev)) { - dev_err(&pci->dev, "cannot register %s device\n", pdevinfo.name); - platform_device_unregister(dmic_dev); - sof_pci_remove(pci); - ret = PTR_ERR(pdev); - } - return ret; }; @@ -158,8 +92,6 @@ static void acp_pci_rmb_remove(struct pci_dev *pci) { if (dmic_dev) platform_device_unregister(dmic_dev); - if (pdev) - platform_device_unregister(pdev); sof_pci_remove(pci); } diff --git a/sound/soc/sof/amd/pci-rn.c b/sound/soc/sof/amd/pci-rn.c index fca40b261671..faab4c33a24d 100644 --- a/sound/soc/sof/amd/pci-rn.c +++ b/sound/soc/sof/amd/pci-rn.c @@ -27,22 +27,6 @@ #define ACP3x_REG_END 0x125C000 static struct platform_device *dmic_dev; -static struct platform_device *pdev; - -static const struct resource renoir_res[] = { - { - .start = 0, - .end = ACP3x_REG_END - ACP3x_REG_START, - .name = "acp_mem", - .flags = IORESOURCE_MEM, - }, - { - .start = 0, - .end = 0, - .name = "acp_dai_irq", - .flags = IORESOURCE_IRQ, - }, -}; static const struct sof_amd_acp_desc renoir_chip_info = { .rev = 3, @@ -83,11 +67,8 @@ static const struct sof_dev_desc renoir_desc = { static int acp_pci_rn_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { - struct platform_device_info pdevinfo; struct device *dev = &pci->dev; - const struct resource *res_i2s; - struct resource *res; - unsigned int flag, i, addr; + unsigned int flag; int ret; flag = snd_amd_acp_find_config(pci); @@ -104,53 +85,6 @@ static int acp_pci_rn_probe(struct pci_dev *pci, const struct pci_device_id *pci sof_pci_remove(pci); return PTR_ERR(dmic_dev); } - - /* Register platform device only if flag set to FLAG_AMD_SOF_ONLY_DMIC */ - if (flag != FLAG_AMD_SOF_ONLY_DMIC) - return 0; - - addr = pci_resource_start(pci, 0); - res = devm_kzalloc(&pci->dev, sizeof(struct resource) * ARRAY_SIZE(renoir_res), GFP_KERNEL); - if (!res) { - sof_pci_remove(pci); - platform_device_unregister(dmic_dev); - return -ENOMEM; - } - - res_i2s = renoir_res; - for (i = 0; i < ARRAY_SIZE(renoir_res); i++, res_i2s++) { - res[i].name = res_i2s->name; - res[i].flags = res_i2s->flags; - res[i].start = addr + res_i2s->start; - res[i].end = addr + res_i2s->end; - if (res_i2s->flags == IORESOURCE_IRQ) { - res[i].start = pci->irq; - res[i].end = res[i].start; - } - } - - memset(&pdevinfo, 0, sizeof(pdevinfo)); - - /* - * We have common PCI driver probe for ACP device but we have to support I2S without SOF - * for some distributions. Register platform device that will be used to support non dsp - * ACP's audio ends points on some machines. - */ - - pdevinfo.name = "acp_asoc_renoir"; - pdevinfo.id = 0; - pdevinfo.parent = &pci->dev; - pdevinfo.num_res = ARRAY_SIZE(renoir_res); - pdevinfo.res = &res[0]; - - pdev = platform_device_register_full(&pdevinfo); - if (IS_ERR(pdev)) { - dev_err(&pci->dev, "cannot register %s device\n", pdevinfo.name); - sof_pci_remove(pci); - platform_device_unregister(dmic_dev); - ret = PTR_ERR(pdev); - } - return ret; }; @@ -158,8 +92,6 @@ static void acp_pci_rn_remove(struct pci_dev *pci) { if (dmic_dev) platform_device_unregister(dmic_dev); - if (pdev) - platform_device_unregister(pdev); return sof_pci_remove(pci); } From 9eb48aeddd8dcf2defd94a837a65e052576cf42b Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Mon, 3 Apr 2023 12:46:42 +0530 Subject: [PATCH 658/778] ASoC: SOF: amd: remove acp_dai_probe() function ACP SOF driver supports different audio configurations. Explicit condition check for I2S configuration will break other audio endpoint configurations. acp_dai_probe() function is not required as we have machine select logic to select the exact machine. Remove acp_dai_probe() from existing AMD PCI driver code base. Signed-off-by: Vijendar Mukunda Link: https://lore.kernel.org/r/20230403071651.919027-2-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/sof/amd/acp-common.c | 16 ---------------- sound/soc/sof/amd/acp.h | 1 - sound/soc/sof/amd/rembrandt.c | 4 ---- sound/soc/sof/amd/renoir.c | 3 --- 4 files changed, 24 deletions(-) diff --git a/sound/soc/sof/amd/acp-common.c b/sound/soc/sof/amd/acp-common.c index 8ce4c8956933..df36b411a12e 100644 --- a/sound/soc/sof/amd/acp-common.c +++ b/sound/soc/sof/amd/acp-common.c @@ -18,22 +18,6 @@ #include "acp-dsp-offset.h" #include -int acp_dai_probe(struct snd_soc_dai *dai) -{ - struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(dai->component); - const struct sof_amd_acp_desc *desc = get_chip_info(sdev->pdata); - unsigned int val; - - val = snd_sof_dsp_read(sdev, ACP_DSP_BAR, desc->i2s_pin_config_offset); - if (val != desc->i2s_mode) { - dev_err(sdev->dev, "I2S Mode is not supported (I2S_PIN_CONFIG: %#x)\n", val); - return -EINVAL; - } - - return 0; -} -EXPORT_SYMBOL_NS(acp_dai_probe, SND_SOC_SOF_AMD_COMMON); - /** * amd_sof_ipc_dump() - This function is called when IPC tx times out. * @sdev: SOF device. diff --git a/sound/soc/sof/amd/acp.h b/sound/soc/sof/amd/acp.h index acad57947616..d7fc24917b3c 100644 --- a/sound/soc/sof/amd/acp.h +++ b/sound/soc/sof/amd/acp.h @@ -248,7 +248,6 @@ int sof_renoir_ops_init(struct snd_sof_dev *sdev); extern struct snd_sof_dsp_ops sof_rembrandt_ops; int sof_rembrandt_ops_init(struct snd_sof_dev *sdev); -int acp_dai_probe(struct snd_soc_dai *dai); struct snd_soc_acpi_mach *amd_sof_machine_select(struct snd_sof_dev *sdev); /* Machine configuration */ int snd_amd_acp_find_config(struct pci_dev *pci); diff --git a/sound/soc/sof/amd/rembrandt.c b/sound/soc/sof/amd/rembrandt.c index 5288ab882fc9..f1d1ba57ab3a 100644 --- a/sound/soc/sof/amd/rembrandt.c +++ b/sound/soc/sof/amd/rembrandt.c @@ -48,7 +48,6 @@ static struct snd_soc_dai_driver rembrandt_sof_dai[] = { .rate_min = 8000, .rate_max = 48000, }, - .probe = &acp_dai_probe, }, [I2S_BT_INSTANCE] = { @@ -73,7 +72,6 @@ static struct snd_soc_dai_driver rembrandt_sof_dai[] = { .rate_min = 8000, .rate_max = 48000, }, - .probe = &acp_dai_probe, }, [I2S_SP_INSTANCE] = { @@ -98,7 +96,6 @@ static struct snd_soc_dai_driver rembrandt_sof_dai[] = { .rate_min = 8000, .rate_max = 48000, }, - .probe = &acp_dai_probe, }, [PDM_DMIC_INSTANCE] = { @@ -126,7 +123,6 @@ static struct snd_soc_dai_driver rembrandt_sof_dai[] = { .rate_min = 8000, .rate_max = 96000, }, - .probe = &acp_dai_probe, }, }; diff --git a/sound/soc/sof/amd/renoir.c b/sound/soc/sof/amd/renoir.c index adade2e3d3be..47b863f6258c 100644 --- a/sound/soc/sof/amd/renoir.c +++ b/sound/soc/sof/amd/renoir.c @@ -47,7 +47,6 @@ static struct snd_soc_dai_driver renoir_sof_dai[] = { .rate_min = 8000, .rate_max = 48000, }, - .probe = &acp_dai_probe, }, [I2S_SP_INSTANCE] = { @@ -72,7 +71,6 @@ static struct snd_soc_dai_driver renoir_sof_dai[] = { .rate_min = 8000, .rate_max = 48000, }, - .probe = &acp_dai_probe, }, [PDM_DMIC_INSTANCE] = { @@ -100,7 +98,6 @@ static struct snd_soc_dai_driver renoir_sof_dai[] = { .rate_min = 8000, .rate_max = 96000, }, - .probe = &acp_dai_probe, }, }; From 2675de62de702dbda936eb0f9a20ce3d8fed5ab5 Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Mon, 3 Apr 2023 12:46:43 +0530 Subject: [PATCH 659/778] ASoC: SOF: amd: remove unused variables Remove unused variables - i2s_mode, i2s_pin_config_offset from code. Signed-off-by: Vijendar Mukunda Link: https://lore.kernel.org/r/20230403071651.919027-3-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/sof/amd/acp.h | 2 -- sound/soc/sof/amd/pci-rmb.c | 2 -- sound/soc/sof/amd/pci-rn.c | 2 -- 3 files changed, 6 deletions(-) diff --git a/sound/soc/sof/amd/acp.h b/sound/soc/sof/amd/acp.h index d7fc24917b3c..fd04e5ae7303 100644 --- a/sound/soc/sof/amd/acp.h +++ b/sound/soc/sof/amd/acp.h @@ -158,12 +158,10 @@ struct acp_dsp_stream { struct sof_amd_acp_desc { unsigned int rev; unsigned int host_bridge_id; - unsigned int i2s_mode; u32 pgfsm_base; u32 ext_intr_stat; u32 dsp_intr_base; u32 sram_pte_offset; - u32 i2s_pin_config_offset; u32 hw_semaphore_offset; u32 acp_clkmux_sel; u32 fusion_dsp_offset; diff --git a/sound/soc/sof/amd/pci-rmb.c b/sound/soc/sof/amd/pci-rmb.c index d0a56e8f09c0..2b84f95072d3 100644 --- a/sound/soc/sof/amd/pci-rmb.c +++ b/sound/soc/sof/amd/pci-rmb.c @@ -31,12 +31,10 @@ static struct platform_device *dmic_dev; static const struct sof_amd_acp_desc rembrandt_chip_info = { .rev = 6, .host_bridge_id = HOST_BRIDGE_RMB, - .i2s_mode = 0x0a, .pgfsm_base = ACP6X_PGFSM_BASE, .ext_intr_stat = ACP6X_EXT_INTR_STAT, .dsp_intr_base = ACP6X_DSP_SW_INTR_BASE, .sram_pte_offset = ACP6X_SRAM_PTE_OFFSET, - .i2s_pin_config_offset = ACP6X_I2S_PIN_CONFIG, .hw_semaphore_offset = ACP6X_AXI2DAGB_SEM_0, .acp_clkmux_sel = ACP6X_CLKMUX_SEL, .fusion_dsp_offset = ACP6X_DSP_FUSION_RUNSTALL, diff --git a/sound/soc/sof/amd/pci-rn.c b/sound/soc/sof/amd/pci-rn.c index faab4c33a24d..a17b15552a7d 100644 --- a/sound/soc/sof/amd/pci-rn.c +++ b/sound/soc/sof/amd/pci-rn.c @@ -31,12 +31,10 @@ static struct platform_device *dmic_dev; static const struct sof_amd_acp_desc renoir_chip_info = { .rev = 3, .host_bridge_id = HOST_BRIDGE_CZN, - .i2s_mode = 0x04, .pgfsm_base = ACP3X_PGFSM_BASE, .ext_intr_stat = ACP3X_EXT_INTR_STAT, .dsp_intr_base = ACP3X_DSP_SW_INTR_BASE, .sram_pte_offset = ACP3X_SRAM_PTE_OFFSET, - .i2s_pin_config_offset = ACP3X_I2S_PIN_CONFIG, .hw_semaphore_offset = ACP3X_AXI2DAGB_SEM_0, .acp_clkmux_sel = ACP3X_CLKMUX_SEL, }; From 292b544ef4555ec5c69522e9c6eace6a90c4cd00 Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Mon, 3 Apr 2023 12:46:44 +0530 Subject: [PATCH 660/778] ASoC: SOF: amd: refactor get_chip_info callback Move get_chip_info callback to the start of API. This should be first check in probe() call. Signed-off-by: Vijendar Mukunda Link: https://lore.kernel.org/r/20230403071651.919027-4-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/sof/amd/acp.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/sound/soc/sof/amd/acp.c b/sound/soc/sof/amd/acp.c index d5ccd4d09278..e8fe324c23d0 100644 --- a/sound/soc/sof/amd/acp.c +++ b/sound/soc/sof/amd/acp.c @@ -470,6 +470,11 @@ int amd_sof_acp_probe(struct snd_sof_dev *sdev) unsigned int addr; int ret; + chip = get_chip_info(sdev->pdata); + if (!chip) { + dev_err(sdev->dev, "no such device supported, chip id:%x\n", pci->device); + return -EIO; + } adata = devm_kzalloc(sdev->dev, sizeof(struct acp_dev_data), GFP_KERNEL); if (!adata) @@ -486,13 +491,6 @@ int amd_sof_acp_probe(struct snd_sof_dev *sdev) pci_set_master(pci); sdev->pdata->hw_pdata = adata; - - chip = get_chip_info(sdev->pdata); - if (!chip) { - dev_err(sdev->dev, "no such device supported, chip id:%x\n", pci->device); - return -EIO; - } - adata->smn_dev = pci_get_device(PCI_VENDOR_ID_AMD, chip->host_bridge_id, NULL); if (!adata->smn_dev) { dev_err(sdev->dev, "Failed to get host bridge device\n"); From c7a3662f14d7e0add7b50dc2f971e77bebb333cc Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Mon, 3 Apr 2023 12:46:45 +0530 Subject: [PATCH 661/778] ASoC: SOF: amd: refactor error checks in probe call Refactor error checks code in probe() callback. Signed-off-by: Vijendar Mukunda Link: https://lore.kernel.org/r/20230403071651.919027-5-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/sof/amd/acp.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/sound/soc/sof/amd/acp.c b/sound/soc/sof/amd/acp.c index e8fe324c23d0..dbf9ee6d79ed 100644 --- a/sound/soc/sof/amd/acp.c +++ b/sound/soc/sof/amd/acp.c @@ -503,16 +503,12 @@ int amd_sof_acp_probe(struct snd_sof_dev *sdev) if (ret < 0) { dev_err(sdev->dev, "failed to register IRQ %d\n", sdev->ipc_irq); - pci_dev_put(adata->smn_dev); - return ret; + goto free_smn_dev; } ret = acp_init(sdev); - if (ret < 0) { - free_irq(sdev->ipc_irq, sdev); - pci_dev_put(adata->smn_dev); - return ret; - } + if (ret < 0) + goto free_ipc_irq; sdev->dsp_box.offset = 0; sdev->dsp_box.size = BOX_SIZE_512; @@ -528,6 +524,12 @@ int amd_sof_acp_probe(struct snd_sof_dev *sdev) acp_dsp_stream_init(sdev); return 0; + +free_ipc_irq: + free_irq(sdev->ipc_irq, sdev); +free_smn_dev: + pci_dev_put(adata->smn_dev); + return ret; } EXPORT_SYMBOL_NS(amd_sof_acp_probe, SND_SOC_SOF_AMD_COMMON); From dd6bdd8b4d41b8f9db4b88dff2d10c0c62dbeb1d Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Mon, 3 Apr 2023 12:46:46 +0530 Subject: [PATCH 662/778] ASoC: SOF: amd: refactor dmic codec platform device creation Under snd_sof_dev device scope, create platform device for dmic codec. Signed-off-by: Vijendar Mukunda Link: https://lore.kernel.org/r/168050621098.26.7486882101201297853@mailman-core.alsa-project.org Signed-off-by: Mark Brown --- sound/soc/sof/amd/acp.c | 17 +++++++++++++++-- sound/soc/sof/amd/acp.h | 2 ++ sound/soc/sof/amd/pci-rmb.c | 19 +------------------ sound/soc/sof/amd/pci-rn.c | 19 +------------------ 4 files changed, 19 insertions(+), 38 deletions(-) diff --git a/sound/soc/sof/amd/acp.c b/sound/soc/sof/amd/acp.c index dbf9ee6d79ed..2ae76bcd3590 100644 --- a/sound/soc/sof/amd/acp.c +++ b/sound/soc/sof/amd/acp.c @@ -481,11 +481,18 @@ int amd_sof_acp_probe(struct snd_sof_dev *sdev) return -ENOMEM; adata->dev = sdev; + adata->dmic_dev = platform_device_register_data(sdev->dev, "dmic-codec", + PLATFORM_DEVID_NONE, NULL, 0); + if (IS_ERR(adata->dmic_dev)) { + dev_err(sdev->dev, "failed to register platform for dmic codec\n"); + return PTR_ERR(adata->dmic_dev); + } addr = pci_resource_start(pci, ACP_DSP_BAR); sdev->bar[ACP_DSP_BAR] = devm_ioremap(sdev->dev, addr, pci_resource_len(pci, ACP_DSP_BAR)); if (!sdev->bar[ACP_DSP_BAR]) { dev_err(sdev->dev, "ioremap error\n"); - return -ENXIO; + ret = -ENXIO; + goto unregister_dev; } pci_set_master(pci); @@ -494,7 +501,8 @@ int amd_sof_acp_probe(struct snd_sof_dev *sdev) adata->smn_dev = pci_get_device(PCI_VENDOR_ID_AMD, chip->host_bridge_id, NULL); if (!adata->smn_dev) { dev_err(sdev->dev, "Failed to get host bridge device\n"); - return -ENODEV; + ret = -ENODEV; + goto unregister_dev; } sdev->ipc_irq = pci->irq; @@ -529,6 +537,8 @@ free_ipc_irq: free_irq(sdev->ipc_irq, sdev); free_smn_dev: pci_dev_put(adata->smn_dev); +unregister_dev: + platform_device_unregister(adata->dmic_dev); return ret; } EXPORT_SYMBOL_NS(amd_sof_acp_probe, SND_SOC_SOF_AMD_COMMON); @@ -543,6 +553,9 @@ int amd_sof_acp_remove(struct snd_sof_dev *sdev) if (sdev->ipc_irq) free_irq(sdev->ipc_irq, sdev); + if (adata->dmic_dev) + platform_device_unregister(adata->dmic_dev); + return acp_reset(sdev); } EXPORT_SYMBOL_NS(amd_sof_acp_remove, SND_SOC_SOF_AMD_COMMON); diff --git a/sound/soc/sof/amd/acp.h b/sound/soc/sof/amd/acp.h index fd04e5ae7303..1c535cc6c3a9 100644 --- a/sound/soc/sof/amd/acp.h +++ b/sound/soc/sof/amd/acp.h @@ -170,6 +170,8 @@ struct sof_amd_acp_desc { /* Common device data struct for ACP devices */ struct acp_dev_data { struct snd_sof_dev *dev; + /* DMIC device */ + struct platform_device *dmic_dev; unsigned int fw_bin_size; unsigned int fw_data_bin_size; u32 fw_bin_page_count; diff --git a/sound/soc/sof/amd/pci-rmb.c b/sound/soc/sof/amd/pci-rmb.c index 2b84f95072d3..eaf70ea6e556 100644 --- a/sound/soc/sof/amd/pci-rmb.c +++ b/sound/soc/sof/amd/pci-rmb.c @@ -26,8 +26,6 @@ #define ACP6x_REG_START 0x1240000 #define ACP6x_REG_END 0x125C000 -static struct platform_device *dmic_dev; - static const struct sof_amd_acp_desc rembrandt_chip_info = { .rev = 6, .host_bridge_id = HOST_BRIDGE_RMB, @@ -65,32 +63,17 @@ static const struct sof_dev_desc rembrandt_desc = { static int acp_pci_rmb_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { - struct device *dev = &pci->dev; unsigned int flag; - int ret; flag = snd_amd_acp_find_config(pci); if (flag != FLAG_AMD_SOF && flag != FLAG_AMD_SOF_ONLY_DMIC) return -ENODEV; - ret = sof_pci_probe(pci, pci_id); - if (ret != 0) - return ret; - - dmic_dev = platform_device_register_data(dev, "dmic-codec", PLATFORM_DEVID_NONE, NULL, 0); - if (IS_ERR(dmic_dev)) { - dev_err(dev, "failed to create DMIC device\n"); - sof_pci_remove(pci); - return PTR_ERR(dmic_dev); - } - return ret; + return sof_pci_probe(pci, pci_id); }; static void acp_pci_rmb_remove(struct pci_dev *pci) { - if (dmic_dev) - platform_device_unregister(dmic_dev); - sof_pci_remove(pci); } diff --git a/sound/soc/sof/amd/pci-rn.c b/sound/soc/sof/amd/pci-rn.c index a17b15552a7d..4809cb644152 100644 --- a/sound/soc/sof/amd/pci-rn.c +++ b/sound/soc/sof/amd/pci-rn.c @@ -26,8 +26,6 @@ #define ACP3x_REG_START 0x1240000 #define ACP3x_REG_END 0x125C000 -static struct platform_device *dmic_dev; - static const struct sof_amd_acp_desc renoir_chip_info = { .rev = 3, .host_bridge_id = HOST_BRIDGE_CZN, @@ -65,32 +63,17 @@ static const struct sof_dev_desc renoir_desc = { static int acp_pci_rn_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { - struct device *dev = &pci->dev; unsigned int flag; - int ret; flag = snd_amd_acp_find_config(pci); if (flag != FLAG_AMD_SOF && flag != FLAG_AMD_SOF_ONLY_DMIC) return -ENODEV; - ret = sof_pci_probe(pci, pci_id); - if (ret != 0) - return ret; - - dmic_dev = platform_device_register_data(dev, "dmic-codec", PLATFORM_DEVID_NONE, NULL, 0); - if (IS_ERR(dmic_dev)) { - dev_err(dev, "failed to create DMIC device\n"); - sof_pci_remove(pci); - return PTR_ERR(dmic_dev); - } - return ret; + return sof_pci_probe(pci, pci_id); }; static void acp_pci_rn_remove(struct pci_dev *pci) { - if (dmic_dev) - platform_device_unregister(dmic_dev); - return sof_pci_remove(pci); } From 3af24372964a8f999d62427c0585d9a4693ae4e4 Mon Sep 17 00:00:00 2001 From: Allen-KH Cheng Date: Wed, 29 Mar 2023 16:04:18 +0800 Subject: [PATCH 663/778] ASoC: mediatek: mt8186: Move some prints to debug level There are many log messages scattered throughout the mt8186 sound drivers, and they are frequently triggered. To avoid spamming the console, move these messages to the debug level. Signed-off-by: Allen-KH Cheng Link: https://lore.kernel.org/r/20230329080418.1100-1-allen-kh.cheng@mediatek.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8186/mt8186-afe-gpio.c | 26 +++++++++---------- sound/soc/mediatek/mt8186/mt8186-dai-adda.c | 4 +-- .../mt8186/mt8186-mt6366-da7219-max98357.c | 2 +- .../mt8186/mt8186-mt6366-rt1019-rt5682s.c | 6 ++--- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/sound/soc/mediatek/mt8186/mt8186-afe-gpio.c b/sound/soc/mediatek/mt8186/mt8186-afe-gpio.c index eda913fa147a..20b9f5d810ec 100644 --- a/sound/soc/mediatek/mt8186/mt8186-afe-gpio.c +++ b/sound/soc/mediatek/mt8186/mt8186-afe-gpio.c @@ -85,7 +85,7 @@ int mt8186_afe_gpio_init(struct device *dev) aud_gpios[i].name); if (IS_ERR(aud_gpios[i].gpioctrl)) { ret = PTR_ERR(aud_gpios[i].gpioctrl); - dev_info(dev, "%s(), pinctrl_lookup_state %s fail, ret %d\n", + dev_dbg(dev, "%s(), pinctrl_lookup_state %s fail, ret %d\n", __func__, aud_gpios[i].name, ret); } else { aud_gpios[i].gpio_prepare = true; @@ -108,13 +108,13 @@ static int mt8186_afe_gpio_select(struct device *dev, int ret = 0; if (type < 0 || type >= MT8186_AFE_GPIO_GPIO_NUM) { - dev_err(dev, "%s(), error, invalid gpio type %d\n", + dev_dbg(dev, "%s(), error, invalid gpio type %d\n", __func__, type); return -EINVAL; } if (!aud_gpios[type].gpio_prepare) { - dev_err(dev, "%s(), error, gpio type %d not prepared\n", + dev_dbg(dev, "%s(), error, gpio type %d not prepared\n", __func__, type); return -EIO; } @@ -122,7 +122,7 @@ static int mt8186_afe_gpio_select(struct device *dev, ret = pinctrl_select_state(aud_pinctrl, aud_gpios[type].gpioctrl); if (ret) { - dev_err(dev, "%s(), error, can not set gpio type %d\n", + dev_dbg(dev, "%s(), error, can not set gpio type %d\n", __func__, type); return ret; } @@ -137,25 +137,25 @@ static int mt8186_afe_gpio_adda_dl(struct device *dev, bool enable) if (enable) { ret = mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_CLK_MOSI_ON); if (ret) { - dev_err(dev, "%s(), MOSI CLK ON select fail!\n", __func__); + dev_dbg(dev, "%s(), MOSI CLK ON select fail!\n", __func__); return ret; } ret = mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_DAT_MOSI_ON); if (ret) { - dev_err(dev, "%s(), MOSI DAT ON select fail!\n", __func__); + dev_dbg(dev, "%s(), MOSI DAT ON select fail!\n", __func__); return ret; } } else { ret = mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_DAT_MOSI_OFF); if (ret) { - dev_err(dev, "%s(), MOSI DAT OFF select fail!\n", __func__); + dev_dbg(dev, "%s(), MOSI DAT OFF select fail!\n", __func__); return ret; } ret = mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_CLK_MOSI_OFF); if (ret) { - dev_err(dev, "%s(), MOSI CLK ON select fail!\n", __func__); + dev_dbg(dev, "%s(), MOSI CLK ON select fail!\n", __func__); return ret; } } @@ -170,25 +170,25 @@ static int mt8186_afe_gpio_adda_ul(struct device *dev, bool enable) if (enable) { ret = mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_CLK_MISO_ON); if (ret) { - dev_err(dev, "%s(), MISO CLK ON select fail!\n", __func__); + dev_dbg(dev, "%s(), MISO CLK ON select fail!\n", __func__); return ret; } ret = mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_DAT_MISO_ON); if (ret) { - dev_err(dev, "%s(), MISO DAT ON select fail!\n", __func__); + dev_dbg(dev, "%s(), MISO DAT ON select fail!\n", __func__); return ret; } } else { ret = mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_DAT_MISO_OFF); if (ret) { - dev_err(dev, "%s(), MISO DAT OFF select fail!\n", __func__); + dev_dbg(dev, "%s(), MISO DAT OFF select fail!\n", __func__); return ret; } ret = mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_CLK_MISO_OFF); if (ret) { - dev_err(dev, "%s(), MISO CLK OFF select fail!\n", __func__); + dev_dbg(dev, "%s(), MISO CLK OFF select fail!\n", __func__); return ret; } } @@ -230,7 +230,7 @@ int mt8186_afe_gpio_request(struct device *dev, bool enable, sel = enable ? MT8186_AFE_GPIO_PCM_ON : MT8186_AFE_GPIO_PCM_OFF; break; default: - dev_err(dev, "%s(), invalid dai %d\n", __func__, dai); + dev_dbg(dev, "%s(), invalid dai %d\n", __func__, dai); goto unlock; } diff --git a/sound/soc/mediatek/mt8186/mt8186-dai-adda.c b/sound/soc/mediatek/mt8186/mt8186-dai-adda.c index 094402470dc2..247ab8df941f 100644 --- a/sound/soc/mediatek/mt8186/mt8186-dai-adda.c +++ b/sound/soc/mediatek/mt8186/mt8186-dai-adda.c @@ -110,7 +110,7 @@ static unsigned int adda_dl_rate_transform(struct mtk_base_afe *afe, case 192000: return MTK_AFE_ADDA_DL_RATE_192K; default: - dev_info(afe->dev, "%s(), rate %d invalid, use 48kHz!!!\n", + dev_dbg(afe->dev, "%s(), rate %d invalid, use 48kHz!!!\n", __func__, rate); } @@ -134,7 +134,7 @@ static unsigned int adda_ul_rate_transform(struct mtk_base_afe *afe, case 192000: return MTK_AFE_ADDA_UL_RATE_192K; default: - dev_info(afe->dev, "%s(), rate %d invalid, use 48kHz!!!\n", + dev_dbg(afe->dev, "%s(), rate %d invalid, use 48kHz!!!\n", __func__, rate); } diff --git a/sound/soc/mediatek/mt8186/mt8186-mt6366-da7219-max98357.c b/sound/soc/mediatek/mt8186/mt8186-mt6366-da7219-max98357.c index 970b980a81e6..cdf54d1eb50d 100644 --- a/sound/soc/mediatek/mt8186/mt8186-mt6366-da7219-max98357.c +++ b/sound/soc/mediatek/mt8186/mt8186-mt6366-da7219-max98357.c @@ -1061,7 +1061,7 @@ static int mt8186_mt6366_da7219_max98357_dev_probe(struct platform_device *pdev) card->name = card->topology_shortname; sof_on = 1; } else { - dev_info(&pdev->dev, "Probe without adsp\n"); + dev_dbg(&pdev->dev, "Probe without adsp\n"); } if (of_property_read_bool(pdev->dev.of_node, "mediatek,dai-link")) { diff --git a/sound/soc/mediatek/mt8186/mt8186-mt6366-rt1019-rt5682s.c b/sound/soc/mediatek/mt8186/mt8186-mt6366-rt1019-rt5682s.c index b333950aa3c3..7538274641fd 100644 --- a/sound/soc/mediatek/mt8186/mt8186-mt6366-rt1019-rt5682s.c +++ b/sound/soc/mediatek/mt8186/mt8186-mt6366-rt1019-rt5682s.c @@ -95,7 +95,7 @@ static int dmic_set(struct snd_kcontrol *kcontrol, priv->dmic_switch = ucontrol->value.integer.value[0]; if (priv->dmic_sel) { gpiod_set_value(priv->dmic_sel, priv->dmic_switch); - dev_info(dapm->card->dev, "dmic_set_value %d\n", + dev_dbg(dapm->card->dev, "dmic_set_value %d\n", priv->dmic_switch); } return 0; @@ -139,7 +139,7 @@ static int primary_codec_init(struct snd_soc_pcm_runtime *rtd) } if (!priv->dmic_sel) { - dev_info(card->dev, "dmic_sel is null\n"); + dev_dbg(card->dev, "dmic_sel is null\n"); return 0; } @@ -1152,7 +1152,7 @@ static int mt8186_mt6366_rt1019_rt5682s_dev_probe(struct platform_device *pdev) card->name = card->topology_shortname; sof_on = 1; } else { - dev_info(&pdev->dev, "Probe without adsp\n"); + dev_dbg(&pdev->dev, "Probe without adsp\n"); } if (of_property_read_bool(pdev->dev.of_node, "mediatek,dai-link")) { From 09255c7ed8ca1f1ed99357b845d2f63fe2ef3e1e Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 4 Apr 2023 12:21:04 +0300 Subject: [PATCH 664/778] ASoC: SOF: Intel: hda-stream: Do not dereference hstream until it is safe Only access hext_stream->hstream after it has been checked for NULL pointer Signed-off-by: Peter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Rander Wang Link: https://lore.kernel.org/r/20230404092115.27949-2-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-stream.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index c37ef581637f..50e92996f928 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -485,9 +485,8 @@ int hda_dsp_stream_hw_params(struct snd_sof_dev *sdev, { const struct sof_intel_dsp_desc *chip = get_chip_info(sdev->pdata); struct hdac_bus *bus = sof_to_bus(sdev); - struct hdac_stream *hstream = &hext_stream->hstream; - int sd_offset = SOF_STREAM_SD_OFFSET(hstream); - int ret; + struct hdac_stream *hstream; + int sd_offset, ret; u32 dma_start = SOF_HDA_SD_CTL_DMA_START; u32 mask; u32 run; @@ -502,6 +501,9 @@ int hda_dsp_stream_hw_params(struct snd_sof_dev *sdev, return -ENODEV; } + hstream = &hext_stream->hstream; + sd_offset = SOF_STREAM_SD_OFFSET(hstream); + /* decouple host and link DMA */ mask = 0x1 << hstream->index; snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL, From 59611370f92923089ceb284072d01445164a0191 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 4 Apr 2023 12:21:05 +0300 Subject: [PATCH 665/778] ASoC: SOF: Add flag and state which will be used for DSP-less mode The DSPless mode of the ASoC/SOF driver can be used for hardware verification and debug on platforms with HDaudio codecs. The DSP mode is still needed on existing platforms for SSP, DMIC, SoundWire interfaces managed by the GP-DMA. This mode is also helpful to compare the legacy HDaudio driver with the ASoC/SOF driver wrt. codec management and handling. In theory we use the same code but differences are sometimes seen on jack detection and event handling. Signed-off-by: Peter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Rander Wang Link: https://lore.kernel.org/r/20230404092115.27949-3-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof.h | 5 +++++ sound/soc/sof/core.c | 9 +++++++++ sound/soc/sof/sof-priv.h | 11 +++++++++++ 3 files changed, 25 insertions(+) diff --git a/include/sound/sof.h b/include/sound/sof.h index 266e66318f9c..d3c41f87ac31 100644 --- a/include/sound/sof.h +++ b/include/sound/sof.h @@ -21,6 +21,7 @@ struct snd_sof_dev; /** * enum sof_fw_state - DSP firmware state definitions * @SOF_FW_BOOT_NOT_STARTED: firmware boot is not yet started + * @SOF_DSPLESS_MODE: DSP is not used * @SOF_FW_BOOT_PREPARE: preparing for boot (firmware loading for exaqmple) * @SOF_FW_BOOT_IN_PROGRESS: firmware boot is in progress * @SOF_FW_BOOT_FAILED: firmware boot failed @@ -31,6 +32,7 @@ struct snd_sof_dev; */ enum sof_fw_state { SOF_FW_BOOT_NOT_STARTED = 0, + SOF_DSPLESS_MODE, SOF_FW_BOOT_PREPARE, SOF_FW_BOOT_IN_PROGRESS, SOF_FW_BOOT_FAILED, @@ -130,6 +132,9 @@ struct sof_dev_desc { unsigned int ipc_supported_mask; enum sof_ipc_type ipc_default; + /* The platform supports DSPless mode */ + bool dspless_mode_supported; + /* defaults paths for firmware, library and topology files */ const char *default_fw_path[SOF_IPC_TYPE_COUNT]; const char *default_lib_path[SOF_IPC_TYPE_COUNT]; diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index 7de8673a01ce..06bcae631612 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -365,6 +365,15 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data) if (sof_core_debug) dev_info(dev, "sof_debug value: %#x\n", sof_core_debug); + if (sof_debug_check_flag(SOF_DBG_DSPLESS_MODE)) { + if (plat_data->desc->dspless_mode_supported) { + dev_info(dev, "Switching to DSPless mode\n"); + sdev->dspless_mode_selected = true; + } else { + dev_info(dev, "DSPless mode is not supported by the platform\n"); + } + } + /* check IPC support */ if (!(BIT(plat_data->ipc_type) & plat_data->desc->ipc_supported_mask)) { dev_err(dev, "ipc_type %d is not supported on this platform, mask is %#x\n", diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 5f919162a555..1170989bea57 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -48,6 +48,7 @@ struct snd_sof_pcm_stream; #define SOF_DBG_FORCE_NOCODEC BIT(10) /* ignore all codec-related * configurations */ +#define SOF_DBG_DSPLESS_MODE BIT(15) /* Do not initialize and use the DSP */ /* Flag definitions used for controlling the DSP dump behavior */ #define SOF_DBG_DUMP_REGS BIT(0) @@ -528,6 +529,16 @@ struct snd_sof_dev { spinlock_t ipc_lock; /* lock for IPC users */ spinlock_t hw_lock; /* lock for HW IO access */ + /* + * When true the DSP is not used. + * It is set under the following condition: + * User sets the SOF_DBG_DSPLESS_MODE flag in sof_debug module parameter + * and + * the platform advertises that it can support such mode + * pdata->desc->dspless_mode_supported is true. + */ + bool dspless_mode_selected; + /* Main, Base firmware image */ struct sof_firmware basefw; From 28d40e7adfd4108c11c9397c6fe9d9f80fed31e9 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 4 Apr 2023 12:21:06 +0300 Subject: [PATCH 666/778] ASoC: SOF: Add support for DSPless mode Via the SOF_DBG_DSPLESS_MODE sof_debug flag the SOF stack can be asked to not use the DSP for audio. The core's support for DSPless mode is only going to be enabled if the platform reports that it can be used without DSP. Signed-off-by: Peter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Rander Wang Link: https://lore.kernel.org/r/20230404092115.27949-4-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/core.c | 22 +++++-- sound/soc/sof/debug.c | 1 + sound/soc/sof/pcm.c | 13 +++- sound/soc/sof/pm.c | 5 ++ sound/soc/sof/sof-audio.c | 2 +- sound/soc/sof/sof-client.c | 3 + sound/soc/sof/topology.c | 130 ++++++++++++++++++++++++++++++++++++- 7 files changed, 168 insertions(+), 8 deletions(-) diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index 06bcae631612..9a9d82220fd0 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -208,6 +208,11 @@ static int sof_probe_continue(struct snd_sof_dev *sdev) /* set up platform component driver */ snd_sof_new_platform_drv(sdev); + if (sdev->dspless_mode_selected) { + sof_set_fw_state(sdev, SOF_DSPLESS_MODE); + goto skip_dsp_init; + } + /* register any debug/trace capabilities */ ret = snd_sof_dbg_init(sdev); if (ret < 0) { @@ -266,6 +271,7 @@ static int sof_probe_continue(struct snd_sof_dev *sdev) dev_dbg(sdev->dev, "SOF firmware trace disabled\n"); } +skip_dsp_init: /* hereafter all FW boot flows are for PM reasons */ sdev->first_boot = false; @@ -387,12 +393,18 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data) return ret; /* check all mandatory ops */ - if (!sof_ops(sdev) || !sof_ops(sdev)->probe || !sof_ops(sdev)->run || - !sof_ops(sdev)->block_read || !sof_ops(sdev)->block_write || - !sof_ops(sdev)->send_msg || !sof_ops(sdev)->load_firmware || - !sof_ops(sdev)->ipc_msg_data) { + if (!sof_ops(sdev) || !sof_ops(sdev)->probe) { sof_ops_free(sdev); - dev_err(dev, "error: missing mandatory ops\n"); + dev_err(dev, "missing mandatory ops\n"); + return -EINVAL; + } + + if (!sdev->dspless_mode_selected && + (!sof_ops(sdev)->run || !sof_ops(sdev)->block_read || + !sof_ops(sdev)->block_write || !sof_ops(sdev)->send_msg || + !sof_ops(sdev)->load_firmware || !sof_ops(sdev)->ipc_msg_data)) { + sof_ops_free(sdev); + dev_err(dev, "missing mandatory DSP ops\n"); return -EINVAL; } diff --git a/sound/soc/sof/debug.c b/sound/soc/sof/debug.c index ade0507328af..b42b5982cbbc 100644 --- a/sound/soc/sof/debug.c +++ b/sound/soc/sof/debug.c @@ -370,6 +370,7 @@ static const struct soc_fw_state_info { const char *name; } fw_state_dbg[] = { {SOF_FW_BOOT_NOT_STARTED, "SOF_FW_BOOT_NOT_STARTED"}, + {SOF_DSPLESS_MODE, "SOF_DSPLESS_MODE"}, {SOF_FW_BOOT_PREPARE, "SOF_FW_BOOT_PREPARE"}, {SOF_FW_BOOT_IN_PROGRESS, "SOF_FW_BOOT_IN_PROGRESS"}, {SOF_FW_BOOT_FAILED, "SOF_FW_BOOT_FAILED"}, diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index d9b4633bba7a..127b68caf9e1 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -330,6 +330,11 @@ static int sof_pcm_trigger(struct snd_soc_component *component, spcm->stream[substream->stream].suspend_ignored = true; return 0; } + + /* On suspend the DMA must be stopped in DSPless mode */ + if (sdev->dspless_mode_selected) + reset_hw_params = true; + fallthrough; case SNDRV_PCM_TRIGGER_STOP: ipc_first = true; @@ -705,7 +710,6 @@ void snd_sof_new_platform_drv(struct snd_sof_dev *sdev) pd->pcm_construct = sof_pcm_new; pd->ignore_machine = drv_name; - pd->be_hw_params_fixup = sof_pcm_dai_link_fixup; pd->be_pcm_base = SOF_BE_PCM_BASE; pd->use_dai_pcm_id = true; pd->topology_name_prefix = "sof"; @@ -714,4 +718,11 @@ void snd_sof_new_platform_drv(struct snd_sof_dev *sdev) pd->module_get_upon_open = 1; pd->legacy_dai_naming = 1; + + /* + * The fixup is only needed when the DSP is in use as with the DSPless + * mode we are directly using the audio interface + */ + if (!sdev->dspless_mode_selected) + pd->be_hw_params_fixup = sof_pcm_dai_link_fixup; } diff --git a/sound/soc/sof/pm.c b/sound/soc/sof/pm.c index 8d3383085d12..c74ce8d414e7 100644 --- a/sound/soc/sof/pm.c +++ b/sound/soc/sof/pm.c @@ -103,6 +103,11 @@ static int sof_resume(struct device *dev, bool runtime_resume) return ret; } + if (sdev->dspless_mode_selected) { + sof_set_fw_state(sdev, SOF_DSPLESS_MODE); + return 0; + } + /* * Nothing further to be done for platforms that support the low power * D0 substate. Resume trace and return when resuming from diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c index 4f12e137ff63..7651644fcd62 100644 --- a/sound/soc/sof/sof-audio.c +++ b/sound/soc/sof/sof-audio.c @@ -688,7 +688,7 @@ int sof_widget_list_setup(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm, struct snd_sof_widget *pipe_widget; struct snd_sof_pipeline *spipe; - if (!swidget) + if (!swidget || sdev->dspless_mode_selected) continue; spipe = swidget->spipe; diff --git a/sound/soc/sof/sof-client.c b/sound/soc/sof/sof-client.c index 9017f0864cdd..d6b7caa0cf03 100644 --- a/sound/soc/sof/sof-client.c +++ b/sound/soc/sof/sof-client.c @@ -130,6 +130,9 @@ int sof_register_clients(struct snd_sof_dev *sdev) { int ret; + if (sdev->dspless_mode_selected) + return 0; + /* Register platform independent client devices */ ret = sof_register_ipc_flood_test(sdev); if (ret) { diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index bc8ca1e05b83..d3d536b0a8f5 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -1144,8 +1144,12 @@ static void sof_disconnect_dai_widget(struct snd_soc_component *scomp, static int spcm_bind(struct snd_soc_component *scomp, struct snd_sof_pcm *spcm, int dir) { + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); struct snd_sof_widget *host_widget; + if (sdev->dspless_mode_selected) + return 0; + host_widget = snd_sof_find_swidget_sname(scomp, spcm->pcm.caps[dir].name, dir); @@ -2270,6 +2274,126 @@ static struct snd_soc_tplg_ops sof_tplg_ops = { .bytes_ext_ops_count = ARRAY_SIZE(sof_bytes_ext_ops), }; +static int snd_sof_dspless_kcontrol(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return 0; +} + +static const struct snd_soc_tplg_kcontrol_ops sof_dspless_io_ops[] = { + {SOF_TPLG_KCTL_VOL_ID, snd_sof_dspless_kcontrol, snd_sof_dspless_kcontrol}, + {SOF_TPLG_KCTL_BYTES_ID, snd_sof_dspless_kcontrol, snd_sof_dspless_kcontrol}, + {SOF_TPLG_KCTL_ENUM_ID, snd_sof_dspless_kcontrol, snd_sof_dspless_kcontrol}, + {SOF_TPLG_KCTL_SWITCH_ID, snd_sof_dspless_kcontrol, snd_sof_dspless_kcontrol}, +}; + +static int snd_sof_dspless_bytes_ext_get(struct snd_kcontrol *kcontrol, + unsigned int __user *binary_data, + unsigned int size) +{ + return 0; +} + +static int snd_sof_dspless_bytes_ext_put(struct snd_kcontrol *kcontrol, + const unsigned int __user *binary_data, + unsigned int size) +{ + return 0; +} + +static const struct snd_soc_tplg_bytes_ext_ops sof_dspless_bytes_ext_ops[] = { + {SOF_TPLG_KCTL_BYTES_ID, snd_sof_dspless_bytes_ext_get, snd_sof_dspless_bytes_ext_put}, + {SOF_TPLG_KCTL_BYTES_VOLATILE_RO, snd_sof_dspless_bytes_ext_get}, +}; + +/* external widget init - used for any driver specific init */ +static int sof_dspless_widget_ready(struct snd_soc_component *scomp, int index, + struct snd_soc_dapm_widget *w, + struct snd_soc_tplg_dapm_widget *tw) +{ + if (WIDGET_IS_DAI(w->id)) { + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); + struct snd_sof_widget *swidget; + struct snd_sof_dai dai; + int ret; + + swidget = kzalloc(sizeof(*swidget), GFP_KERNEL); + if (!swidget) + return -ENOMEM; + + memset(&dai, 0, sizeof(dai)); + + ret = sof_connect_dai_widget(scomp, w, tw, &dai); + if (ret) { + kfree(swidget); + return ret; + } + + swidget->scomp = scomp; + swidget->widget = w; + mutex_init(&swidget->setup_mutex); + w->dobj.private = swidget; + list_add(&swidget->list, &sdev->widget_list); + } + + return 0; +} + +static int sof_dspless_widget_unload(struct snd_soc_component *scomp, + struct snd_soc_dobj *dobj) +{ + struct snd_soc_dapm_widget *w = container_of(dobj, struct snd_soc_dapm_widget, dobj); + + if (WIDGET_IS_DAI(w->id)) { + struct snd_sof_widget *swidget = dobj->private; + + sof_disconnect_dai_widget(scomp, w); + + if (!swidget) + return 0; + + /* remove and free swidget object */ + list_del(&swidget->list); + kfree(swidget); + } + + return 0; +} + +static int sof_dspless_link_load(struct snd_soc_component *scomp, int index, + struct snd_soc_dai_link *link, + struct snd_soc_tplg_link_config *cfg) +{ + link->platforms->name = dev_name(scomp->dev); + + /* Set nonatomic property for FE dai links for FE-BE compatibility */ + if (!link->no_pcm) + link->nonatomic = true; + + return 0; +} + +static struct snd_soc_tplg_ops sof_dspless_tplg_ops = { + /* external widget init - used for any driver specific init */ + .widget_ready = sof_dspless_widget_ready, + .widget_unload = sof_dspless_widget_unload, + + /* FE DAI - used for any driver specific init */ + .dai_load = sof_dai_load, + .dai_unload = sof_dai_unload, + + /* DAI link - used for any driver specific init */ + .link_load = sof_dspless_link_load, + + /* vendor specific kcontrol handlers available for binding */ + .io_ops = sof_dspless_io_ops, + .io_ops_count = ARRAY_SIZE(sof_dspless_io_ops), + + /* vendor specific bytes ext handlers available for binding */ + .bytes_ext_ops = sof_dspless_bytes_ext_ops, + .bytes_ext_ops_count = ARRAY_SIZE(sof_dspless_bytes_ext_ops), +}; + int snd_sof_load_topology(struct snd_soc_component *scomp, const char *file) { struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); @@ -2287,7 +2411,11 @@ int snd_sof_load_topology(struct snd_soc_component *scomp, const char *file) return ret; } - ret = snd_soc_tplg_component_load(scomp, &sof_tplg_ops, fw); + if (sdev->dspless_mode_selected) + ret = snd_soc_tplg_component_load(scomp, &sof_dspless_tplg_ops, fw); + else + ret = snd_soc_tplg_component_load(scomp, &sof_tplg_ops, fw); + if (ret < 0) { dev_err(scomp->dev, "error: tplg component load failed %d\n", ret); From 4a3b1433a8d384ff8d668b4f8665d6c67dbb30d3 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 4 Apr 2023 12:21:07 +0300 Subject: [PATCH 667/778] ASoC: SOF: Intel: hda: Skip interfaces not supported on a platform Not all interfaces (SSP/DMIC/HDA/SDW) are available on all platforms. If the interface is not even supported then there is no point in executing a probe or query for that interface. Introduce a simple function (hda_get_interface_mask) to query the interfaces supported on the platform. Signed-off-by: Peter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Rander Wang Link: https://lore.kernel.org/r/20230404092115.27949-5-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda.c | 50 ++++++++++++++++++++++++++++++++++----- 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 65389c7278e2..19aad4141a78 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -44,6 +44,37 @@ #define EXCEPT_MAX_HDR_SIZE 0x400 #define HDA_EXT_ROM_STATUS_SIZE 8 +static u32 hda_get_interface_mask(struct snd_sof_dev *sdev) +{ + const struct sof_intel_dsp_desc *chip; + u32 interface_mask = 0; + + chip = get_chip_info(sdev->pdata); + switch (chip->hw_ip_version) { + case SOF_INTEL_TANGIER: + case SOF_INTEL_BAYTRAIL: + case SOF_INTEL_BROADWELL: + interface_mask = BIT(SOF_DAI_INTEL_SSP); + break; + case SOF_INTEL_CAVS_1_5: + case SOF_INTEL_CAVS_1_5_PLUS: + interface_mask = BIT(SOF_DAI_INTEL_SSP) | BIT(SOF_DAI_INTEL_DMIC) | + BIT(SOF_DAI_INTEL_HDA); + break; + case SOF_INTEL_CAVS_1_8: + case SOF_INTEL_CAVS_2_0: + case SOF_INTEL_CAVS_2_5: + case SOF_INTEL_ACE_1_0: + interface_mask = BIT(SOF_DAI_INTEL_SSP) | BIT(SOF_DAI_INTEL_DMIC) | + BIT(SOF_DAI_INTEL_HDA) | BIT(SOF_DAI_INTEL_ALH); + break; + default: + break; + } + + return interface_mask; +} + #if IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE) /* @@ -845,6 +876,7 @@ static int dmic_detect_topology_fixup(struct snd_sof_dev *sdev, static int hda_init_caps(struct snd_sof_dev *sdev) { + u32 interface_mask = hda_get_interface_mask(sdev); struct hdac_bus *bus = sof_to_bus(sdev); struct snd_sof_pdata *pdata = sdev->pdata; struct sof_intel_hda_dev *hdev = pdata->hw_pdata; @@ -865,6 +897,10 @@ static int hda_init_caps(struct snd_sof_dev *sdev) hda_bus_ml_get_capabilities(bus); + /* Skip SoundWire if it is not supported */ + if (!(interface_mask & BIT(SOF_DAI_INTEL_ALH))) + goto skip_soundwire; + /* scan SoundWire capabilities exposed by DSDT */ ret = hda_sdw_acpi_scan(sdev); if (ret < 0) { @@ -1486,12 +1522,16 @@ void hda_set_mach_params(struct snd_soc_acpi_mach *mach, struct snd_soc_acpi_mach *hda_machine_select(struct snd_sof_dev *sdev) { + u32 interface_mask = hda_get_interface_mask(sdev); struct snd_sof_pdata *sof_pdata = sdev->pdata; const struct sof_dev_desc *desc = sof_pdata->desc; - struct snd_soc_acpi_mach *mach; + struct snd_soc_acpi_mach *mach = NULL; const char *tplg_filename; - mach = snd_soc_acpi_find_machine(desc->machines); + /* Try I2S or DMIC if it is supported */ + if (interface_mask & (BIT(SOF_DAI_INTEL_SSP) | BIT(SOF_DAI_INTEL_DMIC))) + mach = snd_soc_acpi_find_machine(desc->machines); + if (mach) { bool add_extension = false; bool tplg_fixup = false; @@ -1598,10 +1638,8 @@ struct snd_soc_acpi_mach *hda_machine_select(struct snd_sof_dev *sdev) } } - /* - * If I2S fails, try SoundWire - */ - if (!mach) + /* If I2S fails, try SoundWire if it is supported */ + if (!mach && (interface_mask & BIT(SOF_DAI_INTEL_ALH))) mach = hda_sdw_machine_select(sdev); /* From 1f7b5d52be130e16fda60be446b30136698738c6 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 4 Apr 2023 12:21:08 +0300 Subject: [PATCH 668/778] ASoC: SOF: Intel: hda: Add support for DSPless mode Via the SOF_DBG_DSPLESS_MODE sof_debug flag the SOF stack can be asked to not use the DSP for audio. The use of DSPless mode is governed by the sdev->dspless_mode_selected flag which is only going to be set if the user sets sof_debug=0x8000 and the platform advertises that the DSPless mode is supported on them. Signed-off-by: Peter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Rander Wang Link: https://lore.kernel.org/r/20230404092115.27949-6-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai-ops.c | 33 +++++++++++++++++++++++++++++- sound/soc/sof/intel/hda-dai.c | 25 ++++++++++++++++++----- sound/soc/sof/intel/hda-pcm.c | 24 +++++++++++++++------- sound/soc/sof/intel/hda-stream.c | 34 ++++++++++++++++--------------- sound/soc/sof/intel/hda.c | 19 ++++++++++------- 5 files changed, 99 insertions(+), 36 deletions(-) diff --git a/sound/soc/sof/intel/hda-dai-ops.c b/sound/soc/sof/intel/hda-dai-ops.c index de48f13259f1..4b39cecacd68 100644 --- a/sound/soc/sof/intel/hda-dai-ops.c +++ b/sound/soc/sof/intel/hda-dai-ops.c @@ -319,13 +319,44 @@ static const struct hda_dai_widget_dma_ops hda_ipc3_dma_ops = { .post_trigger = hda_ipc3_post_trigger, }; +static struct hdac_ext_stream * +hda_dspless_get_hext_stream(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai, + struct snd_pcm_substream *substream) +{ + struct hdac_stream *hstream = substream->runtime->private_data; + + return stream_to_hdac_ext_stream(hstream); +} + +static void hda_dspless_setup_hext_stream(struct snd_sof_dev *sdev, + struct hdac_ext_stream *hext_stream, + unsigned int format_val) +{ + /* + * Save the format_val which was adjusted by the maxbps of the codec. + * This information is not available on the FE side since there we are + * using dummy_codec. + */ + hext_stream->hstream.format_val = format_val; +} + +static const struct hda_dai_widget_dma_ops hda_dspless_dma_ops = { + .get_hext_stream = hda_dspless_get_hext_stream, + .setup_hext_stream = hda_dspless_setup_hext_stream, +}; + #endif const struct hda_dai_widget_dma_ops * hda_select_dai_widget_ops(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) { #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) - struct snd_sof_dai *sdai = swidget->private; + struct snd_sof_dai *sdai; + + if (sdev->dspless_mode_selected) + return &hda_dspless_dma_ops; + + sdai = swidget->private; switch (sdev->pdata->ipc_type) { case SOF_IPC: diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index 46a17afdd1ea..0435b7f251aa 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -31,11 +31,18 @@ int hda_dai_config(struct snd_soc_dapm_widget *w, unsigned int flags, struct snd_sof_dai_config_data *data) { struct snd_sof_widget *swidget = w->dobj.private; - struct snd_soc_component *component = swidget->scomp; - struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); - const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); + const struct sof_ipc_tplg_ops *tplg_ops; + struct snd_soc_component *component; + struct snd_sof_dev *sdev; int ret; + if (!swidget) + return 0; + + component = swidget->scomp; + sdev = snd_soc_component_get_drvdata(component); + tplg_ops = sof_ipc_get_ops(sdev, tplg); + if (tplg_ops && tplg_ops->dai_config) { ret = tplg_ops->dai_config(sdev, swidget, flags, data); if (ret < 0) { @@ -56,13 +63,21 @@ hda_dai_get_ops(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream); struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(cpu_dai->component); struct snd_sof_widget *swidget = w->dobj.private; - struct snd_sof_dai *sdai = swidget->private; + struct snd_sof_dai *sdai; + + /* + * The swidget parameter of hda_select_dai_widget_ops() is ignored in + * case of DSPless mode + */ + if (sdev->dspless_mode_selected) + return hda_select_dai_widget_ops(sdev, NULL); + + sdai = swidget->private; /* select and set the DAI widget ops if not set already */ if (!sdai->platform_private) { const struct hda_dai_widget_dma_ops *ops = hda_select_dai_widget_ops(sdev, swidget); - if (!ops) return NULL; diff --git a/sound/soc/sof/intel/hda-pcm.c b/sound/soc/sof/intel/hda-pcm.c index dc0b359ed9b6..981e7b699bdb 100644 --- a/sound/soc/sof/intel/hda-pcm.c +++ b/sound/soc/sof/intel/hda-pcm.c @@ -101,18 +101,23 @@ int hda_dsp_pcm_hw_params(struct snd_sof_dev *sdev, struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; struct snd_dma_buffer *dmab; int ret; - u32 size, rate, bits; - - size = params_buffer_bytes(params); - rate = hda_dsp_get_mult_div(sdev, params_rate(params)); - bits = hda_dsp_get_bits(sdev, params_width(params)); hstream->substream = substream; dmab = substream->runtime->dma_buffer_p; - hstream->format_val = rate | bits | (params_channels(params) - 1); - hstream->bufsize = size; + /* + * Use the codec required format val (which is link_bps adjusted) when + * the DSP is not in use + */ + if (!sdev->dspless_mode_selected) { + u32 rate = hda_dsp_get_mult_div(sdev, params_rate(params)); + u32 bits = hda_dsp_get_bits(sdev, params_width(params)); + + hstream->format_val = rate | bits | (params_channels(params) - 1); + } + + hstream->bufsize = params_buffer_bytes(params); hstream->period_bytes = params_period_bytes(params); hstream->no_period_wakeup = (params->info & SNDRV_PCM_INFO_NO_PERIOD_WAKEUP) && @@ -249,6 +254,11 @@ int hda_dsp_pcm_open(struct snd_sof_dev *sdev, snd_pcm_hw_constraint_integer(substream->runtime, SNDRV_PCM_HW_PARAM_PERIODS); + /* Only S16 and S32 supported by HDA hardware when used without DSP */ + if (sdev->dspless_mode_selected) + snd_pcm_hw_constraint_mask64(substream->runtime, SNDRV_PCM_HW_PARAM_FORMAT, + SNDRV_PCM_FMTBIT_S16 | SNDRV_PCM_FMTBIT_S32); + /* binding pcm substream to hda stream */ substream->runtime->private_data = &dsp_stream->hstream; return 0; diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index 50e92996f928..87e31a65b314 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -503,11 +503,12 @@ int hda_dsp_stream_hw_params(struct snd_sof_dev *sdev, hstream = &hext_stream->hstream; sd_offset = SOF_STREAM_SD_OFFSET(hstream); + mask = BIT(hstream->index); - /* decouple host and link DMA */ - mask = 0x1 << hstream->index; - snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL, - mask, mask); + /* decouple host and link DMA if the DSP is used */ + if (!sdev->dspless_mode_selected) + snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL, + mask, mask); /* clear stream status */ snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, sd_offset, @@ -608,11 +609,10 @@ int hda_dsp_stream_hw_params(struct snd_sof_dev *sdev, * enable decoupled mode */ - if (chip->quirks & SOF_INTEL_PROCEN_FMT_QUIRK) { + if (!sdev->dspless_mode_selected && (chip->quirks & SOF_INTEL_PROCEN_FMT_QUIRK)) /* couple host and link DMA, disable DSP features */ snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL, mask, 0); - } /* program stream format */ snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, @@ -620,11 +620,10 @@ int hda_dsp_stream_hw_params(struct snd_sof_dev *sdev, SOF_HDA_ADSP_REG_SD_FORMAT, 0xffff, hstream->format_val); - if (chip->quirks & SOF_INTEL_PROCEN_FMT_QUIRK) { + if (!sdev->dspless_mode_selected && (chip->quirks & SOF_INTEL_PROCEN_FMT_QUIRK)) /* decouple host and link DMA, enable DSP features */ snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL, mask, mask); - } /* program last valid index */ snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, @@ -677,20 +676,23 @@ int hda_dsp_stream_hw_free(struct snd_sof_dev *sdev, struct hdac_ext_stream *hext_stream = container_of(hstream, struct hdac_ext_stream, hstream); - struct hdac_bus *bus = sof_to_bus(sdev); - u32 mask = 0x1 << hstream->index; int ret; ret = hda_dsp_stream_reset(sdev, hstream); if (ret < 0) return ret; - spin_lock_irq(&bus->reg_lock); - /* couple host and link DMA if link DMA channel is idle */ - if (!hext_stream->link_locked) - snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, - SOF_HDA_REG_PP_PPCTL, mask, 0); - spin_unlock_irq(&bus->reg_lock); + if (!sdev->dspless_mode_selected) { + struct hdac_bus *bus = sof_to_bus(sdev); + u32 mask = BIT(hstream->index); + + spin_lock_irq(&bus->reg_lock); + /* couple host and link DMA if link DMA channel is idle */ + if (!hext_stream->link_locked) + snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, + SOF_HDA_REG_PP_PPCTL, mask, 0); + spin_unlock_irq(&bus->reg_lock); + } hda_dsp_stream_spib_config(sdev, hext_stream, HDA_DSP_SPIB_DISABLE, 0); diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 19aad4141a78..a14733aa7a60 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -47,32 +47,34 @@ static u32 hda_get_interface_mask(struct snd_sof_dev *sdev) { const struct sof_intel_dsp_desc *chip; - u32 interface_mask = 0; + u32 interface_mask[2] = { 0 }; chip = get_chip_info(sdev->pdata); switch (chip->hw_ip_version) { case SOF_INTEL_TANGIER: case SOF_INTEL_BAYTRAIL: case SOF_INTEL_BROADWELL: - interface_mask = BIT(SOF_DAI_INTEL_SSP); + interface_mask[0] = BIT(SOF_DAI_INTEL_SSP); break; case SOF_INTEL_CAVS_1_5: case SOF_INTEL_CAVS_1_5_PLUS: - interface_mask = BIT(SOF_DAI_INTEL_SSP) | BIT(SOF_DAI_INTEL_DMIC) | - BIT(SOF_DAI_INTEL_HDA); + interface_mask[0] = BIT(SOF_DAI_INTEL_SSP) | BIT(SOF_DAI_INTEL_DMIC) | + BIT(SOF_DAI_INTEL_HDA); + interface_mask[1] = BIT(SOF_DAI_INTEL_HDA); break; case SOF_INTEL_CAVS_1_8: case SOF_INTEL_CAVS_2_0: case SOF_INTEL_CAVS_2_5: case SOF_INTEL_ACE_1_0: - interface_mask = BIT(SOF_DAI_INTEL_SSP) | BIT(SOF_DAI_INTEL_DMIC) | - BIT(SOF_DAI_INTEL_HDA) | BIT(SOF_DAI_INTEL_ALH); + interface_mask[0] = BIT(SOF_DAI_INTEL_SSP) | BIT(SOF_DAI_INTEL_DMIC) | + BIT(SOF_DAI_INTEL_HDA) | BIT(SOF_DAI_INTEL_ALH); + interface_mask[1] = BIT(SOF_DAI_INTEL_HDA); break; default: break; } - return interface_mask; + return interface_mask[sdev->dspless_mode_selected]; } #if IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE) @@ -1058,6 +1060,9 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) hdev->no_ipc_position = sof_ops(sdev)->pcm_pointer ? 1 : 0; #endif + if (sdev->dspless_mode_selected) + hdev->no_ipc_position = 1; + /* set up HDA base */ bus = sof_to_bus(sdev); ret = hda_init(sdev); From 9fc6786f549c4d71e55bd646ffb4814933286072 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 4 Apr 2023 12:21:09 +0300 Subject: [PATCH 669/778] ASoC: SOF: Intel: hda: make DSPless mode work with DSP disabled in BIOS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the DSP is disabled in the BIOS, the DSP_BAR and PP_BAR cannot be accessed. One possible objection noted in initial reviews is that this patch adds a number of branches. However the number of branches is actually limited in probe/suspend/resume routines mostly, so there isn't really a degradation in terms of readability and maintainability. Adding yet another level of abstraction/ops/callbacks would increase complexity and not really help in terms of code reuse or readability and maintainability. A split between controller and DSP driver would be even more invasive. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Péter Ujfalusi Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230404092115.27949-7-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dsp.c | 30 +++++++--- sound/soc/sof/intel/hda-ipc.c | 3 + sound/soc/sof/intel/hda-stream.c | 25 +++++---- sound/soc/sof/intel/hda.c | 94 +++++++++++++++++++++++--------- 4 files changed, 107 insertions(+), 45 deletions(-) diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index c9231aeacc53..23c05e6f424a 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -321,6 +321,9 @@ void hda_dsp_ipc_int_enable(struct snd_sof_dev *sdev) struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; const struct sof_intel_dsp_desc *chip = hda->desc; + if (sdev->dspless_mode_selected) + return; + /* enable IPC DONE and BUSY interrupts */ snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, chip->ipc_ctl, HDA_DSP_REG_HIPCCTL_DONE | HDA_DSP_REG_HIPCCTL_BUSY, @@ -336,6 +339,9 @@ void hda_dsp_ipc_int_disable(struct snd_sof_dev *sdev) struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; const struct sof_intel_dsp_desc *chip = hda->desc; + if (sdev->dspless_mode_selected) + return; + /* disable IPC interrupt */ snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPIC, HDA_DSP_ADSPIC_IPC, 0); @@ -681,6 +687,9 @@ static int hda_suspend(struct snd_sof_dev *sdev, bool runtime_suspend) /* power down all hda links */ hda_bus_ml_suspend(bus); + if (sdev->dspless_mode_selected) + goto skip_dsp; + ret = chip->power_down_dsp(sdev); if (ret < 0) { dev_err(sdev->dev, "failed to power down DSP during suspend\n"); @@ -694,6 +703,7 @@ static int hda_suspend(struct snd_sof_dev *sdev, bool runtime_suspend) /* disable ppcap interrupt */ hda_dsp_ctrl_ppcap_enable(sdev, false); hda_dsp_ctrl_ppcap_int_enable(sdev, false); +skip_dsp: /* disable hda bus irq and streams */ hda_dsp_ctrl_stop_chip(sdev); @@ -744,9 +754,11 @@ static int hda_resume(struct snd_sof_dev *sdev, bool runtime_resume) hda_codec_jack_check(sdev); } - /* enable ppcap interrupt */ - hda_dsp_ctrl_ppcap_enable(sdev, true); - hda_dsp_ctrl_ppcap_int_enable(sdev, true); + if (!sdev->dspless_mode_selected) { + /* enable ppcap interrupt */ + hda_dsp_ctrl_ppcap_enable(sdev, true); + hda_dsp_ctrl_ppcap_int_enable(sdev, true); + } cleanup: /* display codec can powered off after controller init */ @@ -843,8 +855,10 @@ int hda_dsp_runtime_suspend(struct snd_sof_dev *sdev) }; int ret; - /* cancel any attempt for DSP D0I3 */ - cancel_delayed_work_sync(&hda->d0i3_work); + if (!sdev->dspless_mode_selected) { + /* cancel any attempt for DSP D0I3 */ + cancel_delayed_work_sync(&hda->d0i3_work); + } /* stop hda controller and power dsp off */ ret = hda_suspend(sdev, true); @@ -866,8 +880,10 @@ int hda_dsp_suspend(struct snd_sof_dev *sdev, u32 target_state) }; int ret; - /* cancel any attempt for DSP D0I3 */ - cancel_delayed_work_sync(&hda->d0i3_work); + if (!sdev->dspless_mode_selected) { + /* cancel any attempt for DSP D0I3 */ + cancel_delayed_work_sync(&hda->d0i3_work); + } if (target_state == SOF_DSP_PM_D0) { /* Set DSP power state */ diff --git a/sound/soc/sof/intel/hda-ipc.c b/sound/soc/sof/intel/hda-ipc.c index df541b22b2d2..a838dddb1d32 100644 --- a/sound/soc/sof/intel/hda-ipc.c +++ b/sound/soc/sof/intel/hda-ipc.c @@ -355,6 +355,9 @@ bool hda_dsp_check_ipc_irq(struct snd_sof_dev *sdev) bool ret = false; u32 irq_status; + if (sdev->dspless_mode_selected) + return false; + /* store status */ irq_status = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPIS); trace_sof_intel_hda_irq_ipc_check(sdev, irq_status); diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index 87e31a65b314..79d818e6a0fa 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -874,12 +874,14 @@ int hda_dsp_stream_init(struct snd_sof_dev *sdev) hext_stream = &hda_stream->hext_stream; - hext_stream->pphc_addr = sdev->bar[HDA_DSP_PP_BAR] + - SOF_HDA_PPHC_BASE + SOF_HDA_PPHC_INTERVAL * i; + if (sdev->bar[HDA_DSP_PP_BAR]) { + hext_stream->pphc_addr = sdev->bar[HDA_DSP_PP_BAR] + + SOF_HDA_PPHC_BASE + SOF_HDA_PPHC_INTERVAL * i; - hext_stream->pplc_addr = sdev->bar[HDA_DSP_PP_BAR] + - SOF_HDA_PPLC_BASE + SOF_HDA_PPLC_MULTI * num_total + - SOF_HDA_PPLC_INTERVAL * i; + hext_stream->pplc_addr = sdev->bar[HDA_DSP_PP_BAR] + + SOF_HDA_PPLC_BASE + SOF_HDA_PPLC_MULTI * num_total + + SOF_HDA_PPLC_INTERVAL * i; + } hstream = &hext_stream->hstream; @@ -930,13 +932,14 @@ int hda_dsp_stream_init(struct snd_sof_dev *sdev) hext_stream = &hda_stream->hext_stream; - /* we always have DSP support */ - hext_stream->pphc_addr = sdev->bar[HDA_DSP_PP_BAR] + - SOF_HDA_PPHC_BASE + SOF_HDA_PPHC_INTERVAL * i; + if (sdev->bar[HDA_DSP_PP_BAR]) { + hext_stream->pphc_addr = sdev->bar[HDA_DSP_PP_BAR] + + SOF_HDA_PPHC_BASE + SOF_HDA_PPHC_INTERVAL * i; - hext_stream->pplc_addr = sdev->bar[HDA_DSP_PP_BAR] + - SOF_HDA_PPLC_BASE + SOF_HDA_PPLC_MULTI * num_total + - SOF_HDA_PPLC_INTERVAL * i; + hext_stream->pplc_addr = sdev->bar[HDA_DSP_PP_BAR] + + SOF_HDA_PPLC_BASE + SOF_HDA_PPLC_MULTI * num_total + + SOF_HDA_PPLC_INTERVAL * i; + } hstream = &hext_stream->hstream; diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index a14733aa7a60..483ec80f3160 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -122,8 +122,12 @@ void hda_common_enable_sdw_irq(struct snd_sof_dev *sdev, bool enable) void hda_sdw_int_enable(struct snd_sof_dev *sdev, bool enable) { + u32 interface_mask = hda_get_interface_mask(sdev); const struct sof_intel_dsp_desc *chip; + if (!(interface_mask & BIT(SOF_DAI_INTEL_ALH))) + return; + chip = get_chip_info(sdev->pdata); if (chip && chip->enable_sdw_irq) chip->enable_sdw_irq(sdev, enable); @@ -131,10 +135,14 @@ void hda_sdw_int_enable(struct snd_sof_dev *sdev, bool enable) static int hda_sdw_acpi_scan(struct snd_sof_dev *sdev) { + u32 interface_mask = hda_get_interface_mask(sdev); struct sof_intel_hda_dev *hdev; acpi_handle handle; int ret; + if (!(interface_mask & BIT(SOF_DAI_INTEL_ALH))) + return -EINVAL; + handle = ACPI_HANDLE(sdev->dev); /* save ACPI info for the probe step */ @@ -288,8 +296,12 @@ out: static bool hda_dsp_check_sdw_irq(struct snd_sof_dev *sdev) { + u32 interface_mask = hda_get_interface_mask(sdev); const struct sof_intel_dsp_desc *chip; + if (!(interface_mask & BIT(SOF_DAI_INTEL_ALH))) + return false; + chip = get_chip_info(sdev->pdata); if (chip && chip->check_sdw_irq) return chip->check_sdw_irq(sdev); @@ -304,8 +316,12 @@ static irqreturn_t hda_dsp_sdw_thread(int irq, void *context) static bool hda_sdw_check_wakeen_irq(struct snd_sof_dev *sdev) { + u32 interface_mask = hda_get_interface_mask(sdev); struct sof_intel_hda_dev *hdev; + if (!(interface_mask & BIT(SOF_DAI_INTEL_ALH))) + return false; + hdev = sdev->pdata->hw_pdata; if (hdev->sdw && snd_sof_dsp_read(sdev, HDA_DSP_BAR, @@ -317,8 +333,12 @@ static bool hda_sdw_check_wakeen_irq(struct snd_sof_dev *sdev) void hda_sdw_process_wakeen(struct snd_sof_dev *sdev) { + u32 interface_mask = hda_get_interface_mask(sdev); struct sof_intel_hda_dev *hdev; + if (!(interface_mask & BIT(SOF_DAI_INTEL_ALH))) + return; + hdev = sdev->pdata->hw_pdata; if (!hdev->sdw) return; @@ -1010,21 +1030,25 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) const struct sof_intel_dsp_desc *chip; int ret = 0; - /* - * detect DSP by checking class/subclass/prog-id information - * class=04 subclass 03 prog-if 00: no DSP, legacy driver is required - * class=04 subclass 01 prog-if 00: DSP is present - * (and may be required e.g. for DMIC or SSP support) - * class=04 subclass 03 prog-if 80: either of DSP or legacy mode works - */ - if (pci->class == 0x040300) { - dev_err(sdev->dev, "error: the DSP is not enabled on this platform, aborting probe\n"); - return -ENODEV; - } else if (pci->class != 0x040100 && pci->class != 0x040380) { - dev_err(sdev->dev, "error: unknown PCI class/subclass/prog-if 0x%06x found, aborting probe\n", pci->class); - return -ENODEV; + if (!sdev->dspless_mode_selected) { + /* + * detect DSP by checking class/subclass/prog-id information + * class=04 subclass 03 prog-if 00: no DSP, legacy driver is required + * class=04 subclass 01 prog-if 00: DSP is present + * (and may be required e.g. for DMIC or SSP support) + * class=04 subclass 03 prog-if 80: either of DSP or legacy mode works + */ + if (pci->class == 0x040300) { + dev_err(sdev->dev, "the DSP is not enabled on this platform, aborting probe\n"); + return -ENODEV; + } else if (pci->class != 0x040100 && pci->class != 0x040380) { + dev_err(sdev->dev, "unknown PCI class/subclass/prog-if 0x%06x found, aborting probe\n", + pci->class); + return -ENODEV; + } + dev_info(sdev->dev, "DSP detected with PCI class/subclass/prog-if 0x%06x\n", + pci->class); } - dev_info(sdev->dev, "DSP detected with PCI class/subclass/prog-if 0x%06x\n", pci->class); chip = get_chip_info(sdev->pdata); if (!chip) { @@ -1069,6 +1093,9 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) if (ret < 0) goto hdac_bus_unmap; + if (sdev->dspless_mode_selected) + goto skip_dsp_setup; + /* DSP base */ sdev->bar[HDA_DSP_BAR] = pci_ioremap_bar(pci, HDA_DSP_BAR); if (!sdev->bar[HDA_DSP_BAR]) { @@ -1079,6 +1106,7 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) sdev->mmio_bar = HDA_DSP_BAR; sdev->mailbox_bar = HDA_DSP_BAR; +skip_dsp_setup: /* allow 64bit DMA address if supported by H/W */ if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(64))) { @@ -1144,14 +1172,16 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) if (ret < 0) goto free_ipc_irq; - /* enable ppcap interrupt */ - hda_dsp_ctrl_ppcap_enable(sdev, true); - hda_dsp_ctrl_ppcap_int_enable(sdev, true); + if (!sdev->dspless_mode_selected) { + /* enable ppcap interrupt */ + hda_dsp_ctrl_ppcap_enable(sdev, true); + hda_dsp_ctrl_ppcap_int_enable(sdev, true); - /* set default mailbox offset for FW ready message */ - sdev->dsp_box.offset = HDA_DSP_MBOX_UPLINK_OFFSET; + /* set default mailbox offset for FW ready message */ + sdev->dsp_box.offset = HDA_DSP_MBOX_UPLINK_OFFSET; - INIT_DELAYED_WORK(&hdev->d0i3_work, hda_dsp_d0i3_work); + INIT_DELAYED_WORK(&hdev->d0i3_work, hda_dsp_d0i3_work); + } init_waitqueue_head(&hdev->waitq); @@ -1167,7 +1197,8 @@ free_irq_vector: free_streams: hda_dsp_stream_free(sdev); /* dsp_unmap: not currently used */ - iounmap(sdev->bar[HDA_DSP_BAR]); + if (!sdev->dspless_mode_selected) + iounmap(sdev->bar[HDA_DSP_BAR]); hdac_bus_unmap: platform_device_unregister(hdev->dmic_dev); iounmap(bus->remap_addr); @@ -1187,8 +1218,9 @@ int hda_dsp_remove(struct snd_sof_dev *sdev) if (nhlt) intel_nhlt_free(nhlt); - /* cancel any attempt for DSP D0I3 */ - cancel_delayed_work_sync(&hda->d0i3_work); + if (!sdev->dspless_mode_selected) + /* cancel any attempt for DSP D0I3 */ + cancel_delayed_work_sync(&hda->d0i3_work); hda_codec_device_remove(sdev); @@ -1197,14 +1229,19 @@ int hda_dsp_remove(struct snd_sof_dev *sdev) if (!IS_ERR_OR_NULL(hda->dmic_dev)) platform_device_unregister(hda->dmic_dev); - /* disable DSP IRQ */ - snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL, - SOF_HDA_PPCTL_PIE, 0); + if (!sdev->dspless_mode_selected) { + /* disable DSP IRQ */ + snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL, + SOF_HDA_PPCTL_PIE, 0); + } /* disable CIE and GIE interrupts */ snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL, SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN, 0); + if (sdev->dspless_mode_selected) + goto skip_disable_dsp; + /* no need to check for error as the DSP will be disabled anyway */ if (chip && chip->power_down_dsp) chip->power_down_dsp(sdev); @@ -1213,6 +1250,7 @@ int hda_dsp_remove(struct snd_sof_dev *sdev) snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL, SOF_HDA_PPCTL_GPROCEN, 0); +skip_disable_dsp: free_irq(sdev->ipc_irq, sdev); if (sdev->msi_enabled) pci_free_irq_vectors(pci); @@ -1221,7 +1259,9 @@ int hda_dsp_remove(struct snd_sof_dev *sdev) hda_bus_ml_free(sof_to_bus(sdev)); - iounmap(sdev->bar[HDA_DSP_BAR]); + if (!sdev->dspless_mode_selected) + iounmap(sdev->bar[HDA_DSP_BAR]); + iounmap(bus->remap_addr); sof_hda_bus_exit(sdev); From 04957f87ae7e862216a3bc901710c82de55c4078 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 4 Apr 2023 12:21:10 +0300 Subject: [PATCH 670/778] ASoC: SOF: Intel: pci-apl: Allow DSPless mode set the dspless_mode_supported flag to true for apl family to allow DSPless mode. Signed-off-by: Peter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Rander Wang Link: https://lore.kernel.org/r/20230404092115.27949-8-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/pci-apl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/sof/intel/pci-apl.c b/sound/soc/sof/intel/pci-apl.c index aff6cb573c27..69cad5a6bc72 100644 --- a/sound/soc/sof/intel/pci-apl.c +++ b/sound/soc/sof/intel/pci-apl.c @@ -29,6 +29,7 @@ static const struct sof_dev_desc bxt_desc = { .chip_info = &apl_chip_info, .ipc_supported_mask = BIT(SOF_IPC) | BIT(SOF_INTEL_IPC4), .ipc_default = SOF_IPC, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_IPC] = "intel/sof", [SOF_INTEL_IPC4] = "intel/avs/apl", @@ -60,6 +61,7 @@ static const struct sof_dev_desc glk_desc = { .chip_info = &apl_chip_info, .ipc_supported_mask = BIT(SOF_IPC) | BIT(SOF_INTEL_IPC4), .ipc_default = SOF_IPC, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_IPC] = "intel/sof", [SOF_INTEL_IPC4] = "intel/avs/glk", From a417d71fd3f6a60d1cda0abf62e7961489908dca Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 4 Apr 2023 12:21:11 +0300 Subject: [PATCH 671/778] ASoC: SOF: Intel: pci-cnl: Allow DSPless mode set the dspless_mode_supported flag to true for cnl/cfl/cml family to allow DSPless mode. Signed-off-by: Peter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Rander Wang Link: https://lore.kernel.org/r/20230404092115.27949-9-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/pci-cnl.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/sof/intel/pci-cnl.c b/sound/soc/sof/intel/pci-cnl.c index 4c0c1c369dcd..8895508a0be6 100644 --- a/sound/soc/sof/intel/pci-cnl.c +++ b/sound/soc/sof/intel/pci-cnl.c @@ -30,6 +30,7 @@ static const struct sof_dev_desc cnl_desc = { .chip_info = &cnl_chip_info, .ipc_supported_mask = BIT(SOF_IPC) | BIT(SOF_INTEL_IPC4), .ipc_default = SOF_IPC, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_IPC] = "intel/sof", [SOF_INTEL_IPC4] = "intel/avs/cnl", @@ -62,6 +63,7 @@ static const struct sof_dev_desc cfl_desc = { .chip_info = &cnl_chip_info, .ipc_supported_mask = BIT(SOF_IPC) | BIT(SOF_INTEL_IPC4), .ipc_default = SOF_IPC, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_IPC] = "intel/sof", [SOF_INTEL_IPC4] = "intel/avs/cnl", @@ -94,6 +96,7 @@ static const struct sof_dev_desc cml_desc = { .chip_info = &cnl_chip_info, .ipc_supported_mask = BIT(SOF_IPC) | BIT(SOF_INTEL_IPC4), .ipc_default = SOF_IPC, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_IPC] = "intel/sof", [SOF_INTEL_IPC4] = "intel/avs/cnl", From 937a7fb441f5f1796398e171eef479de34a7c64f Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 4 Apr 2023 12:21:12 +0300 Subject: [PATCH 672/778] ASoC: SOF: Intel: pci-icl: Allow DSPless mode set the dspless_mode_supported flag to true for icl/jsl family to allow DSPless mode. Signed-off-by: Peter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Rander Wang Link: https://lore.kernel.org/r/20230404092115.27949-10-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/pci-icl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/sof/intel/pci-icl.c b/sound/soc/sof/intel/pci-icl.c index 6785669113b3..5fb5a820693e 100644 --- a/sound/soc/sof/intel/pci-icl.c +++ b/sound/soc/sof/intel/pci-icl.c @@ -30,6 +30,7 @@ static const struct sof_dev_desc icl_desc = { .chip_info = &icl_chip_info, .ipc_supported_mask = BIT(SOF_IPC) | BIT(SOF_INTEL_IPC4), .ipc_default = SOF_IPC, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_IPC] = "intel/sof", [SOF_INTEL_IPC4] = "intel/avs/icl", @@ -61,6 +62,7 @@ static const struct sof_dev_desc jsl_desc = { .chip_info = &jsl_chip_info, .ipc_supported_mask = BIT(SOF_IPC) | BIT(SOF_INTEL_IPC4), .ipc_default = SOF_IPC, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_IPC] = "intel/sof", [SOF_INTEL_IPC4] = "intel/avs/jsl", From b58bbd067585af1f38cc24dbeccf98218c717281 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 4 Apr 2023 12:21:13 +0300 Subject: [PATCH 673/778] ASoC: SOF: Intel: pci-mtl: Allow DSPless mode set the dspless_mode_supported flag to true for mtl family to allow DSPless mode. Signed-off-by: Peter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Rander Wang Link: https://lore.kernel.org/r/20230404092115.27949-11-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/pci-mtl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/sof/intel/pci-mtl.c b/sound/soc/sof/intel/pci-mtl.c index b183dc0014b4..e276e1e37fed 100644 --- a/sound/soc/sof/intel/pci-mtl.c +++ b/sound/soc/sof/intel/pci-mtl.c @@ -31,6 +31,7 @@ static const struct sof_dev_desc mtl_desc = { .chip_info = &mtl_chip_info, .ipc_supported_mask = BIT(SOF_INTEL_IPC4), .ipc_default = SOF_INTEL_IPC4, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_INTEL_IPC4] = "intel/sof-ipc4/mtl", }, From f45b1fd61e874cae0217c04406f8e99d57ddfacc Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 4 Apr 2023 12:21:14 +0300 Subject: [PATCH 674/778] ASoC: SOF: Intel: pci-skl: Allow DSPless mode set the dspless_mode_supported flag to true for skl family to allow DSPless mode. Signed-off-by: Peter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Rander Wang Link: https://lore.kernel.org/r/20230404092115.27949-12-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/pci-skl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/sof/intel/pci-skl.c b/sound/soc/sof/intel/pci-skl.c index 5b4bccf81965..5e69af6eed34 100644 --- a/sound/soc/sof/intel/pci-skl.c +++ b/sound/soc/sof/intel/pci-skl.c @@ -26,6 +26,7 @@ static struct sof_dev_desc skl_desc = { .irqindex_host_ipc = -1, .ipc_supported_mask = BIT(SOF_INTEL_IPC4), .ipc_default = SOF_INTEL_IPC4, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_INTEL_IPC4] = "intel/avs/skl", }, @@ -50,6 +51,7 @@ static struct sof_dev_desc kbl_desc = { .irqindex_host_ipc = -1, .ipc_supported_mask = BIT(SOF_INTEL_IPC4), .ipc_default = SOF_INTEL_IPC4, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_INTEL_IPC4] = "intel/avs/kbl", }, From 5962c2a527b52b95426167ba59a2ef01a522d077 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 4 Apr 2023 12:21:15 +0300 Subject: [PATCH 675/778] ASoC: SOF: Intel: pci-tgl: Allow DSPless mode set the dspless_mode_supported flag to true for tgl/adl family to allow DSPless mode. Signed-off-by: Peter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Rander Wang Link: https://lore.kernel.org/r/20230404092115.27949-13-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/pci-tgl.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sound/soc/sof/intel/pci-tgl.c b/sound/soc/sof/intel/pci-tgl.c index 22e769e0831d..ca37ff1bbd2a 100644 --- a/sound/soc/sof/intel/pci-tgl.c +++ b/sound/soc/sof/intel/pci-tgl.c @@ -30,6 +30,7 @@ static const struct sof_dev_desc tgl_desc = { .chip_info = &tgl_chip_info, .ipc_supported_mask = BIT(SOF_IPC) | BIT(SOF_INTEL_IPC4), .ipc_default = SOF_IPC, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_IPC] = "intel/sof", [SOF_INTEL_IPC4] = "intel/avs/tgl", @@ -62,6 +63,7 @@ static const struct sof_dev_desc tglh_desc = { .chip_info = &tglh_chip_info, .ipc_supported_mask = BIT(SOF_IPC) | BIT(SOF_INTEL_IPC4), .ipc_default = SOF_IPC, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_IPC] = "intel/sof", [SOF_INTEL_IPC4] = "intel/avs/tgl-h", @@ -93,6 +95,7 @@ static const struct sof_dev_desc ehl_desc = { .chip_info = &ehl_chip_info, .ipc_supported_mask = BIT(SOF_IPC) | BIT(SOF_INTEL_IPC4), .ipc_default = SOF_IPC, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_IPC] = "intel/sof", [SOF_INTEL_IPC4] = "intel/avs/ehl", @@ -125,6 +128,7 @@ static const struct sof_dev_desc adls_desc = { .chip_info = &adls_chip_info, .ipc_supported_mask = BIT(SOF_IPC) | BIT(SOF_INTEL_IPC4), .ipc_default = SOF_IPC, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_IPC] = "intel/sof", [SOF_INTEL_IPC4] = "intel/avs/adl-s", @@ -157,6 +161,7 @@ static const struct sof_dev_desc adl_desc = { .chip_info = &tgl_chip_info, .ipc_supported_mask = BIT(SOF_IPC) | BIT(SOF_INTEL_IPC4), .ipc_default = SOF_IPC, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_IPC] = "intel/sof", [SOF_INTEL_IPC4] = "intel/avs/adl", @@ -189,6 +194,7 @@ static const struct sof_dev_desc adl_n_desc = { .chip_info = &tgl_chip_info, .ipc_supported_mask = BIT(SOF_IPC) | BIT(SOF_INTEL_IPC4), .ipc_default = SOF_IPC, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_IPC] = "intel/sof", [SOF_INTEL_IPC4] = "intel/avs/adl-n", @@ -221,6 +227,7 @@ static const struct sof_dev_desc rpls_desc = { .chip_info = &adls_chip_info, .ipc_supported_mask = BIT(SOF_IPC) | BIT(SOF_INTEL_IPC4), .ipc_default = SOF_IPC, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_IPC] = "intel/sof", [SOF_INTEL_IPC4] = "intel/avs/rpl-s", @@ -253,6 +260,7 @@ static const struct sof_dev_desc rpl_desc = { .chip_info = &tgl_chip_info, .ipc_supported_mask = BIT(SOF_IPC) | BIT(SOF_INTEL_IPC4), .ipc_default = SOF_IPC, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_IPC] = "intel/sof", [SOF_INTEL_IPC4] = "intel/avs/rpl", From 194f8692302cbf31d8072f3fc2710fb04720d8a0 Mon Sep 17 00:00:00 2001 From: Zihao Wang Date: Tue, 4 Apr 2023 16:46:22 +0800 Subject: [PATCH 676/778] ASoC: tegra20_ac97: Add missing unwind goto in tegra20_ac97_platform_probe() Smatch Warns: sound/soc/tegra/tegra20_ac97.c:321 tegra20_ac97_platform_probe() warn: missing unwind goto? The goto will set the "soc_ac97_ops" and "soc_ac97_bus" operations to NULL. But they are already NULL at this point so it is a no-op. However, just for consistency, change the direct return to a goto. No functional change. Signed-off-by: Zihao Wang Reviewed-by: Dan Carpenter Link: https://lore.kernel.org/r/20230404084622.1202-1-u202012060@hust.edu.cn Signed-off-by: Mark Brown --- sound/soc/tegra/tegra20_ac97.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/tegra/tegra20_ac97.c b/sound/soc/tegra/tegra20_ac97.c index fea6955f7f43..c498145e76e0 100644 --- a/sound/soc/tegra/tegra20_ac97.c +++ b/sound/soc/tegra/tegra20_ac97.c @@ -318,7 +318,8 @@ static int tegra20_ac97_platform_probe(struct platform_device *pdev) ac97->reset = devm_reset_control_get_exclusive(&pdev->dev, "ac97"); if (IS_ERR(ac97->reset)) { dev_err(&pdev->dev, "Can't retrieve ac97 reset\n"); - return PTR_ERR(ac97->reset); + ret = PTR_ERR(ac97->reset); + goto err; } ac97->clk_ac97 = devm_clk_get(&pdev->dev, NULL); From 009e83b591ddcd945f0d48209debfb8dca967166 Mon Sep 17 00:00:00 2001 From: Saalim Quadri Date: Tue, 28 Mar 2023 14:48:31 +0530 Subject: [PATCH 677/778] ASoC: dt-bindings: ak4458: Convert to dtschema Convert the AK4458 audio DAC bindings to DT schema. Signed-off-by: Saalim Quadri Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230328091831.55690-1-danascape@gmail.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/ak4458.txt | 28 ------- .../bindings/sound/asahi-kasei,ak4458.yaml | 73 +++++++++++++++++++ 2 files changed, 73 insertions(+), 28 deletions(-) delete mode 100644 Documentation/devicetree/bindings/sound/ak4458.txt create mode 100644 Documentation/devicetree/bindings/sound/asahi-kasei,ak4458.yaml diff --git a/Documentation/devicetree/bindings/sound/ak4458.txt b/Documentation/devicetree/bindings/sound/ak4458.txt deleted file mode 100644 index 0416c14895d6..000000000000 --- a/Documentation/devicetree/bindings/sound/ak4458.txt +++ /dev/null @@ -1,28 +0,0 @@ -AK4458 audio DAC - -This device supports I2C mode. - -Required properties: - -- compatible : "asahi-kasei,ak4458" or "asahi-kasei,ak4497" -- reg : The I2C address of the device for I2C - -Optional properties: -- reset-gpios: A GPIO specifier for the power down & reset pin -- mute-gpios: A GPIO specifier for the soft mute pin -- AVDD-supply: Analog power supply -- DVDD-supply: Digital power supply -- dsd-path: Select DSD input pins for ak4497 - 0: select #16, #17, #19 pins - 1: select #3, #4, #5 pins - -Example: - -&i2c { - ak4458: dac@10 { - compatible = "asahi-kasei,ak4458"; - reg = <0x10>; - reset-gpios = <&gpio1 10 GPIO_ACTIVE_LOW> - mute-gpios = <&gpio1 11 GPIO_ACTIVE_HIGH> - }; -}; diff --git a/Documentation/devicetree/bindings/sound/asahi-kasei,ak4458.yaml b/Documentation/devicetree/bindings/sound/asahi-kasei,ak4458.yaml new file mode 100644 index 000000000000..0db0c8e923a0 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/asahi-kasei,ak4458.yaml @@ -0,0 +1,73 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/asahi-kasei,ak4458.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: AK4458 audio DAC + +maintainers: + - Shengjiu Wang + +properties: + compatible: + enum: + - asahi-kasei,ak4458 + - asahi-kasei,ak4497 + + reg: + maxItems: 1 + + avdd-supply: + description: Analog power supply + + dvdd-supply: + description: Digital power supply + + reset-gpios: + maxItems: 1 + + mute-gpios: + maxItems: 1 + description: + GPIO used to mute all the outputs + + dsd-path: + description: Select DSD input pins for ak4497 + $ref: /schemas/types.yaml#/definitions/uint32 + oneOf: + - const: 0 + description: select #16, #17, #19 pins + - const: 1 + description: select #3, #4, #5 pins + +required: + - compatible + - reg + +allOf: + - if: + properties: + compatible: + contains: + const: asahi-kasei,ak4458 + + then: + properties: + dsd-path: false + +additionalProperties: false + +examples: + - | + #include + i2c { + #address-cells = <1>; + #size-cells = <0>; + codec@10 { + compatible = "asahi-kasei,ak4458"; + reg = <0x10>; + reset-gpios = <&gpio1 10 GPIO_ACTIVE_LOW>; + mute-gpios = <&gpio1 11 GPIO_ACTIVE_HIGH>; + }; + }; From 7ddc7f91beb285246e926e3adf0b292b071aea33 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Sun, 2 Apr 2023 22:59:35 +0000 Subject: [PATCH 678/778] ASoC: soc.h: clarify Codec2Codec params snd_soc_dai_link has params/num_params, but it is unclear that params for what. This patch clarify it is params for Codec2Codec. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87o7o5c2lk.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc.h | 12 +++++++++--- sound/soc/soc-core.c | 11 +++++++++++ sound/soc/soc-dapm.c | 44 ++++++++++++++++++++++---------------------- sound/soc/soc-pcm.c | 10 +++++----- 4 files changed, 47 insertions(+), 30 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index 57c5786a625b..276afdb1f445 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -684,8 +684,14 @@ struct snd_soc_dai_link { int id; /* optional ID for machine driver link identification */ - const struct snd_soc_pcm_stream *params; - unsigned int num_params; + /* + * for Codec2Codec + */ + const struct snd_soc_pcm_stream *c2c_params; + unsigned int num_c2c_params; + + const struct snd_soc_pcm_stream *params; /* REMOVE ME */ + unsigned int num_params; /* REMOVE ME */ unsigned int dai_fmt; /* format to set on init */ @@ -1065,7 +1071,7 @@ struct snd_soc_pcm_runtime { struct snd_soc_dai_link *dai_link; struct snd_pcm_ops ops; - unsigned int params_select; /* currently selected param for dai link */ + unsigned int c2c_params_select; /* currently selected c2c_param for dai link */ /* Dynamic PCM BE runtime data */ struct snd_soc_dpcm_runtime dpcm[SNDRV_PCM_STREAM_LAST + 1]; diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 9bbcff492c1e..04f1bc8a3128 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2294,6 +2294,9 @@ EXPORT_SYMBOL_GPL(snd_soc_add_dai_controls); */ int snd_soc_register_card(struct snd_soc_card *card) { + struct snd_soc_dai_link *dai_link; + int i; + if (!card->name || !card->dev) return -EINVAL; @@ -2314,6 +2317,14 @@ int snd_soc_register_card(struct snd_soc_card *card) mutex_init(&card->dapm_mutex); mutex_init(&card->pcm_mutex); + /* REMOVE ME */ + for_each_card_prelinks(card, i, dai_link) { + if (!dai_link->c2c_params) { + dai_link->c2c_params = dai_link->params; + dai_link->num_c2c_params = dai_link->num_params; + } + } + return snd_soc_bind_card(card); } EXPORT_SYMBOL_GPL(snd_soc_register_card); diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 34fdcb7ee079..e7a0c28e0cb1 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -1075,7 +1075,7 @@ static int dapm_new_dai_link(struct snd_soc_dapm_widget *w) struct snd_soc_pcm_runtime *rtd = w->priv; /* create control for links with > 1 config */ - if (rtd->dai_link->num_params <= 1) + if (rtd->dai_link->num_c2c_params <= 1) return 0; /* add kcontrol */ @@ -3864,7 +3864,7 @@ snd_soc_dai_link_event_pre_pmu(struct snd_soc_dapm_widget *w, * either party on the link to alter the configuration if * necessary */ - config = rtd->dai_link->params + rtd->params_select; + config = rtd->dai_link->c2c_params + rtd->c2c_params_select; if (!config) { dev_err(w->dapm->dev, "ASoC: link config missing\n"); ret = -EINVAL; @@ -4010,7 +4010,7 @@ static int snd_soc_dapm_dai_link_get(struct snd_kcontrol *kcontrol, struct snd_soc_dapm_widget *w = snd_kcontrol_chip(kcontrol); struct snd_soc_pcm_runtime *rtd = w->priv; - ucontrol->value.enumerated.item[0] = rtd->params_select; + ucontrol->value.enumerated.item[0] = rtd->c2c_params_select; return 0; } @@ -4025,13 +4025,13 @@ static int snd_soc_dapm_dai_link_put(struct snd_kcontrol *kcontrol, if (w->power) return -EBUSY; - if (ucontrol->value.enumerated.item[0] == rtd->params_select) + if (ucontrol->value.enumerated.item[0] == rtd->c2c_params_select) return 0; - if (ucontrol->value.enumerated.item[0] >= rtd->dai_link->num_params) + if (ucontrol->value.enumerated.item[0] >= rtd->dai_link->num_c2c_params) return -EINVAL; - rtd->params_select = ucontrol->value.enumerated.item[0]; + rtd->c2c_params_select = ucontrol->value.enumerated.item[0]; return 1; } @@ -4039,7 +4039,7 @@ static int snd_soc_dapm_dai_link_put(struct snd_kcontrol *kcontrol, static void snd_soc_dapm_free_kcontrol(struct snd_soc_card *card, unsigned long *private_value, - int num_params, + int num_c2c_params, const char **w_param_text) { int count; @@ -4049,7 +4049,7 @@ snd_soc_dapm_free_kcontrol(struct snd_soc_card *card, if (!w_param_text) return; - for (count = 0 ; count < num_params; count++) + for (count = 0 ; count < num_c2c_params; count++) devm_kfree(card->dev, (void *)w_param_text[count]); devm_kfree(card->dev, w_param_text); } @@ -4057,8 +4057,8 @@ snd_soc_dapm_free_kcontrol(struct snd_soc_card *card, static struct snd_kcontrol_new * snd_soc_dapm_alloc_kcontrol(struct snd_soc_card *card, char *link_name, - const struct snd_soc_pcm_stream *params, - int num_params, const char **w_param_text, + const struct snd_soc_pcm_stream *c2c_params, + int num_c2c_params, const char **w_param_text, unsigned long *private_value) { struct soc_enum w_param_enum[] = { @@ -4070,10 +4070,10 @@ snd_soc_dapm_alloc_kcontrol(struct snd_soc_card *card, snd_soc_dapm_dai_link_put), }; struct snd_kcontrol_new *kcontrol_news; - const struct snd_soc_pcm_stream *config = params; + const struct snd_soc_pcm_stream *config = c2c_params; int count; - for (count = 0 ; count < num_params; count++) { + for (count = 0 ; count < num_c2c_params; count++) { if (!config->stream_name) { dev_warn(card->dapm.dev, "ASoC: anonymous config %d for dai link %s\n", @@ -4093,7 +4093,7 @@ snd_soc_dapm_alloc_kcontrol(struct snd_soc_card *card, config++; } - w_param_enum[0].items = num_params; + w_param_enum[0].items = num_c2c_params; w_param_enum[0].texts = w_param_text; *private_value = @@ -4118,7 +4118,7 @@ snd_soc_dapm_alloc_kcontrol(struct snd_soc_card *card, return kcontrol_news; outfree_w_param: - snd_soc_dapm_free_kcontrol(card, private_value, num_params, w_param_text); + snd_soc_dapm_free_kcontrol(card, private_value, num_c2c_params, w_param_text); return NULL; } @@ -4146,17 +4146,17 @@ snd_soc_dapm_new_dai(struct snd_soc_card *card, w_param_text = NULL; kcontrol_news = NULL; num_kcontrols = 0; - if (rtd->dai_link->num_params > 1) { + if (rtd->dai_link->num_c2c_params > 1) { w_param_text = devm_kcalloc(card->dev, - rtd->dai_link->num_params, + rtd->dai_link->num_c2c_params, sizeof(char *), GFP_KERNEL); if (!w_param_text) goto param_fail; num_kcontrols = 1; kcontrol_news = snd_soc_dapm_alloc_kcontrol(card, link_name, - rtd->dai_link->params, - rtd->dai_link->num_params, + rtd->dai_link->c2c_params, + rtd->dai_link->num_c2c_params, w_param_text, &private_value); if (!kcontrol_news) goto param_fail; @@ -4187,7 +4187,7 @@ snd_soc_dapm_new_dai(struct snd_soc_card *card, outfree_kcontrol_news: devm_kfree(card->dev, (void *)template.kcontrol_news); snd_soc_dapm_free_kcontrol(card, &private_value, - rtd->dai_link->num_params, w_param_text); + rtd->dai_link->num_c2c_params, w_param_text); param_fail: devm_kfree(card->dev, link_name); name_fail: @@ -4336,7 +4336,7 @@ static void dapm_connect_dai_pair(struct snd_soc_card *card, struct snd_pcm_str *streams = rtd->pcm->streams; int stream; - if (dai_link->params) { + if (dai_link->c2c_params) { playback_cpu = snd_soc_dai_get_widget_capture(cpu_dai); capture_cpu = snd_soc_dai_get_widget_playback(cpu_dai); } else { @@ -4349,7 +4349,7 @@ static void dapm_connect_dai_pair(struct snd_soc_card *card, codec = snd_soc_dai_get_widget(codec_dai, stream); if (playback_cpu && codec) { - if (dai_link->params && !rtd->c2c_widget[stream]) { + if (dai_link->c2c_params && !rtd->c2c_widget[stream]) { substream = streams[stream].substream; dai = snd_soc_dapm_new_dai(card, substream, "playback"); if (IS_ERR(dai)) @@ -4368,7 +4368,7 @@ capture: codec = snd_soc_dai_get_widget(codec_dai, stream); if (codec && capture_cpu) { - if (dai_link->params && !rtd->c2c_widget[stream]) { + if (dai_link->c2c_params && !rtd->c2c_widget[stream]) { substream = streams[stream].substream; dai = snd_soc_dapm_new_dai(card, substream, "capture"); if (IS_ERR(dai)) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index b830a53ceacb..913a7d98e742 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2793,9 +2793,9 @@ static int soc_get_playback_capture(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *codec_dai; /* Adapt stream for codec2codec links */ - int cpu_capture = rtd->dai_link->params ? + int cpu_capture = rtd->dai_link->c2c_params ? SNDRV_PCM_STREAM_PLAYBACK : SNDRV_PCM_STREAM_CAPTURE; - int cpu_playback = rtd->dai_link->params ? + int cpu_playback = rtd->dai_link->c2c_params ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK; for_each_rtd_codec_dais(rtd, i, codec_dai) { @@ -2839,7 +2839,7 @@ static int soc_create_pcm(struct snd_pcm **pcm, int ret; /* create the PCM */ - if (rtd->dai_link->params) { + if (rtd->dai_link->c2c_params) { snprintf(new_name, sizeof(new_name), "codec2codec(%s)", rtd->dai_link->stream_name); @@ -2896,7 +2896,7 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) * don't interface with the outside world or application layer * we don't have to do any special handling on close. */ - if (!rtd->dai_link->params) + if (!rtd->dai_link->c2c_params) rtd->close_delayed_work_func = snd_soc_close_delayed_work; rtd->pcm = pcm; @@ -2904,7 +2904,7 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) pcm->private_data = rtd; pcm->no_device_suspend = true; - if (rtd->dai_link->no_pcm || rtd->dai_link->params) { + if (rtd->dai_link->no_pcm || rtd->dai_link->c2c_params) { if (playback) pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd; if (capture) From a1cd7e8017aabe4dded887dcca30e126ec2753c3 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Sun, 2 Apr 2023 22:59:45 +0000 Subject: [PATCH 679/778] ASoC: audio-graph-card2: switch to use c2c_params instead of params ASoC is now using c2c_params instead of params. This patch replace it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87mt3pc2la.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/generic/audio-graph-card2.c | 4 ++-- sound/soc/generic/simple-card-utils.c | 24 ++++++++++++------------ 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/sound/soc/generic/audio-graph-card2.c b/sound/soc/generic/audio-graph-card2.c index d145b74d41e4..25aa79dd55b3 100644 --- a/sound/soc/generic/audio-graph-card2.c +++ b/sound/soc/generic/audio-graph-card2.c @@ -920,8 +920,8 @@ int audio_graph2_link_c2c(struct asoc_simple_priv *priv, c2c_conf->channels_min = c2c_conf->channels_max = 2; /* update ME */ - dai_link->params = c2c_conf; - dai_link->num_params = 1; + dai_link->c2c_params = c2c_conf; + dai_link->num_c2c_params = 1; } ep0 = port_to_endpoint(port0); diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index 34a9b91e676f..467edd96eae5 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -562,12 +562,12 @@ static int asoc_simple_init_for_codec2codec(struct snd_soc_pcm_runtime *rtd, { struct snd_soc_dai_link *dai_link = rtd->dai_link; struct snd_soc_component *component; - struct snd_soc_pcm_stream *params; + struct snd_soc_pcm_stream *c2c_params; struct snd_pcm_hardware hw; int i, ret, stream; /* Do nothing if it already has Codec2Codec settings */ - if (dai_link->params) + if (dai_link->c2c_params) return 0; /* Do nothing if it was DPCM :: BE */ @@ -592,19 +592,19 @@ static int asoc_simple_init_for_codec2codec(struct snd_soc_pcm_runtime *rtd, return ret; } - params = devm_kzalloc(rtd->dev, sizeof(*params), GFP_KERNEL); - if (!params) + c2c_params = devm_kzalloc(rtd->dev, sizeof(*c2c_params), GFP_KERNEL); + if (!c2c_params) return -ENOMEM; - params->formats = hw.formats; - params->rates = hw.rates; - params->rate_min = hw.rate_min; - params->rate_max = hw.rate_max; - params->channels_min = hw.channels_min; - params->channels_max = hw.channels_max; + c2c_params->formats = hw.formats; + c2c_params->rates = hw.rates; + c2c_params->rate_min = hw.rate_min; + c2c_params->rate_max = hw.rate_max; + c2c_params->channels_min = hw.channels_min; + c2c_params->channels_max = hw.channels_max; - dai_link->params = params; - dai_link->num_params = 1; + dai_link->c2c_params = c2c_params; + dai_link->num_c2c_params = 1; return 0; } From 433f4a1697fae78c34377de1ef3abd26aec8214e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Sun, 2 Apr 2023 22:59:57 +0000 Subject: [PATCH 680/778] ASoC: meson: switch to use c2c_params instead of params ASoC is now using c2c_params instead of params. This patch replace it. num_c2c_params (was num_params) was not mandatory before, but let's set it by this patch. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87lej9c2ky.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/meson/axg-card.c | 3 ++- sound/soc/meson/gx-card.c | 3 ++- sound/soc/meson/meson-codec-glue.c | 5 +++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/sound/soc/meson/axg-card.c b/sound/soc/meson/axg-card.c index 2b77010c2c5c..a25c397c66c5 100644 --- a/sound/soc/meson/axg-card.c +++ b/sound/soc/meson/axg-card.c @@ -337,7 +337,8 @@ static int axg_card_add_link(struct snd_soc_card *card, struct device_node *np, return ret; if (axg_card_cpu_is_codec(dai_link->cpus->of_node)) { - dai_link->params = &codec_params; + dai_link->c2c_params = &codec_params; + dai_link->num_c2c_params = 1; } else { dai_link->no_pcm = 1; snd_soc_dai_link_set_capabilities(dai_link); diff --git a/sound/soc/meson/gx-card.c b/sound/soc/meson/gx-card.c index 5119434a81c4..58c411d3c489 100644 --- a/sound/soc/meson/gx-card.c +++ b/sound/soc/meson/gx-card.c @@ -104,7 +104,8 @@ static int gx_card_add_link(struct snd_soc_card *card, struct device_node *np, /* Or apply codec to codec params if necessary */ if (gx_card_cpu_identify(dai_link->cpus, "CODEC CTRL")) { - dai_link->params = &codec_params; + dai_link->c2c_params = &codec_params; + dai_link->num_c2c_params = 1; } else { dai_link->no_pcm = 1; snd_soc_dai_link_set_capabilities(dai_link); diff --git a/sound/soc/meson/meson-codec-glue.c b/sound/soc/meson/meson-codec-glue.c index 5913486c43ab..e702d408ee96 100644 --- a/sound/soc/meson/meson-codec-glue.c +++ b/sound/soc/meson/meson-codec-glue.c @@ -105,13 +105,14 @@ int meson_codec_glue_output_startup(struct snd_pcm_substream *substream, if (!in_data) return -ENODEV; - if (WARN_ON(!rtd->dai_link->params)) { + if (WARN_ON(!rtd->dai_link->c2c_params)) { dev_warn(dai->dev, "codec2codec link expected\n"); return -EINVAL; } /* Replace link params with the input params */ - rtd->dai_link->params = &in_data->params; + rtd->dai_link->c2c_params = &in_data->params; + rtd->dai_link->num_c2c_params = 1; return snd_soc_runtime_set_dai_fmt(rtd, in_data->fmt); } From e7a73b05542d82e209af450dd90b730255f6e775 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Sun, 2 Apr 2023 23:00:07 +0000 Subject: [PATCH 681/778] ASoC: samsung: switch to use c2c_params instead of params ASoC is now using c2c_params instead of params. This patch replace it. num_c2c_params (was num_params) was not mandatory before, but let's set it by this patch. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87jzytc2kp.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/samsung/aries_wm8994.c | 6 ++++-- sound/soc/samsung/bells.c | 21 ++++++++++++++------- sound/soc/samsung/littlemill.c | 3 ++- sound/soc/samsung/lowland.c | 3 ++- sound/soc/samsung/speyside.c | 3 ++- 5 files changed, 24 insertions(+), 12 deletions(-) diff --git a/sound/soc/samsung/aries_wm8994.c b/sound/soc/samsung/aries_wm8994.c index 0fbbf3b02c09..7492bb41456c 100644 --- a/sound/soc/samsung/aries_wm8994.c +++ b/sound/soc/samsung/aries_wm8994.c @@ -483,14 +483,16 @@ static struct snd_soc_dai_link aries_dai[] = { .name = "WM8994 AIF2", .stream_name = "Baseband", .init = &aries_baseband_init, - .params = &baseband_params, + .c2c_params = &baseband_params, + .num_c2c_params = 1, .ignore_suspend = 1, SND_SOC_DAILINK_REG(baseband), }, { .name = "WM8994 AIF3", .stream_name = "Bluetooth", - .params = &bluetooth_params, + .c2c_params = &bluetooth_params, + .num_c2c_params = 1, .ignore_suspend = 1, SND_SOC_DAILINK_REG(bluetooth), }, diff --git a/sound/soc/samsung/bells.c b/sound/soc/samsung/bells.c index 76998a4a4cad..70b63d4faa99 100644 --- a/sound/soc/samsung/bells.c +++ b/sound/soc/samsung/bells.c @@ -264,7 +264,8 @@ static struct snd_soc_dai_link bells_dai_wm2200[] = { .stream_name = "DSP-CODEC", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, - .params = &sub_params, + .c2c_params = &sub_params, + .num_c2c_params = 1, .ignore_suspend = 1, SND_SOC_DAILINK_REG(wm2200_dsp_codec), }, @@ -300,7 +301,8 @@ static struct snd_soc_dai_link bells_dai_wm5102[] = { .stream_name = "DSP-CODEC", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, - .params = &sub_params, + .c2c_params = &sub_params, + .num_c2c_params = 1, .ignore_suspend = 1, SND_SOC_DAILINK_REG(wm5102_dsp_codec), }, @@ -310,7 +312,8 @@ static struct snd_soc_dai_link bells_dai_wm5102[] = { .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, .ignore_suspend = 1, - .params = &baseband_params, + .c2c_params = &baseband_params, + .num_c2c_params = 1, SND_SOC_DAILINK_REG(wm5102_baseband), }, { @@ -319,7 +322,8 @@ static struct snd_soc_dai_link bells_dai_wm5102[] = { .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, .ignore_suspend = 1, - .params = &sub_params, + .c2c_params = &sub_params, + .num_c2c_params = 1, SND_SOC_DAILINK_REG(wm5102_sub), }, }; @@ -355,7 +359,8 @@ static struct snd_soc_dai_link bells_dai_wm5110[] = { .stream_name = "DSP-CODEC", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, - .params = &sub_params, + .c2c_params = &sub_params, + .num_c2c_params = 1, .ignore_suspend = 1, SND_SOC_DAILINK_REG(wm5110_dsp_codec), }, @@ -365,7 +370,8 @@ static struct snd_soc_dai_link bells_dai_wm5110[] = { .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, .ignore_suspend = 1, - .params = &baseband_params, + .c2c_params = &baseband_params, + .num_c2c_params = 1, SND_SOC_DAILINK_REG(wm5110_baseband), }, { @@ -374,7 +380,8 @@ static struct snd_soc_dai_link bells_dai_wm5110[] = { .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, .ignore_suspend = 1, - .params = &sub_params, + .c2c_params = &sub_params, + .num_c2c_params = 1, SND_SOC_DAILINK_REG(wm5110_sub), }, }; diff --git a/sound/soc/samsung/littlemill.c b/sound/soc/samsung/littlemill.c index 411e25cec591..5d8118e69359 100644 --- a/sound/soc/samsung/littlemill.c +++ b/sound/soc/samsung/littlemill.c @@ -167,7 +167,8 @@ static struct snd_soc_dai_link littlemill_dai[] = { .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, .ignore_suspend = 1, - .params = &baseband_params, + .c2c_params = &baseband_params, + .num_c2c_params = 1, SND_SOC_DAILINK_REG(baseband), }, }; diff --git a/sound/soc/samsung/lowland.c b/sound/soc/samsung/lowland.c index b44f5e92224f..106770be6fc5 100644 --- a/sound/soc/samsung/lowland.c +++ b/sound/soc/samsung/lowland.c @@ -119,7 +119,8 @@ static struct snd_soc_dai_link lowland_dai[] = { .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, .ignore_suspend = 1, - .params = &sub_params, + .c2c_params = &sub_params, + .num_c2c_params = 1, .init = lowland_wm9081_init, SND_SOC_DAILINK_REG(speaker), }, diff --git a/sound/soc/samsung/speyside.c b/sound/soc/samsung/speyside.c index 69d7b0115b38..22e2ad63d64d 100644 --- a/sound/soc/samsung/speyside.c +++ b/sound/soc/samsung/speyside.c @@ -219,7 +219,8 @@ static struct snd_soc_dai_link speyside_dai[] = { .init = speyside_wm8996_init, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, - .params = &dsp_codec_params, + .c2c_params = &dsp_codec_params, + .num_c2c_params = 1, .ignore_suspend = 1, SND_SOC_DAILINK_REG(dsp_codec), }, From 1ea63f29c27712d6b9c45af67cd71299d849c5e3 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Sun, 2 Apr 2023 23:00:17 +0000 Subject: [PATCH 682/778] ASoC: soc.h: remove unused params/num_params No drivers are using params/num_params any more. Let's remove these. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87iledc2ke.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc.h | 3 --- sound/soc/soc-core.c | 11 ----------- 2 files changed, 14 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index 276afdb1f445..3833184c187f 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -690,9 +690,6 @@ struct snd_soc_dai_link { const struct snd_soc_pcm_stream *c2c_params; unsigned int num_c2c_params; - const struct snd_soc_pcm_stream *params; /* REMOVE ME */ - unsigned int num_params; /* REMOVE ME */ - unsigned int dai_fmt; /* format to set on init */ enum snd_soc_dpcm_trigger trigger[2]; /* trigger type for DPCM */ diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 04f1bc8a3128..9bbcff492c1e 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2294,9 +2294,6 @@ EXPORT_SYMBOL_GPL(snd_soc_add_dai_controls); */ int snd_soc_register_card(struct snd_soc_card *card) { - struct snd_soc_dai_link *dai_link; - int i; - if (!card->name || !card->dev) return -EINVAL; @@ -2317,14 +2314,6 @@ int snd_soc_register_card(struct snd_soc_card *card) mutex_init(&card->dapm_mutex); mutex_init(&card->pcm_mutex); - /* REMOVE ME */ - for_each_card_prelinks(card, i, dai_link) { - if (!dai_link->c2c_params) { - dai_link->c2c_params = dai_link->params; - dai_link->num_c2c_params = dai_link->num_params; - } - } - return snd_soc_bind_card(card); } EXPORT_SYMBOL_GPL(snd_soc_register_card); From 72456c24c8357793bacf5e67549db1f8c3fafe11 Mon Sep 17 00:00:00 2001 From: Saalim Quadri Date: Wed, 5 Apr 2023 16:46:05 +0530 Subject: [PATCH 683/778] ASoC: dt-bindings: wm8510: Convert to dtschema Convert the WM8510 audio CODEC bindings to DT schema Signed-off-by: Saalim Quadri Link: https://lore.kernel.org/r/20230405111605.5250-1-danascape@gmail.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/wlf,wm8510.yaml | 41 +++++++++++++++++++ .../devicetree/bindings/sound/wm8510.txt | 18 -------- 2 files changed, 41 insertions(+), 18 deletions(-) create mode 100644 Documentation/devicetree/bindings/sound/wlf,wm8510.yaml delete mode 100644 Documentation/devicetree/bindings/sound/wm8510.txt diff --git a/Documentation/devicetree/bindings/sound/wlf,wm8510.yaml b/Documentation/devicetree/bindings/sound/wlf,wm8510.yaml new file mode 100644 index 000000000000..6d12b0ac37e2 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/wlf,wm8510.yaml @@ -0,0 +1,41 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/wlf,wm8510.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: WM8510 audio CODEC + +maintainers: + - patches@opensource.cirrus.com + +allOf: + - $ref: dai-common.yaml# + +properties: + compatible: + const: wlf,wm8510 + + reg: + maxItems: 1 + + "#sound-dai-cells": + const: 0 + +required: + - compatible + - reg + +unevaluatedProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + + codec@1a { + compatible = "wlf,wm8510"; + reg = <0x1a>; + }; + }; diff --git a/Documentation/devicetree/bindings/sound/wm8510.txt b/Documentation/devicetree/bindings/sound/wm8510.txt deleted file mode 100644 index e6b6cc041f89..000000000000 --- a/Documentation/devicetree/bindings/sound/wm8510.txt +++ /dev/null @@ -1,18 +0,0 @@ -WM8510 audio CODEC - -This device supports both I2C and SPI (configured with pin strapping -on the board). - -Required properties: - - - compatible : "wlf,wm8510" - - - reg : the I2C address of the device for I2C, the chip select - number for SPI. - -Example: - -wm8510: codec@1a { - compatible = "wlf,wm8510"; - reg = <0x1a>; -}; From 3456aeb02a28e82235d45da434752e6f441427f0 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 5 Apr 2023 22:57:55 +0000 Subject: [PATCH 684/778] ASoC: soc-dapm.c: tidyup dapm_connect_dai_pair() dapm_connect_dai_pair() handles "Normal/Codec2Codec" x "CPU/Codec" x "Playback/Capture". (A) is "Codec2Codec" case of "CPU" widget x "Playback/Capture", (B) is "Normal" case of "CPU" widget x "Playback/Capture", (C) is each case of "Codec" widget. (X) is handling "Playback" case DAI connecting, (Y) is handling "Capture" case DAI connecting. static void dapm_connect_dai_pair(...) { ... (A) if (dai_link->params) { playback_cpu = ... capture_cpu = ... (B) } else { playback_cpu = ... capture_cpu = ... } ^ /* connect BE DAI playback if widgets are valid */ | stream = SNDRV_PCM_STREAM_PLAYBACK; | (C) codec = codec_dai->playback_widget; | | if (playback_cpu && codec) { (X) if (dai_link->params && !rtd->c2c_widget[stream]) { | ... | } | | (z) dapm_connect_dai_routes(...); v } capture: ^ /* connect BE DAI capture if widgets are valid */ | stream = SNDRV_PCM_STREAM_CAPTURE; | (C) codec = codec_dai->capture_widget; | | if (codec && capture_cpu) { (Y) if (dai_link->params && !rtd->c2c_widget[stream]) { | ... | } | | (z) dapm_connect_dai_routes(...); v } } (X) part and (Y) part are almost same. Main purpose of these parts (and this function) is calling dapm_connect_dai_routes() (= z) on each cases. The difference is "parameter" (= Normal/Codec2Codec x CPU/Codec x Playback/Capture). This patch cleanup these, but nothing changed for meaning. Link: https://lore.kernel.org/r/87ilen6ni4.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/877cuqvswc.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 97 +++++++++++++++++++++++++++----------------- 1 file changed, 59 insertions(+), 38 deletions(-) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index e7a0c28e0cb1..36e6f261bcf7 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -4325,60 +4325,81 @@ static void dapm_connect_dai_routes(struct snd_soc_dapm_context *dapm, snd_soc_dapm_add_path(dapm, src, sink, NULL, NULL); } +static int get_stream_cpu(struct snd_soc_dai_link *dai_link, int stream) +{ + /* + * [Normal] + * + * Playback + * CPU : SNDRV_PCM_STREAM_PLAYBACK + * Codec: SNDRV_PCM_STREAM_PLAYBACK + * + * Playback + * CPU : SNDRV_PCM_STREAM_CAPTURE + * Codec: SNDRV_PCM_STREAM_CAPTURE + */ + if (!dai_link->c2c_params) + return stream; + + /* + * [Codec2Codec] + * + * Playback + * CPU : SNDRV_PCM_STREAM_CAPTURE + * Codec: SNDRV_PCM_STREAM_PLAYBACK + * + * Capture + * CPU : SNDRV_PCM_STREAM_PLAYBACK + * Codec: SNDRV_PCM_STREAM_CAPTURE + */ + if (stream == SNDRV_PCM_STREAM_CAPTURE) + return SNDRV_PCM_STREAM_PLAYBACK; + + return SNDRV_PCM_STREAM_CAPTURE; +} + static void dapm_connect_dai_pair(struct snd_soc_card *card, struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *codec_dai, struct snd_soc_dai *cpu_dai) { struct snd_soc_dai_link *dai_link = rtd->dai_link; - struct snd_soc_dapm_widget *dai, *codec, *playback_cpu, *capture_cpu; - struct snd_pcm_substream *substream; - struct snd_pcm_str *streams = rtd->pcm->streams; + struct snd_soc_dapm_widget *codec, *cpu; + struct snd_soc_dai *src_dai[] = { cpu_dai, codec_dai }; + struct snd_soc_dai *sink_dai[] = { codec_dai, cpu_dai }; + struct snd_soc_dapm_widget **src[] = { &cpu, &codec }; + struct snd_soc_dapm_widget **sink[] = { &codec, &cpu }; + char *widget_name[] = { "playback", "capture" }; int stream; - if (dai_link->c2c_params) { - playback_cpu = snd_soc_dai_get_widget_capture(cpu_dai); - capture_cpu = snd_soc_dai_get_widget_playback(cpu_dai); - } else { - playback_cpu = snd_soc_dai_get_widget_playback(cpu_dai); - capture_cpu = snd_soc_dai_get_widget_capture(cpu_dai); - } + for_each_pcm_streams(stream) { + int stream_cpu, stream_codec; - /* connect BE DAI playback if widgets are valid */ - stream = SNDRV_PCM_STREAM_PLAYBACK; - codec = snd_soc_dai_get_widget(codec_dai, stream); + stream_cpu = get_stream_cpu(dai_link, stream); + stream_codec = stream; - if (playback_cpu && codec) { + /* connect BE DAI playback if widgets are valid */ + cpu = snd_soc_dai_get_widget(cpu_dai, stream_cpu); + codec = snd_soc_dai_get_widget(codec_dai, stream_codec); + + if (!cpu || !codec) + continue; + + /* special handling for [Codec2Codec] */ if (dai_link->c2c_params && !rtd->c2c_widget[stream]) { - substream = streams[stream].substream; - dai = snd_soc_dapm_new_dai(card, substream, "playback"); + struct snd_pcm_substream *substream = rtd->pcm->streams[stream].substream; + struct snd_soc_dapm_widget *dai = snd_soc_dapm_new_dai(card, substream, + widget_name[stream]); + if (IS_ERR(dai)) - goto capture; + continue; + rtd->c2c_widget[stream] = dai; } - dapm_connect_dai_routes(&card->dapm, cpu_dai, playback_cpu, + dapm_connect_dai_routes(&card->dapm, src_dai[stream], *src[stream], rtd->c2c_widget[stream], - codec_dai, codec); - } - -capture: - /* connect BE DAI capture if widgets are valid */ - stream = SNDRV_PCM_STREAM_CAPTURE; - codec = snd_soc_dai_get_widget(codec_dai, stream); - - if (codec && capture_cpu) { - if (dai_link->c2c_params && !rtd->c2c_widget[stream]) { - substream = streams[stream].substream; - dai = snd_soc_dapm_new_dai(card, substream, "capture"); - if (IS_ERR(dai)) - return; - rtd->c2c_widget[stream] = dai; - } - - dapm_connect_dai_routes(&card->dapm, codec_dai, codec, - rtd->c2c_widget[stream], - cpu_dai, capture_cpu); + sink_dai[stream], *sink[stream]); } } From 63a511284c9ea72696a5dd0a2d2721bdef19f774 Mon Sep 17 00:00:00 2001 From: Shuming Fan Date: Thu, 6 Apr 2023 16:55:35 +0800 Subject: [PATCH 685/778] ASoC: rt712-sdca: Add RT712 SDCA driver for Mic topology This is the initial codec driver for rt712 SDCA (Mic topology). The host should connect with rt712 SdW2 interface. Signed-off-by: Shuming Fan Link: https://lore.kernel.org/r/20230406085535.52002-1-shumingf@realtek.com Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 7 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/rt712-sdca-dmic.c | 983 +++++++++++++++++++++++++++++ sound/soc/codecs/rt712-sdca-dmic.h | 108 ++++ 4 files changed, 1100 insertions(+) create mode 100644 sound/soc/codecs/rt712-sdca-dmic.c create mode 100644 sound/soc/codecs/rt712-sdca-dmic.h diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 4062fe3fbb1c..79d2362ad055 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -204,6 +204,7 @@ config SND_SOC_ALL_CODECS imply SND_SOC_RT711_SDW imply SND_SOC_RT711_SDCA_SDW imply SND_SOC_RT712_SDCA_SDW + imply SND_SOC_RT712_SDCA_DMIC_SDW imply SND_SOC_RT715_SDW imply SND_SOC_RT715_SDCA_SDW imply SND_SOC_RT1308_SDW @@ -1532,6 +1533,12 @@ config SND_SOC_RT712_SDCA_SDW select REGMAP_SOUNDWIRE select REGMAP_SOUNDWIRE_MBQ +config SND_SOC_RT712_SDCA_DMIC_SDW + tristate "Realtek RT712 SDCA DMIC Codec - SDW" + depends on SOUNDWIRE + select REGMAP_SOUNDWIRE + select REGMAP_SOUNDWIRE_MBQ + config SND_SOC_RT715 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 44ea747579fd..5cdbae88e6e3 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -234,6 +234,7 @@ snd-soc-rt700-objs := rt700.o rt700-sdw.o snd-soc-rt711-objs := rt711.o rt711-sdw.o snd-soc-rt711-sdca-objs := rt711-sdca.o rt711-sdca-sdw.o snd-soc-rt712-sdca-objs := rt712-sdca.o rt712-sdca-sdw.o +snd-soc-rt712-sdca-dmic-objs := rt712-sdca-dmic.o snd-soc-rt715-objs := rt715.o rt715-sdw.o snd-soc-rt715-sdca-objs := rt715-sdca.o rt715-sdca-sdw.o snd-soc-rt9120-objs := rt9120.o @@ -603,6 +604,7 @@ obj-$(CONFIG_SND_SOC_RT700) += snd-soc-rt700.o obj-$(CONFIG_SND_SOC_RT711) += snd-soc-rt711.o obj-$(CONFIG_SND_SOC_RT711_SDCA_SDW) += snd-soc-rt711-sdca.o obj-$(CONFIG_SND_SOC_RT712_SDCA_SDW) += snd-soc-rt712-sdca.o +obj-$(CONFIG_SND_SOC_RT712_SDCA_DMIC_SDW) += snd-soc-rt712-sdca-dmic.o obj-$(CONFIG_SND_SOC_RT715) += snd-soc-rt715.o obj-$(CONFIG_SND_SOC_RT715_SDCA_SDW) += snd-soc-rt715-sdca.o obj-$(CONFIG_SND_SOC_RT9120) += snd-soc-rt9120.o diff --git a/sound/soc/codecs/rt712-sdca-dmic.c b/sound/soc/codecs/rt712-sdca-dmic.c new file mode 100644 index 000000000000..09807b6d6353 --- /dev/null +++ b/sound/soc/codecs/rt712-sdca-dmic.c @@ -0,0 +1,983 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// rt712-sdca-dmic.c -- rt712 SDCA DMIC ALSA SoC audio driver +// +// Copyright(c) 2023 Realtek Semiconductor Corp. +// +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "rt712-sdca.h" +#include "rt712-sdca-dmic.h" + +static bool rt712_sdca_dmic_readable_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case 0x201a ... 0x201f: + case 0x2029 ... 0x202a: + case 0x202d ... 0x2034: + case 0x2230 ... 0x2232: + case 0x2f01 ... 0x2f0a: + case 0x2f35 ... 0x2f36: + case 0x2f52: + case 0x2f58 ... 0x2f59: + case 0x3201: + case 0x320c: + return true; + default: + return false; + } +} + +static bool rt712_sdca_dmic_volatile_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case 0x201b: + case 0x201c: + case 0x201d: + case 0x201f: + case 0x202d ... 0x202f: + case 0x2230: + case 0x2f01: + case 0x2f35: + case 0x320c: + return true; + default: + return false; + } +} + +static bool rt712_sdca_dmic_mbq_readable_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case 0x2000000 ... 0x200008e: + case 0x5300000 ... 0x530000e: + case 0x5400000 ... 0x540000e: + case 0x5600000 ... 0x5600008: + case 0x5700000 ... 0x570000d: + case 0x5800000 ... 0x5800021: + case 0x5900000 ... 0x5900028: + case 0x5a00000 ... 0x5a00009: + case 0x5b00000 ... 0x5b00051: + case 0x5c00000 ... 0x5c0009a: + case 0x5d00000 ... 0x5d00009: + case 0x5f00000 ... 0x5f00030: + case 0x6100000 ... 0x6100068: + case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_USER_FU1E, RT712_SDCA_CTL_FU_VOLUME, CH_01): + case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_USER_FU1E, RT712_SDCA_CTL_FU_VOLUME, CH_02): + case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_USER_FU1E, RT712_SDCA_CTL_FU_VOLUME, CH_03): + case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_USER_FU1E, RT712_SDCA_CTL_FU_VOLUME, CH_04): + case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_PLATFORM_FU15, RT712_SDCA_CTL_FU_CH_GAIN, CH_01): + case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_PLATFORM_FU15, RT712_SDCA_CTL_FU_CH_GAIN, CH_02): + case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_PLATFORM_FU15, RT712_SDCA_CTL_FU_CH_GAIN, CH_03): + case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_PLATFORM_FU15, RT712_SDCA_CTL_FU_CH_GAIN, CH_04): + return true; + default: + return false; + } +} + +static bool rt712_sdca_dmic_mbq_volatile_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case 0x2000000: + case 0x200001a: + case 0x2000024: + case 0x2000046: + case 0x200008a: + case 0x5800000: + case 0x5800001: + case 0x6100008: + return true; + default: + return false; + } +} + +static const struct regmap_config rt712_sdca_dmic_regmap = { + .reg_bits = 32, + .val_bits = 8, + .readable_reg = rt712_sdca_dmic_readable_register, + .volatile_reg = rt712_sdca_dmic_volatile_register, + .max_register = 0x40981300, + .reg_defaults = rt712_sdca_dmic_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(rt712_sdca_dmic_reg_defaults), + .cache_type = REGCACHE_RBTREE, + .use_single_read = true, + .use_single_write = true, +}; + +static const struct regmap_config rt712_sdca_dmic_mbq_regmap = { + .name = "sdw-mbq", + .reg_bits = 32, + .val_bits = 16, + .readable_reg = rt712_sdca_dmic_mbq_readable_register, + .volatile_reg = rt712_sdca_dmic_mbq_volatile_register, + .max_register = 0x40800f14, + .reg_defaults = rt712_sdca_dmic_mbq_defaults, + .num_reg_defaults = ARRAY_SIZE(rt712_sdca_dmic_mbq_defaults), + .cache_type = REGCACHE_RBTREE, + .use_single_read = true, + .use_single_write = true, +}; + +static int rt712_sdca_dmic_index_write(struct rt712_sdca_dmic_priv *rt712, + unsigned int nid, unsigned int reg, unsigned int value) +{ + int ret; + struct regmap *regmap = rt712->mbq_regmap; + unsigned int addr = (nid << 20) | reg; + + ret = regmap_write(regmap, addr, value); + if (ret < 0) + dev_err(&rt712->slave->dev, + "Failed to set private value: %06x <= %04x ret=%d\n", + addr, value, ret); + + return ret; +} + +static int rt712_sdca_dmic_index_read(struct rt712_sdca_dmic_priv *rt712, + unsigned int nid, unsigned int reg, unsigned int *value) +{ + int ret; + struct regmap *regmap = rt712->mbq_regmap; + unsigned int addr = (nid << 20) | reg; + + ret = regmap_read(regmap, addr, value); + if (ret < 0) + dev_err(&rt712->slave->dev, + "Failed to get private value: %06x => %04x ret=%d\n", + addr, *value, ret); + + return ret; +} + +static int rt712_sdca_dmic_index_update_bits(struct rt712_sdca_dmic_priv *rt712, + unsigned int nid, unsigned int reg, unsigned int mask, unsigned int val) +{ + unsigned int tmp; + int ret; + + ret = rt712_sdca_dmic_index_read(rt712, nid, reg, &tmp); + if (ret < 0) + return ret; + + set_mask_bits(&tmp, mask, val); + return rt712_sdca_dmic_index_write(rt712, nid, reg, tmp); +} + +static int rt712_sdca_dmic_io_init(struct device *dev, struct sdw_slave *slave) +{ + struct rt712_sdca_dmic_priv *rt712 = dev_get_drvdata(dev); + + if (rt712->hw_init) + return 0; + + if (rt712->first_hw_init) { + regcache_cache_only(rt712->regmap, false); + regcache_cache_bypass(rt712->regmap, true); + regcache_cache_only(rt712->mbq_regmap, false); + regcache_cache_bypass(rt712->mbq_regmap, true); + } else { + /* + * PM runtime is only enabled when a Slave reports as Attached + */ + + /* set autosuspend parameters */ + pm_runtime_set_autosuspend_delay(&slave->dev, 3000); + pm_runtime_use_autosuspend(&slave->dev); + + /* update count of parent 'active' children */ + pm_runtime_set_active(&slave->dev); + + /* make sure the device does not suspend immediately */ + pm_runtime_mark_last_busy(&slave->dev); + + pm_runtime_enable(&slave->dev); + } + + pm_runtime_get_noresume(&slave->dev); + + rt712_sdca_dmic_index_write(rt712, RT712_VENDOR_HDA_CTL, + RT712_ADC0A_08_PDE_FLOAT_CTL, 0x1112); + rt712_sdca_dmic_index_write(rt712, RT712_VENDOR_HDA_CTL, + RT712_ADC0B_11_PDE_FLOAT_CTL, 0x1111); + rt712_sdca_dmic_index_write(rt712, RT712_VENDOR_HDA_CTL, + RT712_DMIC1_2_PDE_FLOAT_CTL, 0x1111); + rt712_sdca_dmic_index_write(rt712, RT712_VENDOR_HDA_CTL, + RT712_I2S_IN_OUT_PDE_FLOAT_CTL, 0x1155); + rt712_sdca_dmic_index_write(rt712, RT712_VENDOR_HDA_CTL, + RT712_DMIC_ENT_FLOAT_CTL, 0x2626); + rt712_sdca_dmic_index_write(rt712, RT712_VENDOR_HDA_CTL, + RT712_ADC_ENT_FLOAT_CTL, 0x1e19); + rt712_sdca_dmic_index_write(rt712, RT712_VENDOR_HDA_CTL, + RT712_DMIC_GAIN_ENT_FLOAT_CTL0, 0x1515); + rt712_sdca_dmic_index_write(rt712, RT712_VENDOR_HDA_CTL, + RT712_ADC_VOL_CH_FLOAT_CTL2, 0x0304); + rt712_sdca_dmic_index_write(rt712, RT712_VENDOR_HDA_CTL, + RT712_DMIC_GAIN_ENT_FLOAT_CTL2, 0x0304); + rt712_sdca_dmic_index_write(rt712, RT712_VENDOR_HDA_CTL, + RT712_HDA_LEGACY_CONFIG_CTL0, 0x0050); + regmap_write(rt712->regmap, + SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_IT26, RT712_SDCA_CTL_VENDOR_DEF, 0), 0x01); + rt712_sdca_dmic_index_write(rt712, RT712_ULTRA_SOUND_DET, + RT712_ULTRA_SOUND_DETECTOR6, 0x3200); + regmap_write(rt712->regmap, RT712_RC_CAL, 0x23); + regmap_write(rt712->regmap, 0x2f52, 0x00); + + if (rt712->first_hw_init) { + regcache_cache_bypass(rt712->regmap, false); + regcache_mark_dirty(rt712->regmap); + regcache_cache_bypass(rt712->mbq_regmap, false); + regcache_mark_dirty(rt712->mbq_regmap); + } else + rt712->first_hw_init = true; + + /* Mark Slave initialization complete */ + rt712->hw_init = true; + + pm_runtime_mark_last_busy(&slave->dev); + pm_runtime_put_autosuspend(&slave->dev); + + dev_dbg(&slave->dev, "%s hw_init complete\n", __func__); + return 0; +} + +static int rt712_sdca_dmic_set_gain_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct rt712_sdca_priv *rt712 = snd_soc_component_get_drvdata(component); + struct rt712_sdca_dmic_kctrl_priv *p = + (struct rt712_sdca_dmic_kctrl_priv *)kcontrol->private_value; + unsigned int regvalue, ctl, i; + unsigned int adc_vol_flag = 0; + const unsigned int interval_offset = 0xc0; + + if (strstr(ucontrol->id.name, "FU1E Capture Volume")) + adc_vol_flag = 1; + + /* check all channels */ + for (i = 0; i < p->count; i++) { + regmap_read(rt712->mbq_regmap, p->reg_base + i, ®value); + + if (!adc_vol_flag) /* boost gain */ + ctl = regvalue / 0x0a00; + else { /* ADC gain */ + if (adc_vol_flag) + ctl = p->max - (((0x1e00 - regvalue) & 0xffff) / interval_offset); + else + ctl = p->max - (((0 - regvalue) & 0xffff) / interval_offset); + } + + ucontrol->value.integer.value[i] = ctl; + } + + return 0; +} + +static int rt712_sdca_dmic_set_gain_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct rt712_sdca_dmic_kctrl_priv *p = + (struct rt712_sdca_dmic_kctrl_priv *)kcontrol->private_value; + struct rt712_sdca_priv *rt712 = snd_soc_component_get_drvdata(component); + unsigned int gain_val[4]; + unsigned int i, adc_vol_flag = 0, changed = 0; + unsigned int regvalue[4]; + const unsigned int interval_offset = 0xc0; + int err; + + if (strstr(ucontrol->id.name, "FU1E Capture Volume")) + adc_vol_flag = 1; + + /* check all channels */ + for (i = 0; i < p->count; i++) { + regmap_read(rt712->mbq_regmap, p->reg_base + i, ®value[i]); + + gain_val[i] = ucontrol->value.integer.value[i]; + if (gain_val[i] > p->max) + gain_val[i] = p->max; + + if (!adc_vol_flag) /* boost gain */ + gain_val[i] = gain_val[i] * 0x0a00; + else { /* ADC gain */ + gain_val[i] = 0x1e00 - ((p->max - gain_val[i]) * interval_offset); + gain_val[i] &= 0xffff; + } + + if (regvalue[i] != gain_val[i]) + changed = 1; + } + + if (!changed) + return 0; + + for (i = 0; i < p->count; i++) { + err = regmap_write(rt712->mbq_regmap, p->reg_base + i, gain_val[i]); + if (err < 0) + dev_err(&rt712->slave->dev, "0x%08x can't be set\n", p->reg_base + i); + } + + return changed; +} + +static int rt712_sdca_set_fu1e_capture_ctl(struct rt712_sdca_dmic_priv *rt712) +{ + int err, i; + unsigned int ch_mute; + + for (i = 0; i < ARRAY_SIZE(rt712->fu1e_mixer_mute); i++) { + ch_mute = (rt712->fu1e_dapm_mute || rt712->fu1e_mixer_mute[i]) ? 0x01 : 0x00; + err = regmap_write(rt712->regmap, + SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_USER_FU1E, + RT712_SDCA_CTL_FU_MUTE, CH_01) + i, ch_mute); + if (err < 0) + return err; + } + + return 0; +} + +static int rt712_sdca_dmic_fu1e_capture_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct rt712_sdca_dmic_priv *rt712 = snd_soc_component_get_drvdata(component); + struct rt712_sdca_dmic_kctrl_priv *p = + (struct rt712_sdca_dmic_kctrl_priv *)kcontrol->private_value; + unsigned int i; + + for (i = 0; i < p->count; i++) + ucontrol->value.integer.value[i] = !rt712->fu1e_mixer_mute[i]; + + return 0; +} + +static int rt712_sdca_dmic_fu1e_capture_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct rt712_sdca_dmic_priv *rt712 = snd_soc_component_get_drvdata(component); + struct rt712_sdca_dmic_kctrl_priv *p = + (struct rt712_sdca_dmic_kctrl_priv *)kcontrol->private_value; + int err, changed = 0, i; + + for (i = 0; i < p->count; i++) { + if (rt712->fu1e_mixer_mute[i] != !ucontrol->value.integer.value[i]) + changed = 1; + rt712->fu1e_mixer_mute[i] = !ucontrol->value.integer.value[i]; + } + + err = rt712_sdca_set_fu1e_capture_ctl(rt712); + if (err < 0) + return err; + + return changed; +} + +static int rt712_sdca_fu_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + struct rt712_sdca_dmic_kctrl_priv *p = + (struct rt712_sdca_dmic_kctrl_priv *)kcontrol->private_value; + + if (p->max == 1) + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + else + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = p->count; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = p->max; + return 0; +} + +#define RT712_SDCA_PR_VALUE(xreg_base, xcount, xmax, xinvert) \ + ((unsigned long)&(struct rt712_sdca_dmic_kctrl_priv) \ + {.reg_base = xreg_base, .count = xcount, .max = xmax, \ + .invert = xinvert}) + +#define RT712_SDCA_FU_CTRL(xname, reg_base, xmax, xinvert, xcount) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ + .info = rt712_sdca_fu_info, \ + .get = rt712_sdca_dmic_fu1e_capture_get, \ + .put = rt712_sdca_dmic_fu1e_capture_put, \ + .private_value = RT712_SDCA_PR_VALUE(reg_base, xcount, xmax, xinvert)} + +#define RT712_SDCA_EXT_TLV(xname, reg_base, xhandler_get,\ + xhandler_put, xcount, xmax, tlv_array) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ + .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ + SNDRV_CTL_ELEM_ACCESS_READWRITE, \ + .tlv.p = (tlv_array), \ + .info = rt712_sdca_fu_info, \ + .get = xhandler_get, .put = xhandler_put, \ + .private_value = RT712_SDCA_PR_VALUE(reg_base, xcount, xmax, 0) } + +static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -1725, 75, 0); +static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, 0, 1000, 0); + +static const struct snd_kcontrol_new rt712_sdca_dmic_snd_controls[] = { + RT712_SDCA_FU_CTRL("FU1E Capture Switch", + SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_USER_FU1E, RT712_SDCA_CTL_FU_MUTE, CH_01), + 1, 1, 4), + RT712_SDCA_EXT_TLV("FU1E Capture Volume", + SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_USER_FU1E, RT712_SDCA_CTL_FU_VOLUME, CH_01), + rt712_sdca_dmic_set_gain_get, rt712_sdca_dmic_set_gain_put, 4, 0x3f, in_vol_tlv), + RT712_SDCA_EXT_TLV("FU15 Boost Volume", + SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_PLATFORM_FU15, RT712_SDCA_CTL_FU_CH_GAIN, CH_01), + rt712_sdca_dmic_set_gain_get, rt712_sdca_dmic_set_gain_put, 4, 3, mic_vol_tlv), +}; + +static int rt712_sdca_dmic_mux_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_dapm_kcontrol_component(kcontrol); + struct rt712_sdca_dmic_priv *rt712 = snd_soc_component_get_drvdata(component); + unsigned int val = 0, mask_sft; + + if (strstr(ucontrol->id.name, "ADC 25 Mux")) + mask_sft = 8; + else if (strstr(ucontrol->id.name, "ADC 26 Mux")) + mask_sft = 4; + else + return -EINVAL; + + rt712_sdca_dmic_index_read(rt712, RT712_VENDOR_HDA_CTL, + RT712_HDA_LEGACY_MUX_CTL0, &val); + + ucontrol->value.enumerated.item[0] = (val >> mask_sft) & 0x7; + + return 0; +} + +static int rt712_sdca_dmic_mux_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_dapm_kcontrol_component(kcontrol); + struct snd_soc_dapm_context *dapm = + snd_soc_dapm_kcontrol_dapm(kcontrol); + struct rt712_sdca_dmic_priv *rt712 = snd_soc_component_get_drvdata(component); + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + unsigned int *item = ucontrol->value.enumerated.item; + unsigned int val, val2 = 0, change, mask_sft; + + if (item[0] >= e->items) + return -EINVAL; + + if (strstr(ucontrol->id.name, "ADC 25 Mux")) + mask_sft = 8; + else if (strstr(ucontrol->id.name, "ADC 26 Mux")) + mask_sft = 4; + else + return -EINVAL; + + val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l; + + rt712_sdca_dmic_index_read(rt712, RT712_VENDOR_HDA_CTL, + RT712_HDA_LEGACY_MUX_CTL0, &val2); + val2 = (0x7 << mask_sft) & val2; + + if (val == val2) + change = 0; + else + change = 1; + + if (change) + rt712_sdca_dmic_index_update_bits(rt712, RT712_VENDOR_HDA_CTL, + RT712_HDA_LEGACY_MUX_CTL0, 0x7 << mask_sft, + val << mask_sft); + + snd_soc_dapm_mux_update_power(dapm, kcontrol, + item[0], e, NULL); + + return change; +} + +static const char * const adc_mux_text[] = { + "DMIC1", + "DMIC2", +}; + +static SOC_ENUM_SINGLE_DECL( + rt712_adc25_enum, SND_SOC_NOPM, 0, adc_mux_text); + +static SOC_ENUM_SINGLE_DECL( + rt712_adc26_enum, SND_SOC_NOPM, 0, adc_mux_text); + +static const struct snd_kcontrol_new rt712_sdca_dmic_adc25_mux = + SOC_DAPM_ENUM_EXT("ADC 25 Mux", rt712_adc25_enum, + rt712_sdca_dmic_mux_get, rt712_sdca_dmic_mux_put); + +static const struct snd_kcontrol_new rt712_sdca_dmic_adc26_mux = + SOC_DAPM_ENUM_EXT("ADC 26 Mux", rt712_adc26_enum, + rt712_sdca_dmic_mux_get, rt712_sdca_dmic_mux_put); + +static int rt712_sdca_dmic_fu1e_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct rt712_sdca_dmic_priv *rt712 = snd_soc_component_get_drvdata(component); + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + rt712->fu1e_dapm_mute = false; + rt712_sdca_set_fu1e_capture_ctl(rt712); + break; + case SND_SOC_DAPM_PRE_PMD: + rt712->fu1e_dapm_mute = true; + rt712_sdca_set_fu1e_capture_ctl(rt712); + break; + } + return 0; +} + +static int rt712_sdca_dmic_pde11_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct rt712_sdca_dmic_priv *rt712 = snd_soc_component_get_drvdata(component); + unsigned char ps0 = 0x0, ps3 = 0x3; + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + regmap_write(rt712->regmap, + SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_PDE11, + RT712_SDCA_CTL_REQ_POWER_STATE, 0), + ps0); + break; + case SND_SOC_DAPM_PRE_PMD: + regmap_write(rt712->regmap, + SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_PDE11, + RT712_SDCA_CTL_REQ_POWER_STATE, 0), + ps3); + break; + } + return 0; +} + +static const struct snd_soc_dapm_widget rt712_sdca_dmic_dapm_widgets[] = { + SND_SOC_DAPM_INPUT("DMIC1"), + SND_SOC_DAPM_INPUT("DMIC2"), + + SND_SOC_DAPM_SUPPLY("PDE 11", SND_SOC_NOPM, 0, 0, + rt712_sdca_dmic_pde11_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + + SND_SOC_DAPM_ADC_E("FU 1E", NULL, SND_SOC_NOPM, 0, 0, + rt712_sdca_dmic_fu1e_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_MUX("ADC 25 Mux", SND_SOC_NOPM, 0, 0, + &rt712_sdca_dmic_adc25_mux), + SND_SOC_DAPM_MUX("ADC 26 Mux", SND_SOC_NOPM, 0, 0, + &rt712_sdca_dmic_adc26_mux), + + SND_SOC_DAPM_AIF_OUT("DP2TX", "DP2 Capture", 0, SND_SOC_NOPM, 0, 0), +}; + +static const struct snd_soc_dapm_route rt712_sdca_dmic_audio_map[] = { + {"DP2TX", NULL, "FU 1E"}, + + {"FU 1E", NULL, "PDE 11"}, + {"FU 1E", NULL, "ADC 25 Mux"}, + {"FU 1E", NULL, "ADC 26 Mux"}, + {"ADC 25 Mux", "DMIC1", "DMIC1"}, + {"ADC 25 Mux", "DMIC2", "DMIC2"}, + {"ADC 26 Mux", "DMIC1", "DMIC1"}, + {"ADC 26 Mux", "DMIC2", "DMIC2"}, +}; + +static int rt712_sdca_dmic_probe(struct snd_soc_component *component) +{ + struct rt712_sdca_dmic_priv *rt712 = snd_soc_component_get_drvdata(component); + int ret; + + rt712->component = component; + + ret = pm_runtime_resume(component->dev); + if (ret < 0 && ret != -EACCES) + return ret; + + return 0; +} + +static const struct snd_soc_component_driver soc_sdca_dev_rt712_dmic = { + .probe = rt712_sdca_dmic_probe, + .controls = rt712_sdca_dmic_snd_controls, + .num_controls = ARRAY_SIZE(rt712_sdca_dmic_snd_controls), + .dapm_widgets = rt712_sdca_dmic_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(rt712_sdca_dmic_dapm_widgets), + .dapm_routes = rt712_sdca_dmic_audio_map, + .num_dapm_routes = ARRAY_SIZE(rt712_sdca_dmic_audio_map), + .endianness = 1, +}; + +static int rt712_sdca_dmic_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, + int direction) +{ + snd_soc_dai_dma_data_set(dai, direction, sdw_stream); + + return 0; +} + +static void rt712_sdca_dmic_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + snd_soc_dai_set_dma_data(dai, substream, NULL); +} + +static int rt712_sdca_dmic_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct rt712_sdca_dmic_priv *rt712 = snd_soc_component_get_drvdata(component); + struct sdw_stream_config stream_config; + struct sdw_port_config port_config; + struct sdw_stream_runtime *sdw_stream; + int retval, num_channels; + unsigned int sampling_rate; + + dev_dbg(dai->dev, "%s %s", __func__, dai->name); + sdw_stream = snd_soc_dai_get_dma_data(dai, substream); + + if (!sdw_stream) + return -EINVAL; + + if (!rt712->slave) + return -EINVAL; + + stream_config.frame_rate = params_rate(params); + stream_config.ch_count = params_channels(params); + stream_config.bps = snd_pcm_format_width(params_format(params)); + stream_config.direction = SDW_DATA_DIR_TX; + + num_channels = params_channels(params); + port_config.ch_mask = GENMASK(num_channels - 1, 0); + port_config.num = 2; + + retval = sdw_stream_add_slave(rt712->slave, &stream_config, + &port_config, 1, sdw_stream); + if (retval) { + dev_err(dai->dev, "Unable to configure port\n"); + return retval; + } + + if (params_channels(params) > 4) { + dev_err(component->dev, "Unsupported channels %d\n", + params_channels(params)); + return -EINVAL; + } + + /* sampling rate configuration */ + switch (params_rate(params)) { + case 16000: + sampling_rate = RT712_SDCA_RATE_16000HZ; + break; + case 32000: + sampling_rate = RT712_SDCA_RATE_32000HZ; + break; + case 44100: + sampling_rate = RT712_SDCA_RATE_44100HZ; + break; + case 48000: + sampling_rate = RT712_SDCA_RATE_48000HZ; + break; + case 96000: + sampling_rate = RT712_SDCA_RATE_96000HZ; + break; + case 192000: + sampling_rate = RT712_SDCA_RATE_192000HZ; + break; + default: + dev_err(component->dev, "Rate %d is not supported\n", + params_rate(params)); + return -EINVAL; + } + + /* set sampling frequency */ + regmap_write(rt712->regmap, + SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_CS1F, RT712_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), + sampling_rate); + regmap_write(rt712->regmap, + SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_CS1C, RT712_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), + sampling_rate); + + return 0; +} + +static int rt712_sdca_dmic_hw_free(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct rt712_sdca_dmic_priv *rt712 = snd_soc_component_get_drvdata(component); + struct sdw_stream_runtime *sdw_stream = + snd_soc_dai_get_dma_data(dai, substream); + + if (!rt712->slave) + return -EINVAL; + + sdw_stream_remove_slave(rt712->slave, sdw_stream); + return 0; +} + +#define RT712_STEREO_RATES (SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000) +#define RT712_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ + SNDRV_PCM_FMTBIT_S24_LE) + +static const struct snd_soc_dai_ops rt712_sdca_dmic_ops = { + .hw_params = rt712_sdca_dmic_hw_params, + .hw_free = rt712_sdca_dmic_hw_free, + .set_stream = rt712_sdca_dmic_set_sdw_stream, + .shutdown = rt712_sdca_dmic_shutdown, +}; + +static struct snd_soc_dai_driver rt712_sdca_dmic_dai[] = { + { + .name = "rt712-sdca-dmic-aif1", + .id = RT712_AIF1, + .capture = { + .stream_name = "DP2 Capture", + .channels_min = 1, + .channels_max = 4, + .rates = RT712_STEREO_RATES, + .formats = RT712_FORMATS, + }, + .ops = &rt712_sdca_dmic_ops, + }, +}; + +static int rt712_sdca_dmic_init(struct device *dev, struct regmap *regmap, + struct regmap *mbq_regmap, struct sdw_slave *slave) +{ + struct rt712_sdca_dmic_priv *rt712; + int ret; + + rt712 = devm_kzalloc(dev, sizeof(*rt712), GFP_KERNEL); + if (!rt712) + return -ENOMEM; + + dev_set_drvdata(dev, rt712); + rt712->slave = slave; + rt712->regmap = regmap; + rt712->mbq_regmap = mbq_regmap; + + /* + * Mark hw_init to false + * HW init will be performed when device reports present + */ + rt712->hw_init = false; + rt712->first_hw_init = false; + rt712->fu1e_dapm_mute = true; + rt712->fu1e_mixer_mute[0] = rt712->fu1e_mixer_mute[1] = + rt712->fu1e_mixer_mute[2] = rt712->fu1e_mixer_mute[3] = true; + + ret = devm_snd_soc_register_component(dev, + &soc_sdca_dev_rt712_dmic, + rt712_sdca_dmic_dai, + ARRAY_SIZE(rt712_sdca_dmic_dai)); + + dev_dbg(&slave->dev, "%s\n", __func__); + + return ret; +} + + +static int rt712_sdca_dmic_update_status(struct sdw_slave *slave, + enum sdw_slave_status status) +{ + struct rt712_sdca_dmic_priv *rt712 = dev_get_drvdata(&slave->dev); + + /* Update the status */ + rt712->status = status; + + if (status == SDW_SLAVE_UNATTACHED) + rt712->hw_init = false; + + /* + * Perform initialization only if slave status is present and + * hw_init flag is false + */ + if (rt712->hw_init || rt712->status != SDW_SLAVE_ATTACHED) + return 0; + + /* perform I/O transfers required for Slave initialization */ + return rt712_sdca_dmic_io_init(&slave->dev, slave); +} + +static int rt712_sdca_dmic_read_prop(struct sdw_slave *slave) +{ + struct sdw_slave_prop *prop = &slave->prop; + int nval, i; + u32 bit; + unsigned long addr; + struct sdw_dpn_prop *dpn; + + prop->scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY; + prop->quirks = SDW_SLAVE_QUIRKS_INVALID_INITIAL_PARITY; + + prop->paging_support = true; + + /* first we need to allocate memory for set bits in port lists */ + prop->source_ports = BIT(2); /* BITMAP: 00000100 */ + prop->sink_ports = 0; + + nval = hweight32(prop->source_ports); + prop->src_dpn_prop = devm_kcalloc(&slave->dev, nval, + sizeof(*prop->src_dpn_prop), GFP_KERNEL); + if (!prop->src_dpn_prop) + return -ENOMEM; + + i = 0; + dpn = prop->src_dpn_prop; + addr = prop->source_ports; + for_each_set_bit(bit, &addr, 32) { + dpn[i].num = bit; + dpn[i].type = SDW_DPN_FULL; + dpn[i].simple_ch_prep_sm = true; + dpn[i].ch_prep_timeout = 10; + i++; + } + + /* set the timeout values */ + prop->clk_stop_timeout = 200; + + /* wake-up event */ + prop->wake_capable = 1; + + return 0; +} + +static const struct sdw_device_id rt712_sdca_dmic_id[] = { + SDW_SLAVE_ENTRY_EXT(0x025d, 0x1712, 0x3, 0x1, 0), + SDW_SLAVE_ENTRY_EXT(0x025d, 0x1713, 0x3, 0x1, 0), + SDW_SLAVE_ENTRY_EXT(0x025d, 0x1716, 0x3, 0x1, 0), + SDW_SLAVE_ENTRY_EXT(0x025d, 0x1717, 0x3, 0x1, 0), + {}, +}; +MODULE_DEVICE_TABLE(sdw, rt712_sdca_dmic_id); + +static int __maybe_unused rt712_sdca_dmic_dev_suspend(struct device *dev) +{ + struct rt712_sdca_dmic_priv *rt712 = dev_get_drvdata(dev); + + if (!rt712->hw_init) + return 0; + + regcache_cache_only(rt712->regmap, true); + regcache_cache_only(rt712->mbq_regmap, true); + + return 0; +} + +static int __maybe_unused rt712_sdca_dmic_dev_system_suspend(struct device *dev) +{ + struct rt712_sdca_dmic_priv *rt712_sdca = dev_get_drvdata(dev); + + if (!rt712_sdca->hw_init) + return 0; + + return rt712_sdca_dmic_dev_suspend(dev); +} + +#define RT712_PROBE_TIMEOUT 5000 + +static int __maybe_unused rt712_sdca_dmic_dev_resume(struct device *dev) +{ + struct sdw_slave *slave = dev_to_sdw_dev(dev); + struct rt712_sdca_dmic_priv *rt712 = dev_get_drvdata(dev); + unsigned long time; + + if (!rt712->first_hw_init) + return 0; + + if (!slave->unattach_request) + goto regmap_sync; + + time = wait_for_completion_timeout(&slave->initialization_complete, + msecs_to_jiffies(RT712_PROBE_TIMEOUT)); + if (!time) { + dev_err(&slave->dev, "Initialization not complete, timed out\n"); + sdw_show_ping_status(slave->bus, true); + + return -ETIMEDOUT; + } + +regmap_sync: + slave->unattach_request = 0; + regcache_cache_only(rt712->regmap, false); + regcache_sync(rt712->regmap); + regcache_cache_only(rt712->mbq_regmap, false); + regcache_sync(rt712->mbq_regmap); + return 0; +} + +static const struct dev_pm_ops rt712_sdca_dmic_pm = { + SET_SYSTEM_SLEEP_PM_OPS(rt712_sdca_dmic_dev_system_suspend, rt712_sdca_dmic_dev_resume) + SET_RUNTIME_PM_OPS(rt712_sdca_dmic_dev_suspend, rt712_sdca_dmic_dev_resume, NULL) +}; + + +static struct sdw_slave_ops rt712_sdca_dmic_slave_ops = { + .read_prop = rt712_sdca_dmic_read_prop, + .update_status = rt712_sdca_dmic_update_status, +}; + +static int rt712_sdca_dmic_sdw_probe(struct sdw_slave *slave, + const struct sdw_device_id *id) +{ + struct regmap *regmap, *mbq_regmap; + + /* Regmap Initialization */ + mbq_regmap = devm_regmap_init_sdw_mbq(slave, &rt712_sdca_dmic_mbq_regmap); + if (IS_ERR(mbq_regmap)) + return PTR_ERR(mbq_regmap); + + regmap = devm_regmap_init_sdw(slave, &rt712_sdca_dmic_regmap); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + return rt712_sdca_dmic_init(&slave->dev, regmap, mbq_regmap, slave); +} + +static int rt712_sdca_dmic_sdw_remove(struct sdw_slave *slave) +{ + struct rt712_sdca_dmic_priv *rt712 = dev_get_drvdata(&slave->dev); + + if (rt712->first_hw_init) + pm_runtime_disable(&slave->dev); + + return 0; +} + +static struct sdw_driver rt712_sdca_dmic_sdw_driver = { + .driver = { + .name = "rt712-sdca-dmic", + .owner = THIS_MODULE, + .pm = &rt712_sdca_dmic_pm, + }, + .probe = rt712_sdca_dmic_sdw_probe, + .remove = rt712_sdca_dmic_sdw_remove, + .ops = &rt712_sdca_dmic_slave_ops, + .id_table = rt712_sdca_dmic_id, +}; +module_sdw_driver(rt712_sdca_dmic_sdw_driver); + +MODULE_DESCRIPTION("ASoC RT712 SDCA DMIC SDW driver"); +MODULE_AUTHOR("Shuming Fan "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/rt712-sdca-dmic.h b/sound/soc/codecs/rt712-sdca-dmic.h new file mode 100644 index 000000000000..74c29677c251 --- /dev/null +++ b/sound/soc/codecs/rt712-sdca-dmic.h @@ -0,0 +1,108 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * rt712-sdca-dmic.h -- RT712 SDCA DMIC ALSA SoC audio driver header + * + * Copyright(c) 2023 Realtek Semiconductor Corp. + */ + +#ifndef __RT712_SDW_DMIC_H__ +#define __RT712_SDW_DMIC_H__ + +#include +#include + +struct rt712_sdca_dmic_priv { + struct regmap *regmap; + struct regmap *mbq_regmap; + struct snd_soc_component *component; + struct sdw_slave *slave; + enum sdw_slave_status status; + struct sdw_bus_params params; + bool hw_init; + bool first_hw_init; + bool fu1e_dapm_mute; + bool fu1e_mixer_mute[4]; +}; + +struct rt712_sdca_dmic_kctrl_priv { + unsigned int reg_base; + unsigned int count; + unsigned int max; + unsigned int invert; +}; + +/* SDCA (Channel) */ +#define CH_01 0x01 +#define CH_02 0x02 +#define CH_03 0x03 +#define CH_04 0x04 + +static const struct reg_default rt712_sdca_dmic_reg_defaults[] = { + { 0x201a, 0x00 }, + { 0x201b, 0x00 }, + { 0x201c, 0x00 }, + { 0x201d, 0x00 }, + { 0x201e, 0x00 }, + { 0x201f, 0x00 }, + { 0x2029, 0x00 }, + { 0x202a, 0x00 }, + { 0x202d, 0x00 }, + { 0x202e, 0x00 }, + { 0x202f, 0x00 }, + { 0x2030, 0x00 }, + { 0x2031, 0x00 }, + { 0x2032, 0x00 }, + { 0x2033, 0x00 }, + { 0x2034, 0x00 }, + { 0x2230, 0x00 }, + { 0x2231, 0x2f }, + { 0x2232, 0x80 }, + { 0x2f01, 0x00 }, + { 0x2f02, 0x09 }, + { 0x2f03, 0x00 }, + { 0x2f04, 0x00 }, + { 0x2f05, 0x0b }, + { 0x2f06, 0x01 }, + { 0x2f08, 0x00 }, + { 0x2f09, 0x00 }, + { 0x2f0a, 0x01 }, + { 0x2f35, 0x02 }, + { 0x2f36, 0xcf }, + { 0x2f52, 0x08 }, + { 0x2f58, 0x07 }, + { 0x2f59, 0x07 }, + { 0x3201, 0x01 }, + { 0x320c, 0x00 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_IT26, RT712_SDCA_CTL_VENDOR_DEF, 0), 0x00 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_USER_FU1E, RT712_SDCA_CTL_FU_MUTE, CH_01), 0x01 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_USER_FU1E, RT712_SDCA_CTL_FU_MUTE, CH_02), 0x01 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_USER_FU1E, RT712_SDCA_CTL_FU_MUTE, CH_03), 0x01 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_USER_FU1E, RT712_SDCA_CTL_FU_MUTE, CH_04), 0x01 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_CS1F, RT712_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), 0x09 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_CS1C, RT712_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), 0x09 }, +}; + +static const struct reg_default rt712_sdca_dmic_mbq_defaults[] = { + { 0x0590001e, 0x0020 }, + { 0x06100000, 0x0010 }, + { 0x06100006, 0x0055 }, + { 0x06100010, 0x2630 }, + { 0x06100011, 0x152f }, + { 0x06100013, 0x0102 }, + { 0x06100015, 0x2219 }, + { 0x06100018, 0x0102 }, + { 0x06100026, 0x2c29 }, + { 0x06100027, 0x2d2b }, + { 0x0610002b, 0x2a32 }, + { 0x0610002f, 0x3355 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_PLATFORM_FU15, RT712_SDCA_CTL_FU_CH_GAIN, CH_01), 0x0000 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_PLATFORM_FU15, RT712_SDCA_CTL_FU_CH_GAIN, CH_02), 0x0000 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_PLATFORM_FU15, RT712_SDCA_CTL_FU_CH_GAIN, CH_03), 0x0000 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_PLATFORM_FU15, RT712_SDCA_CTL_FU_CH_GAIN, CH_04), 0x0000 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_USER_FU1E, RT712_SDCA_CTL_FU_VOLUME, CH_01), 0x0000 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_USER_FU1E, RT712_SDCA_CTL_FU_VOLUME, CH_02), 0x0000 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_USER_FU1E, RT712_SDCA_CTL_FU_VOLUME, CH_03), 0x0000 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_USER_FU1E, RT712_SDCA_CTL_FU_VOLUME, CH_04), 0x0000 }, +}; + +#endif /* __RT712_SDW_DMIC_H__ */ From c52615e494f17f44b076ac8ae5a53cfc0041a0dd Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Thu, 23 Mar 2023 16:44:00 +0000 Subject: [PATCH 686/778] ASoC: qcom: q6apm-lpass-dai: close graphs before opening a new one On multiple prepare calls, its possible that the playback graphs are not unloaded from the DSP, which can have some wierd side-effects, one of them is that the data not consumed without any errors. Fixes: c2ac3aec474d("ASoC: qcom: q6apm-lpass-dai: unprepare stream if its already prepared") Signed-off-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20230323164403.6654-2-srinivas.kandagatla@linaro.org Signed-off-by: Mark Brown --- sound/soc/qcom/qdsp6/q6apm-lpass-dais.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c index 23d23bc6fbaa..420e8aa11f42 100644 --- a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c +++ b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c @@ -130,6 +130,9 @@ static int q6apm_lpass_dai_prepare(struct snd_pcm_substream *substream, struct s if (dai_data->is_port_started[dai->id]) { q6apm_graph_stop(dai_data->graph[dai->id]); dai_data->is_port_started[dai->id] = false; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + q6apm_graph_close(dai_data->graph[dai->id]); } /** From e2e530886359246ae782c779be248c59bc2ed111 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Thu, 23 Mar 2023 16:44:01 +0000 Subject: [PATCH 687/778] ASoC: qcom: sdw: do not restart soundwire ports for every prepare unpreparing/disabling and preparing/reenabling soundwire ports is not required for every prepare call, this add lots of click and pop noise if we do this in middle of playback or capture. Signed-off-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20230323164403.6654-3-srinivas.kandagatla@linaro.org Signed-off-by: Mark Brown --- sound/soc/qcom/sdw.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/sound/soc/qcom/sdw.c b/sound/soc/qcom/sdw.c index 10249519a39e..1a41419c7eb8 100644 --- a/sound/soc/qcom/sdw.c +++ b/sound/soc/qcom/sdw.c @@ -32,11 +32,8 @@ int qcom_snd_sdw_prepare(struct snd_pcm_substream *substream, return 0; } - if (*stream_prepared) { - sdw_disable_stream(sruntime); - sdw_deprepare_stream(sruntime); - *stream_prepared = false; - } + if (*stream_prepared) + return 0; ret = sdw_prepare_stream(sruntime); if (ret) From 80a4623eb1910d099e3d3de1564a6dfe16750e60 Mon Sep 17 00:00:00 2001 From: Tom Rix Date: Thu, 6 Apr 2023 11:23:00 -0400 Subject: [PATCH 688/778] ASoC: max98363: Make soc_codec_dev_max98363 static smatch reports sound/soc/codecs/max98363.c:392:39: warning: symbol 'soc_codec_dev_max98363' was not declared. Should it be static? This variable is only used in one file so should be static. Signed-off-by: Tom Rix Link: https://lore.kernel.org/r/20230406152300.1954292-1-trix@redhat.com Signed-off-by: Mark Brown --- sound/soc/codecs/max98363.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/max98363.c b/sound/soc/codecs/max98363.c index 4585ebb1e82c..dcce06bff756 100644 --- a/sound/soc/codecs/max98363.c +++ b/sound/soc/codecs/max98363.c @@ -389,7 +389,7 @@ static const struct snd_soc_dapm_route max98363_audio_map[] = { {"BE_OUT", NULL, "AIFIN"}, }; -const struct snd_soc_component_driver soc_codec_dev_max98363 = { +static const struct snd_soc_component_driver soc_codec_dev_max98363 = { .controls = max98363_snd_controls, .num_controls = ARRAY_SIZE(max98363_snd_controls), .dapm_widgets = max98363_dapm_widgets, From e41e1f4ae47499061bec3446c927bdfd2210a329 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 6 Apr 2023 10:29:37 -0500 Subject: [PATCH 689/778] ASoC: SOF: Intel: hda: add __func__ in SoundWire lcount() error logs Make sure SoundWire lcount helpers have unique error logs, but a common pattern for reporting issues. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Rander Wang Link: https://lore.kernel.org/r/20230406152937.15347-1-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 483ec80f3160..2f1f0756ed75 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -213,8 +213,8 @@ int hda_sdw_check_lcount_common(struct snd_sof_dev *sdev) /* Check HW supported vs property value */ if (caps < ctx->count) { dev_err(sdev->dev, - "BIOS master count %d is larger than hardware capabilities %d\n", - ctx->count, caps); + "%s: BIOS master count %d is larger than hardware capabilities %d\n", + __func__, ctx->count, caps); return -EINVAL; } From c7a92574ec03692a057db541db12e41744a862fa Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 4 Apr 2023 13:41:10 +0300 Subject: [PATCH 690/778] Documentation: sound: add description of Intel HDaudio multi-links MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add description of 'Skylake' multi-link structure added in 2015 and recent extensions to support SoundWire/DMIC/SSP interfaces. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Péter Ujfalusi Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Reviewed-by: Takashi Iwai Link: https://lore.kernel.org/r/20230404104127.5629-2-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- Documentation/sound/hd-audio/index.rst | 1 + .../sound/hd-audio/intel-multi-link.rst | 312 ++++++++++++++++++ 2 files changed, 313 insertions(+) create mode 100644 Documentation/sound/hd-audio/intel-multi-link.rst diff --git a/Documentation/sound/hd-audio/index.rst b/Documentation/sound/hd-audio/index.rst index 6e12de9fc34e..baefe4a5d165 100644 --- a/Documentation/sound/hd-audio/index.rst +++ b/Documentation/sound/hd-audio/index.rst @@ -9,3 +9,4 @@ HD-Audio controls dp-mst realtek-pc-beep + intel-multi-link diff --git a/Documentation/sound/hd-audio/intel-multi-link.rst b/Documentation/sound/hd-audio/intel-multi-link.rst new file mode 100644 index 000000000000..bf0bb78833e7 --- /dev/null +++ b/Documentation/sound/hd-audio/intel-multi-link.rst @@ -0,0 +1,312 @@ +.. SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) +.. include:: + +================================================ +HDAudio multi-link extensions on Intel platforms +================================================ + +:Copyright: |copy| 2023 Intel Corporation + +This file documents the 'multi-link structure' introduced in 2015 with +the Skylake processor and recently extended in newer Intel platforms + +HDaudio existing link mapping (2015 addition in SkyLake) +======================================================== + +External HDAudio codecs are handled with link #0, while iDISP codec +for HDMI/DisplayPort is handled with link #1. + +The only change to the 2015 definitions is the declaration of the +LCAP.ALT=0x0 - since the ALT bit was previously reserved, this is a +backwards-compatible change. + +LCTL.SPA and LCTL.CPA are automatically set when exiting reset. They +are only used in existing drivers when the SCF value needs to be +corrected. + +Basic structure for HDaudio codecs +---------------------------------- + +:: + + +-----------+ + | ML cap #0 | + +-----------+ + | ML cap #1 |---+ + +-----------+ | + | + +--> 0x0 +---------------+ LCAP + | ALT=0 | + +---------------+ + | S192 | + +---------------+ + | S96 | + +---------------+ + | S48 | + +---------------+ + | S24 | + +---------------+ + | S12 | + +---------------+ + | S6 | + +---------------+ + + 0x4 +---------------+ LCTL + | INTSTS | + +---------------+ + | CPA | + +---------------+ + | SPA | + +---------------+ + | SCF | + +---------------+ + + 0x8 +---------------+ LOSIDV + | L1OSIVD15 | + +---------------+ + | L1OSIDV.. | + +---------------+ + | L1OSIDV1 | + +---------------+ + + 0xC +---------------+ LSDIID + | SDIID14 | + +---------------+ + | SDIID... | + +---------------+ + | SDIID0 | + +---------------+ + +SoundWire HDaudio extended link mapping +======================================= + +A SoundWire extended link is identified when LCAP.ALT=1 and +LEPTR.ID=0. + +DMA control uses the existing LOSIDV register. + +Changes include additional descriptions for enumeration that were not +present in earlier generations. + +- multi-link synchronization: capabilities in LCAP.LSS and control in LSYNC +- number of sublinks (manager IP) in LCAP.LSCOUNT +- power management moved from SHIM to LCTL.SPA bits +- hand-over to the DSP for access to multi-link registers, SHIM/IP with LCTL.OFLEN +- mapping of SoundWire codecs to SDI ID bits +- move of SHIM and Cadence registers to different offsets, with no + change in functionality. The LEPTR.PTR value is an offset from the + ML address, with a default value of 0x30000. + +Extended structure for SoundWire (assuming 4 Manager IP) +-------------------------------------------------------- + +:: + + +-----------+ + | ML cap #0 | + +-----------+ + | ML cap #1 | + +-----------+ + | ML cap #2 |---+ + +-----------+ | + | + +--> 0x0 +---------------+ LCAP + | ALT=1 | + +---------------+ + | INTC | + +---------------+ + | OFLS | + +---------------+ + | LSS | + +---------------+ + | SLCOUNT=4 |-----------+ + +---------------+ | + | + 0x4 +---------------+ LCTL | + | INTSTS | | + +---------------+ | + | CPA (x bits) | | + +---------------+ | + | SPA (x bits) | | + +---------------+ for each sublink x + | INTEN | | + +---------------+ | + | OFLEN | | + +---------------+ | + | + 0x8 +---------------+ LOSIDV | + | L1OSIVD15 | | + +---------------+ | + | L1OSIDV.. | | + +---------------+ | + | L1OSIDV1 | +---+----------------------------------------------------------+ + +---------------+ | | + v | + 0xC + 0x2 * x +---------------+ LSDIIDx +---> 0x30000 +-----------------+ 0x00030000 | + | SDIID14 | | | SoundWire SHIM | | + +---------------+ | | generic | | + | SDIID... | | +-----------------+ 0x00030100 | + +---------------+ | | SoundWire IP | | + | SDIID0 | | +-----------------+ 0x00036000 | + +---------------+ | | SoundWire SHIM | | + | | vendor-specific | | + 0x1C +---------------+ LSYNC | +-----------------+ | + | CMDSYNC | | v + +---------------+ | +-----------------+ 0x00030000 + 0x8000 * x + | SYNCGO | | | SoundWire SHIM | + +---------------+ | | generic | + | SYNCPU | | +-----------------+ 0x00030100 + 0x8000 * x + +---------------+ | | SoundWire IP | + | SYNPRD | | +-----------------+ 0x00036000 + 0x8000 * x + +---------------+ | | SoundWire SHIM | + | | vendor-specific | + 0x20 +---------------+ LEPTR | +-----------------+ + | ID = 0 | | + +---------------+ | + | VER | | + +---------------+ | + | PTR |------------+ + +---------------+ + + +DMIC HDaudio extended link mapping +================================== + +A DMIC extended link is identified when LCAP.ALT=1 and +LEPTR.ID=0xC1 are set. + +DMA control uses the existing LOSIDV register + +Changes include additional descriptions for enumeration that were not +present in earlier generations. + +- multi-link synchronization: capabilities in LCAP.LSS and control in LSYNC +- power management with LCTL.SPA bits +- hand-over to the DSP for access to multi-link registers, SHIM/IP with LCTL.OFLEN + +- move of DMIC registers to different offsets, with no change in + functionality. The LEPTR.PTR value is an offset from the ML + address, with a default value of 0x10000. + +Extended structure for DMIC +--------------------------- + +:: + + +-----------+ + | ML cap #0 | + +-----------+ + | ML cap #1 | + +-----------+ + | ML cap #2 |---+ + +-----------+ | + | + +--> 0x0 +---------------+ LCAP + | ALT=1 | + +---------------+ + | INTC | + +---------------+ + | OFLS | + +---------------+ + | SLCOUNT=1 | + +---------------+ + + 0x4 +---------------+ LCTL + | INTSTS | + +---------------+ + | CPA | + +---------------+ + | SPA | + +---------------+ + | INTEN | + +---------------+ + | OFLEN | + +---------------+ +---> 0x10000 +-----------------+ 0x00010000 + | | DMIC SHIM | + 0x8 +---------------+ LOSIDV | | generic | + | L1OSIVD15 | | +-----------------+ 0x00010100 + +---------------+ | | DMIC IP | + | L1OSIDV.. | | +-----------------+ 0x00016000 + +---------------+ | | DMIC SHIM | + | L1OSIDV1 | | | vendor-specific | + +---------------+ | +-----------------+ + | + 0x20 +---------------+ LEPTR | + | ID = 0xC1 | | + +---------------+ | + | VER | | + +---------------+ | + | PTR |-----------+ + +---------------+ + + +SSP HDaudio extended link mapping +================================= + +A DMIC extended link is identified when LCAP.ALT=1 and +LEPTR.ID=0xC0 are set. + +DMA control uses the existing LOSIDV register + +Changes include additional descriptions for enumeration and control that were not +present in earlier generations: +- number of sublinks (SSP IP instances) in LCAP.LSCOUNT +- power management moved from SHIM to LCTL.SPA bits +- hand-over to the DSP for access to multi-link registers, SHIM/IP +with LCTL.OFLEN +- move of SHIM and SSP IP registers to different offsets, with no +change in functionality. The LEPTR.PTR value is an offset from the ML +address, with a default value of 0x28000. + +Extended structure for SSP (assuming 3 instances of the IP) +----------------------------------------------------------- + +:: + + +-----------+ + | ML cap #0 | + +-----------+ + | ML cap #1 | + +-----------+ + | ML cap #2 |---+ + +-----------+ | + | + +--> 0x0 +---------------+ LCAP + | ALT=1 | + +---------------+ + | INTC | + +---------------+ + | OFLS | + +---------------+ + | SLCOUNT=3 |-------------------------for each sublink x -------------------------+ + +---------------+ | + | + 0x4 +---------------+ LCTL | + | INTSTS | | + +---------------+ | + | CPA (x bits) | | + +---------------+ | + | SPA (x bits) | | + +---------------+ | + | INTEN | | + +---------------+ | + | OFLEN | | + +---------------+ +---> 0x28000 +-----------------+ 0x00028000 | + | | SSP SHIM | | + 0x8 +---------------+ LOSIDV | | generic | | + | L1OSIVD15 | | +-----------------+ 0x00028100 | + +---------------+ | | SSP IP | | + | L1OSIDV.. | | +-----------------+ 0x00028C00 | + +---------------+ | | SSP SHIM | | + | L1OSIDV1 | | | vendor-specific | | + +---------------+ | +-----------------+ | + | v + 0x20 +---------------+ LEPTR | +-----------------+ 0x00028000 + 0x1000 * x + | ID = 0xC0 | | | SSP SHIM | + +---------------+ | | generic | + | VER | | +-----------------+ 0x00028100 + 0x1000 * x + +---------------+ | | SSP IP | + | PTR |-----------+ +-----------------+ 0x00028C00 + 0x1000 * x + +---------------+ | SSP SHIM | + | vendor-specific | + +-----------------+ From 34e582b559c78746c544442b3925554e0665351b Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 4 Apr 2023 13:41:11 +0300 Subject: [PATCH 691/778] ALSA: hda: add HDaudio Extended link definitions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add new definitions for the HDaudio Extended link support, specifically new registers for SoundWire, Intel DMIC and INTEL SSP interfaces. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Péter Ujfalusi Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Reviewed-by: Takashi Iwai Link: https://lore.kernel.org/r/20230404104127.5629-3-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- include/sound/hda_register.h | 40 ++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/include/sound/hda_register.h b/include/sound/hda_register.h index d37cf43546eb..9c7872c0ca79 100644 --- a/include/sound/hda_register.h +++ b/include/sound/hda_register.h @@ -258,14 +258,27 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; #define AZX_ML_BASE 0x40 #define AZX_ML_INTERVAL 0x40 +/* HDaudio registers valid for HDaudio and HDaudio extended links */ #define AZX_REG_ML_LCAP 0x00 -#define AZX_REG_ML_LCTL 0x04 +#define AZX_ML_HDA_LCAP_ALT BIT(28) +#define AZX_ML_HDA_LCAP_ALT_HDA 0x0 +#define AZX_ML_HDA_LCAP_ALT_HDA_EXT 0x1 + +#define AZX_ML_HDA_LCAP_INTC BIT(27) /* only used if ALT == 1 */ +#define AZX_ML_HDA_LCAP_OFLS BIT(26) /* only used if ALT == 1 */ +#define AZX_ML_HDA_LCAP_LSS BIT(23) /* only used if ALT == 1 */ +#define AZX_ML_HDA_LCAP_SLCOUNT GENMASK(22, 20) /* only used if ALT == 1 */ + +#define AZX_REG_ML_LCTL 0x04 +#define AZX_ML_LCTL_INTSTS BIT(31) /* only used if ALT == 1 */ #define AZX_ML_LCTL_CPA BIT(23) #define AZX_ML_LCTL_CPA_SHIFT 23 #define AZX_ML_LCTL_SPA BIT(16) #define AZX_ML_LCTL_SPA_SHIFT 16 -#define AZX_ML_LCTL_SCF GENMASK(3, 0) +#define AZX_ML_LCTL_INTEN BIT(5) /* only used if ALT == 1 */ +#define AZX_ML_LCTL_OFLEN BIT(4) /* only used if ALT == 1 */ +#define AZX_ML_LCTL_SCF GENMASK(3, 0) /* only used if ALT == 0 */ #define AZX_REG_ML_LOSIDV 0x08 @@ -273,12 +286,35 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; #define AZX_ML_LOSIDV_STREAM_MASK 0xFFFE #define AZX_REG_ML_LSDIID 0x0C +#define AZX_REG_ML_LSDIID_OFFSET(x) (0x0C + (x) * 0x02) /* only used if ALT == 1 */ + +/* HDaudio registers only valid if LCAP.ALT == 0 */ #define AZX_REG_ML_LPSOO 0x10 #define AZX_REG_ML_LPSIO 0x12 #define AZX_REG_ML_LWALFC 0x18 #define AZX_REG_ML_LOUTPAY 0x20 #define AZX_REG_ML_LINPAY 0x30 +/* HDaudio Extended link registers only valid if LCAP.ALT == 1 */ +#define AZX_REG_ML_LSYNC 0x1C + +#define AZX_REG_ML_LSYNC_CMDSYNC BIT(24) +#define AZX_REG_ML_LSYNC_CMDSYNC_SHIFT 24 +#define AZX_REG_ML_LSYNC_SYNCGO BIT(23) +#define AZX_REG_ML_LSYNC_SYNCPU BIT(20) +#define AZX_REG_ML_LSYNC_SYNCPRD GENMASK(19, 0) + +#define AZX_REG_ML_LEPTR 0x20 + +#define AZX_REG_ML_LEPTR_ID GENMASK(31, 24) +#define AZX_REG_ML_LEPTR_ID_SHIFT 24 +#define AZX_REG_ML_LEPTR_ID_SDW 0x00 +#define AZX_REG_ML_LEPTR_ID_INTEL_SSP 0xC0 +#define AZX_REG_ML_LEPTR_ID_INTEL_DMIC 0xC1 +#define AZX_REG_ML_LEPTR_ID_INTEL_UAOL 0xC2 +#define AZX_REG_ML_LEPTR_VER GENMASK(23, 20) +#define AZX_REG_ML_LEPTR_PTR GENMASK(19, 0) + /* registers for DMA Resume Capability Structure */ #define AZX_DRSM_CAP_ID 0x5 #define AZX_REG_DRSM_CTL 0x4 From 8a55786a1875bd0b9c22156e800557a931baacb8 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 4 Apr 2023 13:41:12 +0300 Subject: [PATCH 692/778] ASoC: SOF: Intel: hda-mlink: improve hda_bus_ml_free() helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use list_for_each_entry_safe() instead of open-coding. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Péter Ujfalusi Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Reviewed-by: Takashi Iwai Link: https://lore.kernel.org/r/20230404104127.5629-4-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-mlink.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/sof/intel/hda-mlink.c b/sound/soc/sof/intel/hda-mlink.c index 76ab9a2e7bb3..ac9bf477f413 100644 --- a/sound/soc/sof/intel/hda-mlink.c +++ b/sound/soc/sof/intel/hda-mlink.c @@ -36,13 +36,12 @@ void hda_bus_ml_get_capabilities(struct hdac_bus *bus) void hda_bus_ml_free(struct hdac_bus *bus) { - struct hdac_ext_link *hlink; + struct hdac_ext_link *hlink, *_h; if (!bus->mlcap) return; - while (!list_empty(&bus->hlink_list)) { - hlink = list_first_entry(&bus->hlink_list, struct hdac_ext_link, list); + list_for_each_entry_safe(hlink, _h, &bus->hlink_list, list) { list_del(&hlink->list); kfree(hlink); } From 68376a3ef41f0a2d6c1c603e7293ba0e00b293da Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 4 Apr 2023 13:41:13 +0300 Subject: [PATCH 693/778] ASoC: SOF: Intel: hda-mlink: add return value for hda_bus_ml_get_capabilities() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add return value - this will need additional work in the caller. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Péter Ujfalusi Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Reviewed-by: Takashi Iwai Link: https://lore.kernel.org/r/20230404104127.5629-5-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-mlink.c | 5 +++-- sound/soc/sof/intel/hda.h | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/sound/soc/sof/intel/hda-mlink.c b/sound/soc/sof/intel/hda-mlink.c index ac9bf477f413..e426d5e41e52 100644 --- a/sound/soc/sof/intel/hda-mlink.c +++ b/sound/soc/sof/intel/hda-mlink.c @@ -28,10 +28,11 @@ #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) -void hda_bus_ml_get_capabilities(struct hdac_bus *bus) +int hda_bus_ml_get_capabilities(struct hdac_bus *bus) { if (bus->mlcap) - snd_hdac_ext_bus_get_ml_capabilities(bus); + return snd_hdac_ext_bus_get_ml_capabilities(bus); + return 0; } void hda_bus_ml_free(struct hdac_bus *bus) diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 2a43bfc14583..259b34eea677 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -765,7 +765,7 @@ static inline int hda_codec_i915_exit(struct snd_sof_dev *sdev) { return 0; } #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) -void hda_bus_ml_get_capabilities(struct hdac_bus *bus); +int hda_bus_ml_get_capabilities(struct hdac_bus *bus); void hda_bus_ml_free(struct hdac_bus *bus); void hda_bus_ml_put_all(struct hdac_bus *bus); void hda_bus_ml_reset_losidv(struct hdac_bus *bus); @@ -774,7 +774,7 @@ int hda_bus_ml_suspend(struct hdac_bus *bus); #else -static inline void hda_bus_ml_get_capabilities(struct hdac_bus *bus) { } +static inline int hda_bus_ml_get_capabilities(struct hdac_bus *bus) { return 0; } static inline void hda_bus_ml_free(struct hdac_bus *bus) { } static inline void hda_bus_ml_put_all(struct hdac_bus *bus) { } static inline void hda_bus_ml_reset_losidv(struct hdac_bus *bus) { } From 18227585d8374ce16d3a2792deb125794710de43 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 4 Apr 2023 13:41:14 +0300 Subject: [PATCH 694/778] ASoC: SOF: Intel: hda-mlink: move to a dedicated module MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some of the functions will be used for SoundWire enumeration and power management, to avoid cycles in module dependencies and simplify integration all the HDaudio multi-link needs to move to a dedicated module. Drop no longer needed headers at the same time. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Péter Ujfalusi Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Reviewed-by: Takashi Iwai Link: https://lore.kernel.org/r/20230404104127.5629-6-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- include/sound/hda-mlink.h | 31 +++++++++++++++++++++++++++++++ sound/soc/sof/intel/Kconfig | 7 +++++++ sound/soc/sof/intel/Makefile | 5 ++++- sound/soc/sof/intel/hda-ctrl.c | 1 + sound/soc/sof/intel/hda-dsp.c | 1 + sound/soc/sof/intel/hda-mlink.c | 22 ++++++++++------------ sound/soc/sof/intel/hda.c | 2 ++ sound/soc/sof/intel/hda.h | 20 -------------------- 8 files changed, 56 insertions(+), 33 deletions(-) create mode 100644 include/sound/hda-mlink.h diff --git a/include/sound/hda-mlink.h b/include/sound/hda-mlink.h new file mode 100644 index 000000000000..beef5f509e47 --- /dev/null +++ b/include/sound/hda-mlink.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * Copyright(c) 2022-2023 Intel Corporation. All rights reserved. + */ + +struct hdac_bus; + +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_MLINK) + +int hda_bus_ml_get_capabilities(struct hdac_bus *bus); +void hda_bus_ml_free(struct hdac_bus *bus); +void hda_bus_ml_put_all(struct hdac_bus *bus); +void hda_bus_ml_reset_losidv(struct hdac_bus *bus); +int hda_bus_ml_resume(struct hdac_bus *bus); +int hda_bus_ml_suspend(struct hdac_bus *bus); + +#else + +static inline int +hda_bus_ml_get_capabilities(struct hdac_bus *bus) { return 0; } + +static inline void hda_bus_ml_free(struct hdac_bus *bus) { } +static inline void hda_bus_ml_put_all(struct hdac_bus *bus) { } +static inline void hda_bus_ml_reset_losidv(struct hdac_bus *bus) { } +static inline int hda_bus_ml_resume(struct hdac_bus *bus) { return 0; } +static inline int hda_bus_ml_suspend(struct hdac_bus *bus) { return 0; } + +#endif /* CONFIG_SND_SOC_SOF_HDA */ diff --git a/sound/soc/sof/intel/Kconfig b/sound/soc/sof/intel/Kconfig index 715ba8a7f2f8..f4eeacf1f281 100644 --- a/sound/soc/sof/intel/Kconfig +++ b/sound/soc/sof/intel/Kconfig @@ -269,6 +269,13 @@ config SND_SOC_SOF_HDA_COMMON select SND_INTEL_DSP_CONFIG select SND_SOC_SOF_HDA_LINK_BASELINE select SND_SOC_SOF_HDA_PROBES + select SND_SOC_SOF_HDA_MLINK if SND_SOC_SOF_HDA_LINK + help + This option is not user-selectable but automagically handled by + 'select' statements at a higher level. + +config SND_SOC_SOF_HDA_MLINK + tristate help This option is not user-selectable but automagically handled by 'select' statements at a higher level. diff --git a/sound/soc/sof/intel/Makefile b/sound/soc/sof/intel/Makefile index 38ab86b6a9fe..fdb463c12e91 100644 --- a/sound/soc/sof/intel/Makefile +++ b/sound/soc/sof/intel/Makefile @@ -5,10 +5,12 @@ snd-sof-acpi-intel-bdw-objs := bdw.o snd-sof-intel-hda-common-objs := hda.o hda-loader.o hda-stream.o hda-trace.o \ hda-dsp.o hda-ipc.o hda-ctrl.o hda-pcm.o \ - hda-dai.o hda-dai-ops.o hda-bus.o hda-mlink.o \ + hda-dai.o hda-dai-ops.o hda-bus.o \ skl.o hda-loader-skl.o \ apl.o cnl.o tgl.o icl.o mtl.o hda-common-ops.o +snd-sof-intel-hda-mlink-objs := hda-mlink.o + snd-sof-intel-hda-common-$(CONFIG_SND_SOC_SOF_HDA_PROBES) += hda-probes.o snd-sof-intel-hda-objs := hda-codec.o @@ -19,6 +21,7 @@ obj-$(CONFIG_SND_SOC_SOF_INTEL_ATOM_HIFI_EP) += snd-sof-intel-atom.o obj-$(CONFIG_SND_SOC_SOF_BAYTRAIL) += snd-sof-acpi-intel-byt.o obj-$(CONFIG_SND_SOC_SOF_BROADWELL) += snd-sof-acpi-intel-bdw.o obj-$(CONFIG_SND_SOC_SOF_HDA_COMMON) += snd-sof-intel-hda-common.o +obj-$(CONFIG_SND_SOC_SOF_HDA_MLINK) += snd-sof-intel-hda-mlink.o obj-$(CONFIG_SND_SOC_SOF_HDA) += snd-sof-intel-hda.o snd-sof-pci-intel-tng-objs := pci-tng.o diff --git a/sound/soc/sof/intel/hda-ctrl.c b/sound/soc/sof/intel/hda-ctrl.c index e1dba6b79065..84bf01bd360a 100644 --- a/sound/soc/sof/intel/hda-ctrl.c +++ b/sound/soc/sof/intel/hda-ctrl.c @@ -19,6 +19,7 @@ #include #include #include +#include #include "../ops.h" #include "hda.h" diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index 23c05e6f424a..77df536cf901 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include "../sof-audio.h" #include "../ops.h" diff --git a/sound/soc/sof/intel/hda-mlink.c b/sound/soc/sof/intel/hda-mlink.c index e426d5e41e52..fbf86f2350fb 100644 --- a/sound/soc/sof/intel/hda-mlink.c +++ b/sound/soc/sof/intel/hda-mlink.c @@ -12,21 +12,11 @@ #include #include +#include -#include #include -#include -#include -#include -#include -#include -#include -#include "../sof-audio.h" -#include "../sof-pci-dev.h" -#include "../ops.h" -#include "hda.h" -#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_MLINK) int hda_bus_ml_get_capabilities(struct hdac_bus *bus) { @@ -34,6 +24,7 @@ int hda_bus_ml_get_capabilities(struct hdac_bus *bus) return snd_hdac_ext_bus_get_ml_capabilities(bus); return 0; } +EXPORT_SYMBOL_NS(hda_bus_ml_get_capabilities, SND_SOC_SOF_HDA_MLINK); void hda_bus_ml_free(struct hdac_bus *bus) { @@ -47,6 +38,7 @@ void hda_bus_ml_free(struct hdac_bus *bus) kfree(hlink); } } +EXPORT_SYMBOL_NS(hda_bus_ml_free, SND_SOC_SOF_HDA_MLINK); void hda_bus_ml_put_all(struct hdac_bus *bus) { @@ -55,6 +47,7 @@ void hda_bus_ml_put_all(struct hdac_bus *bus) list_for_each_entry(hlink, &bus->hlink_list, list) snd_hdac_ext_bus_link_put(bus, hlink); } +EXPORT_SYMBOL_NS(hda_bus_ml_put_all, SND_SOC_SOF_HDA_MLINK); void hda_bus_ml_reset_losidv(struct hdac_bus *bus) { @@ -64,6 +57,7 @@ void hda_bus_ml_reset_losidv(struct hdac_bus *bus) list_for_each_entry(hlink, &bus->hlink_list, list) writel(0, hlink->ml_addr + AZX_REG_ML_LOSIDV); } +EXPORT_SYMBOL_NS(hda_bus_ml_reset_losidv, SND_SOC_SOF_HDA_MLINK); int hda_bus_ml_resume(struct hdac_bus *bus) { @@ -80,10 +74,14 @@ int hda_bus_ml_resume(struct hdac_bus *bus) } return 0; } +EXPORT_SYMBOL_NS(hda_bus_ml_resume, SND_SOC_SOF_HDA_MLINK); int hda_bus_ml_suspend(struct hdac_bus *bus) { return snd_hdac_ext_bus_link_power_down_all(bus); } +EXPORT_SYMBOL_NS(hda_bus_ml_suspend, SND_SOC_SOF_HDA_MLINK); #endif + +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 483ec80f3160..8845ae255f1e 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "../sof-audio.h" #include "../sof-pci-dev.h" #include "../ops.h" @@ -1730,3 +1731,4 @@ MODULE_IMPORT_NS(SND_SOC_SOF_XTENSA); MODULE_IMPORT_NS(SND_INTEL_SOUNDWIRE_ACPI); MODULE_IMPORT_NS(SOUNDWIRE_INTEL_INIT); MODULE_IMPORT_NS(SOUNDWIRE_INTEL); +MODULE_IMPORT_NS(SND_SOC_SOF_HDA_MLINK); diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 259b34eea677..0e0cfa81a8f2 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -763,26 +763,6 @@ static inline int hda_codec_i915_exit(struct snd_sof_dev *sdev) { return 0; } #endif -#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) - -int hda_bus_ml_get_capabilities(struct hdac_bus *bus); -void hda_bus_ml_free(struct hdac_bus *bus); -void hda_bus_ml_put_all(struct hdac_bus *bus); -void hda_bus_ml_reset_losidv(struct hdac_bus *bus); -int hda_bus_ml_resume(struct hdac_bus *bus); -int hda_bus_ml_suspend(struct hdac_bus *bus); - -#else - -static inline int hda_bus_ml_get_capabilities(struct hdac_bus *bus) { return 0; } -static inline void hda_bus_ml_free(struct hdac_bus *bus) { } -static inline void hda_bus_ml_put_all(struct hdac_bus *bus) { } -static inline void hda_bus_ml_reset_losidv(struct hdac_bus *bus) { } -static inline int hda_bus_ml_resume(struct hdac_bus *bus) { return 0; } -static inline int hda_bus_ml_suspend(struct hdac_bus *bus) { return 0; } - -#endif /* CONFIG_SND_SOC_SOF_HDA */ - /* * Trace Control. */ From 17c9b6ec35c0d6228db4f94590702a0cb03cd96a Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 4 Apr 2023 13:41:15 +0300 Subject: [PATCH 695/778] ASoC: SOF: Intel: hda-mlink: add structures to parse ALT links MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extend hdac_ext_link to store information needed for ALT links. Follow-up patches will include more functional patches for power-up and down. Note that this patch suggests the use of an 'eml_lock' to serialize access to shared registers. SoundWire-specific sequence require the lock to be taken at a higher level, as a result the helpers added in follow-up patches will provide 'unlocked' versions when needed. Also note that the low-level sequences with the 'hdaml_' prefix are taken directly from the hardware specifications - naming conventions included. The code will be split in two, with locking and linked-list management handled separately to avoid mixing required hardware setup and Linux-based resource management. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Péter Ujfalusi Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Reviewed-by: Takashi Iwai Link: https://lore.kernel.org/r/20230404104127.5629-7-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- include/sound/hda-mlink.h | 4 +- sound/soc/sof/intel/hda-mlink.c | 221 +++++++++++++++++++++++++++++++- sound/soc/sof/intel/hda.c | 2 +- 3 files changed, 219 insertions(+), 8 deletions(-) diff --git a/include/sound/hda-mlink.h b/include/sound/hda-mlink.h index beef5f509e47..8048bf01c133 100644 --- a/include/sound/hda-mlink.h +++ b/include/sound/hda-mlink.h @@ -10,7 +10,7 @@ struct hdac_bus; #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_MLINK) -int hda_bus_ml_get_capabilities(struct hdac_bus *bus); +int hda_bus_ml_init(struct hdac_bus *bus); void hda_bus_ml_free(struct hdac_bus *bus); void hda_bus_ml_put_all(struct hdac_bus *bus); void hda_bus_ml_reset_losidv(struct hdac_bus *bus); @@ -20,7 +20,7 @@ int hda_bus_ml_suspend(struct hdac_bus *bus); #else static inline int -hda_bus_ml_get_capabilities(struct hdac_bus *bus) { return 0; } +hda_bus_ml_init(struct hdac_bus *bus) { return 0; } static inline void hda_bus_ml_free(struct hdac_bus *bus) { } static inline void hda_bus_ml_put_all(struct hdac_bus *bus) { } diff --git a/sound/soc/sof/intel/hda-mlink.c b/sound/soc/sof/intel/hda-mlink.c index fbf86f2350fb..e6b20182f099 100644 --- a/sound/soc/sof/intel/hda-mlink.c +++ b/sound/soc/sof/intel/hda-mlink.c @@ -14,28 +14,239 @@ #include #include +#include #include #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_MLINK) -int hda_bus_ml_get_capabilities(struct hdac_bus *bus) +/** + * struct hdac_ext2_link - HDAudio extended+alternate link + * + * @hext_link: hdac_ext_link + * @alt: flag set for alternate extended links + * @intc: boolean for interrupt capable + * @ofls: boolean for offload support + * @lss: boolean for link synchronization capabilities + * @slcount: sublink count + * @elid: extended link ID (AZX_REG_ML_LEPTR_ID_ defines) + * @elver: extended link version + * @leptr: extended link pointer + * @eml_lock: mutual exclusion to access shared registers e.g. CPA/SPA bits + * in LCTL register + * @base_ptr: pointer to shim/ip/shim_vs space + * @instance_offset: offset between each of @slcount instances managed by link + * @shim_offset: offset to SHIM register base + * @ip_offset: offset to IP register base + * @shim_vs_offset: offset to vendor-specific (VS) SHIM base + */ +struct hdac_ext2_link { + struct hdac_ext_link hext_link; + + /* read directly from LCAP register */ + bool alt; + bool intc; + bool ofls; + bool lss; + int slcount; + int elid; + int elver; + u32 leptr; + + struct mutex eml_lock; /* prevent concurrent access to e.g. CPA/SPA */ + + /* internal values computed from LCAP contents */ + void __iomem *base_ptr; + u32 instance_offset; + u32 shim_offset; + u32 ip_offset; + u32 shim_vs_offset; +}; + +#define hdac_ext_link_to_ext2(h) container_of(h, struct hdac_ext2_link, hext_link) + +#define AZX_REG_SDW_INSTANCE_OFFSET 0x8000 +#define AZX_REG_SDW_SHIM_OFFSET 0x0 +#define AZX_REG_SDW_IP_OFFSET 0x100 +#define AZX_REG_SDW_VS_SHIM_OFFSET 0x6000 + +/* only one instance supported */ +#define AZX_REG_INTEL_DMIC_SHIM_OFFSET 0x0 +#define AZX_REG_INTEL_DMIC_IP_OFFSET 0x100 +#define AZX_REG_INTEL_DMIC_VS_SHIM_OFFSET 0x6000 + +#define AZX_REG_INTEL_SSP_INSTANCE_OFFSET 0x1000 +#define AZX_REG_INTEL_SSP_SHIM_OFFSET 0x0 +#define AZX_REG_INTEL_SSP_IP_OFFSET 0x100 +#define AZX_REG_INTEL_SSP_VS_SHIM_OFFSET 0xC00 + +/* only one instance supported */ +#define AZX_REG_INTEL_UAOL_SHIM_OFFSET 0x0 +#define AZX_REG_INTEL_UAOL_IP_OFFSET 0x100 +#define AZX_REG_INTEL_UAOL_VS_SHIM_OFFSET 0xC00 + +/* HDAML section - this part follows sequences in the hardware specification, + * including naming conventions and the use of the hdaml_ prefix. + * The code is intentionally minimal with limited dependencies on frameworks or + * helpers. Locking and scanning lists is handled at a higher level + */ + +static int hdaml_lnk_enum(struct device *dev, struct hdac_ext2_link *h2link, + void __iomem *ml_addr, int link_idx) { - if (bus->mlcap) - return snd_hdac_ext_bus_get_ml_capabilities(bus); + struct hdac_ext_link *hlink = &h2link->hext_link; + u32 base_offset; + + hlink->lcaps = readl(ml_addr + AZX_REG_ML_LCAP); + + h2link->alt = FIELD_GET(AZX_ML_HDA_LCAP_ALT, hlink->lcaps); + + /* handle alternate extensions */ + if (!h2link->alt) { + h2link->slcount = 1; + + /* + * LSDIID is initialized by hardware for HDaudio link, + * it needs to be setup by software for alternate links + */ + hlink->lsdiid = readw(ml_addr + AZX_REG_ML_LSDIID); + + dev_dbg(dev, "Link %d: HDAudio - lsdiid=%d\n", + link_idx, hlink->lsdiid); + + return 0; + } + + h2link->intc = FIELD_GET(AZX_ML_HDA_LCAP_INTC, hlink->lcaps); + h2link->ofls = FIELD_GET(AZX_ML_HDA_LCAP_OFLS, hlink->lcaps); + h2link->lss = FIELD_GET(AZX_ML_HDA_LCAP_LSS, hlink->lcaps); + + /* read slcount (increment due to zero-based hardware representation */ + h2link->slcount = FIELD_GET(AZX_ML_HDA_LCAP_SLCOUNT, hlink->lcaps) + 1; + dev_dbg(dev, "Link %d: HDAudio extended - sublink count %d\n", + link_idx, h2link->slcount); + + /* find IP ID and offsets */ + h2link->leptr = readl(hlink->ml_addr + AZX_REG_ML_LEPTR); + + h2link->elid = FIELD_GET(AZX_REG_ML_LEPTR_ID, h2link->leptr); + + base_offset = FIELD_GET(AZX_REG_ML_LEPTR_PTR, h2link->leptr); + h2link->base_ptr = hlink->ml_addr + base_offset; + + switch (h2link->elid) { + case AZX_REG_ML_LEPTR_ID_SDW: + h2link->shim_offset = AZX_REG_SDW_SHIM_OFFSET; + h2link->ip_offset = AZX_REG_SDW_IP_OFFSET; + h2link->shim_vs_offset = AZX_REG_SDW_VS_SHIM_OFFSET; + dev_dbg(dev, "Link %d: HDAudio extended - SoundWire alternate link, leptr.ptr %#x\n", + link_idx, base_offset); + break; + case AZX_REG_ML_LEPTR_ID_INTEL_DMIC: + h2link->shim_offset = AZX_REG_INTEL_DMIC_SHIM_OFFSET; + h2link->ip_offset = AZX_REG_INTEL_DMIC_IP_OFFSET; + h2link->shim_vs_offset = AZX_REG_INTEL_DMIC_VS_SHIM_OFFSET; + dev_dbg(dev, "Link %d: HDAudio extended - INTEL DMIC alternate link, leptr.ptr %#x\n", + link_idx, base_offset); + break; + case AZX_REG_ML_LEPTR_ID_INTEL_SSP: + h2link->shim_offset = AZX_REG_INTEL_SSP_SHIM_OFFSET; + h2link->ip_offset = AZX_REG_INTEL_SSP_IP_OFFSET; + h2link->shim_vs_offset = AZX_REG_INTEL_SSP_VS_SHIM_OFFSET; + dev_dbg(dev, "Link %d: HDAudio extended - INTEL SSP alternate link, leptr.ptr %#x\n", + link_idx, base_offset); + break; + case AZX_REG_ML_LEPTR_ID_INTEL_UAOL: + h2link->shim_offset = AZX_REG_INTEL_UAOL_SHIM_OFFSET; + h2link->ip_offset = AZX_REG_INTEL_UAOL_IP_OFFSET; + h2link->shim_vs_offset = AZX_REG_INTEL_UAOL_VS_SHIM_OFFSET; + dev_dbg(dev, "Link %d: HDAudio extended - INTEL UAOL alternate link, leptr.ptr %#x\n", + link_idx, base_offset); + break; + default: + dev_err(dev, "Link %d: HDAudio extended - Unsupported alternate link, leptr.id=%#02x value\n", + link_idx, h2link->elid); + return -EINVAL; + } return 0; } -EXPORT_SYMBOL_NS(hda_bus_ml_get_capabilities, SND_SOC_SOF_HDA_MLINK); + +/* END HDAML section */ + +static int hda_ml_alloc_h2link(struct hdac_bus *bus, int index) +{ + struct hdac_ext2_link *h2link; + struct hdac_ext_link *hlink; + int ret; + + h2link = kzalloc(sizeof(*h2link), GFP_KERNEL); + if (!h2link) + return -ENOMEM; + + /* basic initialization */ + hlink = &h2link->hext_link; + + hlink->index = index; + hlink->bus = bus; + hlink->ml_addr = bus->mlcap + AZX_ML_BASE + (AZX_ML_INTERVAL * index); + + ret = hdaml_lnk_enum(bus->dev, h2link, hlink->ml_addr, index); + if (ret < 0) { + kfree(h2link); + return ret; + } + + mutex_init(&h2link->eml_lock); + + list_add_tail(&hlink->list, &bus->hlink_list); + + /* + * HDaudio regular links are powered-on by default, the + * refcount needs to be initialized. + */ + if (!h2link->alt) + hlink->ref_count = 1; + + return 0; +} + +int hda_bus_ml_init(struct hdac_bus *bus) +{ + u32 link_count; + int ret; + int i; + + if (!bus->mlcap) + return 0; + + link_count = readl(bus->mlcap + AZX_REG_ML_MLCD) + 1; + + dev_dbg(bus->dev, "HDAudio Multi-Link count: %d\n", link_count); + + for (i = 0; i < link_count; i++) { + ret = hda_ml_alloc_h2link(bus, i); + if (ret < 0) { + hda_bus_ml_free(bus); + return ret; + } + } + return 0; +} +EXPORT_SYMBOL_NS(hda_bus_ml_init, SND_SOC_SOF_HDA_MLINK); void hda_bus_ml_free(struct hdac_bus *bus) { struct hdac_ext_link *hlink, *_h; + struct hdac_ext2_link *h2link; if (!bus->mlcap) return; list_for_each_entry_safe(hlink, _h, &bus->hlink_list, list) { list_del(&hlink->list); - kfree(hlink); + h2link = hdac_ext_link_to_ext2(hlink); + + mutex_destroy(&h2link->eml_lock); + kfree(h2link); } } EXPORT_SYMBOL_NS(hda_bus_ml_free, SND_SOC_SOF_HDA_MLINK); diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 8845ae255f1e..5980cf1e27a3 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -918,7 +918,7 @@ static int hda_init_caps(struct snd_sof_dev *sdev) return ret; } - hda_bus_ml_get_capabilities(bus); + hda_bus_ml_init(bus); /* Skip SoundWire if it is not supported */ if (!(interface_mask & BIT(SOF_DAI_INTEL_ALH))) From 4c2d4e446d5673db2c653a6e53ca9be908582c4e Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 4 Apr 2023 13:41:16 +0300 Subject: [PATCH 696/778] ASoC: SOF: Intel: hda-mlink: special-case HDaudio regular links MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For backwards compatibility, HDaudio/iDISP links are powered-on when exiting reset, and the existing driver forces them to be powered-off when entering S0ix. In addition, the get/put helpers are invoked directly by the ASoC codec drivers, which a historical layering violation. Extended links are powered-on by software only, during the probe and DAI startup phases. This calls for a different handling of the 'regular' and 'extended' audio links. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Péter Ujfalusi Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Reviewed-by: Takashi Iwai Link: https://lore.kernel.org/r/20230404104127.5629-8-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-mlink.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/sound/soc/sof/intel/hda-mlink.c b/sound/soc/sof/intel/hda-mlink.c index e6b20182f099..8a66c0a67589 100644 --- a/sound/soc/sof/intel/hda-mlink.c +++ b/sound/soc/sof/intel/hda-mlink.c @@ -255,8 +255,12 @@ void hda_bus_ml_put_all(struct hdac_bus *bus) { struct hdac_ext_link *hlink; - list_for_each_entry(hlink, &bus->hlink_list, list) - snd_hdac_ext_bus_link_put(bus, hlink); + list_for_each_entry(hlink, &bus->hlink_list, list) { + struct hdac_ext2_link *h2link = hdac_ext_link_to_ext2(hlink); + + if (!h2link->alt) + snd_hdac_ext_bus_link_put(bus, hlink); + } } EXPORT_SYMBOL_NS(hda_bus_ml_put_all, SND_SOC_SOF_HDA_MLINK); @@ -277,7 +281,9 @@ int hda_bus_ml_resume(struct hdac_bus *bus) /* power up links that were active before suspend */ list_for_each_entry(hlink, &bus->hlink_list, list) { - if (hlink->ref_count) { + struct hdac_ext2_link *h2link = hdac_ext_link_to_ext2(hlink); + + if (!h2link->alt && hlink->ref_count) { ret = snd_hdac_ext_bus_link_power_up(hlink); if (ret < 0) return ret; @@ -289,7 +295,19 @@ EXPORT_SYMBOL_NS(hda_bus_ml_resume, SND_SOC_SOF_HDA_MLINK); int hda_bus_ml_suspend(struct hdac_bus *bus) { - return snd_hdac_ext_bus_link_power_down_all(bus); + struct hdac_ext_link *hlink; + int ret; + + list_for_each_entry(hlink, &bus->hlink_list, list) { + struct hdac_ext2_link *h2link = hdac_ext_link_to_ext2(hlink); + + if (!h2link->alt) { + ret = snd_hdac_ext_bus_link_power_down(hlink); + if (ret < 0) + return ret; + } + } + return 0; } EXPORT_SYMBOL_NS(hda_bus_ml_suspend, SND_SOC_SOF_HDA_MLINK); From fc7dab8ec0b4a451dd5737aa4f06a0e8bd6efa32 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 4 Apr 2023 13:41:17 +0300 Subject: [PATCH 697/778] ASoC: SOF: Intel: hda-mlink: introduce helpers for 'extended links' PM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add helpers to program SPA/CPA bits, using a mutex to access the shared LCTL register if required. All links are managed with the same LCTLx.SPA bits. However there are quite a few implementation details to be aware of: Legacy HDaudio multi-links are powered-up when exiting reset, which requires the ref_count to be manually set to one when initializing the link. Alternate links for SoundWire/DMIC/SSP need to be explicitly powered-up before accessing the SHIM/IP/Vendor-Specific SHIM space for each sublink. DMIC/SSP/SoundWire are all different cases with a different device/dai/hlink relationship. SoundWire will handle power management with the auxiliary device resume/suspend routine. The ref_count is not necessary in this case. The DMIC/SSP will by contrast handle the power management from DAI .startup and .shutdown callbacks. The SSP has a 1:1 mapping between sublink and DAI, but it's bidirectional so the ref_count will help avoid turning off the sublink when one of the two directions is still in use. The DMIC has a single link but two DAIs for data generated at different sampling frequencies, again the ref_count will make sure the two DAIs can be used concurrently. And last the SoundWire Intel require power-up/down and bank switch to be handled with a lock already taken, so the 'eml_lock' is made optional with the _unlocked versions of the helpers. Note that the _check_power_active() implementation is similar to previous helpers in sound/hda/ext, with sleep duration and timeout aligned with hardware recommendations. If desired, this helper could be modified in a second step with .e.g. readl_poll_timeout() Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Péter Ujfalusi Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Reviewed-by: Takashi Iwai Link: https://lore.kernel.org/r/20230404104127.5629-9-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- include/sound/hda-mlink.h | 32 +++++++ sound/soc/sof/intel/hda-mlink.c | 163 ++++++++++++++++++++++++++++++++ 2 files changed, 195 insertions(+) diff --git a/include/sound/hda-mlink.h b/include/sound/hda-mlink.h index 8048bf01c133..6ecb4c29e472 100644 --- a/include/sound/hda-mlink.h +++ b/include/sound/hda-mlink.h @@ -12,6 +12,13 @@ struct hdac_bus; int hda_bus_ml_init(struct hdac_bus *bus); void hda_bus_ml_free(struct hdac_bus *bus); + +int hdac_bus_eml_power_up(struct hdac_bus *bus, bool alt, int elid, int sublink); +int hdac_bus_eml_power_up_unlocked(struct hdac_bus *bus, bool alt, int elid, int sublink); + +int hdac_bus_eml_power_down(struct hdac_bus *bus, bool alt, int elid, int sublink); +int hdac_bus_eml_power_down_unlocked(struct hdac_bus *bus, bool alt, int elid, int sublink); + void hda_bus_ml_put_all(struct hdac_bus *bus); void hda_bus_ml_reset_losidv(struct hdac_bus *bus); int hda_bus_ml_resume(struct hdac_bus *bus); @@ -23,6 +30,31 @@ static inline int hda_bus_ml_init(struct hdac_bus *bus) { return 0; } static inline void hda_bus_ml_free(struct hdac_bus *bus) { } + +static inline int +hdac_bus_eml_power_up(struct hdac_bus *bus, bool alt, int elid, int sublink) +{ + return 0; +} + +static inline int +hdac_bus_eml_power_up_unlocked(struct hdac_bus *bus, bool alt, int elid, int sublink) +{ + return 0; +} + +static inline int +hdac_bus_eml_power_down(struct hdac_bus *bus, bool alt, int elid, int sublink) +{ + return 0; +} + +static inline int +hdac_bus_eml_power_down_unlocked(struct hdac_bus *bus, bool alt, int elid, int sublink) +{ + return 0; +} + static inline void hda_bus_ml_put_all(struct hdac_bus *bus) { } static inline void hda_bus_ml_reset_losidv(struct hdac_bus *bus) { } static inline int hda_bus_ml_resume(struct hdac_bus *bus) { return 0; } diff --git a/sound/soc/sof/intel/hda-mlink.c b/sound/soc/sof/intel/hda-mlink.c index 8a66c0a67589..4d016f6ab773 100644 --- a/sound/soc/sof/intel/hda-mlink.c +++ b/sound/soc/sof/intel/hda-mlink.c @@ -170,6 +170,68 @@ static int hdaml_lnk_enum(struct device *dev, struct hdac_ext2_link *h2link, return 0; } +/* + * Hardware recommendations are to wait ~10us before checking any hardware transition + * reported by bits changing status. + * This value does not need to be super-precise, a slack of 5us is perfectly acceptable. + * The worst-case is about 1ms before reporting an issue + */ +#define HDAML_POLL_DELAY_MIN_US 10 +#define HDAML_POLL_DELAY_SLACK_US 5 +#define HDAML_POLL_DELAY_RETRY 100 + +static int check_sublink_power(u32 __iomem *lctl, int sublink, bool enabled) +{ + int mask = BIT(sublink) << AZX_ML_LCTL_CPA_SHIFT; + int retry = HDAML_POLL_DELAY_RETRY; + u32 val; + + usleep_range(HDAML_POLL_DELAY_MIN_US, + HDAML_POLL_DELAY_MIN_US + HDAML_POLL_DELAY_SLACK_US); + do { + val = readl(lctl); + if (enabled) { + if (val & mask) + return 0; + } else { + if (!(val & mask)) + return 0; + } + usleep_range(HDAML_POLL_DELAY_MIN_US, + HDAML_POLL_DELAY_MIN_US + HDAML_POLL_DELAY_SLACK_US); + + } while (--retry); + + return -EIO; +} + +static int hdaml_link_init(u32 __iomem *lctl, int sublink) +{ + u32 val; + u32 mask = BIT(sublink) << AZX_ML_LCTL_SPA_SHIFT; + + val = readl(lctl); + val |= mask; + + writel(val, lctl); + + return check_sublink_power(lctl, sublink, true); +} + +static int hdaml_link_shutdown(u32 __iomem *lctl, int sublink) +{ + u32 val; + u32 mask; + + val = readl(lctl); + mask = BIT(sublink) << AZX_ML_LCTL_SPA_SHIFT; + val &= ~mask; + + writel(val, lctl); + + return check_sublink_power(lctl, sublink, false); +} + /* END HDAML section */ static int hda_ml_alloc_h2link(struct hdac_bus *bus, int index) @@ -251,6 +313,107 @@ void hda_bus_ml_free(struct hdac_bus *bus) } EXPORT_SYMBOL_NS(hda_bus_ml_free, SND_SOC_SOF_HDA_MLINK); +static struct hdac_ext2_link * +find_ext2_link(struct hdac_bus *bus, bool alt, int elid) +{ + struct hdac_ext_link *hlink; + + list_for_each_entry(hlink, &bus->hlink_list, list) { + struct hdac_ext2_link *h2link = hdac_ext_link_to_ext2(hlink); + + if (h2link->alt == alt && h2link->elid == elid) + return h2link; + } + + return NULL; +} + +static int hdac_bus_eml_power_up_base(struct hdac_bus *bus, bool alt, int elid, int sublink, + bool eml_lock) +{ + struct hdac_ext2_link *h2link; + struct hdac_ext_link *hlink; + int ret = 0; + + h2link = find_ext2_link(bus, alt, elid); + if (!h2link) + return -ENODEV; + + if (sublink >= h2link->slcount) + return -EINVAL; + + hlink = &h2link->hext_link; + + if (eml_lock) + mutex_lock(&h2link->eml_lock); + + if (++hlink->ref_count > 1) + goto skip_init; + + ret = hdaml_link_init(hlink->ml_addr + AZX_REG_ML_LCTL, sublink); + +skip_init: + if (eml_lock) + mutex_unlock(&h2link->eml_lock); + + return ret; +} + +int hdac_bus_eml_power_up(struct hdac_bus *bus, bool alt, int elid, int sublink) +{ + return hdac_bus_eml_power_up_base(bus, alt, elid, sublink, true); +} +EXPORT_SYMBOL_NS(hdac_bus_eml_power_up, SND_SOC_SOF_HDA_MLINK); + +int hdac_bus_eml_power_up_unlocked(struct hdac_bus *bus, bool alt, int elid, int sublink) +{ + return hdac_bus_eml_power_up_base(bus, alt, elid, sublink, false); +} +EXPORT_SYMBOL_NS(hdac_bus_eml_power_up_unlocked, SND_SOC_SOF_HDA_MLINK); + +static int hdac_bus_eml_power_down_base(struct hdac_bus *bus, bool alt, int elid, int sublink, + bool eml_lock) +{ + struct hdac_ext2_link *h2link; + struct hdac_ext_link *hlink; + int ret = 0; + + h2link = find_ext2_link(bus, alt, elid); + if (!h2link) + return -ENODEV; + + if (sublink >= h2link->slcount) + return -EINVAL; + + hlink = &h2link->hext_link; + + if (eml_lock) + mutex_lock(&h2link->eml_lock); + + if (--hlink->ref_count > 0) + goto skip_shutdown; + + ret = hdaml_link_shutdown(hlink->ml_addr + AZX_REG_ML_LCTL, sublink); + +skip_shutdown: + if (eml_lock) + mutex_unlock(&h2link->eml_lock); + + return ret; +} + +int hdac_bus_eml_power_down(struct hdac_bus *bus, bool alt, int elid, int sublink) +{ + return hdac_bus_eml_power_down_base(bus, alt, elid, sublink, true); +} +EXPORT_SYMBOL_NS(hdac_bus_eml_power_down, SND_SOC_SOF_HDA_MLINK); + +int hdac_bus_eml_power_down_unlocked(struct hdac_bus *bus, bool alt, int elid, int sublink) +{ + return hdac_bus_eml_power_down_base(bus, alt, elid, sublink, false); +} +EXPORT_SYMBOL_NS(hdac_bus_eml_power_down_unlocked, SND_SOC_SOF_HDA_MLINK); + void hda_bus_ml_put_all(struct hdac_bus *bus) { struct hdac_ext_link *hlink; From 725218f1d8210ee6eba2c2e923ea26a312fb3f46 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 4 Apr 2023 13:41:18 +0300 Subject: [PATCH 698/778] ASoC: SOF: Intel: hda-mlink: add convenience helpers for SoundWire PM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The updated SoundWire Intel driver will need to rely on Extended HDaudio links for power management, but it doesn't need to be aware of all the HDaudio structures. Add convenience helpers to avoid polluting SoundWire drivers too much with HDaudio information. Since the SoundWire/Intel solution already takes the lock at a higher level, the _unlocked PM helpers are used. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Péter Ujfalusi Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Reviewed-by: Takashi Iwai Link: https://lore.kernel.org/r/20230404104127.5629-10-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- include/sound/hda-mlink.h | 9 +++++++++ sound/soc/sof/intel/hda-mlink.c | 12 ++++++++++++ 2 files changed, 21 insertions(+) diff --git a/include/sound/hda-mlink.h b/include/sound/hda-mlink.h index 6ecb4c29e472..c47008a603d0 100644 --- a/include/sound/hda-mlink.h +++ b/include/sound/hda-mlink.h @@ -19,6 +19,9 @@ int hdac_bus_eml_power_up_unlocked(struct hdac_bus *bus, bool alt, int elid, int int hdac_bus_eml_power_down(struct hdac_bus *bus, bool alt, int elid, int sublink); int hdac_bus_eml_power_down_unlocked(struct hdac_bus *bus, bool alt, int elid, int sublink); +int hdac_bus_eml_sdw_power_up_unlocked(struct hdac_bus *bus, int sublink); +int hdac_bus_eml_sdw_power_down_unlocked(struct hdac_bus *bus, int sublink); + void hda_bus_ml_put_all(struct hdac_bus *bus); void hda_bus_ml_reset_losidv(struct hdac_bus *bus); int hda_bus_ml_resume(struct hdac_bus *bus); @@ -55,6 +58,12 @@ hdac_bus_eml_power_down_unlocked(struct hdac_bus *bus, bool alt, int elid, int s return 0; } +static inline int +hdac_bus_eml_sdw_power_up_unlocked(struct hdac_bus *bus, int sublink) { return 0; } + +static inline int +hdac_bus_eml_sdw_power_down_unlocked(struct hdac_bus *bus, int sublink) { return 0; } + static inline void hda_bus_ml_put_all(struct hdac_bus *bus) { } static inline void hda_bus_ml_reset_losidv(struct hdac_bus *bus) { } static inline int hda_bus_ml_resume(struct hdac_bus *bus) { return 0; } diff --git a/sound/soc/sof/intel/hda-mlink.c b/sound/soc/sof/intel/hda-mlink.c index 4d016f6ab773..5045c10bed76 100644 --- a/sound/soc/sof/intel/hda-mlink.c +++ b/sound/soc/sof/intel/hda-mlink.c @@ -414,6 +414,18 @@ int hdac_bus_eml_power_down_unlocked(struct hdac_bus *bus, bool alt, int elid, i } EXPORT_SYMBOL_NS(hdac_bus_eml_power_down_unlocked, SND_SOC_SOF_HDA_MLINK); +int hdac_bus_eml_sdw_power_up_unlocked(struct hdac_bus *bus, int sublink) +{ + return hdac_bus_eml_power_up_unlocked(bus, true, AZX_REG_ML_LEPTR_ID_SDW, sublink); +} +EXPORT_SYMBOL_NS(hdac_bus_eml_sdw_power_up_unlocked, SND_SOC_SOF_HDA_MLINK); + +int hdac_bus_eml_sdw_power_down_unlocked(struct hdac_bus *bus, int sublink) +{ + return hdac_bus_eml_power_down_unlocked(bus, true, AZX_REG_ML_LEPTR_ID_SDW, sublink); +} +EXPORT_SYMBOL_NS(hdac_bus_eml_sdw_power_down_unlocked, SND_SOC_SOF_HDA_MLINK); + void hda_bus_ml_put_all(struct hdac_bus *bus) { struct hdac_ext_link *hlink; From 6857c7ee202cf4b8224882bcee8e3b97c26b6484 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 4 Apr 2023 13:41:19 +0300 Subject: [PATCH 699/778] ASoC: SOF: Intel: hda-mlink: add helper to return sublink count MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is needed for SoundWire integration. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Péter Ujfalusi Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Reviewed-by: Takashi Iwai Link: https://lore.kernel.org/r/20230404104127.5629-11-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- include/sound/hda-mlink.h | 5 +++++ sound/soc/sof/intel/hda-mlink.c | 12 ++++++++++++ 2 files changed, 17 insertions(+) diff --git a/include/sound/hda-mlink.h b/include/sound/hda-mlink.h index c47008a603d0..d7f65cb6e175 100644 --- a/include/sound/hda-mlink.h +++ b/include/sound/hda-mlink.h @@ -13,6 +13,8 @@ struct hdac_bus; int hda_bus_ml_init(struct hdac_bus *bus); void hda_bus_ml_free(struct hdac_bus *bus); +int hdac_bus_eml_get_count(struct hdac_bus *bus, bool alt, int elid); + int hdac_bus_eml_power_up(struct hdac_bus *bus, bool alt, int elid, int sublink); int hdac_bus_eml_power_up_unlocked(struct hdac_bus *bus, bool alt, int elid, int sublink); @@ -34,6 +36,9 @@ hda_bus_ml_init(struct hdac_bus *bus) { return 0; } static inline void hda_bus_ml_free(struct hdac_bus *bus) { } +static inline int +hdac_bus_eml_get_count(struct hdac_bus *bus, bool alt, int elid) { return 0; } + static inline int hdac_bus_eml_power_up(struct hdac_bus *bus, bool alt, int elid, int sublink) { diff --git a/sound/soc/sof/intel/hda-mlink.c b/sound/soc/sof/intel/hda-mlink.c index 5045c10bed76..02743c342f28 100644 --- a/sound/soc/sof/intel/hda-mlink.c +++ b/sound/soc/sof/intel/hda-mlink.c @@ -328,6 +328,18 @@ find_ext2_link(struct hdac_bus *bus, bool alt, int elid) return NULL; } +int hdac_bus_eml_get_count(struct hdac_bus *bus, bool alt, int elid) +{ + struct hdac_ext2_link *h2link; + + h2link = find_ext2_link(bus, alt, elid); + if (!h2link) + return 0; + + return h2link->slcount; +} +EXPORT_SYMBOL_NS(hdac_bus_eml_get_count, SND_SOC_SOF_HDA_MLINK); + static int hdac_bus_eml_power_up_base(struct hdac_bus *bus, bool alt, int elid, int sublink, bool eml_lock) { From 2e4288319ad3e18a266461d3e63c86eb36f7a152 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 4 Apr 2023 13:41:20 +0300 Subject: [PATCH 700/778] ASoC: SOF: Intel: hda-mlink: add helpers to enable/check interrupts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When INTC is set, LCTL exposes INTEN and INTSTS fields. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Péter Ujfalusi Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Reviewed-by: Takashi Iwai Link: https://lore.kernel.org/r/20230404104127.5629-12-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- include/sound/hda-mlink.h | 8 +++++ sound/soc/sof/intel/hda-mlink.c | 62 +++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/include/sound/hda-mlink.h b/include/sound/hda-mlink.h index d7f65cb6e175..872652209a47 100644 --- a/include/sound/hda-mlink.h +++ b/include/sound/hda-mlink.h @@ -14,6 +14,8 @@ int hda_bus_ml_init(struct hdac_bus *bus); void hda_bus_ml_free(struct hdac_bus *bus); int hdac_bus_eml_get_count(struct hdac_bus *bus, bool alt, int elid); +void hdac_bus_eml_enable_interrupt(struct hdac_bus *bus, bool alt, int elid, bool enable); +bool hdac_bus_eml_check_interrupt(struct hdac_bus *bus, bool alt, int elid); int hdac_bus_eml_power_up(struct hdac_bus *bus, bool alt, int elid, int sublink); int hdac_bus_eml_power_up_unlocked(struct hdac_bus *bus, bool alt, int elid, int sublink); @@ -39,6 +41,12 @@ static inline void hda_bus_ml_free(struct hdac_bus *bus) { } static inline int hdac_bus_eml_get_count(struct hdac_bus *bus, bool alt, int elid) { return 0; } +static inline void +hdac_bus_eml_enable_interrupt(struct hdac_bus *bus, bool alt, int elid, bool enable) { } + +static inline bool +hdac_bus_eml_check_interrupt(struct hdac_bus *bus, bool alt, int elid) { return false; } + static inline int hdac_bus_eml_power_up(struct hdac_bus *bus, bool alt, int elid, int sublink) { diff --git a/sound/soc/sof/intel/hda-mlink.c b/sound/soc/sof/intel/hda-mlink.c index 02743c342f28..026642659037 100644 --- a/sound/soc/sof/intel/hda-mlink.c +++ b/sound/soc/sof/intel/hda-mlink.c @@ -232,6 +232,28 @@ static int hdaml_link_shutdown(u32 __iomem *lctl, int sublink) return check_sublink_power(lctl, sublink, false); } +static void hdaml_link_enable_interrupt(u32 __iomem *lctl, bool enable) +{ + u32 val; + + val = readl(lctl); + if (enable) + val |= AZX_ML_LCTL_INTEN; + else + val &= ~AZX_ML_LCTL_INTEN; + + writel(val, lctl); +} + +static bool hdaml_link_check_interrupt(u32 __iomem *lctl) +{ + u32 val; + + val = readl(lctl); + + return val & AZX_ML_LCTL_INTSTS; +} + /* END HDAML section */ static int hda_ml_alloc_h2link(struct hdac_bus *bus, int index) @@ -340,6 +362,46 @@ int hdac_bus_eml_get_count(struct hdac_bus *bus, bool alt, int elid) } EXPORT_SYMBOL_NS(hdac_bus_eml_get_count, SND_SOC_SOF_HDA_MLINK); +void hdac_bus_eml_enable_interrupt(struct hdac_bus *bus, bool alt, int elid, bool enable) +{ + struct hdac_ext2_link *h2link; + struct hdac_ext_link *hlink; + + h2link = find_ext2_link(bus, alt, elid); + if (!h2link) + return; + + if (!h2link->intc) + return; + + hlink = &h2link->hext_link; + + mutex_lock(&h2link->eml_lock); + + hdaml_link_enable_interrupt(hlink->ml_addr + AZX_REG_ML_LCTL, enable); + + mutex_unlock(&h2link->eml_lock); +} +EXPORT_SYMBOL_NS(hdac_bus_eml_enable_interrupt, SND_SOC_SOF_HDA_MLINK); + +bool hdac_bus_eml_check_interrupt(struct hdac_bus *bus, bool alt, int elid) +{ + struct hdac_ext2_link *h2link; + struct hdac_ext_link *hlink; + + h2link = find_ext2_link(bus, alt, elid); + if (!h2link) + return false; + + if (!h2link->intc) + return false; + + hlink = &h2link->hext_link; + + return hdaml_link_check_interrupt(hlink->ml_addr + AZX_REG_ML_LCTL); +} +EXPORT_SYMBOL_NS(hdac_bus_eml_check_interrupt, SND_SOC_SOF_HDA_MLINK); + static int hdac_bus_eml_power_up_base(struct hdac_bus *bus, bool alt, int elid, int sublink, bool eml_lock) { From 02ba1b021c28670011b361be3be4bda49f348c43 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 4 Apr 2023 13:41:21 +0300 Subject: [PATCH 701/778] ASoC: SOF: Intel: hda-mlink: add helpers to set link SYNC frequency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These helpers configure the ratio between the base clock and the hardware signal used for link synchronization. The SYNCPRD is written before the first sublink is powered-up. The SYNCPU bit is set, but it will only be cleared after the link is powered-up, hence the implementation with a set/wait pattern. These helpers are currently only needed by SoundWire support, where the lock is taken at a higher level, so only the _unlocked versions are exposed for now. Note that the _wait_bit() implementation is similar to previous helpers in drivers/soundwire, but with sleep duration and timeout aligned with hardware recommendations. If desired, this helper could be modified in a second step with e.g. readl_poll_timeout(). Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Péter Ujfalusi Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Reviewed-by: Takashi Iwai Link: https://lore.kernel.org/r/20230404104127.5629-13-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- include/sound/hda-mlink.h | 27 ++++++++++ sound/soc/sof/intel/hda-mlink.c | 90 +++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+) diff --git a/include/sound/hda-mlink.h b/include/sound/hda-mlink.h index 872652209a47..80af2a3996d7 100644 --- a/include/sound/hda-mlink.h +++ b/include/sound/hda-mlink.h @@ -17,6 +17,12 @@ int hdac_bus_eml_get_count(struct hdac_bus *bus, bool alt, int elid); void hdac_bus_eml_enable_interrupt(struct hdac_bus *bus, bool alt, int elid, bool enable); bool hdac_bus_eml_check_interrupt(struct hdac_bus *bus, bool alt, int elid); +int hdac_bus_eml_set_syncprd_unlocked(struct hdac_bus *bus, bool alt, int elid, u32 syncprd); +int hdac_bus_eml_sdw_set_syncprd_unlocked(struct hdac_bus *bus, u32 syncprd); + +int hdac_bus_eml_wait_syncpu_unlocked(struct hdac_bus *bus, bool alt, int elid); +int hdac_bus_eml_sdw_wait_syncpu_unlocked(struct hdac_bus *bus); + int hdac_bus_eml_power_up(struct hdac_bus *bus, bool alt, int elid, int sublink); int hdac_bus_eml_power_up_unlocked(struct hdac_bus *bus, bool alt, int elid, int sublink); @@ -47,6 +53,27 @@ hdac_bus_eml_enable_interrupt(struct hdac_bus *bus, bool alt, int elid, bool ena static inline bool hdac_bus_eml_check_interrupt(struct hdac_bus *bus, bool alt, int elid) { return false; } +static inline int +hdac_bus_eml_set_syncprd_unlocked(struct hdac_bus *bus, bool alt, int elid, u32 syncprd) +{ + return 0; +} + +static inline int +hdac_bus_eml_sdw_set_syncprd_unlocked(struct hdac_bus *bus, u32 syncprd) +{ + return 0; +} + +static inline int +hdac_bus_eml_wait_syncpu_unlocked(struct hdac_bus *bus, bool alt, int elid) +{ + return 0; +} + +static inline int +hdac_bus_eml_sdw_wait_syncpu_unlocked(struct hdac_bus *bus) { return 0; } + static inline int hdac_bus_eml_power_up(struct hdac_bus *bus, bool alt, int elid, int sublink) { diff --git a/sound/soc/sof/intel/hda-mlink.c b/sound/soc/sof/intel/hda-mlink.c index 026642659037..a364d6b5935d 100644 --- a/sound/soc/sof/intel/hda-mlink.c +++ b/sound/soc/sof/intel/hda-mlink.c @@ -254,6 +254,46 @@ static bool hdaml_link_check_interrupt(u32 __iomem *lctl) return val & AZX_ML_LCTL_INTSTS; } +static int hdaml_wait_bit(void __iomem *base, int offset, u32 mask, u32 target) +{ + int timeout = HDAML_POLL_DELAY_RETRY; + u32 reg_read; + + do { + reg_read = readl(base + offset); + if ((reg_read & mask) == target) + return 0; + + timeout--; + usleep_range(HDAML_POLL_DELAY_MIN_US, + HDAML_POLL_DELAY_MIN_US + HDAML_POLL_DELAY_SLACK_US); + } while (timeout != 0); + + return -EAGAIN; +} + +static void hdaml_link_set_syncprd(u32 __iomem *lsync, u32 syncprd) +{ + u32 val; + + val = readl(lsync); + val &= ~AZX_REG_ML_LSYNC_SYNCPRD; + val |= (syncprd & AZX_REG_ML_LSYNC_SYNCPRD); + + /* + * set SYNCPU but do not wait. The bit is cleared by hardware when + * the link becomes active. + */ + val |= AZX_REG_ML_LSYNC_SYNCPU; + + writel(val, lsync); +} + +static int hdaml_link_wait_syncpu(u32 __iomem *lsync) +{ + return hdaml_wait_bit(lsync, 0, AZX_REG_ML_LSYNC_SYNCPU, 0); +} + /* END HDAML section */ static int hda_ml_alloc_h2link(struct hdac_bus *bus, int index) @@ -402,6 +442,56 @@ bool hdac_bus_eml_check_interrupt(struct hdac_bus *bus, bool alt, int elid) } EXPORT_SYMBOL_NS(hdac_bus_eml_check_interrupt, SND_SOC_SOF_HDA_MLINK); +int hdac_bus_eml_set_syncprd_unlocked(struct hdac_bus *bus, bool alt, int elid, u32 syncprd) +{ + struct hdac_ext2_link *h2link; + struct hdac_ext_link *hlink; + + h2link = find_ext2_link(bus, alt, elid); + if (!h2link) + return 0; + + if (!h2link->lss) + return 0; + + hlink = &h2link->hext_link; + + hdaml_link_set_syncprd(hlink->ml_addr + AZX_REG_ML_LSYNC, syncprd); + + return 0; +} +EXPORT_SYMBOL_NS(hdac_bus_eml_set_syncprd_unlocked, SND_SOC_SOF_HDA_MLINK); + +int hdac_bus_eml_sdw_set_syncprd_unlocked(struct hdac_bus *bus, u32 syncprd) +{ + return hdac_bus_eml_set_syncprd_unlocked(bus, true, AZX_REG_ML_LEPTR_ID_SDW, syncprd); +} +EXPORT_SYMBOL_NS(hdac_bus_eml_sdw_set_syncprd_unlocked, SND_SOC_SOF_HDA_MLINK); + +int hdac_bus_eml_wait_syncpu_unlocked(struct hdac_bus *bus, bool alt, int elid) +{ + struct hdac_ext2_link *h2link; + struct hdac_ext_link *hlink; + + h2link = find_ext2_link(bus, alt, elid); + if (!h2link) + return 0; + + if (!h2link->lss) + return 0; + + hlink = &h2link->hext_link; + + return hdaml_link_wait_syncpu(hlink->ml_addr + AZX_REG_ML_LSYNC); +} +EXPORT_SYMBOL_NS(hdac_bus_eml_wait_syncpu_unlocked, SND_SOC_SOF_HDA_MLINK); + +int hdac_bus_eml_sdw_wait_syncpu_unlocked(struct hdac_bus *bus) +{ + return hdac_bus_eml_wait_syncpu_unlocked(bus, true, AZX_REG_ML_LEPTR_ID_SDW); +} +EXPORT_SYMBOL_NS(hdac_bus_eml_sdw_wait_syncpu_unlocked, SND_SOC_SOF_HDA_MLINK); + static int hdac_bus_eml_power_up_base(struct hdac_bus *bus, bool alt, int elid, int sublink, bool eml_lock) { From 1f5a6e8b5147b7bc49c0e091f8b458e45d8ee56c Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 4 Apr 2023 13:41:22 +0300 Subject: [PATCH 702/778] ASoC: SOF: Intel: hda-mlink: add helpers for sync_arm/sync_go MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The multi-link synchronization uses the same concept and registers, but moved to the HDAudio extended links. Add helpers for sync_arm and sync_go which are the basic for the bus reset, bank switch and clock stop. Since SoundWire is the only user of those helpers, only expose the _unlocked versions for now. Note that SYNCGO is a write-only bit, so no error can be reported. We still return 0 for compatibility with the SoundWire stream management headers. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Péter Ujfalusi Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Reviewed-by: Takashi Iwai Link: https://lore.kernel.org/r/20230404104127.5629-14-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- include/sound/hda-mlink.h | 18 +++++++++ sound/soc/sof/intel/hda-mlink.c | 70 +++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+) diff --git a/include/sound/hda-mlink.h b/include/sound/hda-mlink.h index 80af2a3996d7..234af269495e 100644 --- a/include/sound/hda-mlink.h +++ b/include/sound/hda-mlink.h @@ -23,6 +23,12 @@ int hdac_bus_eml_sdw_set_syncprd_unlocked(struct hdac_bus *bus, u32 syncprd); int hdac_bus_eml_wait_syncpu_unlocked(struct hdac_bus *bus, bool alt, int elid); int hdac_bus_eml_sdw_wait_syncpu_unlocked(struct hdac_bus *bus); +void hdac_bus_eml_sync_arm_unlocked(struct hdac_bus *bus, bool alt, int elid, int sublink); +void hdac_bus_eml_sdw_sync_arm_unlocked(struct hdac_bus *bus, int sublink); + +int hdac_bus_eml_sync_go_unlocked(struct hdac_bus *bus, bool alt, int elid); +int hdac_bus_eml_sdw_sync_go_unlocked(struct hdac_bus *bus); + int hdac_bus_eml_power_up(struct hdac_bus *bus, bool alt, int elid, int sublink); int hdac_bus_eml_power_up_unlocked(struct hdac_bus *bus, bool alt, int elid, int sublink); @@ -74,6 +80,18 @@ hdac_bus_eml_wait_syncpu_unlocked(struct hdac_bus *bus, bool alt, int elid) static inline int hdac_bus_eml_sdw_wait_syncpu_unlocked(struct hdac_bus *bus) { return 0; } +static inline void +hdac_bus_eml_sync_arm_unlocked(struct hdac_bus *bus, bool alt, int elid, int sublink) { } + +static inline void +hdac_bus_eml_sdw_sync_arm_unlocked(struct hdac_bus *bus, int sublink) { } + +static inline int +hdac_bus_eml_sync_go_unlocked(struct hdac_bus *bus, bool alt, int elid) { return 0; } + +static inline int +hdac_bus_eml_sdw_sync_go_unlocked(struct hdac_bus *bus) { return 0; } + static inline int hdac_bus_eml_power_up(struct hdac_bus *bus, bool alt, int elid, int sublink) { diff --git a/sound/soc/sof/intel/hda-mlink.c b/sound/soc/sof/intel/hda-mlink.c index a364d6b5935d..c8371ab03c0a 100644 --- a/sound/soc/sof/intel/hda-mlink.c +++ b/sound/soc/sof/intel/hda-mlink.c @@ -294,6 +294,26 @@ static int hdaml_link_wait_syncpu(u32 __iomem *lsync) return hdaml_wait_bit(lsync, 0, AZX_REG_ML_LSYNC_SYNCPU, 0); } +static void hdaml_link_sync_arm(u32 __iomem *lsync, int sublink) +{ + u32 val; + + val = readl(lsync); + val |= (AZX_REG_ML_LSYNC_CMDSYNC << sublink); + + writel(val, lsync); +} + +static void hdaml_link_sync_go(u32 __iomem *lsync) +{ + u32 val; + + val = readl(lsync); + val |= AZX_REG_ML_LSYNC_SYNCGO; + + writel(val, lsync); +} + /* END HDAML section */ static int hda_ml_alloc_h2link(struct hdac_bus *bus, int index) @@ -492,6 +512,56 @@ int hdac_bus_eml_sdw_wait_syncpu_unlocked(struct hdac_bus *bus) } EXPORT_SYMBOL_NS(hdac_bus_eml_sdw_wait_syncpu_unlocked, SND_SOC_SOF_HDA_MLINK); +void hdac_bus_eml_sync_arm_unlocked(struct hdac_bus *bus, bool alt, int elid, int sublink) +{ + struct hdac_ext2_link *h2link; + struct hdac_ext_link *hlink; + + h2link = find_ext2_link(bus, alt, elid); + if (!h2link) + return; + + if (!h2link->lss) + return; + + hlink = &h2link->hext_link; + + hdaml_link_sync_arm(hlink->ml_addr + AZX_REG_ML_LSYNC, sublink); +} +EXPORT_SYMBOL_NS(hdac_bus_eml_sync_arm_unlocked, SND_SOC_SOF_HDA_MLINK); + +void hdac_bus_eml_sdw_sync_arm_unlocked(struct hdac_bus *bus, int sublink) +{ + hdac_bus_eml_sync_arm_unlocked(bus, true, AZX_REG_ML_LEPTR_ID_SDW, sublink); +} +EXPORT_SYMBOL_NS(hdac_bus_eml_sdw_sync_arm_unlocked, SND_SOC_SOF_HDA_MLINK); + +int hdac_bus_eml_sync_go_unlocked(struct hdac_bus *bus, bool alt, int elid) +{ + struct hdac_ext2_link *h2link; + struct hdac_ext_link *hlink; + + h2link = find_ext2_link(bus, alt, elid); + if (!h2link) + return 0; + + if (!h2link->lss) + return 0; + + hlink = &h2link->hext_link; + + hdaml_link_sync_go(hlink->ml_addr + AZX_REG_ML_LSYNC); + + return 0; +} +EXPORT_SYMBOL_NS(hdac_bus_eml_sync_go_unlocked, SND_SOC_SOF_HDA_MLINK); + +int hdac_bus_eml_sdw_sync_go_unlocked(struct hdac_bus *bus) +{ + return hdac_bus_eml_sync_go_unlocked(bus, true, AZX_REG_ML_LEPTR_ID_SDW); +} +EXPORT_SYMBOL_NS(hdac_bus_eml_sdw_sync_go_unlocked, SND_SOC_SOF_HDA_MLINK); + static int hdac_bus_eml_power_up_base(struct hdac_bus *bus, bool alt, int elid, int sublink, bool eml_lock) { From d56d205857a2f6e10a1047532134321072f758b7 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 4 Apr 2023 13:41:23 +0300 Subject: [PATCH 703/778] ASoC: SOF: Intel: hda-mlink: add helper to check cmdsync MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This helper is an optimization where sync_go is only called when the cmdsync field is actually set to a non-zero value. Since this is also only used by SoundWire for now, only expose the _unlocked version. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Péter Ujfalusi Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Reviewed-by: Takashi Iwai Link: https://lore.kernel.org/r/20230404104127.5629-15-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- include/sound/hda-mlink.h | 9 ++++++++ sound/soc/sof/intel/hda-mlink.c | 38 +++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/include/sound/hda-mlink.h b/include/sound/hda-mlink.h index 234af269495e..0c71b843f2cf 100644 --- a/include/sound/hda-mlink.h +++ b/include/sound/hda-mlink.h @@ -29,6 +29,9 @@ void hdac_bus_eml_sdw_sync_arm_unlocked(struct hdac_bus *bus, int sublink); int hdac_bus_eml_sync_go_unlocked(struct hdac_bus *bus, bool alt, int elid); int hdac_bus_eml_sdw_sync_go_unlocked(struct hdac_bus *bus); +bool hdac_bus_eml_check_cmdsync_unlocked(struct hdac_bus *bus, bool alt, int elid); +bool hdac_bus_eml_sdw_check_cmdsync_unlocked(struct hdac_bus *bus); + int hdac_bus_eml_power_up(struct hdac_bus *bus, bool alt, int elid, int sublink); int hdac_bus_eml_power_up_unlocked(struct hdac_bus *bus, bool alt, int elid, int sublink); @@ -92,6 +95,12 @@ hdac_bus_eml_sync_go_unlocked(struct hdac_bus *bus, bool alt, int elid) { return static inline int hdac_bus_eml_sdw_sync_go_unlocked(struct hdac_bus *bus) { return 0; } +static inline bool +hdac_bus_eml_check_cmdsync_unlocked(struct hdac_bus *bus, bool alt, int elid) { return false; } + +static inline bool +hdac_bus_eml_sdw_check_cmdsync_unlocked(struct hdac_bus *bus) { return false; } + static inline int hdac_bus_eml_power_up(struct hdac_bus *bus, bool alt, int elid, int sublink) { diff --git a/sound/soc/sof/intel/hda-mlink.c b/sound/soc/sof/intel/hda-mlink.c index c8371ab03c0a..cbbc8639691c 100644 --- a/sound/soc/sof/intel/hda-mlink.c +++ b/sound/soc/sof/intel/hda-mlink.c @@ -314,6 +314,15 @@ static void hdaml_link_sync_go(u32 __iomem *lsync) writel(val, lsync); } +static bool hdaml_link_check_cmdsync(u32 __iomem *lsync, u32 cmdsync_mask) +{ + u32 val; + + val = readl(lsync); + + return !!(val & cmdsync_mask); +} + /* END HDAML section */ static int hda_ml_alloc_h2link(struct hdac_bus *bus, int index) @@ -562,6 +571,35 @@ int hdac_bus_eml_sdw_sync_go_unlocked(struct hdac_bus *bus) } EXPORT_SYMBOL_NS(hdac_bus_eml_sdw_sync_go_unlocked, SND_SOC_SOF_HDA_MLINK); +bool hdac_bus_eml_check_cmdsync_unlocked(struct hdac_bus *bus, bool alt, int elid) +{ + struct hdac_ext2_link *h2link; + struct hdac_ext_link *hlink; + u32 cmdsync_mask; + + h2link = find_ext2_link(bus, alt, elid); + if (!h2link) + return 0; + + if (!h2link->lss) + return 0; + + hlink = &h2link->hext_link; + + cmdsync_mask = GENMASK(AZX_REG_ML_LSYNC_CMDSYNC_SHIFT + h2link->slcount - 1, + AZX_REG_ML_LSYNC_CMDSYNC_SHIFT); + + return hdaml_link_check_cmdsync(hlink->ml_addr + AZX_REG_ML_LSYNC, + cmdsync_mask); +} +EXPORT_SYMBOL_NS(hdac_bus_eml_check_cmdsync_unlocked, SND_SOC_SOF_HDA_MLINK); + +bool hdac_bus_eml_sdw_check_cmdsync_unlocked(struct hdac_bus *bus) +{ + return hdac_bus_eml_check_cmdsync_unlocked(bus, true, AZX_REG_ML_LEPTR_ID_SDW); +} +EXPORT_SYMBOL_NS(hdac_bus_eml_sdw_check_cmdsync_unlocked, SND_SOC_SOF_HDA_MLINK); + static int hdac_bus_eml_power_up_base(struct hdac_bus *bus, bool alt, int elid, int sublink, bool eml_lock) { From 87a6ddc0cf1c62dbc7c2cc4b5f764a2e992c5ba6 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 4 Apr 2023 13:41:24 +0300 Subject: [PATCH 704/778] ASoC: SOF: Intel: hda-mlink: program SoundWire LSDIID registers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Each SoundWire peripheral can be programmed from the manager side either with a regular command FIFO, or with the HDaudio CORB/RIRB DMA-based mechanism. The mapping between SoundWire peripheral and SDI address is handled with the LSDIID register. This mapping only works of course if each peripheral has a unique address across all links. This has already been enforced in previous Intel contributions allowing for an IDA-based solution for the device number allocation. The checks on the dev_num are handled at the SoundWire level, but the locking is handled at the hda-mlink level. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Péter Ujfalusi Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Reviewed-by: Takashi Iwai Link: https://lore.kernel.org/r/20230404104127.5629-16-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- include/sound/hda-mlink.h | 5 +++++ sound/soc/sof/intel/hda-mlink.c | 30 ++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/include/sound/hda-mlink.h b/include/sound/hda-mlink.h index 0c71b843f2cf..d626ef964ea7 100644 --- a/include/sound/hda-mlink.h +++ b/include/sound/hda-mlink.h @@ -41,6 +41,8 @@ int hdac_bus_eml_power_down_unlocked(struct hdac_bus *bus, bool alt, int elid, i int hdac_bus_eml_sdw_power_up_unlocked(struct hdac_bus *bus, int sublink); int hdac_bus_eml_sdw_power_down_unlocked(struct hdac_bus *bus, int sublink); +int hdac_bus_eml_sdw_set_lsdiid(struct hdac_bus *bus, int sublink, int dev_num); + void hda_bus_ml_put_all(struct hdac_bus *bus); void hda_bus_ml_reset_losidv(struct hdac_bus *bus); int hda_bus_ml_resume(struct hdac_bus *bus); @@ -131,6 +133,9 @@ hdac_bus_eml_sdw_power_up_unlocked(struct hdac_bus *bus, int sublink) { return 0 static inline int hdac_bus_eml_sdw_power_down_unlocked(struct hdac_bus *bus, int sublink) { return 0; } +static inline int +hdac_bus_eml_sdw_set_lsdiid(struct hdac_bus *bus, int sublink, int dev_num) { return 0; } + static inline void hda_bus_ml_put_all(struct hdac_bus *bus) { } static inline void hda_bus_ml_reset_losidv(struct hdac_bus *bus) { } static inline int hda_bus_ml_resume(struct hdac_bus *bus) { return 0; } diff --git a/sound/soc/sof/intel/hda-mlink.c b/sound/soc/sof/intel/hda-mlink.c index cbbc8639691c..5810d6f8719c 100644 --- a/sound/soc/sof/intel/hda-mlink.c +++ b/sound/soc/sof/intel/hda-mlink.c @@ -323,6 +323,16 @@ static bool hdaml_link_check_cmdsync(u32 __iomem *lsync, u32 cmdsync_mask) return !!(val & cmdsync_mask); } +static void hdaml_link_set_lsdiid(u32 __iomem *lsdiid, int dev_num) +{ + u32 val; + + val = readl(lsdiid); + val |= BIT(dev_num); + + writel(val, lsdiid); +} + /* END HDAML section */ static int hda_ml_alloc_h2link(struct hdac_bus *bus, int index) @@ -698,6 +708,26 @@ int hdac_bus_eml_sdw_power_down_unlocked(struct hdac_bus *bus, int sublink) } EXPORT_SYMBOL_NS(hdac_bus_eml_sdw_power_down_unlocked, SND_SOC_SOF_HDA_MLINK); +int hdac_bus_eml_sdw_set_lsdiid(struct hdac_bus *bus, int sublink, int dev_num) +{ + struct hdac_ext2_link *h2link; + struct hdac_ext_link *hlink; + + h2link = find_ext2_link(bus, true, AZX_REG_ML_LEPTR_ID_SDW); + if (!h2link) + return -ENODEV; + + hlink = &h2link->hext_link; + + mutex_lock(&h2link->eml_lock); + + hdaml_link_set_lsdiid(hlink->ml_addr + AZX_REG_ML_LSDIID_OFFSET(sublink), dev_num); + + mutex_unlock(&h2link->eml_lock); + + return 0; +} EXPORT_SYMBOL_NS(hdac_bus_eml_sdw_set_lsdiid, SND_SOC_SOF_HDA_MLINK); + void hda_bus_ml_put_all(struct hdac_bus *bus) { struct hdac_ext_link *hlink; From 2b864e969be29958eb810fb611d1eac50eb7104b Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 4 Apr 2023 13:41:25 +0300 Subject: [PATCH 705/778] ASoC: SOF: Intel: hda-mlink: add helpers to retrieve DMIC/SSP hlink MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Small helpers to make DAI ops simpler. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Péter Ujfalusi Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Reviewed-by: Takashi Iwai Link: https://lore.kernel.org/r/20230404104127.5629-17-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- include/sound/hda-mlink.h | 10 ++++++++++ sound/soc/sof/intel/hda-mlink.c | 24 ++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/include/sound/hda-mlink.h b/include/sound/hda-mlink.h index d626ef964ea7..bfd2c77c184d 100644 --- a/include/sound/hda-mlink.h +++ b/include/sound/hda-mlink.h @@ -7,6 +7,7 @@ */ struct hdac_bus; +struct hdac_ext_link; #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_MLINK) @@ -48,6 +49,9 @@ void hda_bus_ml_reset_losidv(struct hdac_bus *bus); int hda_bus_ml_resume(struct hdac_bus *bus); int hda_bus_ml_suspend(struct hdac_bus *bus); +struct hdac_ext_link *hdac_bus_eml_ssp_get_hlink(struct hdac_bus *bus); +struct hdac_ext_link *hdac_bus_eml_dmic_get_hlink(struct hdac_bus *bus); + #else static inline int @@ -141,4 +145,10 @@ static inline void hda_bus_ml_reset_losidv(struct hdac_bus *bus) { } static inline int hda_bus_ml_resume(struct hdac_bus *bus) { return 0; } static inline int hda_bus_ml_suspend(struct hdac_bus *bus) { return 0; } +static inline struct hdac_ext_link * +hdac_bus_eml_ssp_get_hlink(struct hdac_bus *bus) { return NULL; } + +static inline struct hdac_ext_link * +hdac_bus_eml_dmic_get_hlink(struct hdac_bus *bus) { return NULL; } + #endif /* CONFIG_SND_SOC_SOF_HDA */ diff --git a/sound/soc/sof/intel/hda-mlink.c b/sound/soc/sof/intel/hda-mlink.c index 5810d6f8719c..06613c081410 100644 --- a/sound/soc/sof/intel/hda-mlink.c +++ b/sound/soc/sof/intel/hda-mlink.c @@ -788,6 +788,30 @@ int hda_bus_ml_suspend(struct hdac_bus *bus) } EXPORT_SYMBOL_NS(hda_bus_ml_suspend, SND_SOC_SOF_HDA_MLINK); +struct hdac_ext_link *hdac_bus_eml_ssp_get_hlink(struct hdac_bus *bus) +{ + struct hdac_ext2_link *h2link; + + h2link = find_ext2_link(bus, true, AZX_REG_ML_LEPTR_ID_INTEL_SSP); + if (!h2link) + return NULL; + + return &h2link->hext_link; +} +EXPORT_SYMBOL_NS(hdac_bus_eml_ssp_get_hlink, SND_SOC_SOF_HDA_MLINK); + +struct hdac_ext_link *hdac_bus_eml_dmic_get_hlink(struct hdac_bus *bus) +{ + struct hdac_ext2_link *h2link; + + h2link = find_ext2_link(bus, true, AZX_REG_ML_LEPTR_ID_INTEL_DMIC); + if (!h2link) + return NULL; + + return &h2link->hext_link; +} +EXPORT_SYMBOL_NS(hdac_bus_eml_dmic_get_hlink, SND_SOC_SOF_HDA_MLINK); + #endif MODULE_LICENSE("Dual BSD/GPL"); From 82958c406da4fec8f818826624c33cf2e62f4147 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 4 Apr 2023 13:41:26 +0300 Subject: [PATCH 706/778] ASoC: SOF: Intel: hda-mlink: add helper to offload link ownership MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For DMIC and SSP, the DSP will be responsible for programming the blobs and link registers. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Péter Ujfalusi Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Reviewed-by: Takashi Iwai Link: https://lore.kernel.org/r/20230404104127.5629-18-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- include/sound/hda-mlink.h | 7 +++++++ sound/soc/sof/intel/hda-mlink.c | 36 +++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/include/sound/hda-mlink.h b/include/sound/hda-mlink.h index bfd2c77c184d..fee42c432fa3 100644 --- a/include/sound/hda-mlink.h +++ b/include/sound/hda-mlink.h @@ -52,6 +52,8 @@ int hda_bus_ml_suspend(struct hdac_bus *bus); struct hdac_ext_link *hdac_bus_eml_ssp_get_hlink(struct hdac_bus *bus); struct hdac_ext_link *hdac_bus_eml_dmic_get_hlink(struct hdac_bus *bus); +int hdac_bus_eml_enable_offload(struct hdac_bus *bus, bool alt, int elid, bool enable); + #else static inline int @@ -151,4 +153,9 @@ hdac_bus_eml_ssp_get_hlink(struct hdac_bus *bus) { return NULL; } static inline struct hdac_ext_link * hdac_bus_eml_dmic_get_hlink(struct hdac_bus *bus) { return NULL; } +static inline int +hdac_bus_eml_enable_offload(struct hdac_bus *bus, bool alt, int elid, bool enable) +{ + return 0; +} #endif /* CONFIG_SND_SOC_SOF_HDA */ diff --git a/sound/soc/sof/intel/hda-mlink.c b/sound/soc/sof/intel/hda-mlink.c index 06613c081410..b9ce07c38bb5 100644 --- a/sound/soc/sof/intel/hda-mlink.c +++ b/sound/soc/sof/intel/hda-mlink.c @@ -333,6 +333,18 @@ static void hdaml_link_set_lsdiid(u32 __iomem *lsdiid, int dev_num) writel(val, lsdiid); } +static void hdaml_lctl_offload_enable(u32 __iomem *lctl, bool enable) +{ + u32 val = readl(lctl); + + if (enable) + val |= AZX_ML_LCTL_OFLEN; + else + val &= ~AZX_ML_LCTL_OFLEN; + + writel(val, lctl); +} + /* END HDAML section */ static int hda_ml_alloc_h2link(struct hdac_bus *bus, int index) @@ -812,6 +824,30 @@ struct hdac_ext_link *hdac_bus_eml_dmic_get_hlink(struct hdac_bus *bus) } EXPORT_SYMBOL_NS(hdac_bus_eml_dmic_get_hlink, SND_SOC_SOF_HDA_MLINK); +int hdac_bus_eml_enable_offload(struct hdac_bus *bus, bool alt, int elid, bool enable) +{ + struct hdac_ext2_link *h2link; + struct hdac_ext_link *hlink; + + h2link = find_ext2_link(bus, alt, elid); + if (!h2link) + return -ENODEV; + + if (!h2link->ofls) + return 0; + + hlink = &h2link->hext_link; + + mutex_lock(&h2link->eml_lock); + + hdaml_lctl_offload_enable(hlink->ml_addr + AZX_REG_ML_LCTL, enable); + + mutex_unlock(&h2link->eml_lock); + + return 0; +} +EXPORT_SYMBOL_NS(hdac_bus_eml_enable_offload, SND_SOC_SOF_HDA_MLINK); + #endif MODULE_LICENSE("Dual BSD/GPL"); From 681f27f302ff85ddf3f6e7fd0231059f99c0f26e Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 4 Apr 2023 13:41:27 +0300 Subject: [PATCH 707/778] ASoC: SOF: Intel: hda-mlink: add helper to retrieve eml_lock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For SoundWire usages, we need to use the global eml_lock to serialize/protect all accesses to shared registers. Due to the split implementation across two subsystems, we need to pass a pointer around. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Péter Ujfalusi Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Reviewed-by: Takashi Iwai Link: https://lore.kernel.org/r/20230404104127.5629-19-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- include/sound/hda-mlink.h | 5 +++++ sound/soc/sof/intel/hda-mlink.c | 12 ++++++++++++ 2 files changed, 17 insertions(+) diff --git a/include/sound/hda-mlink.h b/include/sound/hda-mlink.h index fee42c432fa3..dbc47af08135 100644 --- a/include/sound/hda-mlink.h +++ b/include/sound/hda-mlink.h @@ -52,6 +52,8 @@ int hda_bus_ml_suspend(struct hdac_bus *bus); struct hdac_ext_link *hdac_bus_eml_ssp_get_hlink(struct hdac_bus *bus); struct hdac_ext_link *hdac_bus_eml_dmic_get_hlink(struct hdac_bus *bus); +struct mutex *hdac_bus_eml_get_mutex(struct hdac_bus *bus, bool alt, int elid); + int hdac_bus_eml_enable_offload(struct hdac_bus *bus, bool alt, int elid, bool enable); #else @@ -153,6 +155,9 @@ hdac_bus_eml_ssp_get_hlink(struct hdac_bus *bus) { return NULL; } static inline struct hdac_ext_link * hdac_bus_eml_dmic_get_hlink(struct hdac_bus *bus) { return NULL; } +static inline struct mutex * +hdac_bus_eml_get_mutex(struct hdac_bus *bus, bool alt, int elid) { return NULL; } + static inline int hdac_bus_eml_enable_offload(struct hdac_bus *bus, bool alt, int elid, bool enable) { diff --git a/sound/soc/sof/intel/hda-mlink.c b/sound/soc/sof/intel/hda-mlink.c index b9ce07c38bb5..775582ab7494 100644 --- a/sound/soc/sof/intel/hda-mlink.c +++ b/sound/soc/sof/intel/hda-mlink.c @@ -800,6 +800,18 @@ int hda_bus_ml_suspend(struct hdac_bus *bus) } EXPORT_SYMBOL_NS(hda_bus_ml_suspend, SND_SOC_SOF_HDA_MLINK); +struct mutex *hdac_bus_eml_get_mutex(struct hdac_bus *bus, bool alt, int elid) +{ + struct hdac_ext2_link *h2link; + + h2link = find_ext2_link(bus, alt, elid); + if (!h2link) + return NULL; + + return &h2link->eml_lock; +} +EXPORT_SYMBOL_NS(hdac_bus_eml_get_mutex, SND_SOC_SOF_HDA_MLINK); + struct hdac_ext_link *hdac_bus_eml_ssp_get_hlink(struct hdac_bus *bus) { struct hdac_ext2_link *h2link; From a7fe7e24b2cddbe995b5b49e274d3a69dde7c7d9 Mon Sep 17 00:00:00 2001 From: Curtis Malainey Date: Thu, 6 Apr 2023 10:37:02 -0500 Subject: [PATCH 708/778] ASoC: Intel: Add rpl_mx98360_rt5682 driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Boards were using this in older kernels before adl and rpl ids were split. Add this back to maintain support. Signed-off-by: Curtis Malainey Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Bard Liao Link: https://lore.kernel.org/r/20230406153703.17194-1-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_rt5682.c | 11 +++++++++++ .../soc/intel/common/soc-acpi-intel-rpl-match.c | 17 +++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index 8735519cf4ed..791a59c5f00d 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -1116,6 +1116,17 @@ static const struct platform_device_id board_ids[] = { SOF_BT_OFFLOAD_SSP(2) | SOF_SSP_BT_OFFLOAD_PRESENT), }, + { + .name = "rpl_mx98360_rt5682", + .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | + SOF_RT5682_SSP_CODEC(0) | + SOF_SPEAKER_AMP_PRESENT | + SOF_MAX98360A_SPEAKER_AMP_PRESENT | + SOF_RT5682_SSP_AMP(1) | + SOF_RT5682_NUM_HDMIDEV(4) | + SOF_BT_OFFLOAD_SSP(2) | + SOF_SSP_BT_OFFLOAD_PRESENT), + }, { .name = "mtl_mx98357_rt5682", .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | diff --git a/sound/soc/intel/common/soc-acpi-intel-rpl-match.c b/sound/soc/intel/common/soc-acpi-intel-rpl-match.c index 07f96a11ea2f..13cbd8e9d41f 100644 --- a/sound/soc/intel/common/soc-acpi-intel-rpl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-rpl-match.c @@ -284,7 +284,24 @@ static const struct snd_soc_acpi_link_adr rpl_sdw_rt1316_link12_rt714_link0[] = {} }; +static const struct snd_soc_acpi_codecs rpl_rt5682_hp = { + .num_codecs = 2, + .codecs = {"10EC5682", "RTL5682"}, +}; + +static const struct snd_soc_acpi_codecs rpl_max98360a_amp = { + .num_codecs = 1, + .codecs = {"MX98360A"}, +}; + struct snd_soc_acpi_mach snd_soc_acpi_intel_rpl_machines[] = { + { + .comp_ids = &rpl_rt5682_hp, + .drv_name = "rpl_mx98360_rt5682", + .machine_quirk = snd_soc_acpi_codec_list, + .quirk_data = &rpl_max98360a_amp, + .sof_tplg_filename = "sof-rpl-max98360a-rt5682.tplg", + }, {}, }; EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_rpl_machines); From f747eb86e4a82d0823328f642a667bffce703028 Mon Sep 17 00:00:00 2001 From: Yong Zhi Date: Thu, 6 Apr 2023 10:44:54 -0500 Subject: [PATCH 709/778] ASoC: SOF: Intel: MTL: conditionally wake WPIO1PG domain MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Wake IO1 from power gating if there is SoundWire enabled link discovered by ACPI scan. Signed-off-by: Yong Zhi Signed-off-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Péter Ujfalusi Link: https://lore.kernel.org/r/20230406154454.18163-1-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/mtl.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/sound/soc/sof/intel/mtl.c b/sound/soc/sof/intel/mtl.c index 58959c24cb71..882ce5536ab6 100644 --- a/sound/soc/sof/intel/mtl.c +++ b/sound/soc/sof/intel/mtl.c @@ -217,6 +217,7 @@ static int mtl_enable_interrupts(struct snd_sof_dev *sdev, bool enable) /* pre fw run operations */ static int mtl_dsp_pre_fw_run(struct snd_sof_dev *sdev) { + struct sof_intel_hda_dev *hdev = sdev->pdata->hw_pdata; u32 dsphfpwrsts; u32 dsphfdsscs; u32 cpa; @@ -255,9 +256,11 @@ static int mtl_dsp_pre_fw_run(struct snd_sof_dev *sdev) if (ret < 0) dev_err(sdev->dev, "failed to power up gated DSP domain\n"); - /* make sure SoundWire is not power-gated */ - snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_HFPWRCTL, - MTL_HfPWRCTL_WPIOXPG(1), MTL_HfPWRCTL_WPIOXPG(1)); + /* if SoundWire is used, make sure it is not power-gated */ + if (hdev->info.handle && hdev->info.link_mask > 0) + snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_HFPWRCTL, + MTL_HfPWRCTL_WPIOXPG(1), MTL_HfPWRCTL_WPIOXPG(1)); + return ret; } From ef736f30548951870e2a5bfc41b6b0bb1d455641 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 6 Apr 2023 10:52:19 -0500 Subject: [PATCH 710/778] ASoC: SOF: Intel: hda-dai: Print the format_val as hexadecimal number The format_val is a set of bitfileds, printing it as a decimal just makes interpreting it complicated. In other HDA core code the format_val is printed as hexadecimal also. Signed-off-by: Peter Ujfalusi Signed-off-by: Pierre-Louis Bossart Reviewed-by: Kai Vehmanen Reviewed-by: Jaska Uimonen Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20230406155219.18997-1-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index 0435b7f251aa..44a5d94c5050 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -177,8 +177,8 @@ static int hda_link_dma_hw_params(struct snd_pcm_substream *substream, format_val = snd_hdac_calc_stream_format(params_rate(params), params_channels(params), params_format(params), link_bps, 0); - dev_dbg(bus->dev, "format_val=%d, rate=%d, ch=%d, format=%d\n", - format_val, params_rate(params), params_channels(params), params_format(params)); + dev_dbg(bus->dev, "format_val=%#x, rate=%d, ch=%d, format=%d\n", format_val, + params_rate(params), params_channels(params), params_format(params)); if (ops->setup_hext_stream) ops->setup_hext_stream(sdev, hext_stream, format_val); From 672029caa5708934817a331f3323bbe48d456c5c Mon Sep 17 00:00:00 2001 From: Tom Rix Date: Fri, 7 Apr 2023 07:55:53 -0400 Subject: [PATCH 711/778] ASoC: mediatek: mt8186: set variable aud_pinctrl to static smatch reports sound/soc/mediatek/mt8186/mt8186-afe-gpio.c:14:16: warning: symbol 'aud_pinctrl' was not declared. Should it be static? This variable is only used in one file so should be static. Signed-off-by: Tom Rix Link: https://lore.kernel.org/r/20230407115553.1968111-1-trix@redhat.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8186/mt8186-afe-gpio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/mediatek/mt8186/mt8186-afe-gpio.c b/sound/soc/mediatek/mt8186/mt8186-afe-gpio.c index 20b9f5d810ec..f12e91cc4fcf 100644 --- a/sound/soc/mediatek/mt8186/mt8186-afe-gpio.c +++ b/sound/soc/mediatek/mt8186/mt8186-afe-gpio.c @@ -11,7 +11,7 @@ #include "mt8186-afe-common.h" #include "mt8186-afe-gpio.h" -struct pinctrl *aud_pinctrl; +static struct pinctrl *aud_pinctrl; enum mt8186_afe_gpio { MT8186_AFE_GPIO_CLK_MOSI_OFF, From be5418dfc1460e82a005dfb9dd76e4ef846c203d Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 7 Apr 2023 19:00:32 +0200 Subject: [PATCH 712/778] ASoC: dt-bindings: asahi-kasei,ak4458: fix missing quotes around hash The yamllint expect comments to start with hash and space ('# '), so quote the description to fix: asahi-kasei,ak4458.yaml:40:30: [error] missing starting space in comment (comments) Reported-by: Rob Herring Closes: https://lore.kernel.org/all/CAL_JsqJzxQb1g=yVgHduLnYOpk8-Q3jppA1qQT1Ce51_gNWjhg@mail.gmail.com/ Fixes: 009e83b591dd ("ASoC: dt-bindings: ak4458: Convert to dtschema") Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230407170032.102412-1-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/asahi-kasei,ak4458.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/asahi-kasei,ak4458.yaml b/Documentation/devicetree/bindings/sound/asahi-kasei,ak4458.yaml index 0db0c8e923a0..4477f84b7acc 100644 --- a/Documentation/devicetree/bindings/sound/asahi-kasei,ak4458.yaml +++ b/Documentation/devicetree/bindings/sound/asahi-kasei,ak4458.yaml @@ -37,9 +37,9 @@ properties: $ref: /schemas/types.yaml#/definitions/uint32 oneOf: - const: 0 - description: select #16, #17, #19 pins + description: "select #16, #17, #19 pins" - const: 1 - description: select #3, #4, #5 pins + description: "select #3, #4, #5 pins" required: - compatible From 80f47122538d40b1a6a2c1a3c2d37b6e51b74224 Mon Sep 17 00:00:00 2001 From: Alexander Sverdlin Date: Tue, 11 Apr 2023 00:39:00 +0200 Subject: [PATCH 713/778] ASoC: ep93xx: i2s: move enable call to startup callback Make startup/shutdown callbacks symmetric to avoid clock subsystem warnings (reproduced with "aplay --dump-hw-params" + ctrl-c): WARNING: CPU: 0 PID: 102 at drivers/clk/clk.c:1048 clk_core_disable lrclk already disabled CPU: 0 PID: 102 Comm: aplay Not tainted 6.2.0-rc4 #1 Hardware name: Generic DT based system ... clk_core_disable from clk_core_disable_lock clk_core_disable_lock from ep93xx_i2s_shutdown ep93xx_i2s_shutdown from snd_soc_dai_shutdown snd_soc_dai_shutdown from soc_pcm_clean soc_pcm_clean from soc_pcm_close soc_pcm_close from snd_pcm_release_substream.part.0 snd_pcm_release_substream.part.0 from snd_pcm_release snd_pcm_release from __fput __fput from task_work_run ... WARNING: CPU: 0 PID: 102 at drivers/clk/clk.c:907 clk_core_unprepare lrclk already unprepared CPU: 0 PID: 102 Comm: aplay Tainted: G W 6.2.0-rc4 #1 Hardware name: Generic DT based system ... clk_core_unprepare from clk_unprepare clk_unprepare from ep93xx_i2s_shutdown ep93xx_i2s_shutdown from snd_soc_dai_shutdown snd_soc_dai_shutdown from soc_pcm_clean soc_pcm_clean from soc_pcm_close soc_pcm_close from snd_pcm_release_substream.part.0 snd_pcm_release_substream.part.0 from snd_pcm_release snd_pcm_release from __fput __fput from task_work_run ... Signed-off-by: Alexander Sverdlin Link: https://lore.kernel.org/r/20230410223902.2321834-2-alexander.sverdlin@gmail.com Signed-off-by: Mark Brown --- sound/soc/cirrus/ep93xx-i2s.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/sound/soc/cirrus/ep93xx-i2s.c b/sound/soc/cirrus/ep93xx-i2s.c index 9760453d9d79..2abd1bce2290 100644 --- a/sound/soc/cirrus/ep93xx-i2s.c +++ b/sound/soc/cirrus/ep93xx-i2s.c @@ -208,6 +208,16 @@ static int ep93xx_i2s_dai_probe(struct snd_soc_dai *dai) return 0; } +static int ep93xx_i2s_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai); + + ep93xx_i2s_enable(info, substream->stream); + + return 0; +} + static void ep93xx_i2s_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { @@ -348,7 +358,6 @@ static int ep93xx_i2s_hw_params(struct snd_pcm_substream *substream, if (err) return err; - ep93xx_i2s_enable(info, substream->stream); return 0; } @@ -397,6 +406,7 @@ static int ep93xx_i2s_resume(struct snd_soc_component *component) #endif static const struct snd_soc_dai_ops ep93xx_i2s_dai_ops = { + .startup = ep93xx_i2s_startup, .shutdown = ep93xx_i2s_shutdown, .hw_params = ep93xx_i2s_hw_params, .set_sysclk = ep93xx_i2s_set_sysclk, From 2e9688c81cfc48b210af6f313cb04589b7943e86 Mon Sep 17 00:00:00 2001 From: Alexander Sverdlin Date: Tue, 11 Apr 2023 00:39:01 +0200 Subject: [PATCH 714/778] ASoC: cs4271: flat regcache, trivial simplifications - Switch to REGCACHE_FLAT, the whole overhead of RBTREE is not worth it with non sparse register set in the address range 1..7. - Move register width to central location Signed-off-by: Alexander Sverdlin Link: https://lore.kernel.org/r/20230410223902.2321834-3-alexander.sverdlin@gmail.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs4271-i2c.c | 1 - sound/soc/codecs/cs4271-spi.c | 1 - sound/soc/codecs/cs4271.c | 4 ++-- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/cs4271-i2c.c b/sound/soc/codecs/cs4271-i2c.c index 0e8a7cf0da50..4033be1c3bc1 100644 --- a/sound/soc/codecs/cs4271-i2c.c +++ b/sound/soc/codecs/cs4271-i2c.c @@ -17,7 +17,6 @@ static int cs4271_i2c_probe(struct i2c_client *client) config = cs4271_regmap_config; config.reg_bits = 8; - config.val_bits = 8; return cs4271_probe(&client->dev, devm_regmap_init_i2c(client, &config)); diff --git a/sound/soc/codecs/cs4271-spi.c b/sound/soc/codecs/cs4271-spi.c index 7ef0a66b7778..4feb80436bd9 100644 --- a/sound/soc/codecs/cs4271-spi.c +++ b/sound/soc/codecs/cs4271-spi.c @@ -17,7 +17,6 @@ static int cs4271_spi_probe(struct spi_device *spi) config = cs4271_regmap_config; config.reg_bits = 16; - config.val_bits = 8; config.read_flag_mask = 0x21; config.write_flag_mask = 0x20; diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c index 2021cf442606..188b8b43c524 100644 --- a/sound/soc/codecs/cs4271.c +++ b/sound/soc/codecs/cs4271.c @@ -689,8 +689,8 @@ const struct regmap_config cs4271_regmap_config = { .reg_defaults = cs4271_reg_defaults, .num_reg_defaults = ARRAY_SIZE(cs4271_reg_defaults), - .cache_type = REGCACHE_RBTREE, - + .cache_type = REGCACHE_FLAT, + .val_bits = 8, .volatile_reg = cs4271_volatile_reg, }; EXPORT_SYMBOL_GPL(cs4271_regmap_config); From 24f934becf60598fdec9c9f2e06437c831ffa374 Mon Sep 17 00:00:00 2001 From: Alexander Sverdlin Date: Tue, 11 Apr 2023 00:39:02 +0200 Subject: [PATCH 715/778] ASoC: ep93xx: i2s: Make it individually selectable This is necessary to replace EDB93XX specific SoC audio driver with generic "simple-audio-card". Signed-off-by: Alexander Sverdlin Link: https://lore.kernel.org/r/20230410223902.2321834-4-alexander.sverdlin@gmail.com Signed-off-by: Mark Brown --- sound/soc/cirrus/Kconfig | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sound/soc/cirrus/Kconfig b/sound/soc/cirrus/Kconfig index 34870c2d0cba..38a83c4dcc2d 100644 --- a/sound/soc/cirrus/Kconfig +++ b/sound/soc/cirrus/Kconfig @@ -8,7 +8,11 @@ config SND_EP93XX_SOC the EP93xx I2S or AC97 interfaces. config SND_EP93XX_SOC_I2S - tristate + tristate "I2S controller support for the Cirrus Logic EP93xx series" + depends on SND_EP93XX_SOC + help + Say Y or M if you want to add support for codecs attached to + the EP93xx I2S interface. if SND_EP93XX_SOC_I2S From faf15233e59052f4d61cad2da6e56daf33124d96 Mon Sep 17 00:00:00 2001 From: Cem Kaya Date: Mon, 10 Apr 2023 20:38:15 +0200 Subject: [PATCH 716/778] ASoC: amd: Add Dell G15 5525 to quirks list Add Dell G15 5525 Ryzen Edition to quirks list for acp6x so that internal mic works. Link: https://bugzilla.kernel.org/show_bug.cgi?id=217155 Signed-off-by: Cem Kaya Link: https://lore.kernel.org/r/20230410183814.260518-1-cemkaya.boun@gmail.com Signed-off-by: Mark Brown --- sound/soc/amd/yc/acp6x-mach.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sound/soc/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c index a428e17f0325..1d59163a882c 100644 --- a/sound/soc/amd/yc/acp6x-mach.c +++ b/sound/soc/amd/yc/acp6x-mach.c @@ -45,6 +45,13 @@ static struct snd_soc_card acp6x_card = { }; static const struct dmi_system_id yc_acp_quirk_table[] = { + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Dell G15 5525"), + } + }, { .driver_data = &acp6x_card, .matches = { From beed115c2ce78f990222a29abed042582df4e87c Mon Sep 17 00:00:00 2001 From: Aashish Sharma Date: Tue, 11 Apr 2023 06:04:31 +0530 Subject: [PATCH 717/778] ASoC: mediatek: common: Fix refcount leak in parse_dai_link_info Add missing of_node_put()s before the returns to balance of_node_get()s and of_node_put()s, which may get unbalanced in case the for loop 'for_each_available_child_of_node' returns early. Fixes: 4302187d955f ("ASoC: mediatek: common: add soundcard driver common code") Reported-by: kernel test robot Reported-by: Julia Lawall Link: https://lore.kernel.org/r/202304090504.2K8L6soj-lkp@intel.com/ Signed-off-by: Aashish Sharma Reviewed-by: Guenter Roeck Reviewed-by: Trevor Wu Link: https://lore.kernel.org/r/20230411003431.4048700-1-shraash@google.com Signed-off-by: Mark Brown --- sound/soc/mediatek/common/mtk-soundcard-driver.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/sound/soc/mediatek/common/mtk-soundcard-driver.c b/sound/soc/mediatek/common/mtk-soundcard-driver.c index 7c55c2cb1f21..738093451ccb 100644 --- a/sound/soc/mediatek/common/mtk-soundcard-driver.c +++ b/sound/soc/mediatek/common/mtk-soundcard-driver.c @@ -47,20 +47,26 @@ int parse_dai_link_info(struct snd_soc_card *card) /* Loop over all the dai link sub nodes */ for_each_available_child_of_node(dev->of_node, sub_node) { if (of_property_read_string(sub_node, "link-name", - &dai_link_name)) + &dai_link_name)) { + of_node_put(sub_node); return -EINVAL; + } for_each_card_prelinks(card, i, dai_link) { if (!strcmp(dai_link_name, dai_link->name)) break; } - if (i >= card->num_links) + if (i >= card->num_links) { + of_node_put(sub_node); return -EINVAL; + } ret = set_card_codec_info(card, sub_node, dai_link); - if (ret < 0) + if (ret < 0) { + of_node_put(sub_node); return ret; + } } return 0; From 48edd3d1670f4fe749df7a1dd8c1df89882f4c60 Mon Sep 17 00:00:00 2001 From: Saalim Quadri Date: Thu, 6 Apr 2023 02:20:25 +0530 Subject: [PATCH 718/778] ASoC: dt-bindings: wm8580: Convert to dtschema Convert the WM8580 and WM8581 audio CODEC bindings to DT schema Signed-off-by: Saalim Quadri Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230405205025.6448-1-danascape@gmail.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/wlf,wm8580.yaml | 42 +++++++++++++++++++ .../devicetree/bindings/sound/wm8580.txt | 16 ------- 2 files changed, 42 insertions(+), 16 deletions(-) create mode 100644 Documentation/devicetree/bindings/sound/wlf,wm8580.yaml delete mode 100644 Documentation/devicetree/bindings/sound/wm8580.txt diff --git a/Documentation/devicetree/bindings/sound/wlf,wm8580.yaml b/Documentation/devicetree/bindings/sound/wlf,wm8580.yaml new file mode 100644 index 000000000000..2f27852cdc20 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/wlf,wm8580.yaml @@ -0,0 +1,42 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/wlf,wm8580.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: WM8580 and WM8581 audio CODEC + +maintainers: + - patches@opensource.cirrus.com + +allOf: + - $ref: dai-common.yaml# + +properties: + compatible: + enum: + - wlf,wm8580 + - wlf,wm8581 + + reg: + maxItems: 1 + + "#sound-dai-cells": + const: 0 + +required: + - compatible + - reg + +unevaluatedProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + codec@1a { + compatible = "wlf,wm8580"; + reg = <0x1a>; + }; + }; diff --git a/Documentation/devicetree/bindings/sound/wm8580.txt b/Documentation/devicetree/bindings/sound/wm8580.txt deleted file mode 100644 index ff3f9f5f2111..000000000000 --- a/Documentation/devicetree/bindings/sound/wm8580.txt +++ /dev/null @@ -1,16 +0,0 @@ -WM8580 and WM8581 audio CODEC - -This device supports I2C only. - -Required properties: - - - compatible : "wlf,wm8580", "wlf,wm8581" - - - reg : the I2C address of the device. - -Example: - -wm8580: codec@1a { - compatible = "wlf,wm8580"; - reg = <0x1a>; -}; From 25500613de4a867d16068b28faa963cd3ce0a11a Mon Sep 17 00:00:00 2001 From: Saalim Quadri Date: Thu, 6 Apr 2023 02:28:20 +0530 Subject: [PATCH 719/778] ASoC: dt-bindings: wm8711: Convert to dtschema Convert the WM8711 audio CODEC bindings to DT schema Signed-off-by: Saalim Quadri Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230405205820.6836-1-danascape@gmail.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/wlf,wm8711.yaml | 40 +++++++++++++++++++ .../devicetree/bindings/sound/wm8711.txt | 18 --------- 2 files changed, 40 insertions(+), 18 deletions(-) create mode 100644 Documentation/devicetree/bindings/sound/wlf,wm8711.yaml delete mode 100644 Documentation/devicetree/bindings/sound/wm8711.txt diff --git a/Documentation/devicetree/bindings/sound/wlf,wm8711.yaml b/Documentation/devicetree/bindings/sound/wlf,wm8711.yaml new file mode 100644 index 000000000000..ecaac2818b44 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/wlf,wm8711.yaml @@ -0,0 +1,40 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/wlf,wm8711.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: WM8711 audio CODEC + +maintainers: + - patches@opensource.cirrus.com + +allOf: + - $ref: dai-common.yaml# + +properties: + compatible: + const: wlf,wm8711 + + reg: + maxItems: 1 + + "#sound-dai-cells": + const: 0 + +required: + - compatible + - reg + +unevaluatedProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + codec@1a { + compatible = "wlf,wm8711"; + reg = <0x1a>; + }; + }; diff --git a/Documentation/devicetree/bindings/sound/wm8711.txt b/Documentation/devicetree/bindings/sound/wm8711.txt deleted file mode 100644 index c30a1387c4bf..000000000000 --- a/Documentation/devicetree/bindings/sound/wm8711.txt +++ /dev/null @@ -1,18 +0,0 @@ -WM8711 audio CODEC - -This device supports both I2C and SPI (configured with pin strapping -on the board). - -Required properties: - - - compatible : "wlf,wm8711" - - - reg : the I2C address of the device for I2C, the chip select - number for SPI. - -Example: - -wm8711: codec@1a { - compatible = "wlf,wm8711"; - reg = <0x1a>; -}; From 3e5f79723dc3f22fed30ba5a559db11b53b632ae Mon Sep 17 00:00:00 2001 From: Saalim Quadri Date: Thu, 6 Apr 2023 02:04:19 +0530 Subject: [PATCH 720/778] ASoC: dt-bindings: wm8523: Convert to dtschema Convert the WM8523 audio CODEC bindings to DT schema Signed-off-by: Saalim Quadri Link: https://lore.kernel.org/r/20230405203419.5621-1-danascape@gmail.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/wlf,wm8523.yaml | 40 +++++++++++++++++++ .../devicetree/bindings/sound/wm8523.txt | 16 -------- 2 files changed, 40 insertions(+), 16 deletions(-) create mode 100644 Documentation/devicetree/bindings/sound/wlf,wm8523.yaml delete mode 100644 Documentation/devicetree/bindings/sound/wm8523.txt diff --git a/Documentation/devicetree/bindings/sound/wlf,wm8523.yaml b/Documentation/devicetree/bindings/sound/wlf,wm8523.yaml new file mode 100644 index 000000000000..decc395bb873 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/wlf,wm8523.yaml @@ -0,0 +1,40 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/wlf,wm8523.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: WM8523 audio CODEC + +maintainers: + - patches@opensource.cirrus.com + +allOf: + - $ref: dai-common.yaml# + +properties: + compatible: + const: wlf,wm8523 + + reg: + maxItems: 1 + + "#sound-dai-cells": + const: 0 + +required: + - compatible + - reg + +unevaluatedProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + codec@1a { + compatible = "wlf,wm8523"; + reg = <0x1a>; + }; + }; diff --git a/Documentation/devicetree/bindings/sound/wm8523.txt b/Documentation/devicetree/bindings/sound/wm8523.txt deleted file mode 100644 index f3a6485f4b8a..000000000000 --- a/Documentation/devicetree/bindings/sound/wm8523.txt +++ /dev/null @@ -1,16 +0,0 @@ -WM8523 audio CODEC - -This device supports I2C only. - -Required properties: - - - compatible : "wlf,wm8523" - - - reg : the I2C address of the device. - -Example: - -wm8523: codec@1a { - compatible = "wlf,wm8523"; - reg = <0x1a>; -}; From a8f5da0bf4d85a6ad03810d902aba61c572102a6 Mon Sep 17 00:00:00 2001 From: Baishan Jiang Date: Wed, 12 Apr 2023 16:40:43 +0800 Subject: [PATCH 721/778] ASoC: amd: yc: Add ThinkBook 14 G5+ ARP to quirks list for acp6x ThinkBook 14 G5+ ARP uses Ryzen 7735H processor, and has the same microphone problem as ThinkBook 14 G4+ ARA. Adding 21HY to acp6x quirks table enables microphone for ThinkBook 14 G5+ ARP. Signed-off-by: Baishan Jiang Link: https://lore.kernel.org/r/OS3P286MB1711DD6556284B69C79C0C4FE19B9@OS3P286MB1711.JPNP286.PROD.OUTLOOK.COM Signed-off-by: Mark Brown --- sound/soc/amd/yc/acp6x-mach.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sound/soc/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c index 1d59163a882c..b9958e555367 100644 --- a/sound/soc/amd/yc/acp6x-mach.c +++ b/sound/soc/amd/yc/acp6x-mach.c @@ -185,6 +185,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "21EN"), } }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "21HY"), + } + }, { .driver_data = &acp6x_card, .matches = { From ef0128afa1655f8d024dc5058fbfa0c6deecf117 Mon Sep 17 00:00:00 2001 From: Fred Oh Date: Wed, 12 Apr 2023 09:14:57 +0300 Subject: [PATCH 722/778] ASoC: SOF: Intel: mtl: fix page fault in dspless mode when DSP is disabled The patch to make DSPless mode work even if the DSP is disabled in BIOS missed to touch the MTL code to add the needed checks. If the DSP is disabled this can lead to page fault due to not accesible registers. Fixes: 9fc6786f549c ("ASoC: SOF: Intel: hda: make DSPless mode work with DSP disabled in BIOS") Signed-off-by: Fred Oh Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230412061457.27937-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/mtl.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/sound/soc/sof/intel/mtl.c b/sound/soc/sof/intel/mtl.c index 882ce5536ab6..9f969e07fc27 100644 --- a/sound/soc/sof/intel/mtl.c +++ b/sound/soc/sof/intel/mtl.c @@ -60,6 +60,9 @@ static bool mtl_dsp_check_ipc_irq(struct snd_sof_dev *sdev) u32 irq_status; u32 hfintipptr; + if (sdev->dspless_mode_selected) + return false; + /* read Interrupt IP Pointer */ hfintipptr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_HFINTIPPTR) & MTL_HFINTIPPTR_PTR_MASK; irq_status = snd_sof_dsp_read(sdev, HDA_DSP_BAR, hfintipptr + MTL_DSP_IRQSTS); @@ -120,6 +123,9 @@ static void mtl_enable_ipc_interrupts(struct snd_sof_dev *sdev) struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; const struct sof_intel_dsp_desc *chip = hda->desc; + if (sdev->dspless_mode_selected) + return; + /* enable IPC DONE and BUSY interrupts */ snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, chip->ipc_ctl, MTL_DSP_REG_HFIPCXCTL_BUSY | MTL_DSP_REG_HFIPCXCTL_DONE, @@ -131,6 +137,9 @@ static void mtl_disable_ipc_interrupts(struct snd_sof_dev *sdev) struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; const struct sof_intel_dsp_desc *chip = hda->desc; + if (sdev->dspless_mode_selected) + return; + /* disable IPC DONE and BUSY interrupts */ snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, chip->ipc_ctl, MTL_DSP_REG_HFIPCXCTL_BUSY | MTL_DSP_REG_HFIPCXCTL_DONE, 0); @@ -143,6 +152,9 @@ static void mtl_enable_sdw_irq(struct snd_sof_dev *sdev, bool enable) u32 val; int ret; + if (sdev->dspless_mode_selected) + return; + /* Enable/Disable SoundWire interrupt */ mask = MTL_DSP_REG_HfSNDWIE_IE_MASK; if (enable) @@ -170,6 +182,9 @@ static int mtl_enable_interrupts(struct snd_sof_dev *sdev, bool enable) u32 val; int ret; + if (sdev->dspless_mode_selected) + return 0; + /* read Interrupt IP Pointer */ hfintipptr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_HFINTIPPTR) & MTL_HFINTIPPTR_PTR_MASK; From d93ee84e3eb5d1afc081e57ca37f1411a01f2c94 Mon Sep 17 00:00:00 2001 From: Ying Liu Date: Wed, 12 Apr 2023 01:09:12 +0800 Subject: [PATCH 723/778] ASoC: tas5720: add missing unwind goto in tas5720_codec_probe Smatch complains that missing unwind goto in tas5720_codec_probe. When tas5720 has an invalid devtype, it is expected to invoke regulator_bulk_disable to handle the failure. But the default option return an error code directly. Fix it by reusing the probe_fail label. Signed-off-by: Ying Liu Link: https://lore.kernel.org/r/20230411170912.1939906-1-lyre@hust.edu.cn Signed-off-by: Mark Brown --- sound/soc/codecs/tas5720.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/tas5720.c b/sound/soc/codecs/tas5720.c index de6d01c8fdd3..4d27b60bd804 100644 --- a/sound/soc/codecs/tas5720.c +++ b/sound/soc/codecs/tas5720.c @@ -339,7 +339,8 @@ static int tas5720_codec_probe(struct snd_soc_component *component) break; default: dev_err(component->dev, "unexpected private driver data\n"); - return -EINVAL; + ret = -EINVAL; + goto probe_fail; } if (device_id != expected_device_id) From bddcfb0802eb69b0f51293eab5db33d344c0262f Mon Sep 17 00:00:00 2001 From: Syed Saba Kareem Date: Wed, 12 Apr 2023 14:46:16 +0530 Subject: [PATCH 724/778] ASoC: amd: Add check for acp config flags We have SOF and generic ACP support enabled for Rembrandt and pheonix platforms on some machines. Since we have same PCI id used for probing, add check for machine configuration flag to avoid conflict with newer pci drivers. Such machine flag has been initialized via dmi match on few Chrome machines. If no flag is specified probe and register older platform device. Signed-off-by: Syed Saba Kareem Reviewed-by: Vijendar Mukunda Link: https://lore.kernel.org/r/20230412091638.1158901-1-Syed.SabaKareem@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/Kconfig | 2 ++ sound/soc/amd/ps/acp63.h | 2 ++ sound/soc/amd/ps/pci-ps.c | 8 +++++++- sound/soc/amd/yc/acp6x.h | 3 +++ sound/soc/amd/yc/pci-acp6x.c | 8 +++++++- 5 files changed, 21 insertions(+), 2 deletions(-) diff --git a/sound/soc/amd/Kconfig b/sound/soc/amd/Kconfig index c88ebd84bdd5..08e42082f5e9 100644 --- a/sound/soc/amd/Kconfig +++ b/sound/soc/amd/Kconfig @@ -90,6 +90,7 @@ config SND_SOC_AMD_VANGOGH_MACH config SND_SOC_AMD_ACP6x tristate "AMD Audio Coprocessor-v6.x Yellow Carp support" + select SND_AMD_ACP_CONFIG depends on X86 && PCI help This option enables Audio Coprocessor i.e ACP v6.x support on @@ -130,6 +131,7 @@ config SND_SOC_AMD_RPL_ACP6x config SND_SOC_AMD_PS tristate "AMD Audio Coprocessor-v6.3 Pink Sardine support" + select SND_AMD_ACP_CONFIG depends on X86 && PCI && ACPI help This option enables Audio Coprocessor i.e ACP v6.3 support on diff --git a/sound/soc/amd/ps/acp63.h b/sound/soc/amd/ps/acp63.h index 6bf29b520511..dd36790b25ae 100644 --- a/sound/soc/amd/ps/acp63.h +++ b/sound/soc/amd/ps/acp63.h @@ -111,3 +111,5 @@ struct acp63_dev_data { u16 pdev_count; u16 pdm_dev_index; }; + +int snd_amd_acp_find_config(struct pci_dev *pci); diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c index 688a1d4643d9..afddb9a77ba4 100644 --- a/sound/soc/amd/ps/pci-ps.c +++ b/sound/soc/amd/ps/pci-ps.c @@ -247,11 +247,17 @@ static int snd_acp63_probe(struct pci_dev *pci, { struct acp63_dev_data *adata; u32 addr; - u32 irqflags; + u32 irqflags, flag; int val; int ret; irqflags = IRQF_SHARED; + + /* Return if acp config flag is defined */ + flag = snd_amd_acp_find_config(pci); + if (flag) + return -ENODEV; + /* Pink Sardine device check */ switch (pci->revision) { case 0x63: diff --git a/sound/soc/amd/yc/acp6x.h b/sound/soc/amd/yc/acp6x.h index 036207568c04..2de7d1edf00b 100644 --- a/sound/soc/amd/yc/acp6x.h +++ b/sound/soc/amd/yc/acp6x.h @@ -105,3 +105,6 @@ static inline void acp6x_writel(u32 val, void __iomem *base_addr) { writel(val, base_addr - ACP6x_PHY_BASE_ADDRESS); } + +int snd_amd_acp_find_config(struct pci_dev *pci); + diff --git a/sound/soc/amd/yc/pci-acp6x.c b/sound/soc/amd/yc/pci-acp6x.c index 77c5fa1f7af1..7af6a349b1d4 100644 --- a/sound/soc/amd/yc/pci-acp6x.c +++ b/sound/soc/amd/yc/pci-acp6x.c @@ -149,10 +149,16 @@ static int snd_acp6x_probe(struct pci_dev *pci, int index = 0; int val = 0x00; u32 addr; - unsigned int irqflags; + unsigned int irqflags, flag; int ret; irqflags = IRQF_SHARED; + + /* Return if acp config flag is defined */ + flag = snd_amd_acp_find_config(pci); + if (flag) + return -ENODEV; + /* Yellow Carp device check */ switch (pci->revision) { case 0x60: From 13b1b95245a7c2dc959b06ed7f02f4832e401cd2 Mon Sep 17 00:00:00 2001 From: Alexander Sverdlin Date: Tue, 11 Apr 2023 18:59:50 +0200 Subject: [PATCH 725/778] ASoC: ep93xx: Add I2S description Add device tree bindings for Cirrus Logic EP93xx internal SoCs' I2S controller. Signed-off-by: Alexander Sverdlin Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230411165951.2335899-1-alexander.sverdlin@gmail.com Signed-off-by: Mark Brown --- .../bindings/sound/cirrus,ep9301-i2s.yaml | 66 +++++++++++++++++++ MAINTAINERS | 1 + 2 files changed, 67 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/cirrus,ep9301-i2s.yaml diff --git a/Documentation/devicetree/bindings/sound/cirrus,ep9301-i2s.yaml b/Documentation/devicetree/bindings/sound/cirrus,ep9301-i2s.yaml new file mode 100644 index 000000000000..453d493c941f --- /dev/null +++ b/Documentation/devicetree/bindings/sound/cirrus,ep9301-i2s.yaml @@ -0,0 +1,66 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/cirrus,ep9301-i2s.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Cirrus EP93xx I2S Controller + +description: | + The I2S controller is used to stream serial audio data between the external + I2S CODECs’, ADCs/DACs, and the ARM Core. The controller supports I2S, Left- + and Right-Justified DSP formats. + +maintainers: + - Alexander Sverdlin + +allOf: + - $ref: dai-common.yaml# + +properties: + compatible: + const: cirrus,ep9301-i2s + + '#sound-dai-cells': + const: 0 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + minItems: 3 + maxItems: 3 + + clock-names: + items: + - const: mclk + - const: sclk + - const: lrclk + +required: + - compatible + - '#sound-dai-cells' + - reg + - clocks + - clock-names + +additionalProperties: false + +examples: + - | + i2s: i2s@80820000 { + compatible = "cirrus,ep9301-i2s"; + #sound-dai-cells = <0>; + reg = <0x80820000 0x100>; + interrupt-parent = <&vic1>; + interrupts = <28>; + clocks = <&syscon 29>, + <&syscon 30>, + <&syscon 31>; + clock-names = "mclk", "sclk", "lrclk"; + }; + +... diff --git a/MAINTAINERS b/MAINTAINERS index e52938f962b5..b39ec6dbcdc9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2072,6 +2072,7 @@ M: Alexander Sverdlin L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained F: Documentation/devicetree/bindings/iio/adc/cirrus,ep9301-adc.yaml +F: Documentation/devicetree/bindings/sound/cirrus,ep9301-* F: arch/arm/boot/compressed/misc-ep93xx.h F: arch/arm/mach-ep93xx/ F: drivers/iio/adc/ep93xx_adc.c From b599a4d7d905a8e8cf5c36ccae0b3dd97c956075 Mon Sep 17 00:00:00 2001 From: Alexander Sverdlin Date: Tue, 11 Apr 2023 18:59:51 +0200 Subject: [PATCH 726/778] ASoC: ep93xx: Add OF support Add the new cirrus,ep9301-ac97 and cirrus,ep9301-i2s compatibles. Signed-off-by: Alexander Sverdlin Link: https://lore.kernel.org/r/20230411165951.2335899-2-alexander.sverdlin@gmail.com Signed-off-by: Mark Brown --- sound/soc/cirrus/ep93xx-i2s.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sound/soc/cirrus/ep93xx-i2s.c b/sound/soc/cirrus/ep93xx-i2s.c index 2abd1bce2290..afc6b5b570ea 100644 --- a/sound/soc/cirrus/ep93xx-i2s.c +++ b/sound/soc/cirrus/ep93xx-i2s.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -514,11 +515,18 @@ static void ep93xx_i2s_remove(struct platform_device *pdev) clk_put(info->mclk); } +static const struct of_device_id ep93xx_i2s_of_ids[] = { + { .compatible = "cirrus,ep9301-i2s" }, + {} +}; +MODULE_DEVICE_TABLE(of, ep93xx_i2s_of_ids); + static struct platform_driver ep93xx_i2s_driver = { .probe = ep93xx_i2s_probe, .remove_new = ep93xx_i2s_remove, .driver = { .name = "ep93xx-i2s", + .of_match_table = ep93xx_i2s_of_ids, }, }; From 7b98a1efbabfd729441f46823b24432f2c32deeb Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Tue, 11 Apr 2023 16:25:24 +0100 Subject: [PATCH 727/778] ASoC: cs35l56: Use DAPM widget for firmware PLAY/PAUSE If we use a DAPM widget instead of mute_stream() to send the PLAY command we can issue the plays to multiple amps in parallel. With mute_stream each codec driver instance is called one at a time so we get N * PS0 delay time. DAPM does each stage on every widget in a card before moving to the next stage. So all amps will do the PRE_PMU then all will do the POST_PMU. The PLAY is sent in the PRE_PMU so that they all power-up in parallel. After the PS0 wait in the first POST_PMU all the other amps will also be ready so there won't be any extra delay, or it will be negligible. There's also no point waiting for the MBOX ack in the PRE_PMU. We won't see a PS0 state in POST_PMU if it didn't ack the PLAY command. So we can save a little extra time. Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/20230411152528.329803-3-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l56.c | 105 +++++++++++++++++++------------------ 1 file changed, 55 insertions(+), 50 deletions(-) diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c index d97b465f0d3c..71565e0fccd8 100644 --- a/sound/soc/codecs/cs35l56.c +++ b/sound/soc/codecs/cs35l56.c @@ -32,6 +32,23 @@ static int cs35l56_dsp_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event); +static int cs35l56_mbox_send(struct cs35l56_private *cs35l56, unsigned int command) +{ + unsigned int val; + int ret; + + regmap_write(cs35l56->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, command); + ret = regmap_read_poll_timeout(cs35l56->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, + val, (val == 0), + CS35L56_MBOX_POLL_US, CS35L56_MBOX_TIMEOUT_US); + if (ret) { + dev_warn(cs35l56->dev, "MBOX command %#x failed: %d\n", command, ret); + return ret; + } + + return 0; +} + static int cs35l56_wait_dsp_ready(struct cs35l56_private *cs35l56) { int ret; @@ -182,10 +199,45 @@ static SOC_VALUE_ENUM_SINGLE_DECL(cs35l56_sdw1tx6_enum, static const struct snd_kcontrol_new sdw1_tx6_mux = SOC_DAPM_ENUM("SDW1TX6 SRC", cs35l56_sdw1tx6_enum); +static int cs35l56_play_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component); + unsigned int val; + int ret; + + dev_dbg(cs35l56->dev, "play: %d\n", event); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + /* Don't wait for ACK, we check in POST_PMU that it completed */ + return regmap_write(cs35l56->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, + CS35L56_MBOX_CMD_AUDIO_PLAY); + case SND_SOC_DAPM_POST_PMU: + /* Wait for firmware to enter PS0 power state */ + ret = regmap_read_poll_timeout(cs35l56->regmap, + CS35L56_TRANSDUCER_ACTUAL_PS, + val, (val == CS35L56_PS0), + CS35L56_PS0_POLL_US, + CS35L56_PS0_TIMEOUT_US); + if (ret) + dev_err(cs35l56->dev, "PS0 wait failed: %d\n", ret); + return ret; + case SND_SOC_DAPM_POST_PMD: + return cs35l56_mbox_send(cs35l56, CS35L56_MBOX_CMD_AUDIO_PAUSE); + default: + return 0; + } +} + static const struct snd_soc_dapm_widget cs35l56_dapm_widgets[] = { SND_SOC_DAPM_REGULATOR_SUPPLY("VDD_B", 0, 0), SND_SOC_DAPM_REGULATOR_SUPPLY("VDD_AMP", 0, 0), + SND_SOC_DAPM_SUPPLY("PLAY", SND_SOC_NOPM, 0, 0, cs35l56_play_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_OUT_DRV("AMP", SND_SOC_NOPM, 0, 0, NULL, 0), SND_SOC_DAPM_OUTPUT("SPK"), @@ -252,6 +304,9 @@ static const struct snd_soc_dapm_route cs35l56_audio_map[] = { { "AMP", NULL, "VDD_B" }, { "AMP", NULL, "VDD_AMP" }, + { "ASP1 Playback", NULL, "PLAY" }, + { "SDW1 Playback", NULL, "PLAY" }, + { "ASP1RX1", NULL, "ASP1 Playback" }, { "ASP1RX2", NULL, "ASP1 Playback" }, { "DSP1", NULL, "ASP1RX1" }, @@ -288,23 +343,6 @@ static const struct snd_soc_dapm_route cs35l56_audio_map[] = { { "SDW1 Capture", NULL, "SDW1 TX6 Source" }, }; -static int cs35l56_mbox_send(struct cs35l56_private *cs35l56, unsigned int command) -{ - unsigned int val; - int ret; - - regmap_write(cs35l56->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, command); - ret = regmap_read_poll_timeout(cs35l56->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, - val, (val == 0), - CS35L56_MBOX_POLL_US, CS35L56_MBOX_TIMEOUT_US); - if (ret) { - dev_warn(cs35l56->dev, "MBOX command %#x failed: %d\n", command, ret); - return ret; - } - - return 0; -} - static int cs35l56_dsp_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { @@ -611,43 +649,11 @@ static int cs35l56_asp_dai_set_sysclk(struct snd_soc_dai *dai, return 0; } -static int cs35l56_mute_stream(struct snd_soc_dai *dai, int mute, int stream) -{ - struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(dai->component); - unsigned int val; - int ret; - - dev_dbg(cs35l56->dev, "%s: %d %s\n", __func__, stream, mute ? "mute" : "unmute"); - - if (stream != SNDRV_PCM_STREAM_PLAYBACK) - return 0; - - if (mute) { - ret = cs35l56_mbox_send(cs35l56, CS35L56_MBOX_CMD_AUDIO_PAUSE); - } else { - ret = cs35l56_mbox_send(cs35l56, CS35L56_MBOX_CMD_AUDIO_PLAY); - if (ret == 0) { - /* Wait for firmware to enter PS0 power state */ - ret = regmap_read_poll_timeout(cs35l56->regmap, - CS35L56_TRANSDUCER_ACTUAL_PS, - val, (val == CS35L56_PS0), - CS35L56_PS0_POLL_US, - CS35L56_PS0_TIMEOUT_US); - if (ret) - dev_err(cs35l56->dev, "PS0 wait failed: %d\n", ret); - ret = 0; - } - } - - return ret; -} - static const struct snd_soc_dai_ops cs35l56_ops = { .set_fmt = cs35l56_asp_dai_set_fmt, .set_tdm_slot = cs35l56_asp_dai_set_tdm_slot, .hw_params = cs35l56_asp_dai_hw_params, .set_sysclk = cs35l56_asp_dai_set_sysclk, - .mute_stream = cs35l56_mute_stream, }; static void cs35l56_sdw_dai_shutdown(struct snd_pcm_substream *substream, @@ -749,7 +755,6 @@ static const struct snd_soc_dai_ops cs35l56_sdw_dai_ops = { .shutdown = cs35l56_sdw_dai_shutdown, .hw_params = cs35l56_sdw_dai_hw_params, .hw_free = cs35l56_sdw_dai_hw_free, - .mute_stream = cs35l56_mute_stream, .set_stream = cs35l56_sdw_dai_set_stream, }; From 7816e3407110d887726687740aa18c9ce8eeb0d2 Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Tue, 11 Apr 2023 16:25:25 +0100 Subject: [PATCH 728/778] ASoC: cs35l56: Skip first init_completion wait in dsp_work if init_done At the start of dsp_work() only wait for init_completion if !init_done. This allows system suspend to re-queue dsp_work() without having to do a dummy complete() of init_completion. A dummy completion in system suspend would have to be conditional on init_done. But that would create a possible race condition between our system resume and cs35l56_init() in the corner case that we suspend right after the SoundWire core has enumerated and reported ATTACHED. It is safer and simpler to have cs35l56_init() as the only place that init_completion is completed, and dsp_work() as the only place that it is consumed. Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/20230411152528.329803-4-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l56.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c index 71565e0fccd8..14cdbf5fd523 100644 --- a/sound/soc/codecs/cs35l56.c +++ b/sound/soc/codecs/cs35l56.c @@ -866,7 +866,8 @@ static void cs35l56_dsp_work(struct work_struct *work) unsigned int val; int ret = 0; - if (!wait_for_completion_timeout(&cs35l56->init_completion, + if (!cs35l56->init_done && + !wait_for_completion_timeout(&cs35l56->init_completion, msecs_to_jiffies(5000))) { dev_err(cs35l56->dev, "%s: init_completion timed out\n", __func__); goto complete; From f00abaddf0300bd9ca87918148a26bdb748129db Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Tue, 11 Apr 2023 16:25:26 +0100 Subject: [PATCH 729/778] ASoC: cs35l56: Always wait for firmware boot in runtime-resume When we are resuming from a system suspend the CS35L56 has probably been hard reset (usually a power-on reset). So we must wait for the firmware to boot. On SoundWire we also need it to re-initialize before we can read the registers to check the CS35L56 state. The simplest way to handle this is for runtime-resume to always wait for firmware boot. If the firmware is already booted the overhead is only one register read. The system-resume will have to runtime-resume the driver anyway before attempting any register access. So this will automatically include the wait for initialization on SoundWire. Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/20230411152528.329803-5-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l56.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c index 14cdbf5fd523..372b07fef827 100644 --- a/sound/soc/codecs/cs35l56.c +++ b/sound/soc/codecs/cs35l56.c @@ -1108,10 +1108,8 @@ int cs35l56_runtime_resume_common(struct cs35l56_private *cs35l56) unsigned int val; int ret; - if (!cs35l56->can_hibernate) { - regcache_cache_only(cs35l56->regmap, false); + if (!cs35l56->can_hibernate) goto out_sync; - } if (!cs35l56->sdw_peripheral) { /* @@ -1126,6 +1124,7 @@ int cs35l56_runtime_resume_common(struct cs35l56_private *cs35l56) CS35L56_CONTROL_PORT_READY_US + 400); } +out_sync: regcache_cache_only(cs35l56->regmap, false); ret = cs35l56_wait_for_firmware_boot(cs35l56); @@ -1138,7 +1137,6 @@ int cs35l56_runtime_resume_common(struct cs35l56_private *cs35l56) if (ret) goto err; -out_sync: /* BOOT_DONE will be 1 if the amp reset */ regmap_read(cs35l56->regmap, CS35L56_IRQ1_EINT_4, &val); if (val & CS35L56_OTP_BOOT_DONE_MASK) { From f9dc6b875ec0a6a6d4091cd9603d193ec98c75a2 Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Tue, 11 Apr 2023 16:25:27 +0100 Subject: [PATCH 730/778] ASoC: cs35l56: Add basic system suspend handling This adds the main handling for system suspend but does not handle re-patching the firmware after system resume. This is a multi-stage suspend and resume because if there is a RESET line it is almost certain that it will be shared by all the amps. So every amp must have done its suspend before we can assert RESET. Likewise we must de-assert RESET before the amps can resume. It's preferable to assert RESET before we turning off regulators, and while they power up. The actual suspend and resume is done by using the pair pm_runtime_force_suspend() and pm_runtime_force_resume() to re-use our runtime suspend/resume sequences. pm_runtime_force_suspend() will disable our pm_runtime. If we were runtime-resumed it calls our runtime_suspend(). pm_runtime_force_resume() re-enables pm_runtime and if we were originally runtime-resumed before the pm_runtime_force_suspend() it calls our runtime_resume(). Otherwise it leaves us runtime-suspended. The general process is therefore: suspend() -> finish dsp_work and then run our runtime_suspend suspend_late() -> assert RESET and turn off supplies resume_early() -> enable supplies and de-assert RESET resume() -> pm_runtime_force_resume() In addition, to prevent the IRQ handler running in the period between pm_runtime_force_suspend() and pm_runtime_force_resume() the parent IRQ is temporarily disabled: - from suspend until suspend_noirq - from resume_noirq until resume Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/20230411152528.329803-6-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l56-sdw.c | 26 +++++++ sound/soc/codecs/cs35l56.c | 126 +++++++++++++++++++++++++++++++++ sound/soc/codecs/cs35l56.h | 6 ++ 3 files changed, 158 insertions(+) diff --git a/sound/soc/codecs/cs35l56-sdw.c b/sound/soc/codecs/cs35l56-sdw.c index 448ef3609f4c..947d4e5f4dc9 100644 --- a/sound/soc/codecs/cs35l56-sdw.c +++ b/sound/soc/codecs/cs35l56-sdw.c @@ -450,6 +450,29 @@ static int __maybe_unused cs35l56_sdw_runtime_resume(struct device *dev) return 0; } +static int __maybe_unused cs35l56_sdw_system_suspend(struct device *dev) +{ + struct cs35l56_private *cs35l56 = dev_get_drvdata(dev); + + if (!cs35l56->init_done) + return 0; + + /* + * Disable SoundWire interrupts. + * Flush - don't cancel because that could leave an unbalanced pm_runtime_get. + */ + cs35l56->sdw_irq_no_unmask = true; + flush_work(&cs35l56->sdw_irq_work); + + /* Mask interrupts and flush in case sdw_irq_work was queued again */ + sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_MASK_1, 0); + sdw_read_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_STAT_1); + sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_STAT_1, 0xFF); + flush_work(&cs35l56->sdw_irq_work); + + return cs35l56_system_suspend(dev); +} + static int cs35l56_sdw_probe(struct sdw_slave *peripheral, const struct sdw_device_id *id) { struct device *dev = &peripheral->dev; @@ -499,6 +522,9 @@ static int cs35l56_sdw_remove(struct sdw_slave *peripheral) static const struct dev_pm_ops cs35l56_sdw_pm = { SET_RUNTIME_PM_OPS(cs35l56_sdw_runtime_suspend, cs35l56_sdw_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(cs35l56_sdw_system_suspend, cs35l56_system_resume) + LATE_SYSTEM_SLEEP_PM_OPS(cs35l56_system_suspend_late, cs35l56_system_resume_early) + /* NOIRQ stage not needed, SoundWire doesn't use a hard IRQ */ }; static const struct sdw_device_id cs35l56_sdw_id[] = { diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c index 372b07fef827..74e8de2f81f5 100644 --- a/sound/soc/codecs/cs35l56.c +++ b/sound/soc/codecs/cs35l56.c @@ -11,8 +11,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -1160,6 +1162,127 @@ err: } EXPORT_SYMBOL_NS_GPL(cs35l56_runtime_resume_common, SND_SOC_CS35L56_CORE); +int cs35l56_system_suspend(struct device *dev) +{ + struct cs35l56_private *cs35l56 = dev_get_drvdata(dev); + + dev_dbg(dev, "system_suspend\n"); + + if (cs35l56->component) + flush_work(&cs35l56->dsp_work); + + /* + * The interrupt line is normally shared, but after we start suspending + * we can't check if our device is the source of an interrupt, and can't + * clear it. Prevent this race by temporarily disabling the parent irq + * until we reach _no_irq. + */ + if (cs35l56->irq) + disable_irq(cs35l56->irq); + + return pm_runtime_force_suspend(dev); +} +EXPORT_SYMBOL_GPL(cs35l56_system_suspend); + +int cs35l56_system_suspend_late(struct device *dev) +{ + struct cs35l56_private *cs35l56 = dev_get_drvdata(dev); + + dev_dbg(dev, "system_suspend_late\n"); + + /* + * Assert RESET before removing supplies. + * RESET is usually shared by all amps so it must not be asserted until + * all driver instances have done their suspend() stage. + */ + if (cs35l56->reset_gpio) { + gpiod_set_value_cansleep(cs35l56->reset_gpio, 0); + usleep_range(CS35L56_RESET_PULSE_MIN_US, CS35L56_RESET_PULSE_MIN_US + 400); + } + + regulator_bulk_disable(ARRAY_SIZE(cs35l56->supplies), cs35l56->supplies); + + return 0; +} +EXPORT_SYMBOL_GPL(cs35l56_system_suspend_late); + +int cs35l56_system_suspend_no_irq(struct device *dev) +{ + struct cs35l56_private *cs35l56 = dev_get_drvdata(dev); + + dev_dbg(dev, "system_suspend_no_irq\n"); + + /* Handlers are now disabled so the parent IRQ can safely be re-enabled. */ + if (cs35l56->irq) + enable_irq(cs35l56->irq); + + return 0; +} +EXPORT_SYMBOL_GPL(cs35l56_system_suspend_no_irq); + +int cs35l56_system_resume_no_irq(struct device *dev) +{ + struct cs35l56_private *cs35l56 = dev_get_drvdata(dev); + + dev_dbg(dev, "system_resume_no_irq\n"); + + /* + * WAKE interrupts unmask if the CS35L56 hibernates, which can cause + * spurious interrupts, and the interrupt line is normally shared. + * We can't check if our device is the source of an interrupt, and can't + * clear it, until it has fully resumed. Prevent this race by temporarily + * disabling the parent irq until we complete resume(). + */ + if (cs35l56->irq) + disable_irq(cs35l56->irq); + + return 0; +} +EXPORT_SYMBOL_GPL(cs35l56_system_resume_no_irq); + +int cs35l56_system_resume_early(struct device *dev) +{ + struct cs35l56_private *cs35l56 = dev_get_drvdata(dev); + int ret; + + dev_dbg(dev, "system_resume_early\n"); + + /* Ensure a spec-compliant RESET pulse. */ + if (cs35l56->reset_gpio) { + gpiod_set_value_cansleep(cs35l56->reset_gpio, 0); + usleep_range(CS35L56_RESET_PULSE_MIN_US, CS35L56_RESET_PULSE_MIN_US + 400); + } + + /* Enable supplies before releasing RESET. */ + ret = regulator_bulk_enable(ARRAY_SIZE(cs35l56->supplies), cs35l56->supplies); + if (ret) { + dev_err(dev, "system_resume_early failed to enable supplies: %d\n", ret); + return ret; + } + + /* Release shared RESET before drivers start resume(). */ + gpiod_set_value_cansleep(cs35l56->reset_gpio, 1); + + return 0; +} +EXPORT_SYMBOL_GPL(cs35l56_system_resume_early); + +int cs35l56_system_resume(struct device *dev) +{ + struct cs35l56_private *cs35l56 = dev_get_drvdata(dev); + int ret; + + dev_dbg(dev, "system_resume\n"); + + /* Undo pm_runtime_force_suspend() before re-enabling the irq */ + ret = pm_runtime_force_resume(dev); + if (cs35l56->irq) + enable_irq(cs35l56->irq); + + return ret; +} +EXPORT_SYMBOL_GPL(cs35l56_system_resume); + static int cs35l56_dsp_init(struct cs35l56_private *cs35l56) { struct wm_adsp *dsp; @@ -1457,6 +1580,9 @@ EXPORT_SYMBOL_NS_GPL(cs35l56_remove, SND_SOC_CS35L56_CORE); const struct dev_pm_ops cs35l56_pm_ops_i2c_spi = { SET_RUNTIME_PM_OPS(cs35l56_runtime_suspend, cs35l56_runtime_resume_i2c_spi, NULL) + SYSTEM_SLEEP_PM_OPS(cs35l56_system_suspend, cs35l56_system_resume) + LATE_SYSTEM_SLEEP_PM_OPS(cs35l56_system_suspend_late, cs35l56_system_resume_early) + NOIRQ_SYSTEM_SLEEP_PM_OPS(cs35l56_system_suspend_no_irq, cs35l56_system_resume_no_irq) }; EXPORT_SYMBOL_NS_GPL(cs35l56_pm_ops_i2c_spi, SND_SOC_CS35L56_CORE); diff --git a/sound/soc/codecs/cs35l56.h b/sound/soc/codecs/cs35l56.h index efc4b99180f9..919ba0267ef9 100644 --- a/sound/soc/codecs/cs35l56.h +++ b/sound/soc/codecs/cs35l56.h @@ -68,6 +68,12 @@ extern const struct dev_pm_ops cs35l56_pm_ops_i2c_spi; int cs35l56_runtime_suspend(struct device *dev); int cs35l56_runtime_resume_common(struct cs35l56_private *cs35l56); +int cs35l56_system_suspend(struct device *dev); +int cs35l56_system_suspend_late(struct device *dev); +int cs35l56_system_suspend_no_irq(struct device *dev); +int cs35l56_system_resume_no_irq(struct device *dev); +int cs35l56_system_resume_early(struct device *dev); +int cs35l56_system_resume(struct device *dev); irqreturn_t cs35l56_irq(int irq, void *data); int cs35l56_irq_request(struct cs35l56_private *cs35l56); int cs35l56_common_probe(struct cs35l56_private *cs35l56); From 39a594dc0b4ac949edf221db33c7061c45e2c90b Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Tue, 11 Apr 2023 16:25:23 +0100 Subject: [PATCH 731/778] ASoC: cs35l56: Remove quick-cancelling of dsp_work() Delete the 'removing' flag and don't kick init_completion to make a quick cancel of dsp_work(). Just let it timeout on the wait for the completion. Simplify the code to standard cancelling or flushing of the work. This avoids introducing corner cases from a layer of custom signalling. It also avoids potential race conditions when system-suspend handling is added. Unless the hardware is broken, the dsp_work() will already have started and passed the completion before the driver would want to cancel it. Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/168122674746.26.16881587647873355224@mailman-core.alsa-project.org Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l56.c | 8 +------- sound/soc/codecs/cs35l56.h | 1 - 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c index 74e8de2f81f5..eb85c27ab087 100644 --- a/sound/soc/codecs/cs35l56.c +++ b/sound/soc/codecs/cs35l56.c @@ -875,7 +875,7 @@ static void cs35l56_dsp_work(struct work_struct *work) goto complete; } - if (!cs35l56->init_done || cs35l56->removing) + if (!cs35l56->init_done) goto complete; cs35l56->dsp.part = devm_kasprintf(cs35l56->dev, GFP_KERNEL, "cs35l56%s-%02x", @@ -925,9 +925,6 @@ static void cs35l56_dsp_work(struct work_struct *work) goto err; } - if (cs35l56->removing) - goto err; - mutex_lock(&cs35l56->irq_lock); init_completion(&cs35l56->init_completion); @@ -975,7 +972,6 @@ static int cs35l56_component_probe(struct snd_soc_component *component) BUILD_BUG_ON(ARRAY_SIZE(cs35l56_tx_input_texts) != ARRAY_SIZE(cs35l56_tx_input_values)); - cs35l56->removing = false; cs35l56->component = component; wm_adsp2_component_probe(&cs35l56->dsp, component); @@ -992,8 +988,6 @@ static void cs35l56_component_remove(struct snd_soc_component *component) { struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component); - cs35l56->removing = true; - complete(&cs35l56->init_completion); cancel_work_sync(&cs35l56->dsp_work); } diff --git a/sound/soc/codecs/cs35l56.h b/sound/soc/codecs/cs35l56.h index 919ba0267ef9..50278dafc9ca 100644 --- a/sound/soc/codecs/cs35l56.h +++ b/sound/soc/codecs/cs35l56.h @@ -49,7 +49,6 @@ struct cs35l56_private { bool soft_resetting; bool init_done; bool sdw_attached; - bool removing; bool fw_patched; bool can_hibernate; struct completion init_completion; From 59322d35179987e85b593e504fd334de8683c835 Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Tue, 11 Apr 2023 16:25:28 +0100 Subject: [PATCH 732/778] ASoC: cs35l56: Re-patch firmware after system suspend Check during cs35l56_system_resume() whether the firmware patch must be applied again. The FIRMWARE_MISSING flag in the PROTECTION_STATUS register indicates whether the firmware has been patched. In non-secure mode the FIRMWARE_MISSING flag is cleared at the end of dsp_work(). If it is set after system-resume we know that dsp_work() must be run again. In secure mode the pre-OS loader will have done the secure patching and cleared the FIRMWARE_MISSING flag. So this flag does not tell us whether firmware memory was lost. But the driver could only be downloading non-secure tunings, which is always safe to do. If the driver has control of RESET we will have asserted it during suspend so the firmware patch will have been lost. The driver would only have control of RESET in non-secure mode. Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/168122674550.26.8545058503709956172@mailman-core.alsa-project.org Signed-off-by: Mark Brown --- include/sound/cs35l56.h | 4 ++ sound/soc/codecs/cs35l56-sdw.c | 12 +++++- sound/soc/codecs/cs35l56.c | 67 +++++++++++++++++++++++++++++++++- 3 files changed, 81 insertions(+), 2 deletions(-) diff --git a/include/sound/cs35l56.h b/include/sound/cs35l56.h index 5f8ea2dfaa21..b3300bce74f4 100644 --- a/include/sound/cs35l56.h +++ b/include/sound/cs35l56.h @@ -95,6 +95,7 @@ #define CS35L56_MAIN_RENDER_USER_MUTE 0x3400024 #define CS35L56_MAIN_RENDER_USER_VOLUME 0x340002C #define CS35L56_MAIN_POSTURE_NUMBER 0x3400094 +#define CS35L56_PROTECTION_STATUS 0x34000D8 #define CS35L56_TRANSDUCER_ACTUAL_PS 0x3400150 #define CS35L56_DSP1_YMEM_UNPACKED24_6141 0x3405FF4 #define CS35L56_DSP1_PMEM_0 0x3800000 @@ -216,6 +217,9 @@ #define CS35L56_MAIN_POSTURE_MAX 255 #define CS35L56_MAIN_POSTURE_MASK CS35L56_MAIN_POSTURE_MAX +/* CS35L56_PROTECTION_STATUS */ +#define CS35L56_FIRMWARE_MISSING BIT(0) + /* Software Values */ #define CS35L56_HALO_STATE_SHUTDOWN 1 #define CS35L56_HALO_STATE_BOOT_DONE 2 diff --git a/sound/soc/codecs/cs35l56-sdw.c b/sound/soc/codecs/cs35l56-sdw.c index 947d4e5f4dc9..e759347423cf 100644 --- a/sound/soc/codecs/cs35l56-sdw.c +++ b/sound/soc/codecs/cs35l56-sdw.c @@ -473,6 +473,16 @@ static int __maybe_unused cs35l56_sdw_system_suspend(struct device *dev) return cs35l56_system_suspend(dev); } +static int __maybe_unused cs35l56_sdw_system_resume(struct device *dev) +{ + struct cs35l56_private *cs35l56 = dev_get_drvdata(dev); + + cs35l56->sdw_irq_no_unmask = false; + /* runtime_resume re-enables the interrupt */ + + return cs35l56_system_resume(dev); +} + static int cs35l56_sdw_probe(struct sdw_slave *peripheral, const struct sdw_device_id *id) { struct device *dev = &peripheral->dev; @@ -522,7 +532,7 @@ static int cs35l56_sdw_remove(struct sdw_slave *peripheral) static const struct dev_pm_ops cs35l56_sdw_pm = { SET_RUNTIME_PM_OPS(cs35l56_sdw_runtime_suspend, cs35l56_sdw_runtime_resume, NULL) - SYSTEM_SLEEP_PM_OPS(cs35l56_sdw_system_suspend, cs35l56_system_resume) + SYSTEM_SLEEP_PM_OPS(cs35l56_sdw_system_suspend, cs35l56_sdw_system_resume) LATE_SYSTEM_SLEEP_PM_OPS(cs35l56_system_suspend_late, cs35l56_system_resume_early) /* NOIRQ stage not needed, SoundWire doesn't use a hard IRQ */ }; diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c index eb85c27ab087..18e341744839 100644 --- a/sound/soc/codecs/cs35l56.c +++ b/sound/soc/codecs/cs35l56.c @@ -946,6 +946,7 @@ static void cs35l56_dsp_work(struct work_struct *work) goto err_unlock; } + regmap_clear_bits(cs35l56->regmap, CS35L56_PROTECTION_STATUS, CS35L56_FIRMWARE_MISSING); cs35l56->fw_patched = true; err_unlock: @@ -1026,6 +1027,8 @@ static const struct snd_soc_component_driver soc_component_dev_cs35l56 = { .num_controls = ARRAY_SIZE(cs35l56_controls), .set_bias_level = cs35l56_set_bias_level, + + .suspend_bias_off = 1, /* see cs35l56_system_resume() */ }; static const struct reg_sequence cs35l56_hibernate_seq[] = { @@ -1156,6 +1159,47 @@ err: } EXPORT_SYMBOL_NS_GPL(cs35l56_runtime_resume_common, SND_SOC_CS35L56_CORE); +static int cs35l56_is_fw_reload_needed(struct cs35l56_private *cs35l56) +{ + unsigned int val; + int ret; + + /* Nothing to re-patch if we haven't done any patching yet. */ + if (!cs35l56->fw_patched) + return false; + + /* + * If we have control of RESET we will have asserted it so the firmware + * will need re-patching. + */ + if (cs35l56->reset_gpio) + return true; + + /* + * In secure mode FIRMWARE_MISSING is cleared by the BIOS loader so + * can't be used here to test for memory retention. + * Assume that tuning must be re-loaded. + */ + if (cs35l56->secured) + return true; + + ret = pm_runtime_resume_and_get(cs35l56->dev); + if (ret) { + dev_err(cs35l56->dev, "Failed to runtime_get: %d\n", ret); + return ret; + } + + ret = regmap_read(cs35l56->regmap, CS35L56_PROTECTION_STATUS, &val); + if (ret) + dev_err(cs35l56->dev, "Failed to read PROTECTION_STATUS: %d\n", ret); + else + ret = !!(val & CS35L56_FIRMWARE_MISSING); + + pm_runtime_put_autosuspend(cs35l56->dev); + + return ret; +} + int cs35l56_system_suspend(struct device *dev) { struct cs35l56_private *cs35l56 = dev_get_drvdata(dev); @@ -1273,7 +1317,28 @@ int cs35l56_system_resume(struct device *dev) if (cs35l56->irq) enable_irq(cs35l56->irq); - return ret; + if (ret) + return ret; + + /* Firmware won't have been loaded if the component hasn't probed */ + if (!cs35l56->component) + return 0; + + ret = cs35l56_is_fw_reload_needed(cs35l56); + dev_dbg(cs35l56->dev, "fw_reload_needed: %d\n", ret); + if (ret < 1) + return ret; + + cs35l56->fw_patched = false; + init_completion(&cs35l56->dsp_ready_completion); + queue_work(cs35l56->dsp_wq, &cs35l56->dsp_work); + + /* + * suspend_bias_off ensures we are now in BIAS_OFF so there will be + * a BIAS_OFF->BIAS_STANDBY transition to complete dsp patching. + */ + + return 0; } EXPORT_SYMBOL_GPL(cs35l56_system_resume); From 2c17277893747e30e41d1a7b57b80f2b298da278 Mon Sep 17 00:00:00 2001 From: David Rau Date: Thu, 13 Apr 2023 02:41:34 +0000 Subject: [PATCH 733/778] ASoC: da7219: Improve the relability of AAD IRQ process - Configure the default gound switch delay time before enabling IRQ to avoid the unexpected delay time is set up - Apply DA7219 AAD own work queue to handle AAD events - Replace msleep with queue_delayed_work to have better relability This commit improves the control of ground switches in AAD IRQ Signed-off-by: David Rau Link: https://lore.kernel.org/r/20230413024134.8612-1-David.Rau.opensource@dm.renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/da7219-aad.c | 60 +++++++++++++++++------------------ sound/soc/codecs/da7219-aad.h | 5 ++- 2 files changed, 31 insertions(+), 34 deletions(-) diff --git a/sound/soc/codecs/da7219-aad.c b/sound/soc/codecs/da7219-aad.c index e3d398b8f54e..993a0d00bc48 100644 --- a/sound/soc/codecs/da7219-aad.c +++ b/sound/soc/codecs/da7219-aad.c @@ -342,36 +342,17 @@ static void da7219_aad_hptest_work(struct work_struct *work) static void da7219_aad_jack_det_work(struct work_struct *work) { struct da7219_aad_priv *da7219_aad = - container_of(work, struct da7219_aad_priv, jack_det_work); + container_of(work, struct da7219_aad_priv, jack_det_work.work); struct snd_soc_component *component = da7219_aad->component; - u8 srm_st; - mutex_lock(&da7219_aad->jack_det_mutex); - - srm_st = snd_soc_component_read(component, DA7219_PLL_SRM_STS) & DA7219_PLL_SRM_STS_MCLK; - msleep(da7219_aad->gnd_switch_delay * ((srm_st == 0x0) ? 2 : 1) - 4); /* Enable ground switch */ snd_soc_component_update_bits(component, 0xFB, 0x01, 0x01); - - mutex_unlock(&da7219_aad->jack_det_mutex); } - /* * IRQ */ -static irqreturn_t da7219_aad_pre_irq_thread(int irq, void *data) -{ - - struct da7219_aad_priv *da7219_aad = data; - - if (!da7219_aad->jack_inserted) - schedule_work(&da7219_aad->jack_det_work); - - return IRQ_WAKE_THREAD; -} - static irqreturn_t da7219_aad_irq_thread(int irq, void *data) { struct da7219_aad_priv *da7219_aad = data; @@ -392,6 +373,18 @@ static irqreturn_t da7219_aad_irq_thread(int irq, void *data) /* Read status register for jack insertion & type status */ statusa = snd_soc_component_read(component, DA7219_ACCDET_STATUS_A); + if (events[DA7219_AAD_IRQ_REG_A] & DA7219_E_JACK_INSERTED_MASK) { + u8 srm_st; + int delay = 0; + + srm_st = snd_soc_component_read(component, + DA7219_PLL_SRM_STS) & DA7219_PLL_SRM_STS_MCLK; + delay = (da7219_aad->gnd_switch_delay * ((srm_st == 0x0) ? 2 : 1) - 2); + queue_delayed_work(da7219_aad->aad_wq, + &da7219_aad->jack_det_work, + msecs_to_jiffies(delay)); + } + /* Clear events */ regmap_bulk_write(da7219->regmap, DA7219_ACCDET_IRQ_EVENT_A, events, DA7219_AAD_IRQ_REG_MAX); @@ -400,9 +393,6 @@ static irqreturn_t da7219_aad_irq_thread(int irq, void *data) events[DA7219_AAD_IRQ_REG_A], events[DA7219_AAD_IRQ_REG_B], statusa); - if (!da7219_aad->jack_inserted) - cancel_work_sync(&da7219_aad->jack_det_work); - if (statusa & DA7219_JACK_INSERTION_STS_MASK) { /* Jack Insertion */ if (events[DA7219_AAD_IRQ_REG_A] & @@ -430,9 +420,9 @@ static irqreturn_t da7219_aad_irq_thread(int irq, void *data) if (statusa & DA7219_JACK_TYPE_STS_MASK) { report |= SND_JACK_HEADSET; mask |= SND_JACK_HEADSET | SND_JACK_LINEOUT; - schedule_work(&da7219_aad->btn_det_work); + queue_work(da7219_aad->aad_wq, &da7219_aad->btn_det_work); } else { - schedule_work(&da7219_aad->hptest_work); + queue_work(da7219_aad->aad_wq, &da7219_aad->hptest_work); } } @@ -465,6 +455,7 @@ static irqreturn_t da7219_aad_irq_thread(int irq, void *data) da7219_aad->jack_inserted = false; /* Cancel any pending work */ + cancel_delayed_work_sync(&da7219_aad->jack_det_work); cancel_work_sync(&da7219_aad->btn_det_work); cancel_work_sync(&da7219_aad->hptest_work); @@ -964,13 +955,19 @@ int da7219_aad_init(struct snd_soc_component *component) snd_soc_component_update_bits(component, DA7219_ACCDET_CONFIG_1, DA7219_BUTTON_CONFIG_MASK, 0); + da7219_aad_handle_gnd_switch_time(component); + + da7219_aad->aad_wq = create_singlethread_workqueue("da7219-aad"); + if (!da7219_aad->aad_wq) { + dev_err(component->dev, "Failed to create aad workqueue\n"); + return -ENOMEM; + } + + INIT_DELAYED_WORK(&da7219_aad->jack_det_work, da7219_aad_jack_det_work); INIT_WORK(&da7219_aad->btn_det_work, da7219_aad_btn_det_work); INIT_WORK(&da7219_aad->hptest_work, da7219_aad_hptest_work); - INIT_WORK(&da7219_aad->jack_det_work, da7219_aad_jack_det_work); - mutex_init(&da7219_aad->jack_det_mutex); - - ret = request_threaded_irq(da7219_aad->irq, da7219_aad_pre_irq_thread, + ret = request_threaded_irq(da7219_aad->irq, NULL, da7219_aad_irq_thread, IRQF_TRIGGER_LOW | IRQF_ONESHOT, "da7219-aad", da7219_aad); @@ -984,8 +981,6 @@ int da7219_aad_init(struct snd_soc_component *component) regmap_bulk_write(da7219->regmap, DA7219_ACCDET_IRQ_MASK_A, &mask, DA7219_AAD_IRQ_REG_MAX); - da7219_aad_handle_gnd_switch_time(component); - return 0; } @@ -1002,8 +997,10 @@ void da7219_aad_exit(struct snd_soc_component *component) free_irq(da7219_aad->irq, da7219_aad); + cancel_delayed_work_sync(&da7219_aad->jack_det_work); cancel_work_sync(&da7219_aad->btn_det_work); cancel_work_sync(&da7219_aad->hptest_work); + destroy_workqueue(da7219_aad->aad_wq); } /* @@ -1031,4 +1028,5 @@ int da7219_aad_probe(struct i2c_client *i2c) MODULE_DESCRIPTION("ASoC DA7219 AAD Driver"); MODULE_AUTHOR("Adam Thomson "); +MODULE_AUTHOR("David Rau "); MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/da7219-aad.h b/sound/soc/codecs/da7219-aad.h index be87ee47edde..fbfbf3e67918 100644 --- a/sound/soc/codecs/da7219-aad.h +++ b/sound/soc/codecs/da7219-aad.h @@ -197,9 +197,8 @@ struct da7219_aad_priv { struct work_struct btn_det_work; struct work_struct hptest_work; - struct work_struct jack_det_work; - - struct mutex jack_det_mutex; + struct delayed_work jack_det_work; + struct workqueue_struct *aad_wq; struct snd_soc_jack *jack; bool micbias_resume_enable; From c6c3581a3e178882c8815462ca129e60be50fde8 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Thu, 13 Apr 2023 07:28:33 +0200 Subject: [PATCH 734/778] ASoC: da7218: Use devm_clk_get_optional() Use devm_clk_get_optional() instead of hand writing it. Signed-off-by: Christophe JAILLET Link: https://lore.kernel.org/r/51976b2515d7007ba5c8aa7524892f147d7cdd51.1681363691.git.christophe.jaillet@wanadoo.fr Signed-off-by: Mark Brown --- sound/soc/codecs/da7218.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/sound/soc/codecs/da7218.c b/sound/soc/codecs/da7218.c index 91372909d184..d9c28e701613 100644 --- a/sound/soc/codecs/da7218.c +++ b/sound/soc/codecs/da7218.c @@ -2893,14 +2893,10 @@ static int da7218_probe(struct snd_soc_component *component) da7218_handle_pdata(component); /* Check if MCLK provided, if not the clock is NULL */ - da7218->mclk = devm_clk_get(component->dev, "mclk"); + da7218->mclk = devm_clk_get_optional(component->dev, "mclk"); if (IS_ERR(da7218->mclk)) { - if (PTR_ERR(da7218->mclk) != -ENOENT) { - ret = PTR_ERR(da7218->mclk); - goto err_disable_reg; - } else { - da7218->mclk = NULL; - } + ret = PTR_ERR(da7218->mclk); + goto err_disable_reg; } /* Default PC to free-running */ From c26c5921e1a770e6c092c4d25dea19052bdfddab Mon Sep 17 00:00:00 2001 From: David Lin Date: Fri, 14 Apr 2023 18:39:42 +0800 Subject: [PATCH 735/778] ASoC: dt-bindings: nau8825: Add delay control for input path Change the original fixed delay to the assignment from property. It will make more flexible to different platforms for avoiding pop noise at the beginning of recording. Signed-off-by: David Lin Link: https://lore.kernel.org/r/20230414103941.39566-1-CTLIN0@nuvoton.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/nau8825.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/nau8825.txt b/Documentation/devicetree/bindings/sound/nau8825.txt index cb861aca8d40..a9c34526f4cb 100644 --- a/Documentation/devicetree/bindings/sound/nau8825.txt +++ b/Documentation/devicetree/bindings/sound/nau8825.txt @@ -74,6 +74,9 @@ Optional properties: - nuvoton,adcout-drive-strong: make the drive strength of ADCOUT IO PIN strong if set. Otherwise, the drive keeps normal strength. + - nuvoton,adc-delay-ms: Delay (in ms) to make input path stable and avoid pop noise. The + default value is 125 and range between 125 to 500 ms. + - clocks: list of phandle and clock specifier pairs according to common clock bindings for the clocks described in clock-names - clock-names: should include "mclk" for the MCLK master clock From fc0b096c92918c2ba4d76411ea763fdeb2ef6b0d Mon Sep 17 00:00:00 2001 From: David Lin Date: Fri, 14 Apr 2023 18:39:44 +0800 Subject: [PATCH 736/778] ASoC: nau8825: Add delay control for input path Change the original fixed delay to the assignment from property. It will make more flexible to different platforms for avoiding pop noise at the beginning of recording. Signed-off-by: David Lin Link: https://lore.kernel.org/r/20230414103941.39566-2-CTLIN0@nuvoton.com Signed-off-by: Mark Brown --- sound/soc/codecs/nau8825.c | 8 +++++++- sound/soc/codecs/nau8825.h | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/nau8825.c b/sound/soc/codecs/nau8825.c index 4bffa9c20f2b..c4389f5fe603 100644 --- a/sound/soc/codecs/nau8825.c +++ b/sound/soc/codecs/nau8825.c @@ -919,7 +919,7 @@ static int nau8825_adc_event(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_POST_PMU: - msleep(125); + msleep(nau8825->adc_delay); regmap_update_bits(nau8825->regmap, NAU8825_REG_ENA_CTRL, NAU8825_ENABLE_ADC, NAU8825_ENABLE_ADC); break; @@ -2752,6 +2752,7 @@ static void nau8825_print_device_properties(struct nau8825 *nau8825) dev_dbg(dev, "crosstalk-enable: %d\n", nau8825->xtalk_enable); dev_dbg(dev, "adcout-drive-strong: %d\n", nau8825->adcout_ds); + dev_dbg(dev, "adc-delay-ms: %d\n", nau8825->adc_delay); } static int nau8825_read_device_properties(struct device *dev, @@ -2819,6 +2820,11 @@ static int nau8825_read_device_properties(struct device *dev, nau8825->xtalk_enable = device_property_read_bool(dev, "nuvoton,crosstalk-enable"); nau8825->adcout_ds = device_property_read_bool(dev, "nuvoton,adcout-drive-strong"); + ret = device_property_read_u32(dev, "nuvoton,adc-delay-ms", &nau8825->adc_delay); + if (ret) + nau8825->adc_delay = 125; + if (nau8825->adc_delay < 125 && nau8825->adc_delay > 500) + dev_warn(dev, "Please set the suitable delay time!\n"); nau8825->mclk = devm_clk_get(dev, "mclk"); if (PTR_ERR(nau8825->mclk) == -EPROBE_DEFER) { diff --git a/sound/soc/codecs/nau8825.h b/sound/soc/codecs/nau8825.h index 0c3a446e0e1a..44b62bc3880f 100644 --- a/sound/soc/codecs/nau8825.h +++ b/sound/soc/codecs/nau8825.h @@ -517,6 +517,7 @@ struct nau8825 { int xtalk_enable; bool xtalk_baktab_initialized; /* True if initialized. */ bool adcout_ds; + int adc_delay; }; int nau8825_enable_jack_detect(struct snd_soc_component *component, From 7d72351a4ef6e1e763bccc24d43c44ffbe1a1555 Mon Sep 17 00:00:00 2001 From: Simon Trimmer Date: Fri, 14 Apr 2023 14:37:49 +0100 Subject: [PATCH 737/778] ASoC: cs35l56: Rework IRQ allocation The irq member was being set before calling the init function and then cs35l56_irq_request() was called only when the init was successful. However cs35l56_release() calls devm_free_irq() when the irq member is set and therefore if init() fails then this will cause an attempted free of an unallocated IRQ. Instead pass the desired IRQ number to the cs35l56_irq_request() function and set cs35l56->irq only when it has been successfully allocated. Signed-off-by: Simon Trimmer Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/168147949598.26.711670799488943454@mailman-core.alsa-project.org Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l56-i2c.c | 3 +-- sound/soc/codecs/cs35l56-spi.c | 3 +-- sound/soc/codecs/cs35l56.c | 11 ++++++----- sound/soc/codecs/cs35l56.h | 2 +- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/sound/soc/codecs/cs35l56-i2c.c b/sound/soc/codecs/cs35l56-i2c.c index 4b7f034a7670..295caad26224 100644 --- a/sound/soc/codecs/cs35l56-i2c.c +++ b/sound/soc/codecs/cs35l56-i2c.c @@ -27,7 +27,6 @@ static int cs35l56_i2c_probe(struct i2c_client *client) return -ENOMEM; cs35l56->dev = dev; - cs35l56->irq = client->irq; cs35l56->can_hibernate = true; i2c_set_clientdata(client, cs35l56); @@ -43,7 +42,7 @@ static int cs35l56_i2c_probe(struct i2c_client *client) ret = cs35l56_init(cs35l56); if (ret == 0) - ret = cs35l56_irq_request(cs35l56); + ret = cs35l56_irq_request(cs35l56, client->irq); if (ret < 0) cs35l56_remove(cs35l56); diff --git a/sound/soc/codecs/cs35l56-spi.c b/sound/soc/codecs/cs35l56-spi.c index 4b2084e85f29..996aab10500e 100644 --- a/sound/soc/codecs/cs35l56-spi.c +++ b/sound/soc/codecs/cs35l56-spi.c @@ -32,7 +32,6 @@ static int cs35l56_spi_probe(struct spi_device *spi) } cs35l56->dev = &spi->dev; - cs35l56->irq = spi->irq; ret = cs35l56_common_probe(cs35l56); if (ret != 0) @@ -40,7 +39,7 @@ static int cs35l56_spi_probe(struct spi_device *spi) ret = cs35l56_init(cs35l56); if (ret == 0) - ret = cs35l56_irq_request(cs35l56); + ret = cs35l56_irq_request(cs35l56, spi->irq); if (ret < 0) cs35l56_remove(cs35l56); diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c index 18e341744839..5ea7f419cda6 100644 --- a/sound/soc/codecs/cs35l56.c +++ b/sound/soc/codecs/cs35l56.c @@ -423,18 +423,19 @@ err_unlock: } EXPORT_SYMBOL_NS_GPL(cs35l56_irq, SND_SOC_CS35L56_CORE); -int cs35l56_irq_request(struct cs35l56_private *cs35l56) +int cs35l56_irq_request(struct cs35l56_private *cs35l56, int irq) { int ret; - if (!cs35l56->irq) + if (!irq) return 0; - ret = devm_request_threaded_irq(cs35l56->dev, cs35l56->irq, NULL, - cs35l56_irq, + ret = devm_request_threaded_irq(cs35l56->dev, irq, NULL, cs35l56_irq, IRQF_ONESHOT | IRQF_SHARED | IRQF_TRIGGER_LOW, "cs35l56", cs35l56); - if (ret < 0) + if (!ret) + cs35l56->irq = irq; + else dev_err(cs35l56->dev, "Failed to get IRQ: %d\n", ret); return ret; diff --git a/sound/soc/codecs/cs35l56.h b/sound/soc/codecs/cs35l56.h index 50278dafc9ca..ac2e9237c27d 100644 --- a/sound/soc/codecs/cs35l56.h +++ b/sound/soc/codecs/cs35l56.h @@ -74,7 +74,7 @@ int cs35l56_system_resume_no_irq(struct device *dev); int cs35l56_system_resume_early(struct device *dev); int cs35l56_system_resume(struct device *dev); irqreturn_t cs35l56_irq(int irq, void *data); -int cs35l56_irq_request(struct cs35l56_private *cs35l56); +int cs35l56_irq_request(struct cs35l56_private *cs35l56, int irq); int cs35l56_common_probe(struct cs35l56_private *cs35l56); int cs35l56_init(struct cs35l56_private *cs35l56); int cs35l56_remove(struct cs35l56_private *cs35l56); From b82396122b028a07ce2977e3f33123d7ab526d91 Mon Sep 17 00:00:00 2001 From: Simon Trimmer Date: Fri, 14 Apr 2023 14:37:50 +0100 Subject: [PATCH 738/778] ASoC: cs35l56: Allow a wider range for reset pulse width There is no reason to have such a tight usleep range of 400us and it is acceptable to allow MIN_US * 2. Also wrap the usleep in an inline function. Signed-off-by: Simon Trimmer Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/168147949455.26.3401634900657387799@mailman-core.alsa-project.org Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l56.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c index 5ea7f419cda6..d60095162bfa 100644 --- a/sound/soc/codecs/cs35l56.c +++ b/sound/soc/codecs/cs35l56.c @@ -835,6 +835,12 @@ static int cs35l56_wait_for_firmware_boot(struct cs35l56_private *cs35l56) return 0; } +static inline void cs35l56_wait_min_reset_pulse(void) +{ + /* Satisfy minimum reset pulse width spec */ + usleep_range(CS35L56_RESET_PULSE_MIN_US, 2 * CS35L56_RESET_PULSE_MIN_US); +} + static const struct reg_sequence cs35l56_system_reset_seq[] = { REG_SEQ0(CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_SYSTEM_RESET), }; @@ -1236,7 +1242,7 @@ int cs35l56_system_suspend_late(struct device *dev) */ if (cs35l56->reset_gpio) { gpiod_set_value_cansleep(cs35l56->reset_gpio, 0); - usleep_range(CS35L56_RESET_PULSE_MIN_US, CS35L56_RESET_PULSE_MIN_US + 400); + cs35l56_wait_min_reset_pulse(); } regulator_bulk_disable(ARRAY_SIZE(cs35l56->supplies), cs35l56->supplies); @@ -1289,7 +1295,7 @@ int cs35l56_system_resume_early(struct device *dev) /* Ensure a spec-compliant RESET pulse. */ if (cs35l56->reset_gpio) { gpiod_set_value_cansleep(cs35l56->reset_gpio, 0); - usleep_range(CS35L56_RESET_PULSE_MIN_US, CS35L56_RESET_PULSE_MIN_US + 400); + cs35l56_wait_min_reset_pulse(); } /* Enable supplies before releasing RESET. */ @@ -1440,9 +1446,7 @@ int cs35l56_common_probe(struct cs35l56_private *cs35l56) return dev_err_probe(cs35l56->dev, ret, "Failed to enable supplies\n"); if (cs35l56->reset_gpio) { - /* satisfy minimum reset pulse width spec */ - usleep_range(CS35L56_RESET_PULSE_MIN_US, - CS35L56_RESET_PULSE_MIN_US + 400); + cs35l56_wait_min_reset_pulse(); gpiod_set_value_cansleep(cs35l56->reset_gpio, 1); } From 440c2d38950f738d7a35d3d29533728e74586d54 Mon Sep 17 00:00:00 2001 From: Simon Trimmer Date: Fri, 14 Apr 2023 14:37:51 +0100 Subject: [PATCH 739/778] ASoC: cs35l56: Wait for init_complete in cs35l56_component_probe() Moving the wait from the beginning of the cs35l56_dsp_work() into cs35l56_component_probe() will prevent the limbo situation that is an artifact of the two stage SoundWire driver probe and initialisation where the card is all registered and shows in ALSA but doesn't actually work because the hardware didn't enumerate. The other bus drivers perform the probe and init sequentially and are not susceptible to this issue. Signed-off-by: Simon Trimmer Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/20230414133753.653139-4-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l56.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c index d60095162bfa..ab2e663af6c2 100644 --- a/sound/soc/codecs/cs35l56.c +++ b/sound/soc/codecs/cs35l56.c @@ -875,13 +875,6 @@ static void cs35l56_dsp_work(struct work_struct *work) unsigned int val; int ret = 0; - if (!cs35l56->init_done && - !wait_for_completion_timeout(&cs35l56->init_completion, - msecs_to_jiffies(5000))) { - dev_err(cs35l56->dev, "%s: init_completion timed out\n", __func__); - goto complete; - } - if (!cs35l56->init_done) goto complete; @@ -980,6 +973,12 @@ static int cs35l56_component_probe(struct snd_soc_component *component) BUILD_BUG_ON(ARRAY_SIZE(cs35l56_tx_input_texts) != ARRAY_SIZE(cs35l56_tx_input_values)); + if (!wait_for_completion_timeout(&cs35l56->init_completion, + msecs_to_jiffies(5000))) { + dev_err(cs35l56->dev, "%s: init_completion timed out\n", __func__); + return -ENODEV; + } + cs35l56->component = component; wm_adsp2_component_probe(&cs35l56->dsp, component); From 4be476830bf96c0095e4e1acdfc12081aa0fb165 Mon Sep 17 00:00:00 2001 From: Simon Trimmer Date: Fri, 14 Apr 2023 14:37:52 +0100 Subject: [PATCH 740/778] ASoC: cs35l56: Remove redundant dsp_ready_completion dsp_ready_completion is redundant and can be replaced by a call flush_work() to wait for cs35l56_dsp_work() to complete. As the dsp_work is queued by component_probe() it must run before other ASoC component callbacks and therefore there is no risk of calling flush_work() before the dsp_work() has been queued. Signed-off-by: Simon Trimmer Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/20230414133753.653139-5-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l56.c | 41 +++++++++----------------------------- sound/soc/codecs/cs35l56.h | 1 - 2 files changed, 9 insertions(+), 33 deletions(-) diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c index ab2e663af6c2..5f66a8e20b2d 100644 --- a/sound/soc/codecs/cs35l56.c +++ b/sound/soc/codecs/cs35l56.c @@ -51,21 +51,10 @@ static int cs35l56_mbox_send(struct cs35l56_private *cs35l56, unsigned int comma return 0; } -static int cs35l56_wait_dsp_ready(struct cs35l56_private *cs35l56) +static void cs35l56_wait_dsp_ready(struct cs35l56_private *cs35l56) { - int ret; - - if (!cs35l56->fw_patched) { - /* block until firmware download completes */ - ret = wait_for_completion_timeout(&cs35l56->dsp_ready_completion, - msecs_to_jiffies(25000)); - if (!ret) { - dev_err(cs35l56->dev, "dsp_ready_completion timeout\n"); - return -ETIMEDOUT; - } - } - - return 0; + /* Wait for patching to complete */ + flush_work(&cs35l56->dsp_work); } static int cs35l56_dspwait_get_volsw(struct snd_kcontrol *kcontrol, @@ -73,11 +62,8 @@ static int cs35l56_dspwait_get_volsw(struct snd_kcontrol *kcontrol, { struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component); - int ret = cs35l56_wait_dsp_ready(cs35l56); - - if (ret) - return ret; + cs35l56_wait_dsp_ready(cs35l56); return snd_soc_get_volsw(kcontrol, ucontrol); } @@ -86,11 +72,8 @@ static int cs35l56_dspwait_put_volsw(struct snd_kcontrol *kcontrol, { struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component); - int ret = cs35l56_wait_dsp_ready(cs35l56); - - if (ret) - return ret; + cs35l56_wait_dsp_ready(cs35l56); return snd_soc_put_volsw(kcontrol, ucontrol); } @@ -876,13 +859,13 @@ static void cs35l56_dsp_work(struct work_struct *work) int ret = 0; if (!cs35l56->init_done) - goto complete; + return; cs35l56->dsp.part = devm_kasprintf(cs35l56->dev, GFP_KERNEL, "cs35l56%s-%02x", cs35l56->secured ? "s" : "", cs35l56->rev); if (!cs35l56->dsp.part) - goto complete; + return; pm_runtime_get_sync(cs35l56->dev); @@ -961,9 +944,6 @@ err: sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_MASK_1, CS35L56_SDW_INT_MASK_CODEC_IRQ); } - -complete: - complete_all(&cs35l56->dsp_ready_completion); } static int cs35l56_component_probe(struct snd_soc_component *component) @@ -1002,7 +982,6 @@ static int cs35l56_set_bias_level(struct snd_soc_component *component, enum snd_soc_bias_level level) { struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component); - int ret = 0; switch (level) { case SND_SOC_BIAS_STANDBY: @@ -1011,14 +990,14 @@ static int cs35l56_set_bias_level(struct snd_soc_component *component, * BIAS_OFF to BIAS_STANDBY */ if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) - ret = cs35l56_wait_dsp_ready(cs35l56); + cs35l56_wait_dsp_ready(cs35l56); break; default: break; } - return ret; + return 0; } static const struct snd_soc_component_driver soc_component_dev_cs35l56 = { @@ -1336,7 +1315,6 @@ int cs35l56_system_resume(struct device *dev) return ret; cs35l56->fw_patched = false; - init_completion(&cs35l56->dsp_ready_completion); queue_work(cs35l56->dsp_wq, &cs35l56->dsp_work); /* @@ -1358,7 +1336,6 @@ static int cs35l56_dsp_init(struct cs35l56_private *cs35l56) return -ENOMEM; INIT_WORK(&cs35l56->dsp_work, cs35l56_dsp_work); - init_completion(&cs35l56->dsp_ready_completion); dsp = &cs35l56->dsp; dsp->part = "cs35l56"; diff --git a/sound/soc/codecs/cs35l56.h b/sound/soc/codecs/cs35l56.h index ac2e9237c27d..09762e70ce81 100644 --- a/sound/soc/codecs/cs35l56.h +++ b/sound/soc/codecs/cs35l56.h @@ -34,7 +34,6 @@ struct cs35l56_private { struct wm_adsp dsp; /* must be first member */ struct work_struct dsp_work; struct workqueue_struct *dsp_wq; - struct completion dsp_ready_completion; struct mutex irq_lock; struct snd_soc_component *component; struct device *dev; From 9ed4c762e214a6592184d0dd65b6db86ad30e6d5 Mon Sep 17 00:00:00 2001 From: Simon Trimmer Date: Fri, 14 Apr 2023 14:37:53 +0100 Subject: [PATCH 741/778] ASoC: cs35l56: Don't return a value from cs35l56_remove() cs35l56_remove() always returns 0. Two of the functions that call it are void and the other one should only return 0. So there's no point returning anything from cs35l56_remove(). Signed-off-by: Simon Trimmer Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/20230414133753.653139-6-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l56-sdw.c | 4 +++- sound/soc/codecs/cs35l56.c | 4 +--- sound/soc/codecs/cs35l56.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/cs35l56-sdw.c b/sound/soc/codecs/cs35l56-sdw.c index e759347423cf..2cde78605ba9 100644 --- a/sound/soc/codecs/cs35l56-sdw.c +++ b/sound/soc/codecs/cs35l56-sdw.c @@ -527,7 +527,9 @@ static int cs35l56_sdw_remove(struct sdw_slave *peripheral) sdw_read_no_pm(peripheral, CS35L56_SDW_GEN_INT_STAT_1); sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_STAT_1, 0xFF); - return cs35l56_remove(cs35l56); + cs35l56_remove(cs35l56); + + return 0; } static const struct dev_pm_ops cs35l56_sdw_pm = { diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c index 5f66a8e20b2d..0f4a94b02ef8 100644 --- a/sound/soc/codecs/cs35l56.c +++ b/sound/soc/codecs/cs35l56.c @@ -1590,7 +1590,7 @@ post_soft_reset: } EXPORT_SYMBOL_NS_GPL(cs35l56_init, SND_SOC_CS35L56_CORE); -int cs35l56_remove(struct cs35l56_private *cs35l56) +void cs35l56_remove(struct cs35l56_private *cs35l56) { cs35l56->init_done = false; @@ -1613,8 +1613,6 @@ int cs35l56_remove(struct cs35l56_private *cs35l56) gpiod_set_value_cansleep(cs35l56->reset_gpio, 0); regulator_bulk_disable(ARRAY_SIZE(cs35l56->supplies), cs35l56->supplies); - - return 0; } EXPORT_SYMBOL_NS_GPL(cs35l56_remove, SND_SOC_CS35L56_CORE); diff --git a/sound/soc/codecs/cs35l56.h b/sound/soc/codecs/cs35l56.h index 09762e70ce81..1f7894662fcb 100644 --- a/sound/soc/codecs/cs35l56.h +++ b/sound/soc/codecs/cs35l56.h @@ -76,6 +76,6 @@ irqreturn_t cs35l56_irq(int irq, void *data); int cs35l56_irq_request(struct cs35l56_private *cs35l56, int irq); int cs35l56_common_probe(struct cs35l56_private *cs35l56); int cs35l56_init(struct cs35l56_private *cs35l56); -int cs35l56_remove(struct cs35l56_private *cs35l56); +void cs35l56_remove(struct cs35l56_private *cs35l56); #endif /* ifndef CS35L56_H */ From 8076c586bbc1c62e075e58f41dafdd8b5022b24d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Anikiel?= Date: Fri, 14 Apr 2023 16:02:00 +0200 Subject: [PATCH 742/778] ASoC: ssm2602: Add support for CLKDIV2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The SSM260x chips have an internal MCLK /2 divider (bit D7 in register R8). Add logic that allows for more MCLK values using this divider. Signed-off-by: Paweł Anikiel Link: https://lore.kernel.org/r/20230414140203.707729-7-pan@semihalf.com Signed-off-by: Mark Brown --- sound/soc/codecs/ssm2602.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c index cbbe83b85ada..00b60369b029 100644 --- a/sound/soc/codecs/ssm2602.c +++ b/sound/soc/codecs/ssm2602.c @@ -280,9 +280,12 @@ static inline int ssm2602_get_coeff(int mclk, int rate) int i; for (i = 0; i < ARRAY_SIZE(ssm2602_coeff_table); i++) { - if (ssm2602_coeff_table[i].rate == rate && - ssm2602_coeff_table[i].mclk == mclk) - return ssm2602_coeff_table[i].srate; + if (ssm2602_coeff_table[i].rate == rate) { + if (ssm2602_coeff_table[i].mclk == mclk) + return ssm2602_coeff_table[i].srate; + if (ssm2602_coeff_table[i].mclk == mclk / 2) + return ssm2602_coeff_table[i].srate | SRATE_CORECLK_DIV2; + } } return -EINVAL; } @@ -365,18 +368,24 @@ static int ssm2602_set_dai_sysclk(struct snd_soc_dai *codec_dai, switch (freq) { case 12288000: case 18432000: + case 24576000: + case 36864000: ssm2602->sysclk_constraints = &ssm2602_constraints_12288000; break; case 11289600: case 16934400: + case 22579200: + case 33868800: ssm2602->sysclk_constraints = &ssm2602_constraints_11289600; break; case 12000000: + case 24000000: ssm2602->sysclk_constraints = NULL; break; default: return -EINVAL; } + ssm2602->sysclk = freq; } else { unsigned int mask; From 59de6c38d713bb16760cc2612a79bc373f79bc6b Mon Sep 17 00:00:00 2001 From: Saalim Quadri Date: Fri, 14 Apr 2023 22:38:01 +0000 Subject: [PATCH 743/778] ASoC: dt-bindings: wm8753: Convert to dtschema Convert the WM8753 audio codec bindings to DT schema. Signed-off-by: Saalim Quadri Acked-by: Charles Keepax Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230414223801.1106550-1-danascape@gmail.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/wlf,wm8753.yaml | 62 +++++++++++++++++++ .../devicetree/bindings/sound/wm8753.txt | 40 ------------ 2 files changed, 62 insertions(+), 40 deletions(-) create mode 100644 Documentation/devicetree/bindings/sound/wlf,wm8753.yaml delete mode 100644 Documentation/devicetree/bindings/sound/wm8753.txt diff --git a/Documentation/devicetree/bindings/sound/wlf,wm8753.yaml b/Documentation/devicetree/bindings/sound/wlf,wm8753.yaml new file mode 100644 index 000000000000..9eebe7d7f0b7 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/wlf,wm8753.yaml @@ -0,0 +1,62 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/wlf,wm8753.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: WM8753 audio CODEC + +description: | + Pins on the device (for linking into audio routes): + * LOUT1 + * LOUT2 + * ROUT1 + * ROUT2 + * MONO1 + * MONO2 + * OUT3 + * OUT4 + * LINE1 + * LINE2 + * RXP + * RXN + * ACIN + * ACOP + * MIC1N + * MIC1 + * MIC2N + * MIC2 + * Mic Bias + +maintainers: + - patches@opensource.cirrus.com + +allOf: + - $ref: dai-common.yaml# + +properties: + compatible: + const: wlf,wm8753 + + reg: + maxItems: 1 + + "#sound-dai-cells": + const: 0 + +required: + - compatible + - reg + +unevaluatedProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + codec@1a { + compatible = "wlf,wm8753"; + reg = <0x1a>; + }; + }; diff --git a/Documentation/devicetree/bindings/sound/wm8753.txt b/Documentation/devicetree/bindings/sound/wm8753.txt deleted file mode 100644 index eca9e5a825a9..000000000000 --- a/Documentation/devicetree/bindings/sound/wm8753.txt +++ /dev/null @@ -1,40 +0,0 @@ -WM8753 audio CODEC - -This device supports both I2C and SPI (configured with pin strapping -on the board). - -Required properties: - - - compatible : "wlf,wm8753" - - - reg : the I2C address of the device for I2C, the chip select - number for SPI. - -Pins on the device (for linking into audio routes): - - * LOUT1 - * LOUT2 - * ROUT1 - * ROUT2 - * MONO1 - * MONO2 - * OUT3 - * OUT4 - * LINE1 - * LINE2 - * RXP - * RXN - * ACIN - * ACOP - * MIC1N - * MIC1 - * MIC2N - * MIC2 - * Mic Bias - -Example: - -wm8753: codec@1a { - compatible = "wlf,wm8753"; - reg = <0x1a>; -}; From 4a778bdc7afbc422bd513c4f1cd7a9faf4bebaab Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Apr 2023 00:15:48 +0000 Subject: [PATCH 744/778] ASoC: expand snd_soc_dapm_mutex_lock/unlock() soc.h has snd_soc_dapm_mutex_lock/unlock() definition and many drivers are using it, but soc-dapm.c is not. 1st reason is snd_soc_dapm_mutex_lock/unlock() requests snd_soc_dapm_context pointer as parameter (A), but sometimes soc-dapm.c needs to use snd_soc_card (B). (A) static inline void snd_soc_dapm_mutex_lock(struct snd_soc_dapm_context *dapm) { mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); } ^^^^^^^^^^ (B) mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); ^^^^ 2nd reason is it want to use SND_SOC_DAPM_CLASS_INIT for mutex_lock_nested(), but helper is using _RUNTIME (A). The conclusion is we want to use "dapm vs card" and "_RUNTIME vs _INIT" for dapm lock/unlock. To enable this selfish request, this patch uses _Generic macro. We can use snd_soc_dapm_mutex_lock/unlock() for both dapm and card case. snd_soc_dapm_mutex_lock(dapm); snd_soc_dapm_mutex_unlock(dapm); snd_soc_dapm_mutex_lock(card); snd_soc_dapm_mutex_unlock(card); Current soc-dapm.c is using both mutex_lock() and mutex_lock_nested(). This patch handles mutex_lock() as mutex_lock_nested(..., 0), in other words, handles below as same. mutex_lock(&card->dapm_mutex); mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT); Because people might misunderstand that _init() is mutex initialization, this patch renames _INIT to _ROOT and adds new snd_soc_dapm_mutex_lock_root() for it. This patch also moves snd_soc_dapm_subclass definition from soc-dapm.h to soc.h to keep related code together. Because very complex soc.h vs soc-dapm.h relationship, it is difficult/impossible to define these helper into soc-dapm.h. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87cz4hx3v0.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dapm.h | 5 -- include/sound/soc.h | 60 ++++++++++++++++++-- sound/soc/soc-dapm.c | 119 +++++++++++++++++++-------------------- 3 files changed, 113 insertions(+), 71 deletions(-) diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 64915ebd641e..87f8e1793af1 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -527,11 +527,6 @@ enum snd_soc_dapm_type { SND_SOC_DAPM_TYPE_COUNT }; -enum snd_soc_dapm_subclass { - SND_SOC_DAPM_CLASS_INIT = 0, - SND_SOC_DAPM_CLASS_RUNTIME = 1, -}; - /* * DAPM audio route definition. * diff --git a/include/sound/soc.h b/include/sound/soc.h index 3833184c187f..0e17e3230c7a 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1364,17 +1364,67 @@ extern struct dentry *snd_soc_debugfs_root; extern const struct dev_pm_ops snd_soc_pm_ops; -/* Helper functions */ -static inline void snd_soc_dapm_mutex_lock(struct snd_soc_dapm_context *dapm) +/* + * DAPM helper functions + */ +enum snd_soc_dapm_subclass { + SND_SOC_DAPM_CLASS_ROOT = 0, + SND_SOC_DAPM_CLASS_RUNTIME = 1, +}; + +static inline void _snd_soc_dapm_mutex_lock_root_c(struct snd_soc_card *card) { - mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); + mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_ROOT); } -static inline void snd_soc_dapm_mutex_unlock(struct snd_soc_dapm_context *dapm) +static inline void _snd_soc_dapm_mutex_lock_c(struct snd_soc_card *card) { - mutex_unlock(&dapm->card->dapm_mutex); + mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); } +static inline void _snd_soc_dapm_mutex_unlock_c(struct snd_soc_card *card) +{ + mutex_unlock(&card->dapm_mutex); +} + +static inline void _snd_soc_dapm_mutex_assert_held_c(struct snd_soc_card *card) +{ + lockdep_assert_held(&card->dapm_mutex); +} + +static inline void _snd_soc_dapm_mutex_lock_root_d(struct snd_soc_dapm_context *dapm) +{ + _snd_soc_dapm_mutex_lock_root_c(dapm->card); +} + +static inline void _snd_soc_dapm_mutex_lock_d(struct snd_soc_dapm_context *dapm) +{ + _snd_soc_dapm_mutex_lock_c(dapm->card); +} + +static inline void _snd_soc_dapm_mutex_unlock_d(struct snd_soc_dapm_context *dapm) +{ + _snd_soc_dapm_mutex_unlock_c(dapm->card); +} + +static inline void _snd_soc_dapm_mutex_assert_held_d(struct snd_soc_dapm_context *dapm) +{ + _snd_soc_dapm_mutex_assert_held_c(dapm->card); +} + +#define snd_soc_dapm_mutex_lock_root(x) _Generic((x), \ + struct snd_soc_card * : _snd_soc_dapm_mutex_lock_root_c, \ + struct snd_soc_dapm_context * : _snd_soc_dapm_mutex_lock_root_d)(x) +#define snd_soc_dapm_mutex_lock(x) _Generic((x), \ + struct snd_soc_card * : _snd_soc_dapm_mutex_lock_c, \ + struct snd_soc_dapm_context * : _snd_soc_dapm_mutex_lock_d)(x) +#define snd_soc_dapm_mutex_unlock(x) _Generic((x), \ + struct snd_soc_card * : _snd_soc_dapm_mutex_unlock_c, \ + struct snd_soc_dapm_context * : _snd_soc_dapm_mutex_unlock_d)(x) +#define snd_soc_dapm_mutex_assert_held(x) _Generic((x), \ + struct snd_soc_card * : _snd_soc_dapm_mutex_assert_held_c, \ + struct snd_soc_dapm_context * : _snd_soc_dapm_mutex_assert_held_d)(x) + #include #include #include diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 36e6f261bcf7..f2f04ce693a1 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -150,7 +150,7 @@ static int dapm_down_seq[] = { static void dapm_assert_locked(struct snd_soc_dapm_context *dapm) { if (snd_soc_card_is_instantiated(dapm->card)) - lockdep_assert_held(&dapm->card->dapm_mutex); + snd_soc_dapm_mutex_assert_held(dapm); } static void pop_wait(u32 pop_time) @@ -302,7 +302,7 @@ void dapm_mark_endpoints_dirty(struct snd_soc_card *card) { struct snd_soc_dapm_widget *w; - mutex_lock(&card->dapm_mutex); + snd_soc_dapm_mutex_lock_root(card); for_each_card_widgets(card, w) { if (w->is_ep) { @@ -314,7 +314,7 @@ void dapm_mark_endpoints_dirty(struct snd_soc_card *card) } } - mutex_unlock(&card->dapm_mutex); + snd_soc_dapm_mutex_unlock(card); } EXPORT_SYMBOL_GPL(dapm_mark_endpoints_dirty); @@ -604,7 +604,7 @@ static void dapm_reset(struct snd_soc_card *card) { struct snd_soc_dapm_widget *w; - lockdep_assert_held(&card->dapm_mutex); + snd_soc_dapm_mutex_assert_held(card); memset(&card->dapm_stats, 0, sizeof(card->dapm_stats)); @@ -1302,7 +1302,7 @@ int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream, int paths; int ret; - mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); + snd_soc_dapm_mutex_lock(card); if (stream == SNDRV_PCM_STREAM_PLAYBACK) { invalidate_paths_ep(w, SND_SOC_DAPM_DIR_OUT); @@ -1322,7 +1322,7 @@ int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream, paths = ret; trace_snd_soc_dapm_connected(paths, stream); - mutex_unlock(&card->dapm_mutex); + snd_soc_dapm_mutex_unlock(card); return paths; } @@ -1952,7 +1952,7 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event) enum snd_soc_bias_level bias; int ret; - lockdep_assert_held(&card->dapm_mutex); + snd_soc_dapm_mutex_assert_held(card); trace_snd_soc_dapm_start(card); @@ -2090,7 +2090,6 @@ static ssize_t dapm_widget_power_read_file(struct file *file, size_t count, loff_t *ppos) { struct snd_soc_dapm_widget *w = file->private_data; - struct snd_soc_card *card = w->dapm->card; enum snd_soc_dapm_direction dir, rdir; char *buf; int in, out; @@ -2101,7 +2100,7 @@ static ssize_t dapm_widget_power_read_file(struct file *file, if (!buf) return -ENOMEM; - mutex_lock(&card->dapm_mutex); + snd_soc_dapm_mutex_lock_root(w->dapm); /* Supply widgets are not handled by is_connected_{input,output}_ep() */ if (w->is_supply) { @@ -2145,7 +2144,7 @@ static ssize_t dapm_widget_power_read_file(struct file *file, } } - mutex_unlock(&card->dapm_mutex); + snd_soc_dapm_mutex_unlock(w->dapm); ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret); @@ -2266,7 +2265,7 @@ static int soc_dapm_mux_update_power(struct snd_soc_card *card, int found = 0; bool connect; - lockdep_assert_held(&card->dapm_mutex); + snd_soc_dapm_mutex_assert_held(card); /* find dapm widget path assoc with kcontrol */ dapm_kcontrol_for_each_path(path, kcontrol) { @@ -2293,11 +2292,11 @@ int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_context *dapm, struct snd_soc_card *card = dapm->card; int ret; - mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); + snd_soc_dapm_mutex_lock(card); card->update = update; ret = soc_dapm_mux_update_power(card, kcontrol, mux, e); card->update = NULL; - mutex_unlock(&card->dapm_mutex); + snd_soc_dapm_mutex_unlock(card); if (ret > 0) snd_soc_dpcm_runtime_update(card); return ret; @@ -2312,7 +2311,7 @@ static int soc_dapm_mixer_update_power(struct snd_soc_card *card, struct snd_soc_dapm_path *path; int found = 0; - lockdep_assert_held(&card->dapm_mutex); + snd_soc_dapm_mutex_assert_held(card); /* find dapm widget path assoc with kcontrol */ dapm_kcontrol_for_each_path(path, kcontrol) { @@ -2358,11 +2357,11 @@ int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_context *dapm, struct snd_soc_card *card = dapm->card; int ret; - mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); + snd_soc_dapm_mutex_lock(card); card->update = update; ret = soc_dapm_mixer_update_power(card, kcontrol, connect, -1); card->update = NULL; - mutex_unlock(&card->dapm_mutex); + snd_soc_dapm_mutex_unlock(card); if (ret > 0) snd_soc_dpcm_runtime_update(card); return ret; @@ -2441,7 +2440,7 @@ static ssize_t dapm_widget_show(struct device *dev, struct snd_soc_dai *codec_dai; int i, count = 0; - mutex_lock(&rtd->card->dapm_mutex); + snd_soc_dapm_mutex_lock_root(rtd->card); for_each_rtd_codec_dais(rtd, i, codec_dai) { struct snd_soc_component *cmpnt = codec_dai->component; @@ -2449,7 +2448,7 @@ static ssize_t dapm_widget_show(struct device *dev, count = dapm_widget_show_component(cmpnt, buf, count); } - mutex_unlock(&rtd->card->dapm_mutex); + snd_soc_dapm_mutex_unlock(rtd->card); return count; } @@ -2632,9 +2631,9 @@ int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm) { int ret; - mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); + snd_soc_dapm_mutex_lock(dapm); ret = snd_soc_dapm_sync_unlocked(dapm); - mutex_unlock(&dapm->card->dapm_mutex); + snd_soc_dapm_mutex_unlock(dapm); return ret; } EXPORT_SYMBOL_GPL(snd_soc_dapm_sync); @@ -2703,9 +2702,9 @@ int snd_soc_dapm_update_dai(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); int ret; - mutex_lock_nested(&rtd->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); + snd_soc_dapm_mutex_lock(rtd->card); ret = dapm_update_dai_unlocked(substream, params, dai); - mutex_unlock(&rtd->card->dapm_mutex); + snd_soc_dapm_mutex_unlock(rtd->card); return ret; } @@ -3090,14 +3089,14 @@ int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm, { int i, ret = 0; - mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); + snd_soc_dapm_mutex_lock(dapm); for (i = 0; i < num; i++) { int r = snd_soc_dapm_add_route(dapm, route); if (r < 0) ret = r; route++; } - mutex_unlock(&dapm->card->dapm_mutex); + snd_soc_dapm_mutex_unlock(dapm); return ret; } @@ -3116,12 +3115,12 @@ int snd_soc_dapm_del_routes(struct snd_soc_dapm_context *dapm, { int i; - mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); + snd_soc_dapm_mutex_lock(dapm); for (i = 0; i < num; i++) { snd_soc_dapm_del_route(dapm, route); route++; } - mutex_unlock(&dapm->card->dapm_mutex); + snd_soc_dapm_mutex_unlock(dapm); return 0; } @@ -3194,14 +3193,14 @@ int snd_soc_dapm_weak_routes(struct snd_soc_dapm_context *dapm, int i; int ret = 0; - mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT); + snd_soc_dapm_mutex_lock_root(dapm); for (i = 0; i < num; i++) { int err = snd_soc_dapm_weak_route(dapm, route); if (err) ret = err; route++; } - mutex_unlock(&dapm->card->dapm_mutex); + snd_soc_dapm_mutex_unlock(dapm); return ret; } @@ -3220,7 +3219,7 @@ int snd_soc_dapm_new_widgets(struct snd_soc_card *card) struct snd_soc_dapm_widget *w; unsigned int val; - mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT); + snd_soc_dapm_mutex_lock_root(card); for_each_card_widgets(card, w) { @@ -3232,7 +3231,7 @@ int snd_soc_dapm_new_widgets(struct snd_soc_card *card) sizeof(struct snd_kcontrol *), GFP_KERNEL); if (!w->kcontrols) { - mutex_unlock(&card->dapm_mutex); + snd_soc_dapm_mutex_unlock(card); return -ENOMEM; } } @@ -3275,7 +3274,7 @@ int snd_soc_dapm_new_widgets(struct snd_soc_card *card) } dapm_power_widgets(card, SND_SOC_DAPM_STREAM_NOP); - mutex_unlock(&card->dapm_mutex); + snd_soc_dapm_mutex_unlock(card); return 0; } EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets); @@ -3293,7 +3292,6 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); - struct snd_soc_card *card = dapm->card; struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; int reg = mc->reg; @@ -3304,7 +3302,7 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, unsigned int invert = mc->invert; unsigned int reg_val, val, rval = 0; - mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); + snd_soc_dapm_mutex_lock(dapm); if (dapm_kcontrol_is_powered(kcontrol) && reg != SND_SOC_NOPM) { reg_val = soc_dapm_read(dapm, reg); val = (reg_val >> shift) & mask; @@ -3321,7 +3319,7 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, if (snd_soc_volsw_is_stereo(mc)) rval = (reg_val >> width) & mask; } - mutex_unlock(&card->dapm_mutex); + snd_soc_dapm_mutex_unlock(dapm); if (invert) ucontrol->value.integer.value[0] = max - val; @@ -3379,7 +3377,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, rval = max - rval; } - mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); + snd_soc_dapm_mutex_lock(card); /* This assumes field width < (bits in unsigned int / 2) */ if (width > sizeof(unsigned int) * 8 / 2) @@ -3421,7 +3419,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, card->update = NULL; } - mutex_unlock(&card->dapm_mutex); + snd_soc_dapm_mutex_unlock(card); if (ret > 0) snd_soc_dpcm_runtime_update(card); @@ -3443,17 +3441,16 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); - struct snd_soc_card *card = dapm->card; struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; unsigned int reg_val, val; - mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); + snd_soc_dapm_mutex_lock(dapm); if (e->reg != SND_SOC_NOPM && dapm_kcontrol_is_powered(kcontrol)) { reg_val = soc_dapm_read(dapm, e->reg); } else { reg_val = dapm_kcontrol_get_value(kcontrol); } - mutex_unlock(&card->dapm_mutex); + snd_soc_dapm_mutex_unlock(dapm); val = (reg_val >> e->shift_l) & e->mask; ucontrol->value.enumerated.item[0] = snd_soc_enum_val_to_item(e, val); @@ -3500,7 +3497,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, mask |= e->mask << e->shift_r; } - mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); + snd_soc_dapm_mutex_lock(card); change = dapm_kcontrol_set_value(kcontrol, val); @@ -3521,7 +3518,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, card->update = NULL; } - mutex_unlock(&card->dapm_mutex); + snd_soc_dapm_mutex_unlock(card); if (ret > 0) snd_soc_dpcm_runtime_update(card); @@ -3562,12 +3559,12 @@ int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol, struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); const char *pin = (const char *)kcontrol->private_value; - mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); + snd_soc_dapm_mutex_lock(card); ucontrol->value.integer.value[0] = snd_soc_dapm_get_pin_status(&card->dapm, pin); - mutex_unlock(&card->dapm_mutex); + snd_soc_dapm_mutex_unlock(card); return 0; } @@ -3586,10 +3583,10 @@ int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol, const char *pin = (const char *)kcontrol->private_value; int ret; - mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); + snd_soc_dapm_mutex_lock(card); ret = __snd_soc_dapm_set_pin(&card->dapm, pin, !!ucontrol->value.integer.value[0]); - mutex_unlock(&card->dapm_mutex); + snd_soc_dapm_mutex_unlock(card); snd_soc_dapm_sync(&card->dapm); return ret; @@ -3762,9 +3759,9 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, { struct snd_soc_dapm_widget *w; - mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); + snd_soc_dapm_mutex_lock(dapm); w = snd_soc_dapm_new_control_unlocked(dapm, widget); - mutex_unlock(&dapm->card->dapm_mutex); + snd_soc_dapm_mutex_unlock(dapm); return w; } @@ -3787,7 +3784,7 @@ int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm, int i; int ret = 0; - mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT); + snd_soc_dapm_mutex_lock_root(dapm); for (i = 0; i < num; i++) { struct snd_soc_dapm_widget *w = snd_soc_dapm_new_control_unlocked(dapm, widget); if (IS_ERR(w)) { @@ -3796,7 +3793,7 @@ int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm, } widget++; } - mutex_unlock(&dapm->card->dapm_mutex); + snd_soc_dapm_mutex_unlock(dapm); return ret; } EXPORT_SYMBOL_GPL(snd_soc_dapm_new_controls); @@ -4499,9 +4496,9 @@ void snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream, { struct snd_soc_card *card = rtd->card; - mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); + snd_soc_dapm_mutex_lock(card); soc_dapm_stream_event(rtd, stream, event); - mutex_unlock(&card->dapm_mutex); + snd_soc_dapm_mutex_unlock(card); } void snd_soc_dapm_stream_stop(struct snd_soc_pcm_runtime *rtd, int stream) @@ -4562,11 +4559,11 @@ int snd_soc_dapm_enable_pin(struct snd_soc_dapm_context *dapm, const char *pin) { int ret; - mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); + snd_soc_dapm_mutex_lock(dapm); ret = snd_soc_dapm_set_pin(dapm, pin, 1); - mutex_unlock(&dapm->card->dapm_mutex); + snd_soc_dapm_mutex_unlock(dapm); return ret; } @@ -4630,11 +4627,11 @@ int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm, { int ret; - mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); + snd_soc_dapm_mutex_lock(dapm); ret = snd_soc_dapm_force_enable_pin_unlocked(dapm, pin); - mutex_unlock(&dapm->card->dapm_mutex); + snd_soc_dapm_mutex_unlock(dapm); return ret; } @@ -4674,11 +4671,11 @@ int snd_soc_dapm_disable_pin(struct snd_soc_dapm_context *dapm, { int ret; - mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); + snd_soc_dapm_mutex_lock(dapm); ret = snd_soc_dapm_set_pin(dapm, pin, 0); - mutex_unlock(&dapm->card->dapm_mutex); + snd_soc_dapm_mutex_unlock(dapm); return ret; } @@ -4725,11 +4722,11 @@ int snd_soc_dapm_nc_pin(struct snd_soc_dapm_context *dapm, const char *pin) { int ret; - mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); + snd_soc_dapm_mutex_lock(dapm); ret = snd_soc_dapm_set_pin(dapm, pin, 0); - mutex_unlock(&dapm->card->dapm_mutex); + snd_soc_dapm_mutex_unlock(dapm); return ret; } @@ -4826,7 +4823,7 @@ static void soc_dapm_shutdown_dapm(struct snd_soc_dapm_context *dapm) LIST_HEAD(down_list); int powerdown = 0; - mutex_lock(&card->dapm_mutex); + snd_soc_dapm_mutex_lock_root(card); for_each_card_widgets(dapm->card, w) { if (w->dapm != dapm) @@ -4851,7 +4848,7 @@ static void soc_dapm_shutdown_dapm(struct snd_soc_dapm_context *dapm) SND_SOC_BIAS_STANDBY); } - mutex_unlock(&card->dapm_mutex); + snd_soc_dapm_mutex_unlock(card); } /* From 38e42f6d6c6702bbfc633fce9b579fb80cec2d59 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Apr 2023 00:16:10 +0000 Subject: [PATCH 745/778] ASoC: expand snd_soc_dpcm_mutex_lock/unlock() soc-pcm.c has snd_soc_dpcm_mutex_lock/unlock(), but other files can't use it because it is static function. It requests snd_soc_pcm_runtime as parameter (A), but sometimes we want to use it by snd_soc_card (B). (A) static inline void snd_soc_dpcm_mutex_lock(struct snd_soc_pcm_runtime *rtd) { mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); } ^^^^^^^^^ (B) mutex_lock_nested(&card->pcm_mutex, card->pcm_subclass); ^^^^ We want to use it with both "rtd" and "card" for dapm lock/unlock. To enable it, this patch uses _Generic macro. This patch makes snd_soc_dpcm_mutex_{un}lock() global function, and use it on each files. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87bkk1x3ud.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc.h | 45 +++++++++++++++++++++++++++++++++++++++ sound/soc/soc-component.c | 12 +++++------ sound/soc/soc-compress.c | 42 ++++++++++++++++++------------------ sound/soc/soc-core.c | 4 ++-- sound/soc/soc-pcm.c | 17 ++------------- 5 files changed, 76 insertions(+), 44 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index 0e17e3230c7a..05004c048dd5 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1425,6 +1425,51 @@ static inline void _snd_soc_dapm_mutex_assert_held_d(struct snd_soc_dapm_context struct snd_soc_card * : _snd_soc_dapm_mutex_assert_held_c, \ struct snd_soc_dapm_context * : _snd_soc_dapm_mutex_assert_held_d)(x) +/* + * PCM helper functions + */ +static inline void _snd_soc_dpcm_mutex_lock_c(struct snd_soc_card *card) +{ + mutex_lock_nested(&card->pcm_mutex, card->pcm_subclass); +} + +static inline void _snd_soc_dpcm_mutex_unlock_c(struct snd_soc_card *card) +{ + mutex_unlock(&card->pcm_mutex); +} + +static inline void _snd_soc_dpcm_mutex_assert_held_c(struct snd_soc_card *card) +{ + lockdep_assert_held(&card->pcm_mutex); +} + +static inline void _snd_soc_dpcm_mutex_lock_r(struct snd_soc_pcm_runtime *rtd) +{ + _snd_soc_dpcm_mutex_lock_c(rtd->card); +} + +static inline void _snd_soc_dpcm_mutex_unlock_r(struct snd_soc_pcm_runtime *rtd) +{ + _snd_soc_dpcm_mutex_unlock_c(rtd->card); +} + +static inline void _snd_soc_dpcm_mutex_assert_held_r(struct snd_soc_pcm_runtime *rtd) +{ + _snd_soc_dpcm_mutex_assert_held_c(rtd->card); +} + +#define snd_soc_dpcm_mutex_lock(x) _Generic((x), \ + struct snd_soc_card * : _snd_soc_dpcm_mutex_lock_c, \ + struct snd_soc_pcm_runtime * : _snd_soc_dpcm_mutex_lock_r)(x) + +#define snd_soc_dpcm_mutex_unlock(x) _Generic((x), \ + struct snd_soc_card * : _snd_soc_dpcm_mutex_unlock_c, \ + struct snd_soc_pcm_runtime * : _snd_soc_dpcm_mutex_unlock_r)(x) + +#define snd_soc_dpcm_mutex_assert_held(x) _Generic((x), \ + struct snd_soc_card * : _snd_soc_dpcm_mutex_assert_held_c, \ + struct snd_soc_pcm_runtime * : _snd_soc_dpcm_mutex_assert_held_r)(x) + #include #include #include diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c index 3cd6952212e1..ff25718ff2e8 100644 --- a/sound/soc/soc-component.c +++ b/sound/soc/soc-component.c @@ -550,7 +550,7 @@ int snd_soc_component_compr_get_caps(struct snd_compr_stream *cstream, struct snd_soc_component *component; int i, ret = 0; - mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); + snd_soc_dpcm_mutex_lock(rtd); for_each_rtd_components(rtd, i, component) { if (component->driver->compress_ops && @@ -561,7 +561,7 @@ int snd_soc_component_compr_get_caps(struct snd_compr_stream *cstream, } } - mutex_unlock(&rtd->card->pcm_mutex); + snd_soc_dpcm_mutex_unlock(rtd); return soc_component_ret(component, ret); } @@ -574,7 +574,7 @@ int snd_soc_component_compr_get_codec_caps(struct snd_compr_stream *cstream, struct snd_soc_component *component; int i, ret = 0; - mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); + snd_soc_dpcm_mutex_lock(rtd); for_each_rtd_components(rtd, i, component) { if (component->driver->compress_ops && @@ -585,7 +585,7 @@ int snd_soc_component_compr_get_codec_caps(struct snd_compr_stream *cstream, } } - mutex_unlock(&rtd->card->pcm_mutex); + snd_soc_dpcm_mutex_unlock(rtd); return soc_component_ret(component, ret); } @@ -638,7 +638,7 @@ int snd_soc_component_compr_copy(struct snd_compr_stream *cstream, struct snd_soc_component *component; int i, ret = 0; - mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); + snd_soc_dpcm_mutex_lock(rtd); for_each_rtd_components(rtd, i, component) { if (component->driver->compress_ops && @@ -649,7 +649,7 @@ int snd_soc_component_compr_copy(struct snd_compr_stream *cstream, } } - mutex_unlock(&rtd->card->pcm_mutex); + snd_soc_dpcm_mutex_unlock(rtd); return soc_component_ret(component, ret); } diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 6e74a6c48986..661e9d70994f 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -62,7 +62,7 @@ static int soc_compr_clean(struct snd_compr_stream *cstream, int rollback) struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */ - mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); + snd_soc_dpcm_mutex_lock(rtd); if (!rollback) snd_soc_runtime_deactivate(rtd, stream); @@ -84,7 +84,7 @@ static int soc_compr_clean(struct snd_compr_stream *cstream, int rollback) if (!rollback) snd_soc_dapm_stream_stop(rtd, stream); - mutex_unlock(&rtd->card->pcm_mutex); + snd_soc_dpcm_mutex_unlock(rtd); snd_soc_pcm_component_pm_runtime_put(rtd, cstream, rollback); @@ -107,7 +107,7 @@ static int soc_compr_open(struct snd_compr_stream *cstream) if (ret < 0) goto err_no_lock; - mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); + snd_soc_dpcm_mutex_lock(rtd); ret = snd_soc_dai_compr_startup(cpu_dai, cstream); if (ret < 0) @@ -123,7 +123,7 @@ static int soc_compr_open(struct snd_compr_stream *cstream) snd_soc_runtime_activate(rtd, stream); err: - mutex_unlock(&rtd->card->pcm_mutex); + snd_soc_dpcm_mutex_unlock(rtd); err_no_lock: if (ret < 0) soc_compr_clean(cstream, 1); @@ -146,7 +146,7 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream) if (ret < 0) goto be_err; - mutex_lock_nested(&fe->card->pcm_mutex, fe->card->pcm_subclass); + snd_soc_dpcm_mutex_lock(fe); /* calculate valid and active FE <-> BE dpcms */ dpcm_process_paths(fe, stream, &list, 1); @@ -182,7 +182,7 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream) fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; snd_soc_runtime_activate(fe, stream); - mutex_unlock(&fe->card->pcm_mutex); + snd_soc_dpcm_mutex_unlock(fe); mutex_unlock(&fe->card->mutex); @@ -209,7 +209,7 @@ static int soc_compr_free_fe(struct snd_compr_stream *cstream) mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); - mutex_lock_nested(&fe->card->pcm_mutex, fe->card->pcm_subclass); + snd_soc_dpcm_mutex_lock(fe); snd_soc_runtime_deactivate(fe, stream); fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; @@ -229,7 +229,7 @@ static int soc_compr_free_fe(struct snd_compr_stream *cstream) dpcm_be_disconnect(fe, stream); - mutex_unlock(&fe->card->pcm_mutex); + snd_soc_dpcm_mutex_unlock(fe); snd_soc_link_compr_shutdown(cstream, 0); @@ -249,7 +249,7 @@ static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd) int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */ int ret; - mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); + snd_soc_dpcm_mutex_lock(rtd); ret = snd_soc_component_compr_trigger(cstream, cmd); if (ret < 0) @@ -269,7 +269,7 @@ static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd) } out: - mutex_unlock(&rtd->card->pcm_mutex); + snd_soc_dpcm_mutex_unlock(rtd); return ret; } @@ -327,7 +327,7 @@ static int soc_compr_set_params(struct snd_compr_stream *cstream, int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */ int ret; - mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); + snd_soc_dpcm_mutex_lock(rtd); /* * First we call set_params for the CPU DAI, then the component @@ -352,14 +352,14 @@ static int soc_compr_set_params(struct snd_compr_stream *cstream, /* cancel any delayed stream shutdown that is pending */ rtd->pop_wait = 0; - mutex_unlock(&rtd->card->pcm_mutex); + snd_soc_dpcm_mutex_unlock(rtd); cancel_delayed_work_sync(&rtd->delayed_work); return 0; err: - mutex_unlock(&rtd->card->pcm_mutex); + snd_soc_dpcm_mutex_unlock(rtd); return ret; } @@ -404,9 +404,9 @@ static int soc_compr_set_params_fe(struct snd_compr_stream *cstream, ret = snd_soc_link_compr_set_params(cstream); if (ret < 0) goto out; - mutex_lock_nested(&fe->card->pcm_mutex, fe->card->pcm_subclass); + snd_soc_dpcm_mutex_lock(fe); dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_START); - mutex_unlock(&fe->card->pcm_mutex); + snd_soc_dpcm_mutex_unlock(fe); fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE; out: @@ -422,7 +422,7 @@ static int soc_compr_get_params(struct snd_compr_stream *cstream, struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); int ret = 0; - mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); + snd_soc_dpcm_mutex_lock(rtd); ret = snd_soc_dai_compr_get_params(cpu_dai, cstream, params); if (ret < 0) @@ -430,7 +430,7 @@ static int soc_compr_get_params(struct snd_compr_stream *cstream, ret = snd_soc_component_compr_get_params(cstream, params); err: - mutex_unlock(&rtd->card->pcm_mutex); + snd_soc_dpcm_mutex_unlock(rtd); return ret; } @@ -440,7 +440,7 @@ static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes) struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); int ret; - mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); + snd_soc_dpcm_mutex_lock(rtd); ret = snd_soc_dai_compr_ack(cpu_dai, cstream, bytes); if (ret < 0) @@ -448,7 +448,7 @@ static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes) ret = snd_soc_component_compr_ack(cstream, bytes); err: - mutex_unlock(&rtd->card->pcm_mutex); + snd_soc_dpcm_mutex_unlock(rtd); return ret; } @@ -459,7 +459,7 @@ static int soc_compr_pointer(struct snd_compr_stream *cstream, int ret; struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); - mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); + snd_soc_dpcm_mutex_lock(rtd); ret = snd_soc_dai_compr_pointer(cpu_dai, cstream, tstamp); if (ret < 0) @@ -467,7 +467,7 @@ static int soc_compr_pointer(struct snd_compr_stream *cstream, ret = snd_soc_component_compr_pointer(cstream, tstamp); out: - mutex_unlock(&rtd->card->pcm_mutex); + snd_soc_dpcm_mutex_unlock(rtd); return ret; } diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 9bbcff492c1e..4594505cdae2 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -348,7 +348,7 @@ void snd_soc_close_delayed_work(struct snd_soc_pcm_runtime *rtd) struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int playback = SNDRV_PCM_STREAM_PLAYBACK; - mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); + snd_soc_dpcm_mutex_lock(rtd); dev_dbg(rtd->dev, "ASoC: pop wq checking: %s status: %s waiting: %s\n", @@ -364,7 +364,7 @@ void snd_soc_close_delayed_work(struct snd_soc_pcm_runtime *rtd) SND_SOC_DAPM_STREAM_STOP); } - mutex_unlock(&rtd->card->pcm_mutex); + snd_soc_dpcm_mutex_unlock(rtd); } EXPORT_SYMBOL_GPL(snd_soc_close_delayed_work); diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 913a7d98e742..adb69d7820a8 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -49,19 +49,6 @@ static inline int _soc_pcm_ret(struct snd_soc_pcm_runtime *rtd, return ret; } -static inline void snd_soc_dpcm_mutex_lock(struct snd_soc_pcm_runtime *rtd) -{ - mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); -} - -static inline void snd_soc_dpcm_mutex_unlock(struct snd_soc_pcm_runtime *rtd) -{ - mutex_unlock(&rtd->card->pcm_mutex); -} - -#define snd_soc_dpcm_mutex_assert_held(rtd) \ - lockdep_assert_held(&(rtd)->card->pcm_mutex) - static inline void snd_soc_dpcm_stream_lock_irq(struct snd_soc_pcm_runtime *rtd, int stream) { @@ -2664,7 +2651,7 @@ int snd_soc_dpcm_runtime_update(struct snd_soc_card *card) struct snd_soc_pcm_runtime *fe; int ret = 0; - mutex_lock_nested(&card->pcm_mutex, card->pcm_subclass); + snd_soc_dpcm_mutex_lock(card); /* shutdown all old paths first */ for_each_card_rtds(card, fe) { ret = soc_dpcm_fe_runtime_update(fe, 0); @@ -2680,7 +2667,7 @@ int snd_soc_dpcm_runtime_update(struct snd_soc_card *card) } out: - mutex_unlock(&card->pcm_mutex); + snd_soc_dpcm_mutex_unlock(card); return ret; } EXPORT_SYMBOL_GPL(snd_soc_dpcm_runtime_update); From 0f3b818486796ec8895fa4ccdf15edb759bff40a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Apr 2023 00:16:27 +0000 Subject: [PATCH 746/778] ASoC: add snd_soc_card_mutex_lock/unlock() ASoC need to use card->mutex with _INIT or _RUNTIME, but there is no helper function for it. This patch adds its helper function and use it. Because people might misunderstand that _init() is mutex initialization, this patch renames _INIT to _ROOT and adds new snd_soc_card_mutex_lock_root() for it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87a5zlx3tw.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-card.h | 17 ++++++++++++++++- sound/soc/soc-compress.c | 18 +++++++++--------- sound/soc/soc-core.c | 4 ++-- 3 files changed, 27 insertions(+), 12 deletions(-) diff --git a/include/sound/soc-card.h b/include/sound/soc-card.h index 9d31a5c0db33..fc94dfb0021f 100644 --- a/include/sound/soc-card.h +++ b/include/sound/soc-card.h @@ -9,10 +9,25 @@ #define __SOC_CARD_H enum snd_soc_card_subclass { - SND_SOC_CARD_CLASS_INIT = 0, + SND_SOC_CARD_CLASS_ROOT = 0, SND_SOC_CARD_CLASS_RUNTIME = 1, }; +static inline void snd_soc_card_mutex_lock_root(struct snd_soc_card *card) +{ + mutex_lock_nested(&card->mutex, SND_SOC_CARD_CLASS_ROOT); +} + +static inline void snd_soc_card_mutex_lock(struct snd_soc_card *card) +{ + mutex_lock_nested(&card->mutex, SND_SOC_CARD_CLASS_RUNTIME); +} + +static inline void snd_soc_card_mutex_unlock(struct snd_soc_card *card) +{ + mutex_unlock(&card->mutex); +} + struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card, const char *name); int snd_soc_card_jack_new(struct snd_soc_card *card, const char *id, int type, diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 661e9d70994f..d8715db5e415 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -140,7 +140,7 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream) int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */ int ret; - mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); + snd_soc_card_mutex_lock(fe->card); ret = dpcm_path_get(fe, stream, &list); if (ret < 0) @@ -184,7 +184,7 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream) snd_soc_runtime_activate(fe, stream); snd_soc_dpcm_mutex_unlock(fe); - mutex_unlock(&fe->card->mutex); + snd_soc_card_mutex_unlock(fe->card); return 0; @@ -196,7 +196,7 @@ out: dpcm_path_put(&list); be_err: fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; - mutex_unlock(&fe->card->mutex); + snd_soc_card_mutex_unlock(fe->card); return ret; } @@ -207,7 +207,7 @@ static int soc_compr_free_fe(struct snd_compr_stream *cstream) struct snd_soc_dpcm *dpcm; int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */ - mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); + snd_soc_card_mutex_lock(fe->card); snd_soc_dpcm_mutex_lock(fe); snd_soc_runtime_deactivate(fe, stream); @@ -237,7 +237,7 @@ static int soc_compr_free_fe(struct snd_compr_stream *cstream) snd_soc_dai_compr_shutdown(cpu_dai, cstream, 0); - mutex_unlock(&fe->card->mutex); + snd_soc_card_mutex_unlock(fe->card); return 0; } @@ -284,7 +284,7 @@ static int soc_compr_trigger_fe(struct snd_compr_stream *cstream, int cmd) cmd == SND_COMPR_TRIGGER_DRAIN) return snd_soc_component_compr_trigger(cstream, cmd); - mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); + snd_soc_card_mutex_lock(fe->card); ret = snd_soc_dai_compr_trigger(cpu_dai, cstream, cmd); if (ret < 0) @@ -315,7 +315,7 @@ static int soc_compr_trigger_fe(struct snd_compr_stream *cstream, int cmd) out: fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; - mutex_unlock(&fe->card->mutex); + snd_soc_card_mutex_unlock(fe->card); return ret; } @@ -373,7 +373,7 @@ static int soc_compr_set_params_fe(struct snd_compr_stream *cstream, int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */ int ret; - mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); + snd_soc_card_mutex_lock(fe->card); /* * Create an empty hw_params for the BE as the machine driver must @@ -411,7 +411,7 @@ static int soc_compr_set_params_fe(struct snd_compr_stream *cstream, out: fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; - mutex_unlock(&fe->card->mutex); + snd_soc_card_mutex_unlock(fe->card); return ret; } diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 4594505cdae2..b48efc3a08d2 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1938,7 +1938,7 @@ static int snd_soc_bind_card(struct snd_soc_card *card) int ret; mutex_lock(&client_mutex); - mutex_lock_nested(&card->mutex, SND_SOC_CARD_CLASS_INIT); + snd_soc_card_mutex_lock_root(card); snd_soc_dapm_init(&card->dapm, card, NULL); @@ -2093,7 +2093,7 @@ probe_end: if (ret < 0) soc_cleanup_card_resources(card); - mutex_unlock(&card->mutex); + snd_soc_card_mutex_unlock(card); mutex_unlock(&client_mutex); return ret; From 1c34890273a020d61d6127ade3f68ed1cb21c16a Mon Sep 17 00:00:00 2001 From: Liliang Ye Date: Mon, 3 Apr 2023 23:26:47 +0800 Subject: [PATCH 747/778] ASoC: fsl_mqs: move of_node_put() to the correct location of_node_put() should have been done directly after mqs_priv->regmap = syscon_node_to_regmap(gpr_np); otherwise it creates a reference leak on the success path. To fix this, of_node_put() is moved to the correct location, and change all the gotos to direct returns. Fixes: a9d273671440 ("ASoC: fsl_mqs: Fix error handling in probe") Signed-off-by: Liliang Ye Reviewed-by: Dan Carpenter Link: https://lore.kernel.org/r/20230403152647.17638-1-yll@hust.edu.cn Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_mqs.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/sound/soc/fsl/fsl_mqs.c b/sound/soc/fsl/fsl_mqs.c index 3fb3d3e4d09a..49ae7f6267d3 100644 --- a/sound/soc/fsl/fsl_mqs.c +++ b/sound/soc/fsl/fsl_mqs.c @@ -210,10 +210,10 @@ static int fsl_mqs_probe(struct platform_device *pdev) } mqs_priv->regmap = syscon_node_to_regmap(gpr_np); + of_node_put(gpr_np); if (IS_ERR(mqs_priv->regmap)) { dev_err(&pdev->dev, "failed to get gpr regmap\n"); - ret = PTR_ERR(mqs_priv->regmap); - goto err_free_gpr_np; + return PTR_ERR(mqs_priv->regmap); } } else { regs = devm_platform_ioremap_resource(pdev, 0); @@ -242,8 +242,7 @@ static int fsl_mqs_probe(struct platform_device *pdev) if (IS_ERR(mqs_priv->mclk)) { dev_err(&pdev->dev, "failed to get the clock: %ld\n", PTR_ERR(mqs_priv->mclk)); - ret = PTR_ERR(mqs_priv->mclk); - goto err_free_gpr_np; + return PTR_ERR(mqs_priv->mclk); } dev_set_drvdata(&pdev->dev, mqs_priv); @@ -252,13 +251,9 @@ static int fsl_mqs_probe(struct platform_device *pdev) ret = devm_snd_soc_register_component(&pdev->dev, &soc_codec_fsl_mqs, &fsl_mqs_dai, 1); if (ret) - goto err_free_gpr_np; + return ret; + return 0; - -err_free_gpr_np: - of_node_put(gpr_np); - - return ret; } static void fsl_mqs_remove(struct platform_device *pdev) From c341b5681fa074faa596fbb0fa0fc256b7e2301a Mon Sep 17 00:00:00 2001 From: Saalim Quadri Date: Mon, 17 Apr 2023 21:24:00 +0000 Subject: [PATCH 748/778] ASoC: dt-bindings: wm8737: Convert to dtschema Convert the WM8737 audio CODEC bindings to DT schema Signed-off-by: Saalim Quadri Acked-by: Charles Keepax Link: https://lore.kernel.org/r/20230417212400.161796-1-danascape@gmail.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/wlf,wm8737.yaml | 40 +++++++++++++++++++ .../devicetree/bindings/sound/wm8737.txt | 18 --------- 2 files changed, 40 insertions(+), 18 deletions(-) create mode 100644 Documentation/devicetree/bindings/sound/wlf,wm8737.yaml delete mode 100644 Documentation/devicetree/bindings/sound/wm8737.txt diff --git a/Documentation/devicetree/bindings/sound/wlf,wm8737.yaml b/Documentation/devicetree/bindings/sound/wlf,wm8737.yaml new file mode 100644 index 000000000000..12d8765726d8 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/wlf,wm8737.yaml @@ -0,0 +1,40 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/wlf,wm8737.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: WM8737 audio CODEC + +maintainers: + - patches@opensource.cirrus.com + +allOf: + - $ref: dai-common.yaml# + +properties: + compatible: + const: wlf,wm8737 + + reg: + maxItems: 1 + + "#sound-dai-cells": + const: 0 + +required: + - compatible + - reg + +unevaluatedProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + codec@1a { + compatible = "wlf,wm8737"; + reg = <0x1a>; + }; + }; diff --git a/Documentation/devicetree/bindings/sound/wm8737.txt b/Documentation/devicetree/bindings/sound/wm8737.txt deleted file mode 100644 index eda1ec6a7563..000000000000 --- a/Documentation/devicetree/bindings/sound/wm8737.txt +++ /dev/null @@ -1,18 +0,0 @@ -WM8737 audio CODEC - -This device supports both I2C and SPI (configured with pin strapping -on the board). - -Required properties: - - - compatible : "wlf,wm8737" - - - reg : the I2C address of the device for I2C, the chip select - number for SPI. - -Example: - -wm8737: codec@1a { - compatible = "wlf,wm8737"; - reg = <0x1a>; -}; From 67380533d450000699848e292d20ec18d0321f0e Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 17 Apr 2023 16:14:50 +0200 Subject: [PATCH 749/778] ASoC: codecs: wcd9335: Simplify with dev_err_probe Code can be a bit simpler with dev_err_probe(). Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230417141453.919158-1-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/wcd9335.c | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c index d2548fdf9ae5..8bf3510a3ea3 100644 --- a/sound/soc/codecs/wcd9335.c +++ b/sound/soc/codecs/wcd9335.c @@ -5138,20 +5138,17 @@ static int wcd9335_irq_init(struct wcd9335_codec *wcd) * INTR2 is a subset of first interrupt sources MAD, VBAT, and SVA */ wcd->intr1 = of_irq_get_byname(wcd->dev->of_node, "intr1"); - if (wcd->intr1 < 0) { - if (wcd->intr1 != -EPROBE_DEFER) - dev_err(wcd->dev, "Unable to configure IRQ\n"); - - return wcd->intr1; - } + if (wcd->intr1 < 0) + return dev_err_probe(wcd->dev, wcd->intr1, + "Unable to configure IRQ\n"); ret = devm_regmap_add_irq_chip(wcd->dev, wcd->regmap, wcd->intr1, IRQF_TRIGGER_HIGH, 0, &wcd9335_regmap_irq1_chip, &wcd->irq_data); if (ret) - dev_err(wcd->dev, "Failed to register IRQ chip: %d\n", ret); + return dev_err_probe(wcd->dev, ret, "Failed to register IRQ chip\n"); - return ret; + return 0; } static int wcd9335_slim_probe(struct slim_device *slim) @@ -5207,17 +5204,15 @@ static int wcd9335_slim_status(struct slim_device *sdev, slim_get_logical_addr(wcd->slim_ifc_dev); wcd->regmap = regmap_init_slimbus(sdev, &wcd9335_regmap_config); - if (IS_ERR(wcd->regmap)) { - dev_err(dev, "Failed to allocate slim register map\n"); - return PTR_ERR(wcd->regmap); - } + if (IS_ERR(wcd->regmap)) + return dev_err_probe(dev, PTR_ERR(wcd->regmap), + "Failed to allocate slim register map\n"); wcd->if_regmap = regmap_init_slimbus(wcd->slim_ifc_dev, &wcd9335_ifc_regmap_config); - if (IS_ERR(wcd->if_regmap)) { - dev_err(dev, "Failed to allocate ifc register map\n"); - return PTR_ERR(wcd->if_regmap); - } + if (IS_ERR(wcd->if_regmap)) + return dev_err_probe(dev, PTR_ERR(wcd->if_regmap), + "Failed to allocate ifc register map\n"); ret = wcd9335_bring_up(wcd); if (ret) { From 5f3d94eb7ae877430d9fe6a9aae7dcef6c3e5fea Mon Sep 17 00:00:00 2001 From: Tom Rix Date: Tue, 18 Apr 2023 08:09:55 -0400 Subject: [PATCH 750/778] ASoC: nau8825: fix bounds check for adc_delay clang build reports sound/soc/codecs/nau8825.c:2826:31: error: overlapping comparisons always evaluate to false [-Werror,-Wtautological-overlap-compare] if (nau8825->adc_delay < 125 && nau8825->adc_delay > 500) ~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~ This is a bug, a logical-or should have been used. Fixes: fc0b096c9291 ("ASoC: nau8825: Add delay control for input path") Signed-off-by: Tom Rix Acked-by: David Lin Link: https://lore.kernel.org/r/20230418120955.3230705-1-trix@redhat.com Signed-off-by: Mark Brown --- sound/soc/codecs/nau8825.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/nau8825.c b/sound/soc/codecs/nau8825.c index c4389f5fe603..f4eb999761a4 100644 --- a/sound/soc/codecs/nau8825.c +++ b/sound/soc/codecs/nau8825.c @@ -2823,7 +2823,7 @@ static int nau8825_read_device_properties(struct device *dev, ret = device_property_read_u32(dev, "nuvoton,adc-delay-ms", &nau8825->adc_delay); if (ret) nau8825->adc_delay = 125; - if (nau8825->adc_delay < 125 && nau8825->adc_delay > 500) + if (nau8825->adc_delay < 125 || nau8825->adc_delay > 500) dev_warn(dev, "Please set the suitable delay time!\n"); nau8825->mclk = devm_clk_get(dev, "mclk"); From 3da9d149eb9f51560163bb0c13a245fd0ba74c6e Mon Sep 17 00:00:00 2001 From: Saalim Quadri Date: Mon, 17 Apr 2023 20:43:23 +0000 Subject: [PATCH 751/778] ASoC: dt-bindings: wm8728: Convert to dtschema Convert the WM8728 audio CODEC bindings to DT schema Signed-off-by: Saalim Quadri Acked-by: Charles Keepax Link: https://lore.kernel.org/r/20230417204323.137681-1-danascape@gmail.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/wlf,wm8728.yaml | 40 +++++++++++++++++++ .../devicetree/bindings/sound/wm8728.txt | 18 --------- 2 files changed, 40 insertions(+), 18 deletions(-) create mode 100644 Documentation/devicetree/bindings/sound/wlf,wm8728.yaml delete mode 100644 Documentation/devicetree/bindings/sound/wm8728.txt diff --git a/Documentation/devicetree/bindings/sound/wlf,wm8728.yaml b/Documentation/devicetree/bindings/sound/wlf,wm8728.yaml new file mode 100644 index 000000000000..fc89475a051e --- /dev/null +++ b/Documentation/devicetree/bindings/sound/wlf,wm8728.yaml @@ -0,0 +1,40 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/wlf,wm8728.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: WM8728 audio CODEC + +maintainers: + - patches@opensource.cirrus.com + +allOf: + - $ref: dai-common.yaml# + +properties: + compatible: + const: wlf,wm8728 + + reg: + maxItems: 1 + + "#sound-dai-cells": + const: 0 + +required: + - compatible + - reg + +unevaluatedProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + codec@1a { + compatible = "wlf,wm8728"; + reg = <0x1a>; + }; + }; diff --git a/Documentation/devicetree/bindings/sound/wm8728.txt b/Documentation/devicetree/bindings/sound/wm8728.txt deleted file mode 100644 index a3608b4c78b9..000000000000 --- a/Documentation/devicetree/bindings/sound/wm8728.txt +++ /dev/null @@ -1,18 +0,0 @@ -WM8728 audio CODEC - -This device supports both I2C and SPI (configured with pin strapping -on the board). - -Required properties: - - - compatible : "wlf,wm8728" - - - reg : the I2C address of the device for I2C, the chip select - number for SPI. - -Example: - -wm8728: codec@1a { - compatible = "wlf,wm8728"; - reg = <0x1a>; -}; From fa92f4294283cc7d1f29151420be9e9336182518 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 18 Apr 2023 09:46:28 +0200 Subject: [PATCH 752/778] ASoC: codecs: wcd934x: Simplify with dev_err_probe Replace dev_err() in probe() path with dev_err_probe() to: 1. Make code a bit simpler and easier to read, 2. Do not print messages on deferred probe. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230418074630.8681-2-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/wcd934x.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/sound/soc/codecs/wcd934x.c b/sound/soc/codecs/wcd934x.c index 783479a4d535..56487ad2f048 100644 --- a/sound/soc/codecs/wcd934x.c +++ b/sound/soc/codecs/wcd934x.c @@ -5868,10 +5868,9 @@ static int wcd934x_codec_parse_data(struct wcd934x_codec *wcd) slim_get_logical_addr(wcd->sidev); wcd->if_regmap = regmap_init_slimbus(wcd->sidev, &wcd934x_ifc_regmap_config); - if (IS_ERR(wcd->if_regmap)) { - dev_err(dev, "Failed to allocate ifc register map\n"); - return PTR_ERR(wcd->if_regmap); - } + if (IS_ERR(wcd->if_regmap)) + return dev_err_probe(dev, PTR_ERR(wcd->if_regmap), + "Failed to allocate ifc register map\n"); of_property_read_u32(dev->parent->of_node, "qcom,dmic-sample-rate", &wcd->dmic_sample_rate); @@ -5923,19 +5922,15 @@ static int wcd934x_codec_probe(struct platform_device *pdev) memcpy(wcd->tx_chs, wcd934x_tx_chs, sizeof(wcd934x_tx_chs)); irq = regmap_irq_get_virq(data->irq_data, WCD934X_IRQ_SLIMBUS); - if (irq < 0) { - dev_err(wcd->dev, "Failed to get SLIM IRQ\n"); - return irq; - } + if (irq < 0) + return dev_err_probe(wcd->dev, irq, "Failed to get SLIM IRQ\n"); ret = devm_request_threaded_irq(dev, irq, NULL, wcd934x_slim_irq_handler, IRQF_TRIGGER_RISING | IRQF_ONESHOT, "slim", wcd); - if (ret) { - dev_err(dev, "Failed to request slimbus irq\n"); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, "Failed to request slimbus irq\n"); wcd934x_register_mclk_output(wcd); platform_set_drvdata(pdev, wcd); From 92864de45c3e445419d1e99e3a409469a5f3ef57 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 18 Apr 2023 09:46:29 +0200 Subject: [PATCH 753/778] ASoC: codecs: wcd934x: Simplify &pdev->dev in probe The probe already stores pointer to &pdev->dev, so use it to make the code a bit easier to read. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230418074630.8681-3-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/wcd934x.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/wcd934x.c b/sound/soc/codecs/wcd934x.c index 56487ad2f048..c0d1fa36d841 100644 --- a/sound/soc/codecs/wcd934x.c +++ b/sound/soc/codecs/wcd934x.c @@ -5892,12 +5892,12 @@ static int wcd934x_codec_parse_data(struct wcd934x_codec *wcd) static int wcd934x_codec_probe(struct platform_device *pdev) { - struct wcd934x_ddata *data = dev_get_drvdata(pdev->dev.parent); - struct wcd934x_codec *wcd; struct device *dev = &pdev->dev; + struct wcd934x_ddata *data = dev_get_drvdata(dev->parent); + struct wcd934x_codec *wcd; int ret, irq; - wcd = devm_kzalloc(&pdev->dev, sizeof(*wcd), GFP_KERNEL); + wcd = devm_kzalloc(dev, sizeof(*wcd), GFP_KERNEL); if (!wcd) return -ENOMEM; From 60ba2fda5280528e70fa26b44e36d1530f6d1d7e Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 18 Apr 2023 09:46:30 +0200 Subject: [PATCH 754/778] ASoC: codecs: wcd938x: Simplify with dev_err_probe Replace dev_err() in probe() path with dev_err_probe() to: 1. Make code a bit simpler and easier to read, 2. Do not print messages on deferred probe. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230418074630.8681-4-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/wcd938x.c | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/sound/soc/codecs/wcd938x.c b/sound/soc/codecs/wcd938x.c index f033f79ed238..11b264a63b04 100644 --- a/sound/soc/codecs/wcd938x.c +++ b/sound/soc/codecs/wcd938x.c @@ -4235,18 +4235,15 @@ static int wcd938x_populate_dt_data(struct wcd938x_priv *wcd938x, struct device int ret; wcd938x->reset_gpio = of_get_named_gpio(dev->of_node, "reset-gpios", 0); - if (wcd938x->reset_gpio < 0) { - dev_err(dev, "Failed to get reset gpio: err = %d\n", - wcd938x->reset_gpio); - return wcd938x->reset_gpio; - } + if (wcd938x->reset_gpio < 0) + return dev_err_probe(dev, wcd938x->reset_gpio, + "Failed to get reset gpio\n"); wcd938x->us_euro_gpio = devm_gpiod_get_optional(dev, "us-euro", GPIOD_OUT_LOW); - if (IS_ERR(wcd938x->us_euro_gpio)) { - dev_err(dev, "us-euro swap Control GPIO not found\n"); - return PTR_ERR(wcd938x->us_euro_gpio); - } + if (IS_ERR(wcd938x->us_euro_gpio)) + return dev_err_probe(dev, PTR_ERR(wcd938x->us_euro_gpio), + "us-euro swap Control GPIO not found\n"); cfg->swap_gnd_mic = wcd938x_swap_gnd_mic; @@ -4256,16 +4253,12 @@ static int wcd938x_populate_dt_data(struct wcd938x_priv *wcd938x, struct device wcd938x->supplies[3].supply = "vdd-mic-bias"; ret = regulator_bulk_get(dev, WCD938X_MAX_SUPPLY, wcd938x->supplies); - if (ret) { - dev_err(dev, "Failed to get supplies: err = %d\n", ret); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, "Failed to get supplies\n"); ret = regulator_bulk_enable(WCD938X_MAX_SUPPLY, wcd938x->supplies); - if (ret) { - dev_err(dev, "Failed to enable supplies: err = %d\n", ret); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, "Failed to enable supplies\n"); wcd938x_dt_parse_micbias_info(dev, wcd938x); From 16e5fc8ae793947d7dd0de63c7a613798f75c237 Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Tue, 18 Apr 2023 15:43:06 +0100 Subject: [PATCH 755/778] ASoC: cs35l56: Update comment on masking of EINT20 interrupts EINT20 contains wake-source interrupts and also interface-blocked interrupts, which all default to unmasked after reset or wake. The comment in cs35l56_init() only mentioned the wake interrupts. Update the comment so it's clear that it's intentional to also mask the *_BLOCKED interrupts. Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/20230418144309.1100721-2-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l56.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c index 0f4a94b02ef8..1b80cae5026e 100644 --- a/sound/soc/codecs/cs35l56.c +++ b/sound/soc/codecs/cs35l56.c @@ -1537,7 +1537,7 @@ int cs35l56_init(struct cs35l56_private *cs35l56) cs35l56_patch(cs35l56->dev, cs35l56->regmap, cs35l56->rev); - /* Wake source interrupts default to unmasked, so mask them */ + /* Wake source and *_BLOCKED interrupts default to unmasked, so mask them */ regmap_write(cs35l56->regmap, CS35L56_IRQ1_MASK_20, 0xffffffff); regmap_update_bits(cs35l56->regmap, CS35L56_IRQ1_MASK_1, CS35L56_AMP_SHORT_ERR_EINT1_MASK, From 5ab28c78a125a724684958f4caf8210127d3f528 Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Tue, 18 Apr 2023 15:43:07 +0100 Subject: [PATCH 756/778] ASoC: cs35l56: Remove SDW1 TX5 and TX6 Reduce SDW1 to 4 channels and remove the controls for SDW1 TX5 and TX6. The TX5 and TX6 channels have been removed from B0 silicon. There is no need to support them on A1 silicon. Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/20230418144309.1100721-3-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- include/sound/cs35l56.h | 3 --- sound/soc/codecs/cs35l56-shared.c | 27 --------------------------- sound/soc/codecs/cs35l56.c | 28 +--------------------------- 3 files changed, 1 insertion(+), 57 deletions(-) diff --git a/include/sound/cs35l56.h b/include/sound/cs35l56.h index b3300bce74f4..dd7503464651 100644 --- a/include/sound/cs35l56.h +++ b/include/sound/cs35l56.h @@ -43,8 +43,6 @@ #define CS35L56_SWIRE_DP3_CH2_INPUT 0x0004C74 #define CS35L56_SWIRE_DP3_CH3_INPUT 0x0004C78 #define CS35L56_SWIRE_DP3_CH4_INPUT 0x0004C7C -#define CS35L56_SWIRE_DP3_CH5_INPUT 0x0004C80 -#define CS35L56_SWIRE_DP3_CH6_INPUT 0x0004C84 #define CS35L56_IRQ1_CFG 0x000E000 #define CS35L56_IRQ1_STATUS 0x000E004 #define CS35L56_IRQ1_EINT_1 0x000E010 @@ -262,7 +260,6 @@ extern const struct cs_dsp_region cs35l56_dsp1_regions[CS35L56_NUM_DSP_REGIONS]; extern const char * const cs35l56_tx_input_texts[CS35L56_NUM_INPUT_SRC]; extern const unsigned int cs35l56_tx_input_values[CS35L56_NUM_INPUT_SRC]; -void cs35l56_patch(struct device *dev, struct regmap *regmap, u8 revid); void cs35l56_reread_firmware_registers(struct device *dev, struct regmap *regmap); int cs35l56_get_bclk_freq_id(unsigned int freq); void cs35l56_fill_supply_names(struct regulator_bulk_data *data); diff --git a/sound/soc/codecs/cs35l56-shared.c b/sound/soc/codecs/cs35l56-shared.c index d8bc06ad4888..f5fa6bb04d38 100644 --- a/sound/soc/codecs/cs35l56-shared.c +++ b/sound/soc/codecs/cs35l56-shared.c @@ -28,8 +28,6 @@ static const struct reg_default cs35l56_reg_defaults[] = { { CS35L56_SWIRE_DP3_CH2_INPUT, 0x00000019 }, { CS35L56_SWIRE_DP3_CH3_INPUT, 0x00000029 }, { CS35L56_SWIRE_DP3_CH4_INPUT, 0x00000028 }, - { CS35L56_SWIRE_DP3_CH5_INPUT, 0x00000018 }, - { CS35L56_SWIRE_DP3_CH6_INPUT, 0x00000018 }, { CS35L56_IRQ1_CFG, 0x00000000 }, { CS35L56_IRQ1_MASK_1, 0x83ffffff }, { CS35L56_IRQ1_MASK_2, 0xffff7fff }, @@ -42,29 +40,6 @@ static const struct reg_default cs35l56_reg_defaults[] = { /* CS35L56_MAIN_POSTURE_NUMBER - soft register, no default */ }; -/* - * The Ax devices have different default register values to that of B0, - * establish a common set of register defaults. - */ -static const struct reg_sequence cs35l56_reva_patch[] = { - { CS35L56_SWIRE_DP3_CH5_INPUT, 0x00000018 }, - { CS35L56_SWIRE_DP3_CH6_INPUT, 0x00000018 }, -}; - -void cs35l56_patch(struct device *dev, struct regmap *regmap, u8 revid) -{ - int ret; - - if (revid >= CS35L56_REVID_B0) - return; - - ret = regmap_register_patch(regmap, cs35l56_reva_patch, - ARRAY_SIZE(cs35l56_reva_patch)); - if (ret) - dev_err(dev, "Failed to apply patch: %d\n", ret); -} -EXPORT_SYMBOL_NS_GPL(cs35l56_patch, SND_SOC_CS35L56_SHARED); - static bool cs35l56_is_dsp_memory(unsigned int reg) { switch (reg) { @@ -114,8 +89,6 @@ static bool cs35l56_readable_reg(struct device *dev, unsigned int reg) case CS35L56_SWIRE_DP3_CH2_INPUT: case CS35L56_SWIRE_DP3_CH3_INPUT: case CS35L56_SWIRE_DP3_CH4_INPUT: - case CS35L56_SWIRE_DP3_CH5_INPUT: - case CS35L56_SWIRE_DP3_CH6_INPUT: case CS35L56_IRQ1_CFG: case CS35L56_IRQ1_STATUS: case CS35L56_IRQ1_EINT_1 ... CS35L56_IRQ1_EINT_8: diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c index 1b80cae5026e..c0a857cfb8cb 100644 --- a/sound/soc/codecs/cs35l56.c +++ b/sound/soc/codecs/cs35l56.c @@ -166,24 +166,6 @@ static SOC_VALUE_ENUM_SINGLE_DECL(cs35l56_sdw1tx4_enum, static const struct snd_kcontrol_new sdw1_tx4_mux = SOC_DAPM_ENUM("SDW1TX4 SRC", cs35l56_sdw1tx4_enum); -static SOC_VALUE_ENUM_SINGLE_DECL(cs35l56_sdw1tx5_enum, - CS35L56_SWIRE_DP3_CH5_INPUT, - 0, CS35L56_SWIRETXn_SRC_MASK, - cs35l56_tx_input_texts, - cs35l56_tx_input_values); - -static const struct snd_kcontrol_new sdw1_tx5_mux = - SOC_DAPM_ENUM("SDW1TX5 SRC", cs35l56_sdw1tx5_enum); - -static SOC_VALUE_ENUM_SINGLE_DECL(cs35l56_sdw1tx6_enum, - CS35L56_SWIRE_DP3_CH6_INPUT, - 0, CS35L56_SWIRETXn_SRC_MASK, - cs35l56_tx_input_texts, - cs35l56_tx_input_values); - -static const struct snd_kcontrol_new sdw1_tx6_mux = - SOC_DAPM_ENUM("SDW1TX6 SRC", cs35l56_sdw1tx6_enum); - static int cs35l56_play_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { @@ -251,8 +233,6 @@ static const struct snd_soc_dapm_widget cs35l56_dapm_widgets[] = { SND_SOC_DAPM_MUX("SDW1 TX2 Source", SND_SOC_NOPM, 0, 0, &sdw1_tx2_mux), SND_SOC_DAPM_MUX("SDW1 TX3 Source", SND_SOC_NOPM, 0, 0, &sdw1_tx3_mux), SND_SOC_DAPM_MUX("SDW1 TX4 Source", SND_SOC_NOPM, 0, 0, &sdw1_tx4_mux), - SND_SOC_DAPM_MUX("SDW1 TX5 Source", SND_SOC_NOPM, 0, 0, &sdw1_tx5_mux), - SND_SOC_DAPM_MUX("SDW1 TX6 Source", SND_SOC_NOPM, 0, 0, &sdw1_tx6_mux), SND_SOC_DAPM_SIGGEN("VMON ADC"), SND_SOC_DAPM_SIGGEN("IMON ADC"), @@ -318,14 +298,10 @@ static const struct snd_soc_dapm_route cs35l56_audio_map[] = { CS35L56_SRC_ROUTE("SDW1 TX2") CS35L56_SRC_ROUTE("SDW1 TX3") CS35L56_SRC_ROUTE("SDW1 TX4") - CS35L56_SRC_ROUTE("SDW1 TX5") - CS35L56_SRC_ROUTE("SDW1 TX6") { "SDW1 Capture", NULL, "SDW1 TX1 Source" }, { "SDW1 Capture", NULL, "SDW1 TX2 Source" }, { "SDW1 Capture", NULL, "SDW1 TX3 Source" }, { "SDW1 Capture", NULL, "SDW1 TX4 Source" }, - { "SDW1 Capture", NULL, "SDW1 TX5 Source" }, - { "SDW1 Capture", NULL, "SDW1 TX6 Source" }, }; static int cs35l56_dsp_event(struct snd_soc_dapm_widget *w, @@ -779,7 +755,7 @@ static struct snd_soc_dai_driver cs35l56_dai[] = { .capture = { .stream_name = "SDW1 Capture", .channels_min = 1, - .channels_max = 6, + .channels_max = 4, .rates = CS35L56_RATES, .formats = CS35L56_TX_FORMATS, }, @@ -1535,8 +1511,6 @@ int cs35l56_init(struct cs35l56_private *cs35l56) dev_info(cs35l56->dev, "Cirrus Logic CS35L56%s Rev %02X OTP%d\n", cs35l56->secured ? "s" : "", cs35l56->rev, otpid); - cs35l56_patch(cs35l56->dev, cs35l56->regmap, cs35l56->rev); - /* Wake source and *_BLOCKED interrupts default to unmasked, so mask them */ regmap_write(cs35l56->regmap, CS35L56_IRQ1_MASK_20, 0xffffffff); regmap_update_bits(cs35l56->regmap, CS35L56_IRQ1_MASK_1, From d3a4efb334e5f6cbb3f2741fa07a873a2a78b016 Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Tue, 18 Apr 2023 15:43:08 +0100 Subject: [PATCH 757/778] ASoC: cs35l56: Remove SDW2RX1 mixer source The mixer source index value for SDW2RX1 is different between A1 and B0 silicon. As the driver doesn't provide a DAI for SDW2 just remove it as a mixer source option. Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/20230418144309.1100721-4-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- include/sound/cs35l56.h | 3 +-- sound/soc/codecs/cs35l56-shared.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/include/sound/cs35l56.h b/include/sound/cs35l56.h index dd7503464651..0b2f7cfc6a4a 100644 --- a/include/sound/cs35l56.h +++ b/include/sound/cs35l56.h @@ -181,10 +181,9 @@ #define CS35L56_INPUT_SRC_INTERPOLATOR 0x40 #define CS35L56_INPUT_SRC_SWIRE_RX1 0x44 #define CS35L56_INPUT_SRC_SWIRE_RX2 0x45 -#define CS35L56_INPUT_SRC_SWIRE_RX3 0x46 #define CS35L56_INPUT_MASK 0x7F -#define CS35L56_NUM_INPUT_SRC 22 +#define CS35L56_NUM_INPUT_SRC 21 /* ASP formats */ #define CS35L56_ASP_FMT_DSP_A 0 diff --git a/sound/soc/codecs/cs35l56-shared.c b/sound/soc/codecs/cs35l56-shared.c index f5fa6bb04d38..93a1b056660b 100644 --- a/sound/soc/codecs/cs35l56-shared.c +++ b/sound/soc/codecs/cs35l56-shared.c @@ -278,7 +278,7 @@ const char * const cs35l56_tx_input_texts[] = { "None", "ASP1RX1", "ASP1RX2", "VMON", "IMON", "ERRVOL", "CLASSH", "VDDBMON", "VBSTMON", "DSP1TX1", "DSP1TX2", "DSP1TX3", "DSP1TX4", "DSP1TX5", "DSP1TX6", "DSP1TX7", "DSP1TX8", "TEMPMON", - "INTERPOLATOR", "SDW1RX1", "SDW1RX2", "SDW2RX1", + "INTERPOLATOR", "SDW1RX1", "SDW1RX2", }; EXPORT_SYMBOL_NS_GPL(cs35l56_tx_input_texts, SND_SOC_CS35L56_SHARED); @@ -304,7 +304,6 @@ const unsigned int cs35l56_tx_input_values[] = { CS35L56_INPUT_SRC_INTERPOLATOR, CS35L56_INPUT_SRC_SWIRE_RX1, CS35L56_INPUT_SRC_SWIRE_RX2, - CS35L56_INPUT_SRC_SWIRE_RX3, }; EXPORT_SYMBOL_NS_GPL(cs35l56_tx_input_values, SND_SOC_CS35L56_SHARED); From d29a966b72fb370128096393961f2c456ff24e3d Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Tue, 18 Apr 2023 15:43:09 +0100 Subject: [PATCH 758/778] ASoC: cs35l56: Rename mixer source defines for SoundWire DP1 Rename the mixer source defines from CS35L56_INPUT_SRC_SWIRE_RXn to CS35L56_INPUT_SRC_SWIRE_DP1_CHANNELn to match the latest datasheet. Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/20230418144309.1100721-5-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- include/sound/cs35l56.h | 4 ++-- sound/soc/codecs/cs35l56-shared.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/sound/cs35l56.h b/include/sound/cs35l56.h index 0b2f7cfc6a4a..002042b1c73c 100644 --- a/include/sound/cs35l56.h +++ b/include/sound/cs35l56.h @@ -179,8 +179,8 @@ #define CS35L56_INPUT_SRC_DSP1TX8 0x39 #define CS35L56_INPUT_SRC_TEMPMON 0x3A #define CS35L56_INPUT_SRC_INTERPOLATOR 0x40 -#define CS35L56_INPUT_SRC_SWIRE_RX1 0x44 -#define CS35L56_INPUT_SRC_SWIRE_RX2 0x45 +#define CS35L56_INPUT_SRC_SWIRE_DP1_CHANNEL1 0x44 +#define CS35L56_INPUT_SRC_SWIRE_DP1_CHANNEL2 0x45 #define CS35L56_INPUT_MASK 0x7F #define CS35L56_NUM_INPUT_SRC 21 diff --git a/sound/soc/codecs/cs35l56-shared.c b/sound/soc/codecs/cs35l56-shared.c index 93a1b056660b..60da8c75b7b9 100644 --- a/sound/soc/codecs/cs35l56-shared.c +++ b/sound/soc/codecs/cs35l56-shared.c @@ -302,8 +302,8 @@ const unsigned int cs35l56_tx_input_values[] = { CS35L56_INPUT_SRC_DSP1TX8, CS35L56_INPUT_SRC_TEMPMON, CS35L56_INPUT_SRC_INTERPOLATOR, - CS35L56_INPUT_SRC_SWIRE_RX1, - CS35L56_INPUT_SRC_SWIRE_RX2, + CS35L56_INPUT_SRC_SWIRE_DP1_CHANNEL1, + CS35L56_INPUT_SRC_SWIRE_DP1_CHANNEL2, }; EXPORT_SYMBOL_NS_GPL(cs35l56_tx_input_values, SND_SOC_CS35L56_SHARED); From 574399f4c997ad71fab95dd875a9ff55424f9a3d Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sun, 16 Apr 2023 08:29:34 +0200 Subject: [PATCH 759/778] ASoC: fsl: Simplify an error message dev_err_probe() already display the error code. There is no need to duplicate it explicitly in the error message. Signed-off-by: Christophe JAILLET Reviewed-by: Iuliana Prodan Acked-by: Shengjiu Wang Link: https://lore.kernel.org/r/c167c16a535049d56f817bbede9c9f6f0a0f4c68.1681626553.git.christophe.jaillet@wanadoo.fr Signed-off-by: Mark Brown --- sound/soc/fsl/fsl-asoc-card.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c index bffa1048d31e..40870668ee24 100644 --- a/sound/soc/fsl/fsl-asoc-card.c +++ b/sound/soc/fsl/fsl-asoc-card.c @@ -858,7 +858,7 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) ret = devm_snd_soc_register_card(&pdev->dev, &priv->card); if (ret) { - dev_err_probe(&pdev->dev, ret, "snd_soc_register_card failed: %d\n", ret); + dev_err_probe(&pdev->dev, ret, "snd_soc_register_card failed\n"); goto asrc_fail; } From 09cda705860125ffee1b1359b1da79f8e0c77a40 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Wed, 19 Apr 2023 18:29:18 +0800 Subject: [PATCH 760/778] ASoC: fsl: Restore configuration of platform This reverts commit 33683cbf49b54 ("ASoC: fsl: remove unnecessary dai_link->platform"). dai_link->platform is needed. The platform component is "snd_dmaengine_pcm", which is registered from cpu driver, If dai_link->platform is not assigned, then platform component will not be probed, then there will be issue: aplay: main:831: audio open error: Invalid argument Signed-off-by: Shengjiu Wang Link: https://lore.kernel.org/r/1681900158-17428-1-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/imx-audmix.c | 14 ++++++++++---- sound/soc/fsl/imx-spdif.c | 5 ++++- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/sound/soc/fsl/imx-audmix.c b/sound/soc/fsl/imx-audmix.c index 2c57fe9d2d08..1292a845c424 100644 --- a/sound/soc/fsl/imx-audmix.c +++ b/sound/soc/fsl/imx-audmix.c @@ -207,8 +207,8 @@ static int imx_audmix_probe(struct platform_device *pdev) for (i = 0; i < num_dai; i++) { struct snd_soc_dai_link_component *dlc; - /* for CPU/Codec x 2 */ - dlc = devm_kcalloc(&pdev->dev, 4, sizeof(*dlc), GFP_KERNEL); + /* for CPU/Codec/Platform x 2 */ + dlc = devm_kcalloc(&pdev->dev, 6, sizeof(*dlc), GFP_KERNEL); if (!dlc) return -ENOMEM; @@ -240,9 +240,11 @@ static int imx_audmix_probe(struct platform_device *pdev) priv->dai[i].cpus = &dlc[0]; priv->dai[i].codecs = &dlc[1]; + priv->dai[i].platforms = &dlc[2]; priv->dai[i].num_cpus = 1; priv->dai[i].num_codecs = 1; + priv->dai[i].num_platforms = 1; priv->dai[i].name = dai_name; priv->dai[i].stream_name = "HiFi-AUDMIX-FE"; @@ -250,6 +252,7 @@ static int imx_audmix_probe(struct platform_device *pdev) priv->dai[i].codecs->name = "snd-soc-dummy"; priv->dai[i].cpus->of_node = args.np; priv->dai[i].cpus->dai_name = dev_name(&cpu_pdev->dev); + priv->dai[i].platforms->of_node = args.np; priv->dai[i].dynamic = 1; priv->dai[i].dpcm_playback = 1; priv->dai[i].dpcm_capture = (i == 0 ? 1 : 0); @@ -264,17 +267,20 @@ static int imx_audmix_probe(struct platform_device *pdev) be_cp = devm_kasprintf(&pdev->dev, GFP_KERNEL, "AUDMIX-Capture-%d", i); - priv->dai[num_dai + i].cpus = &dlc[2]; - priv->dai[num_dai + i].codecs = &dlc[3]; + priv->dai[num_dai + i].cpus = &dlc[3]; + priv->dai[num_dai + i].codecs = &dlc[4]; + priv->dai[num_dai + i].platforms = &dlc[5]; priv->dai[num_dai + i].num_cpus = 1; priv->dai[num_dai + i].num_codecs = 1; + priv->dai[num_dai + i].num_platforms = 1; priv->dai[num_dai + i].name = be_name; priv->dai[num_dai + i].codecs->dai_name = "snd-soc-dummy-dai"; priv->dai[num_dai + i].codecs->name = "snd-soc-dummy"; priv->dai[num_dai + i].cpus->of_node = audmix_np; priv->dai[num_dai + i].cpus->dai_name = be_name; + priv->dai[num_dai + i].platforms->name = "snd-soc-dummy"; priv->dai[num_dai + i].no_pcm = 1; priv->dai[num_dai + i].dpcm_playback = 1; priv->dai[num_dai + i].dpcm_capture = 1; diff --git a/sound/soc/fsl/imx-spdif.c b/sound/soc/fsl/imx-spdif.c index 114b49660193..4446fba755b9 100644 --- a/sound/soc/fsl/imx-spdif.c +++ b/sound/soc/fsl/imx-spdif.c @@ -26,7 +26,7 @@ static int imx_spdif_audio_probe(struct platform_device *pdev) } data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); - comp = devm_kzalloc(&pdev->dev, 2 * sizeof(*comp), GFP_KERNEL); + comp = devm_kzalloc(&pdev->dev, 3 * sizeof(*comp), GFP_KERNEL); if (!data || !comp) { ret = -ENOMEM; goto end; @@ -34,15 +34,18 @@ static int imx_spdif_audio_probe(struct platform_device *pdev) data->dai.cpus = &comp[0]; data->dai.codecs = &comp[1]; + data->dai.platforms = &comp[2]; data->dai.num_cpus = 1; data->dai.num_codecs = 1; + data->dai.num_platforms = 1; data->dai.name = "S/PDIF PCM"; data->dai.stream_name = "S/PDIF PCM"; data->dai.codecs->dai_name = "snd-soc-dummy-dai"; data->dai.codecs->name = "snd-soc-dummy"; data->dai.cpus->of_node = spdif_np; + data->dai.platforms->of_node = spdif_np; data->dai.playback_only = true; data->dai.capture_only = true; From ccb541a00b5bf87f1b7b9301373bf88a3257c688 Mon Sep 17 00:00:00 2001 From: Curtis Malainey Date: Wed, 19 Apr 2023 14:40:56 -0500 Subject: [PATCH 761/778] ASoC: SOF: ipc: Add no reply inline calls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 95% of the calls inside SOF to TX an IPC don't care about a reply. Yet the previous commit cleaned up a bunch of replies that were being populated and then thrown away. This adds some functions so users who do not need replies don't feel obligated to provide the space to the API. Signed-off-by: Curtis Malainey Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20230419194057.42205-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/sof-client.h | 4 ++++ sound/soc/sof/sof-priv.h | 10 ++++++++++ 2 files changed, 14 insertions(+) diff --git a/sound/soc/sof/sof-client.h b/sound/soc/sof/sof-client.h index 2589714eaa91..10571d1ea9a7 100644 --- a/sound/soc/sof/sof-client.h +++ b/sound/soc/sof/sof-client.h @@ -39,6 +39,10 @@ struct sof_client_dev { int sof_client_ipc_tx_message(struct sof_client_dev *cdev, void *ipc_msg, void *reply_data, size_t reply_bytes); +static inline int sof_client_ipc_tx_message_no_reply(struct sof_client_dev *cdev, void *ipc_msg) +{ + return sof_client_ipc_tx_message(cdev, ipc_msg, NULL, 0); +} int sof_client_ipc_set_get_data(struct sof_client_dev *cdev, void *ipc_msg, bool set); diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 1170989bea57..cd4f6ac126ec 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -711,10 +711,20 @@ static inline void snd_sof_ipc_msgs_rx(struct snd_sof_dev *sdev) } int sof_ipc_tx_message(struct snd_sof_ipc *ipc, void *msg_data, size_t msg_bytes, void *reply_data, size_t reply_bytes); +static inline int sof_ipc_tx_message_no_reply(struct snd_sof_ipc *ipc, void *msg_data, + size_t msg_bytes) +{ + return sof_ipc_tx_message(ipc, msg_data, msg_bytes, NULL, 0); +} int sof_ipc_set_get_data(struct snd_sof_ipc *ipc, void *msg_data, size_t msg_bytes, bool set); int sof_ipc_tx_message_no_pm(struct snd_sof_ipc *ipc, void *msg_data, size_t msg_bytes, void *reply_data, size_t reply_bytes); +static inline int sof_ipc_tx_message_no_pm_no_reply(struct snd_sof_ipc *ipc, void *msg_data, + size_t msg_bytes) +{ + return sof_ipc_tx_message_no_pm(ipc, msg_data, msg_bytes, NULL, 0); +} int sof_ipc_send_msg(struct snd_sof_dev *sdev, void *msg_data, size_t msg_bytes, size_t reply_bytes); From 367fd6ffa294ca3346902aa0814fac31bb5a6059 Mon Sep 17 00:00:00 2001 From: Curtis Malainey Date: Wed, 19 Apr 2023 14:40:57 -0500 Subject: [PATCH 762/778] ASoC: SOF: Use no_reply calls for TX MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Convert all existing calls that pass "NULL, 0" for reply data to the new no_reply calls. Also convert any calls that pass in data but don't actually parse the result. Signed-off-by: Curtis Malainey Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20230419194057.42205-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/compress.c | 8 ++---- sound/soc/sof/intel/hda-loader.c | 2 +- sound/soc/sof/ipc3-dtrace.c | 12 +++------ sound/soc/sof/ipc3-pcm.c | 6 ++--- sound/soc/sof/ipc3-topology.c | 33 +++++++---------------- sound/soc/sof/ipc3.c | 12 +++------ sound/soc/sof/ipc4-pcm.c | 6 ++--- sound/soc/sof/ipc4-topology.c | 10 +++---- sound/soc/sof/sof-client-ipc-flood-test.c | 3 +-- sound/soc/sof/sof-client-probes-ipc3.c | 12 +++------ sound/soc/sof/sof-client-probes-ipc4.c | 4 +-- 11 files changed, 37 insertions(+), 71 deletions(-) diff --git a/sound/soc/sof/compress.c b/sound/soc/sof/compress.c index 8d205eb16d2f..d7b044f33d79 100644 --- a/sound/soc/sof/compress.c +++ b/sound/soc/sof/compress.c @@ -135,7 +135,6 @@ static int sof_compr_free(struct snd_soc_component *component, struct sof_compr_stream *sstream = cstream->runtime->private_data; struct snd_soc_pcm_runtime *rtd = cstream->private_data; struct sof_ipc_stream stream; - struct sof_ipc_reply reply; struct snd_sof_pcm *spcm; int ret = 0; @@ -148,8 +147,7 @@ static int sof_compr_free(struct snd_soc_component *component, stream.comp_id = spcm->stream[cstream->direction].comp_id; if (spcm->prepared[cstream->direction]) { - ret = sof_ipc_tx_message(sdev->ipc, &stream, sizeof(stream), - &reply, sizeof(reply)); + ret = sof_ipc_tx_message_no_reply(sdev->ipc, &stream, sizeof(stream)); if (!ret) spcm->prepared[cstream->direction] = false; } @@ -273,7 +271,6 @@ static int sof_compr_trigger(struct snd_soc_component *component, struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); struct snd_soc_pcm_runtime *rtd = cstream->private_data; struct sof_ipc_stream stream; - struct sof_ipc_reply reply; struct snd_sof_pcm *spcm; spcm = snd_sof_find_spcm_dai(component, rtd); @@ -302,8 +299,7 @@ static int sof_compr_trigger(struct snd_soc_component *component, break; } - return sof_ipc_tx_message(sdev->ipc, &stream, sizeof(stream), - &reply, sizeof(reply)); + return sof_ipc_tx_message_no_reply(sdev->ipc, &stream, sizeof(stream)); } static int sof_compr_copy_playback(struct snd_compr_runtime *rtd, diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c index de8d9ad89bc7..50ce6b190002 100644 --- a/sound/soc/sof/intel/hda-loader.c +++ b/sound/soc/sof/intel/hda-loader.c @@ -557,7 +557,7 @@ int hda_dsp_ipc4_load_library(struct snd_sof_dev *sdev, goto cleanup; } - ret = sof_ipc_tx_message(sdev->ipc, &msg, 0, NULL, 0); + ret = sof_ipc_tx_message_no_reply(sdev->ipc, &msg, 0); ret1 = cl_trigger(sdev, hext_stream, SNDRV_PCM_TRIGGER_STOP); if (ret1 < 0) { diff --git a/sound/soc/sof/ipc3-dtrace.c b/sound/soc/sof/ipc3-dtrace.c index b815b0244d9e..1d3bca2d28dd 100644 --- a/sound/soc/sof/ipc3-dtrace.c +++ b/sound/soc/sof/ipc3-dtrace.c @@ -150,7 +150,6 @@ static int ipc3_trace_update_filter(struct snd_sof_dev *sdev, int num_elems, struct sof_ipc_trace_filter_elem *elems) { struct sof_ipc_trace_filter *msg; - struct sof_ipc_reply reply; size_t size; int ret; @@ -172,13 +171,13 @@ static int ipc3_trace_update_filter(struct snd_sof_dev *sdev, int num_elems, dev_err(sdev->dev, "enabling device failed: %d\n", ret); goto error; } - ret = sof_ipc_tx_message(sdev->ipc, msg, msg->hdr.size, &reply, sizeof(reply)); + ret = sof_ipc_tx_message_no_reply(sdev->ipc, msg, msg->hdr.size); pm_runtime_mark_last_busy(sdev->dev); pm_runtime_put_autosuspend(sdev->dev); error: kfree(msg); - return ret ? ret : reply.error; + return ret; } static ssize_t dfsentry_trace_filter_write(struct file *file, const char __user *from, @@ -434,7 +433,6 @@ static int ipc3_dtrace_enable(struct snd_sof_dev *sdev) struct sof_ipc_fw_ready *ready = &sdev->fw_ready; struct sof_ipc_fw_version *v = &ready->version; struct sof_ipc_dma_trace_params_ext params; - struct sof_ipc_reply ipc_reply; int ret; if (!sdev->fw_trace_is_supported) @@ -474,7 +472,7 @@ static int ipc3_dtrace_enable(struct snd_sof_dev *sdev) /* send IPC to the DSP */ priv->dtrace_state = SOF_DTRACE_INITIALIZING; - ret = sof_ipc_tx_message(sdev->ipc, ¶ms, sizeof(params), &ipc_reply, sizeof(ipc_reply)); + ret = sof_ipc_tx_message_no_reply(sdev->ipc, ¶ms, sizeof(params)); if (ret < 0) { dev_err(sdev->dev, "can't set params for DMA for trace %d\n", ret); goto trace_release; @@ -604,7 +602,6 @@ static void ipc3_dtrace_release(struct snd_sof_dev *sdev, bool only_stop) struct sof_ipc_fw_ready *ready = &sdev->fw_ready; struct sof_ipc_fw_version *v = &ready->version; struct sof_ipc_cmd_hdr hdr; - struct sof_ipc_reply ipc_reply; int ret; if (!sdev->fw_trace_is_supported || priv->dtrace_state == SOF_DTRACE_DISABLED) @@ -623,8 +620,7 @@ static void ipc3_dtrace_release(struct snd_sof_dev *sdev, bool only_stop) hdr.size = sizeof(hdr); hdr.cmd = SOF_IPC_GLB_TRACE_MSG | SOF_IPC_TRACE_DMA_FREE; - ret = sof_ipc_tx_message(sdev->ipc, &hdr, hdr.size, - &ipc_reply, sizeof(ipc_reply)); + ret = sof_ipc_tx_message_no_reply(sdev->ipc, &hdr, hdr.size); if (ret < 0) dev_err(sdev->dev, "DMA_TRACE_FREE failed with error: %d\n", ret); } diff --git a/sound/soc/sof/ipc3-pcm.c b/sound/soc/sof/ipc3-pcm.c index b7f1eb21ca26..304faf6425ab 100644 --- a/sound/soc/sof/ipc3-pcm.c +++ b/sound/soc/sof/ipc3-pcm.c @@ -19,7 +19,6 @@ static int sof_ipc3_pcm_hw_free(struct snd_soc_component *component, struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct sof_ipc_stream stream; - struct sof_ipc_reply reply; struct snd_sof_pcm *spcm; spcm = snd_sof_find_spcm_dai(component, rtd); @@ -34,7 +33,7 @@ static int sof_ipc3_pcm_hw_free(struct snd_soc_component *component, stream.comp_id = spcm->stream[substream->stream].comp_id; /* send IPC to the DSP */ - return sof_ipc_tx_message(sdev->ipc, &stream, sizeof(stream), &reply, sizeof(reply)); + return sof_ipc_tx_message_no_reply(sdev->ipc, &stream, sizeof(stream)); } static int sof_ipc3_pcm_hw_params(struct snd_soc_component *component, @@ -146,7 +145,6 @@ static int sof_ipc3_pcm_trigger(struct snd_soc_component *component, struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); struct sof_ipc_stream stream; - struct sof_ipc_reply reply; struct snd_sof_pcm *spcm; spcm = snd_sof_find_spcm_dai(component, rtd); @@ -178,7 +176,7 @@ static int sof_ipc3_pcm_trigger(struct snd_soc_component *component, } /* send IPC to the DSP */ - return sof_ipc_tx_message(sdev->ipc, &stream, sizeof(stream), &reply, sizeof(reply)); + return sof_ipc_tx_message_no_reply(sdev->ipc, &stream, sizeof(stream)); } static void ssp_dai_config_pcm_params_match(struct snd_sof_dev *sdev, const char *link_name, diff --git a/sound/soc/sof/ipc3-topology.c b/sound/soc/sof/ipc3-topology.c index b1f425b39db9..fc1eb8e2de2c 100644 --- a/sound/soc/sof/ipc3-topology.c +++ b/sound/soc/sof/ipc3-topology.c @@ -1627,7 +1627,6 @@ static void sof_ipc3_widget_free_comp_dai(struct snd_sof_widget *swidget) static int sof_ipc3_route_setup(struct snd_sof_dev *sdev, struct snd_sof_route *sroute) { struct sof_ipc_pipe_comp_connect connect; - struct sof_ipc_reply reply; int ret; connect.hdr.size = sizeof(connect); @@ -1640,7 +1639,7 @@ static int sof_ipc3_route_setup(struct snd_sof_dev *sdev, struct snd_sof_route * sroute->sink_widget->widget->name); /* send ipc */ - ret = sof_ipc_tx_message(sdev->ipc, &connect, sizeof(connect), &reply, sizeof(reply)); + ret = sof_ipc_tx_message_no_reply(sdev->ipc, &connect, sizeof(connect)); if (ret < 0) dev_err(sdev->dev, "%s: route %s -> %s failed\n", __func__, sroute->src_widget->widget->name, sroute->sink_widget->widget->name); @@ -1789,7 +1788,7 @@ static int sof_ipc3_control_free(struct snd_sof_dev *sdev, struct snd_sof_contro fcomp.id = scontrol->comp_id; /* send IPC to the DSP */ - return sof_ipc_tx_message(sdev->ipc, &fcomp, sizeof(fcomp), NULL, 0); + return sof_ipc_tx_message_no_reply(sdev->ipc, &fcomp, sizeof(fcomp)); } /* send pcm params ipc */ @@ -1797,7 +1796,6 @@ static int sof_ipc3_keyword_detect_pcm_params(struct snd_sof_widget *swidget, in { struct snd_soc_component *scomp = swidget->scomp; struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); - struct sof_ipc_pcm_params_reply ipc_params_reply; struct snd_pcm_hw_params *params; struct sof_ipc_pcm_params pcm; struct snd_sof_pcm *spcm; @@ -1841,8 +1839,7 @@ static int sof_ipc3_keyword_detect_pcm_params(struct snd_sof_widget *swidget, in } /* send IPC to the DSP */ - ret = sof_ipc_tx_message(sdev->ipc, &pcm, sizeof(pcm), - &ipc_params_reply, sizeof(ipc_params_reply)); + ret = sof_ipc_tx_message_no_reply(sdev->ipc, &pcm, sizeof(pcm)); if (ret < 0) dev_err(scomp->dev, "%s: PCM params failed for %s\n", __func__, swidget->widget->name); @@ -1856,7 +1853,6 @@ static int sof_ipc3_keyword_detect_trigger(struct snd_sof_widget *swidget, int c struct snd_soc_component *scomp = swidget->scomp; struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); struct sof_ipc_stream stream; - struct sof_ipc_reply reply; int ret; /* set IPC stream params */ @@ -1865,7 +1861,7 @@ static int sof_ipc3_keyword_detect_trigger(struct snd_sof_widget *swidget, int c stream.comp_id = swidget->comp_id; /* send IPC to the DSP */ - ret = sof_ipc_tx_message(sdev->ipc, &stream, sizeof(stream), &reply, sizeof(reply)); + ret = sof_ipc_tx_message_no_reply(sdev->ipc, &stream, sizeof(stream)); if (ret < 0) dev_err(scomp->dev, "%s: Failed to trigger %s\n", __func__, swidget->widget->name); @@ -1982,7 +1978,6 @@ static int sof_ipc3_widget_bind_event(struct snd_soc_component *scomp, static int sof_ipc3_complete_pipeline(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) { struct sof_ipc_pipe_ready ready; - struct sof_ipc_reply reply; int ret; dev_dbg(sdev->dev, "tplg: complete pipeline %s id %d\n", @@ -1993,7 +1988,7 @@ static int sof_ipc3_complete_pipeline(struct snd_sof_dev *sdev, struct snd_sof_w ready.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_PIPE_COMPLETE; ready.comp_id = swidget->comp_id; - ret = sof_ipc_tx_message(sdev->ipc, &ready, sizeof(ready), &reply, sizeof(reply)); + ret = sof_ipc_tx_message_no_reply(sdev->ipc, &ready, sizeof(ready)); if (ret < 0) return ret; @@ -2009,7 +2004,6 @@ static int sof_ipc3_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget }, .id = swidget->comp_id, }; - struct sof_ipc_reply reply; int ret; if (!swidget->private) @@ -2029,8 +2023,7 @@ static int sof_ipc3_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget break; } - ret = sof_ipc_tx_message(sdev->ipc, &ipc_free, sizeof(ipc_free), - &reply, sizeof(reply)); + ret = sof_ipc_tx_message_no_reply(sdev->ipc, &ipc_free, sizeof(ipc_free)); if (ret < 0) dev_err(sdev->dev, "failed to free widget %s\n", swidget->widget->name); @@ -2044,7 +2037,6 @@ static int sof_ipc3_dai_config(struct snd_sof_dev *sdev, struct snd_sof_widget * struct snd_sof_dai *dai = swidget->private; struct sof_dai_private_data *private; struct sof_ipc_dai_config *config; - struct sof_ipc_reply reply; int ret = 0; if (!dai || !dai->private) { @@ -2118,8 +2110,7 @@ static int sof_ipc3_dai_config(struct snd_sof_dev *sdev, struct snd_sof_widget * /* only send the IPC if the widget is set up in the DSP */ if (swidget->use_count > 0) { - ret = sof_ipc_tx_message(sdev->ipc, config, config->hdr.size, - &reply, sizeof(reply)); + ret = sof_ipc_tx_message_no_reply(sdev->ipc, config, config->hdr.size); if (ret < 0) dev_err(sdev->dev, "Failed to set dai config for %s\n", dai->name); @@ -2132,7 +2123,6 @@ static int sof_ipc3_dai_config(struct snd_sof_dev *sdev, struct snd_sof_widget * static int sof_ipc3_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) { - struct sof_ipc_comp_reply reply; int ret; if (!swidget->private) @@ -2146,8 +2136,7 @@ static int sof_ipc3_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget struct sof_dai_private_data *dai_data = dai->private; struct sof_ipc_comp *comp = &dai_data->comp_dai->comp; - ret = sof_ipc_tx_message(sdev->ipc, dai_data->comp_dai, - comp->hdr.size, &reply, sizeof(reply)); + ret = sof_ipc_tx_message_no_reply(sdev->ipc, dai_data->comp_dai, comp->hdr.size); break; } case snd_soc_dapm_scheduler: @@ -2155,8 +2144,7 @@ static int sof_ipc3_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget struct sof_ipc_pipe_new *pipeline; pipeline = swidget->private; - ret = sof_ipc_tx_message(sdev->ipc, pipeline, sizeof(*pipeline), - &reply, sizeof(reply)); + ret = sof_ipc_tx_message_no_reply(sdev->ipc, pipeline, sizeof(*pipeline)); break; } default: @@ -2164,8 +2152,7 @@ static int sof_ipc3_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget struct sof_ipc_cmd_hdr *hdr; hdr = swidget->private; - ret = sof_ipc_tx_message(sdev->ipc, swidget->private, hdr->size, - &reply, sizeof(reply)); + ret = sof_ipc_tx_message_no_reply(sdev->ipc, swidget->private, hdr->size); break; } } diff --git a/sound/soc/sof/ipc3.c b/sound/soc/sof/ipc3.c index 4493bbd7faf1..c67767742093 100644 --- a/sound/soc/sof/ipc3.c +++ b/sound/soc/sof/ipc3.c @@ -1044,15 +1044,13 @@ static int sof_ipc3_set_core_state(struct snd_sof_dev *sdev, int core_idx, bool .hdr.size = sizeof(core_cfg), .hdr.cmd = SOF_IPC_GLB_PM_MSG | SOF_IPC_PM_CORE_ENABLE, }; - struct sof_ipc_reply reply; if (on) core_cfg.enable_mask = sdev->enabled_cores_mask | BIT(core_idx); else core_cfg.enable_mask = sdev->enabled_cores_mask & ~BIT(core_idx); - return sof_ipc3_tx_msg(sdev, &core_cfg, sizeof(core_cfg), - &reply, sizeof(reply), false); + return sof_ipc3_tx_msg(sdev, &core_cfg, sizeof(core_cfg), NULL, 0, false); } static int sof_ipc3_ctx_ipc(struct snd_sof_dev *sdev, int cmd) @@ -1061,11 +1059,9 @@ static int sof_ipc3_ctx_ipc(struct snd_sof_dev *sdev, int cmd) .hdr.size = sizeof(pm_ctx), .hdr.cmd = SOF_IPC_GLB_PM_MSG | cmd, }; - struct sof_ipc_reply reply; /* send ctx save ipc to dsp */ - return sof_ipc3_tx_msg(sdev, &pm_ctx, sizeof(pm_ctx), - &reply, sizeof(reply), false); + return sof_ipc3_tx_msg(sdev, &pm_ctx, sizeof(pm_ctx), NULL, 0, false); } static int sof_ipc3_ctx_save(struct snd_sof_dev *sdev) @@ -1081,7 +1077,6 @@ static int sof_ipc3_ctx_restore(struct snd_sof_dev *sdev) static int sof_ipc3_set_pm_gate(struct snd_sof_dev *sdev, u32 flags) { struct sof_ipc_pm_gate pm_gate; - struct sof_ipc_reply reply; memset(&pm_gate, 0, sizeof(pm_gate)); @@ -1091,8 +1086,7 @@ static int sof_ipc3_set_pm_gate(struct snd_sof_dev *sdev, u32 flags) pm_gate.flags = flags; /* send pm_gate ipc to dsp */ - return sof_ipc_tx_message_no_pm(sdev->ipc, &pm_gate, sizeof(pm_gate), - &reply, sizeof(reply)); + return sof_ipc_tx_message_no_pm_no_reply(sdev->ipc, &pm_gate, sizeof(pm_gate)); } static const struct sof_ipc_pm_ops ipc3_pm_ops = { diff --git a/sound/soc/sof/ipc4-pcm.c b/sound/soc/sof/ipc4-pcm.c index a2cd21256e44..6a4c91ea47ed 100644 --- a/sound/soc/sof/ipc4-pcm.c +++ b/sound/soc/sof/ipc4-pcm.c @@ -39,7 +39,7 @@ static int sof_ipc4_set_multi_pipeline_state(struct snd_sof_dev *sdev, u32 state msg.data_size = ipc_size; msg.data_ptr = trigger_list; - return sof_ipc_tx_message(sdev->ipc, &msg, ipc_size, NULL, 0); + return sof_ipc_tx_message_no_reply(sdev->ipc, &msg, ipc_size); } int sof_ipc4_set_pipeline_state(struct snd_sof_dev *sdev, u32 id, u32 state) @@ -57,7 +57,7 @@ int sof_ipc4_set_pipeline_state(struct snd_sof_dev *sdev, u32 id, u32 state) msg.primary = primary; - return sof_ipc_tx_message(sdev->ipc, &msg, 0, NULL, 0); + return sof_ipc_tx_message_no_reply(sdev->ipc, &msg, 0); } EXPORT_SYMBOL(sof_ipc4_set_pipeline_state); @@ -272,7 +272,7 @@ static int sof_ipc4_chain_dma_trigger(struct snd_sof_dev *sdev, if (enable) msg.primary |= SOF_IPC4_GLB_CHAIN_DMA_ENABLE_MASK; - return sof_ipc_tx_message(sdev->ipc, &msg, 0, NULL, 0); + return sof_ipc_tx_message_no_reply(sdev->ipc, &msg, 0); } static int sof_ipc4_trigger_pipelines(struct snd_soc_component *component, diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index d2d41c53260c..a010e7c38817 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -2118,7 +2118,7 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget msg->data_size = ipc_size; msg->data_ptr = ipc_data; - ret = sof_ipc_tx_message(sdev->ipc, msg, ipc_size, NULL, 0); + ret = sof_ipc_tx_message_no_reply(sdev->ipc, msg, ipc_size); if (ret < 0) { dev_err(sdev->dev, "failed to create module %s\n", swidget->widget->name); @@ -2162,7 +2162,7 @@ static int sof_ipc4_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget msg.primary = header; - ret = sof_ipc_tx_message(sdev->ipc, &msg, 0, NULL, 0); + ret = sof_ipc_tx_message_no_reply(sdev->ipc, &msg, 0); if (ret < 0) dev_err(sdev->dev, "failed to free pipeline widget %s\n", swidget->widget->name); @@ -2320,7 +2320,7 @@ static int sof_ipc4_set_copier_sink_format(struct snd_sof_dev *sdev, msg.primary = header; msg.extension = extension; - return sof_ipc_tx_message(sdev->ipc, &msg, msg.data_size, NULL, 0); + return sof_ipc_tx_message_no_reply(sdev->ipc, &msg, msg.data_size); } static int sof_ipc4_route_setup(struct snd_sof_dev *sdev, struct snd_sof_route *sroute) @@ -2403,7 +2403,7 @@ static int sof_ipc4_route_setup(struct snd_sof_dev *sdev, struct snd_sof_route * msg.primary = header; msg.extension = extension; - ret = sof_ipc_tx_message(sdev->ipc, &msg, 0, NULL, 0); + ret = sof_ipc_tx_message_no_reply(sdev->ipc, &msg, 0); if (ret < 0) { dev_err(sdev->dev, "failed to bind modules %s:%d -> %s:%d\n", src_widget->widget->name, sroute->src_queue_id, @@ -2462,7 +2462,7 @@ static int sof_ipc4_route_free(struct snd_sof_dev *sdev, struct snd_sof_route *s msg.primary = header; msg.extension = extension; - ret = sof_ipc_tx_message(sdev->ipc, &msg, 0, NULL, 0); + ret = sof_ipc_tx_message_no_reply(sdev->ipc, &msg, 0); if (ret < 0) dev_err(sdev->dev, "failed to unbind modules %s:%d -> %s:%d\n", src_widget->widget->name, sroute->src_queue_id, diff --git a/sound/soc/sof/sof-client-ipc-flood-test.c b/sound/soc/sof/sof-client-ipc-flood-test.c index 4bdecd80248a..c0d6723aed59 100644 --- a/sound/soc/sof/sof-client-ipc-flood-test.c +++ b/sound/soc/sof/sof-client-ipc-flood-test.c @@ -64,7 +64,6 @@ static int sof_debug_ipc_flood_test(struct sof_client_dev *cdev, struct sof_ipc_flood_priv *priv = cdev->data; struct device *dev = &cdev->auxdev.dev; struct sof_ipc_cmd_hdr hdr; - struct sof_ipc_reply reply; u64 min_response_time = U64_MAX; ktime_t start, end, test_end; u64 avg_response_time = 0; @@ -84,7 +83,7 @@ static int sof_debug_ipc_flood_test(struct sof_client_dev *cdev, /* send test IPC's */ while (1) { start = ktime_get(); - ret = sof_client_ipc_tx_message(cdev, &hdr, &reply, sizeof(reply)); + ret = sof_client_ipc_tx_message_no_reply(cdev, &hdr); end = ktime_get(); if (ret < 0) diff --git a/sound/soc/sof/sof-client-probes-ipc3.c b/sound/soc/sof/sof-client-probes-ipc3.c index ef768db5f04d..5e8eb19582a8 100644 --- a/sound/soc/sof/sof-client-probes-ipc3.c +++ b/sound/soc/sof/sof-client-probes-ipc3.c @@ -65,7 +65,6 @@ static int ipc3_probes_init(struct sof_client_dev *cdev, u32 stream_tag, { struct sof_ipc_probe_dma_add_params *msg; size_t size = struct_size(msg, dma, 1); - struct sof_ipc_reply reply; int ret; msg = kmalloc(size, GFP_KERNEL); @@ -77,7 +76,7 @@ static int ipc3_probes_init(struct sof_client_dev *cdev, u32 stream_tag, msg->dma[0].stream_tag = stream_tag; msg->dma[0].dma_buffer_size = buffer_size; - ret = sof_client_ipc_tx_message(cdev, msg, &reply, sizeof(reply)); + ret = sof_client_ipc_tx_message_no_reply(cdev, msg); kfree(msg); return ret; } @@ -93,12 +92,11 @@ static int ipc3_probes_init(struct sof_client_dev *cdev, u32 stream_tag, static int ipc3_probes_deinit(struct sof_client_dev *cdev) { struct sof_ipc_cmd_hdr msg; - struct sof_ipc_reply reply; msg.size = sizeof(msg); msg.cmd = SOF_IPC_GLB_PROBE | SOF_IPC_PROBE_DEINIT; - return sof_client_ipc_tx_message(cdev, &msg, &reply, sizeof(reply)); + return sof_client_ipc_tx_message_no_reply(cdev, &msg); } static int ipc3_probes_info(struct sof_client_dev *cdev, unsigned int cmd, @@ -180,7 +178,6 @@ static int ipc3_probes_points_add(struct sof_client_dev *cdev, { struct sof_ipc_probe_point_add_params *msg; size_t size = struct_size(msg, desc, num_desc); - struct sof_ipc_reply reply; int ret; msg = kmalloc(size, GFP_KERNEL); @@ -191,7 +188,7 @@ static int ipc3_probes_points_add(struct sof_client_dev *cdev, msg->hdr.cmd = SOF_IPC_GLB_PROBE | SOF_IPC_PROBE_POINT_ADD; memcpy(&msg->desc[0], desc, size - sizeof(*msg)); - ret = sof_client_ipc_tx_message(cdev, msg, &reply, sizeof(reply)); + ret = sof_client_ipc_tx_message_no_reply(cdev, msg); kfree(msg); return ret; } @@ -211,7 +208,6 @@ static int ipc3_probes_points_remove(struct sof_client_dev *cdev, { struct sof_ipc_probe_point_remove_params *msg; size_t size = struct_size(msg, buffer_id, num_buffer_id); - struct sof_ipc_reply reply; int ret; msg = kmalloc(size, GFP_KERNEL); @@ -222,7 +218,7 @@ static int ipc3_probes_points_remove(struct sof_client_dev *cdev, msg->hdr.cmd = SOF_IPC_GLB_PROBE | SOF_IPC_PROBE_POINT_REMOVE; memcpy(&msg->buffer_id[0], buffer_id, size - sizeof(*msg)); - ret = sof_client_ipc_tx_message(cdev, msg, &reply, sizeof(reply)); + ret = sof_client_ipc_tx_message_no_reply(cdev, msg); kfree(msg); return ret; } diff --git a/sound/soc/sof/sof-client-probes-ipc4.c b/sound/soc/sof/sof-client-probes-ipc4.c index 66fa7c2f390a..ea21ef176c42 100644 --- a/sound/soc/sof/sof-client-probes-ipc4.c +++ b/sound/soc/sof/sof-client-probes-ipc4.c @@ -129,7 +129,7 @@ static int ipc4_probes_init(struct sof_client_dev *cdev, u32 stream_tag, msg.data_size = sizeof(cfg); msg.data_ptr = &cfg; - return sof_client_ipc_tx_message(cdev, &msg, NULL, 0); + return sof_client_ipc_tx_message_no_reply(cdev, &msg); } /** @@ -156,7 +156,7 @@ static int ipc4_probes_deinit(struct sof_client_dev *cdev) msg.data_size = 0; msg.data_ptr = NULL; - return sof_client_ipc_tx_message(cdev, &msg, NULL, 0); + return sof_client_ipc_tx_message_no_reply(cdev, &msg); } /** From 058924644f9596b8c55fc81f01f741d628eed940 Mon Sep 17 00:00:00 2001 From: Curtis Malainey Date: Wed, 19 Apr 2023 14:55:18 -0500 Subject: [PATCH 763/778] ASoC: Intel: sof_cirrus_common: Guard against missing buses Even if we find a acpi device we can still be missing the physical node. Signed-off-by: Curtis Malainey Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Link: https://lore.kernel.org/r/20230419195524.46995-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_cirrus_common.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/sound/soc/intel/boards/sof_cirrus_common.c b/sound/soc/intel/boards/sof_cirrus_common.c index 851c516c8f5b..8b8b07e4f2fe 100644 --- a/sound/soc/intel/boards/sof_cirrus_common.c +++ b/sound/soc/intel/boards/sof_cirrus_common.c @@ -168,11 +168,16 @@ static int cs35l41_compute_codec_conf(void) continue; } physdev = get_device(acpi_get_first_physical_node(adev)); + acpi_dev_put(adev); + if (!physdev) { + pr_devel("Cannot find physical node for HID %s UID %u (%s)\n", CS35L41_HID, + uid, cs35l41_name_prefixes[uid]); + return 0; + } cs35l41_components[sz].name = dev_name(physdev); cs35l41_components[sz].dai_name = CS35L41_CODEC_DAI; cs35l41_codec_conf[sz].dlc.name = dev_name(physdev); cs35l41_codec_conf[sz].name_prefix = cs35l41_name_prefixes[uid]; - acpi_dev_put(adev); sz++; } From f5460a155ecb961463f6ff766c7d3092f07e6642 Mon Sep 17 00:00:00 2001 From: apoorv Date: Wed, 19 Apr 2023 14:55:19 -0500 Subject: [PATCH 764/778] ASoC: Intel: soc-acpi: Add entry for rt711-sdca-sdw at link 2 in RPL match table RT711 sdca sdw is added with SDW2 link for RPL-P CRB platform. Signed-off-by: apoorv Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Link: https://lore.kernel.org/r/20230419195524.46995-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- .../soc/intel/common/soc-acpi-intel-rpl-match.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/sound/soc/intel/common/soc-acpi-intel-rpl-match.c b/sound/soc/intel/common/soc-acpi-intel-rpl-match.c index 13cbd8e9d41f..749d371a86ae 100644 --- a/sound/soc/intel/common/soc-acpi-intel-rpl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-rpl-match.c @@ -284,6 +284,15 @@ static const struct snd_soc_acpi_link_adr rpl_sdw_rt1316_link12_rt714_link0[] = {} }; +static const struct snd_soc_acpi_link_adr rplp_crb[] = { + { + .mask = BIT(2), + .num_adr = ARRAY_SIZE(rt711_sdca_2_adr), + .adr_d = rt711_sdca_2_adr, + }, + {} +}; + static const struct snd_soc_acpi_codecs rpl_rt5682_hp = { .num_codecs = 2, .codecs = {"10EC5682", "RTL5682"}, @@ -348,7 +357,13 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_rpl_sdw_machines[] = { .link_mask = 0x1, /* link0 required */ .links = rpl_rvp, .drv_name = "sof_sdw", - .sof_tplg_filename = "sof-rpl-rt711.tplg", + .sof_tplg_filename = "sof-rpl-rt711-l0.tplg", + }, + { + .link_mask = 0x4, /* link2 required */ + .links = rplp_crb, + .drv_name = "sof_sdw", + .sof_tplg_filename = "sof-rpl-rt711-l2.tplg", }, {}, }; From 06b830bd73ec66b9316b899ae37b1d5b83d16a32 Mon Sep 17 00:00:00 2001 From: Yong Zhi Date: Wed, 19 Apr 2023 14:55:20 -0500 Subject: [PATCH 765/778] ASoC: Intel: sof_sdw: remove late_probe flag in struct sof_sdw_codec_info Just use codec_card_late_probe ptr in struct sof_sdw_codec_info for validation check and drop late_probe variable. Signed-off-by: Yong Zhi Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Link: https://lore.kernel.org/r/20230419195524.46995-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 11 +++++------ sound/soc/intel/boards/sof_sdw_common.h | 1 - sound/soc/intel/boards/sof_sdw_max98373.c | 2 +- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 6897705a193c..7d398b45d48f 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -621,7 +621,6 @@ static struct sof_sdw_codec_info codec_info_list[] = { .direction = {true, true}, .dai_name = "max98373-aif1", .init = sof_sdw_mx8373_init, - .codec_card_late_probe = sof_sdw_mx8373_late_probe, .codec_type = SOF_SDW_CODEC_TYPE_AMP, }, { @@ -1490,12 +1489,12 @@ static int sof_sdw_card_late_probe(struct snd_soc_card *card) int i; for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) { - if (!codec_info_list[i].late_probe) - continue; + if (codec_info_list[i].codec_card_late_probe) { + ret = codec_info_list[i].codec_card_late_probe(card); - ret = codec_info_list[i].codec_card_late_probe(card); - if (ret < 0) - return ret; + if (ret < 0) + return ret; + } } if (ctx->idisp_codec) diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h index 350010b0e5f4..4962dc11a088 100644 --- a/sound/soc/intel/boards/sof_sdw_common.h +++ b/sound/soc/intel/boards/sof_sdw_common.h @@ -74,7 +74,6 @@ struct sof_sdw_codec_info { bool playback); int (*exit)(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link); - bool late_probe; int (*codec_card_late_probe)(struct snd_soc_card *card); }; diff --git a/sound/soc/intel/boards/sof_sdw_max98373.c b/sound/soc/intel/boards/sof_sdw_max98373.c index 77a3f32db11e..22bd1e356e22 100644 --- a/sound/soc/intel/boards/sof_sdw_max98373.c +++ b/sound/soc/intel/boards/sof_sdw_max98373.c @@ -130,7 +130,7 @@ int sof_sdw_mx8373_init(struct snd_soc_card *card, if (info->amp_num == 2) dai_links->init = spk_init; - info->late_probe = true; + info->codec_card_late_probe = sof_sdw_mx8373_late_probe; dai_links->ops = &max_98373_sdw_ops; From e9fcbaff5fb871f1a10f09d7d1a4cd13c923e280 Mon Sep 17 00:00:00 2001 From: Yong Zhi Date: Wed, 19 Apr 2023 14:55:21 -0500 Subject: [PATCH 766/778] ASoC: Intel: sof_sdw_max98373: change sof_sdw_mx8373_late_probe to static call sof_sdw_mx8373_late_probe is only used in sof_sdw_max98373, so it should be static and rename it to 'mx8373_sdw_late_probe'. Signed-off-by: Yong Zhi Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Link: https://lore.kernel.org/r/20230419195524.46995-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw_common.h | 2 -- sound/soc/intel/boards/sof_sdw_max98373.c | 22 +++++++++++----------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h index 4962dc11a088..081ab7eac5b6 100644 --- a/sound/soc/intel/boards/sof_sdw_common.h +++ b/sound/soc/intel/boards/sof_sdw_common.h @@ -158,8 +158,6 @@ int sof_sdw_mx8373_init(struct snd_soc_card *card, struct sof_sdw_codec_info *info, bool playback); -int sof_sdw_mx8373_late_probe(struct snd_soc_card *card); - /* RT5682 support */ int sof_sdw_rt5682_init(struct snd_soc_card *card, const struct snd_soc_acpi_link_adr *link, diff --git a/sound/soc/intel/boards/sof_sdw_max98373.c b/sound/soc/intel/boards/sof_sdw_max98373.c index 22bd1e356e22..3d7df58c0f1d 100644 --- a/sound/soc/intel/boards/sof_sdw_max98373.c +++ b/sound/soc/intel/boards/sof_sdw_max98373.c @@ -120,6 +120,16 @@ static const struct snd_soc_ops max_98373_sdw_ops = { .shutdown = sdw_shutdown, }; +static int mx8373_sdw_late_probe(struct snd_soc_card *card) +{ + struct snd_soc_dapm_context *dapm = &card->dapm; + + /* Disable Left and Right Spk pin after boot */ + snd_soc_dapm_disable_pin(dapm, "Left Spk"); + snd_soc_dapm_disable_pin(dapm, "Right Spk"); + return snd_soc_dapm_sync(dapm); +} + int sof_sdw_mx8373_init(struct snd_soc_card *card, const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, @@ -130,19 +140,9 @@ int sof_sdw_mx8373_init(struct snd_soc_card *card, if (info->amp_num == 2) dai_links->init = spk_init; - info->codec_card_late_probe = sof_sdw_mx8373_late_probe; + info->codec_card_late_probe = mx8373_sdw_late_probe; dai_links->ops = &max_98373_sdw_ops; return 0; } - -int sof_sdw_mx8373_late_probe(struct snd_soc_card *card) -{ - struct snd_soc_dapm_context *dapm = &card->dapm; - - /* Disable Left and Right Spk pin after boot */ - snd_soc_dapm_disable_pin(dapm, "Left Spk"); - snd_soc_dapm_disable_pin(dapm, "Right Spk"); - return snd_soc_dapm_sync(dapm); -} From 16373f30777f45823fa68e850b230fa2ef9d7e92 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Wed, 19 Apr 2023 14:55:22 -0500 Subject: [PATCH 767/778] ASoC: Intel: sof_sdw: set codec_num = 1 if the device is not aggregated We assume adr_link->num_adr = 1 if a device is not aggregated. However, the assumption is not valid if there are different type devices on the same soundwire link. Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Link: https://lore.kernel.org/r/20230419195524.46995-6-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 7d398b45d48f..e5729df4fd44 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -961,6 +961,7 @@ static int get_slave_info(const struct snd_soc_acpi_link_adr *adr_link, cpu_dai_id[index++] = ffs(adr_link->mask) - 1; if (!adr_d->endpoints->aggregated || no_aggregation) { *cpu_dai_num = 1; + *codec_num = 1; *group_id = 0; return 0; } From c8db7b50128b8cc61a5ca6e4717cf8158fca302a Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Wed, 19 Apr 2023 14:55:23 -0500 Subject: [PATCH 768/778] ASoC: Intel: sof_sdw: support different devices on the same sdw link The existing code assumes all devices on the same soundwire link are the same devices. eg. all rt1316. This commit removes the assumption and supports different devices on the same soundwire link. Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Link: https://lore.kernel.org/r/20230419195524.46995-7-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 130 ++++++++++++++++++------------- 1 file changed, 77 insertions(+), 53 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index e5729df4fd44..6a6c81df72bd 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -732,34 +732,36 @@ static int get_sdw_dailink_info(struct device *dev, const struct snd_soc_acpi_li int stream; u64 adr; - adr = link->adr_d->adr; - codec_index = find_codec_info_part(adr); - if (codec_index < 0) - return codec_index; + for (i = 0; i < link->num_adr; i++) { + adr = link->adr_d[i].adr; + codec_index = find_codec_info_part(adr); + if (codec_index < 0) + return codec_index; - if (codec_info_list[codec_index].codec_type < _codec_type) - dev_warn(dev, - "Unexpected address table ordering. Expected order: jack -> amp -> mic\n"); + if (codec_info_list[codec_index].codec_type < _codec_type) + dev_warn(dev, + "Unexpected address table ordering. Expected order: jack -> amp -> mic\n"); - _codec_type = codec_info_list[codec_index].codec_type; + _codec_type = codec_info_list[codec_index].codec_type; - endpoint = link->adr_d->endpoints; + endpoint = link->adr_d[i].endpoints; - /* count DAI number for playback and capture */ - for_each_pcm_streams(stream) { - if (!codec_info_list[codec_index].direction[stream]) - continue; + /* count DAI number for playback and capture */ + for_each_pcm_streams(stream) { + if (!codec_info_list[codec_index].direction[stream]) + continue; - (*sdw_cpu_dai_num)++; + (*sdw_cpu_dai_num)++; - /* count BE for each non-aggregated slave or group */ - if (!endpoint->aggregated || no_aggregation || - !group_visited[endpoint->group_id]) - (*sdw_be_num)++; + /* count BE for each non-aggregated slave or group */ + if (!endpoint->aggregated || no_aggregation || + !group_visited[endpoint->group_id]) + (*sdw_be_num)++; + } + + if (endpoint->aggregated) + group_visited[endpoint->group_id] = true; } - - if (endpoint->aggregated) - group_visited[endpoint->group_id] = true; } return 0; @@ -829,17 +831,19 @@ static int create_codec_dai_name(struct device *dev, int offset, struct snd_soc_codec_conf *codec_conf, int codec_count, - int *codec_conf_index) + int *codec_conf_index, + int adr_index) { + int _codec_index = -1; int i; /* sanity check */ - if (*codec_conf_index + link->num_adr > codec_count) { + if (*codec_conf_index + link->num_adr - adr_index > codec_count) { dev_err(dev, "codec_conf: out-of-bounds access requested\n"); return -EINVAL; } - for (i = 0; i < link->num_adr; i++) { + for (i = adr_index; i < link->num_adr; i++) { unsigned int sdw_version, unique_id, mfg_id; unsigned int link_id, part_id, class_id; int codec_index, comp_index; @@ -855,7 +859,7 @@ static int create_codec_dai_name(struct device *dev, part_id = SDW_PART_ID(adr); class_id = SDW_CLASS_ID(adr); - comp_index = i + offset; + comp_index = i - adr_index + offset; if (is_unique_device(link, sdw_version, mfg_id, part_id, class_id, i)) { codec_str = "sdw:%01x:%04x:%04x:%02x"; @@ -877,6 +881,11 @@ static int create_codec_dai_name(struct device *dev, codec_index = find_codec_info_part(adr); if (codec_index < 0) return codec_index; + if (_codec_index != -1 && codec_index != _codec_index) { + dev_dbg(dev, "Different devices on the same sdw link\n"); + break; + } + _codec_index = codec_index; codec[comp_index].dai_name = codec_info_list[codec_index].dai_name; @@ -943,16 +952,16 @@ static int set_codec_init_func(struct snd_soc_card *card, static int get_slave_info(const struct snd_soc_acpi_link_adr *adr_link, struct device *dev, int *cpu_dai_id, int *cpu_dai_num, int *codec_num, unsigned int *group_id, - bool *group_generated) + bool *group_generated, int adr_index) { const struct snd_soc_acpi_adr_device *adr_d; const struct snd_soc_acpi_link_adr *adr_next; bool no_aggregation; int index = 0; + int i; no_aggregation = sof_sdw_quirk & SOF_SDW_NO_AGGREGATION; - *codec_num = adr_link->num_adr; - adr_d = adr_link->adr_d; + adr_d = &adr_link->adr_d[adr_index]; /* make sure the link mask has a single bit set */ if (!is_power_of_2(adr_link->mask)) @@ -968,6 +977,14 @@ static int get_slave_info(const struct snd_soc_acpi_link_adr *adr_link, *group_id = adr_d->endpoints->group_id; + /* Count endpoints with the same group_id in the adr_link */ + *codec_num = 0; + for (i = 0; i < adr_link->num_adr; i++) { + if (adr_link->adr_d[i].endpoints->aggregated && + adr_link->adr_d[i].endpoints->group_id == *group_id) + (*codec_num)++; + } + /* gather other link ID of slaves in the same group */ for (adr_next = adr_link + 1; adr_next && adr_next->num_adr; adr_next++) { @@ -988,7 +1005,11 @@ static int get_slave_info(const struct snd_soc_acpi_link_adr *adr_link, } cpu_dai_id[index++] = ffs(adr_next->mask) - 1; - *codec_num += adr_next->num_adr; + for (i = 0; i < adr_next->num_adr; i++) { + if (adr_next->adr_d[i].endpoints->aggregated && + adr_next->adr_d[i].endpoints->group_id == *group_id) + (*codec_num)++; + } } /* @@ -1011,7 +1032,8 @@ static int create_sdw_dailink(struct snd_soc_card *card, struct snd_soc_codec_conf *codec_conf, int codec_count, int *link_id, int *codec_conf_index, - bool *ignore_pch_dmic) + bool *ignore_pch_dmic, + int adr_index) { const struct snd_soc_acpi_link_adr *link_next; struct snd_soc_dai_link_component *codecs; @@ -1027,7 +1049,7 @@ static int create_sdw_dailink(struct snd_soc_card *card, int k; ret = get_slave_info(link, dev, cpu_dai_id, &cpu_dai_num, &codec_num, - &group_id, group_generated); + &group_id, group_generated, adr_index); if (ret) return ret; @@ -1050,7 +1072,7 @@ static int create_sdw_dailink(struct snd_soc_card *card, continue; ret = create_codec_dai_name(dev, link_next, codecs, codec_idx, - codec_conf, codec_count, codec_conf_index); + codec_conf, codec_count, codec_conf_index, adr_index); if (ret < 0) return ret; @@ -1060,7 +1082,7 @@ static int create_sdw_dailink(struct snd_soc_card *card, } /* find codec info to create BE DAI */ - codec_index = find_codec_info_part(link->adr_d[0].adr); + codec_index = find_codec_info_part(link->adr_d[adr_index].adr); if (codec_index < 0) return codec_index; @@ -1303,29 +1325,31 @@ static int sof_card_dai_links_create(struct device *dev, /* generate DAI links by each sdw link */ for (; adr_link->num_adr; adr_link++) { - const struct snd_soc_acpi_endpoint *endpoint; + for (i = 0; i < adr_link->num_adr; i++) { + const struct snd_soc_acpi_endpoint *endpoint; - endpoint = adr_link->adr_d->endpoints; - if (endpoint->aggregated && !endpoint->group_id) { - dev_err(dev, "invalid group id on link %x", - adr_link->mask); - continue; - } + endpoint = adr_link->adr_d[i].endpoints; + if (endpoint->aggregated && !endpoint->group_id) { + dev_err(dev, "invalid group id on link %x", + adr_link->mask); + continue; + } - /* this group has been generated */ - if (endpoint->aggregated && - group_generated[endpoint->group_id]) - continue; + /* this group has been generated */ + if (endpoint->aggregated && + group_generated[endpoint->group_id]) + continue; - ret = create_sdw_dailink(card, dev, &link_index, links, sdw_be_num, - sdw_cpu_dai_num, cpus, adr_link, - &cpu_id, group_generated, - codec_conf, codec_conf_count, - &be_id, &codec_conf_index, - &ignore_pch_dmic); - if (ret < 0) { - dev_err(dev, "failed to create dai link %d", link_index); - return ret; + ret = create_sdw_dailink(card, dev, &link_index, links, sdw_be_num, + sdw_cpu_dai_num, cpus, adr_link, + &cpu_id, group_generated, + codec_conf, codec_conf_count, + &be_id, &codec_conf_index, + &ignore_pch_dmic, i); + if (ret < 0) { + dev_err(dev, "failed to create dai link %d", link_index); + return ret; + } } } From dc5a3e60a4b5974a0cb5bf2c5df70a490dce9df2 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Wed, 19 Apr 2023 14:55:24 -0500 Subject: [PATCH 769/778] ASoC: Intel: sof_sdw: append codec type to dai link name The existing sdw_sof machine driver constructs two SoundWire interfaces by direction and sdw link id. It means that we will have exactly the same dai link name if two dai links are on the same sdw link with the same direction. The new Realtek codec has two SoundWire interfaces for jack and DMIC functions and they are treated as different codecs. To create two dai links for jack and DMIC, we need to have different dai link names. This patch suggests to append codec type if there are two or more different types of devices on the same sdw bus. Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Link: https://lore.kernel.org/r/20230419195524.46995-8-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 41 ++++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 6a6c81df72bd..6faf4a43eaf5 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1022,6 +1022,8 @@ static int get_slave_info(const struct snd_soc_acpi_link_adr *adr_link, return 0; } +static const char * const type_strings[] = {"SimpleJack", "SmartAmp", "SmartMic"}; + static int create_sdw_dailink(struct snd_soc_card *card, struct device *dev, int *link_index, struct snd_soc_dai_link *dai_links, @@ -1033,6 +1035,7 @@ static int create_sdw_dailink(struct snd_soc_card *card, int codec_count, int *link_id, int *codec_conf_index, bool *ignore_pch_dmic, + bool append_codec_type, int adr_index) { const struct snd_soc_acpi_link_adr *link_next; @@ -1109,14 +1112,22 @@ static int create_sdw_dailink(struct snd_soc_card *card, static const char * const sdw_stream_name[] = { "SDW%d-Playback", "SDW%d-Capture", + "SDW%d-Playback-%s", + "SDW%d-Capture-%s", }; if (!codec_info_list[codec_index].direction[stream]) continue; /* create stream name according to first link id */ - name = devm_kasprintf(dev, GFP_KERNEL, - sdw_stream_name[stream], cpu_dai_id[0]); + if (append_codec_type) { + name = devm_kasprintf(dev, GFP_KERNEL, + sdw_stream_name[stream + 2], cpu_dai_id[0], + type_strings[codec_info_list[codec_index].codec_type]); + } else { + name = devm_kasprintf(dev, GFP_KERNEL, + sdw_stream_name[stream], cpu_dai_id[0]); + } if (!name) return -ENOMEM; @@ -1232,6 +1243,7 @@ static int sof_card_dai_links_create(struct device *dev, const struct snd_soc_acpi_link_adr *adr_link; struct snd_soc_dai_link_component *cpus; struct snd_soc_codec_conf *codec_conf; + bool append_codec_type = false; bool ignore_pch_dmic = false; int codec_conf_count; int codec_conf_index = 0; @@ -1323,8 +1335,29 @@ static int sof_card_dai_links_create(struct device *dev, for (i = 0; i < SDW_MAX_GROUPS; i++) group_generated[i] = false; - /* generate DAI links by each sdw link */ for (; adr_link->num_adr; adr_link++) { + /* + * If there are two or more different devices on the same sdw link, we have to + * append the codec type to the dai link name to prevent duplicated dai link name. + * The same type devices on the same sdw link will be in the same + * snd_soc_acpi_adr_device array. They won't be described in different adr_links. + */ + for (i = 0; i < adr_link->num_adr; i++) { + for (j = 0; j < i; j++) { + if ((SDW_PART_ID(adr_link->adr_d[i].adr) != + SDW_PART_ID(adr_link->adr_d[j].adr)) || + (SDW_MFG_ID(adr_link->adr_d[i].adr) != + SDW_MFG_ID(adr_link->adr_d[i].adr))) { + append_codec_type = true; + goto out; + } + } + } + } +out: + + /* generate DAI links by each sdw link */ + for (adr_link = mach_params->links ; adr_link->num_adr; adr_link++) { for (i = 0; i < adr_link->num_adr; i++) { const struct snd_soc_acpi_endpoint *endpoint; @@ -1345,7 +1378,7 @@ static int sof_card_dai_links_create(struct device *dev, &cpu_id, group_generated, codec_conf, codec_conf_count, &be_id, &codec_conf_index, - &ignore_pch_dmic, i); + &ignore_pch_dmic, append_codec_type, i); if (ret < 0) { dev_err(dev, "failed to create dai link %d", link_index); return ret; From 3e94369729ea8a825cf8bf304bfb1749de62ebf4 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Thu, 20 Apr 2023 14:41:36 +0300 Subject: [PATCH 770/778] ASoC: SOF: Intel: hda: Do not stop/start DMA during pause/release MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The FW does not pause/stop the host DMA during pause and stopping the host DMA from the driver could result in an unknown behaviour. So, skip triggering the HD-Audio host DMA during pause/release. Signed-off-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230420114137.27613-2-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-stream.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index 79d818e6a0fa..8de422604ad5 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -337,7 +337,13 @@ int hda_dsp_stream_trigger(struct snd_sof_dev *sdev, /* cmd must be for audio stream */ switch (cmd) { case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + if (!sdev->dspless_mode_selected) + break; + fallthrough; case SNDRV_PCM_TRIGGER_START: + if (hstream->running) + break; + snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL, 1 << hstream->index, 1 << hstream->index); @@ -360,8 +366,11 @@ int hda_dsp_stream_trigger(struct snd_sof_dev *sdev, hstream->running = true; break; - case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + if (!sdev->dspless_mode_selected) + break; + fallthrough; + case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_STOP: snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, sd_offset, From 6d0a21dd95c349bbe3663a4870ff7e70ddc6c9b6 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Thu, 20 Apr 2023 14:41:37 +0300 Subject: [PATCH 771/778] ASoC: SOF: pcm: Add an option to skip platform trigger during stop MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the case of IPC4, a pipeline is only paused during STOP/PAUSE/SUSPEND triggers and the FW keeps the host DMA running when a pipeline is paused. The start/stop tests iterate through STOP/START triggers without involving a hw_free. This means that the pipeline state will only toggle between PAUSED (during the STOP trigger) and RUNNING (during the START trigger). So this test should be treated in the same way as a PAUSE_PUSH/PAUSE_RELEASE test and the DMA should be kept running when toggling the pipeline states between PAUSED and RUNNING. Since there is no way to tell if a STOP trigger will be followed by hw_free or not, this patch proposes to always skip DMA stop during the STOP trigger and handle it later during hw_free. Introduce a new flag in struct sof_ipc_pcm_ops, delayed_platform_trigger, that will be used to ensure that the host DMA will not be stopped during the STOP/PAUSE/RELEASE triggers and set it for IPC4. The platform_trigger call to stop the DMA will be invoked during PCM hw_free instead when the pipeline is reset. Signed-off-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230420114137.27613-3-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-pcm.c | 3 ++- sound/soc/sof/pcm.c | 23 +++++++++++++++-------- sound/soc/sof/sof-audio.c | 22 ++++++++++++++-------- sound/soc/sof/sof-audio.h | 6 ++++++ 4 files changed, 37 insertions(+), 17 deletions(-) diff --git a/sound/soc/sof/ipc4-pcm.c b/sound/soc/sof/ipc4-pcm.c index a2cd21256e44..ea19bd0330e2 100644 --- a/sound/soc/sof/ipc4-pcm.c +++ b/sound/soc/sof/ipc4-pcm.c @@ -836,5 +836,6 @@ const struct sof_ipc_pcm_ops ipc4_pcm_ops = { .pcm_setup = sof_ipc4_pcm_setup, .pcm_free = sof_ipc4_pcm_free, .delay = sof_ipc4_pcm_delay, - .ipc_first_on_start = true + .ipc_first_on_start = true, + .platform_stop_during_hw_free = true, }; diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index 127b68caf9e1..567db32173a8 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -211,16 +211,22 @@ static int sof_pcm_hw_free(struct snd_soc_component *component, dev_dbg(component->dev, "pcm: free stream %d dir %d\n", spcm->pcm.pcm_id, substream->stream); - /* free PCM in the DSP */ - if (pcm_ops && pcm_ops->hw_free && spcm->prepared[substream->stream]) { - ret = pcm_ops->hw_free(component, substream); - if (ret < 0) - err = ret; + if (spcm->prepared[substream->stream]) { + /* stop DMA first if needed */ + if (pcm_ops && pcm_ops->platform_stop_during_hw_free) + snd_sof_pcm_platform_trigger(sdev, substream, SNDRV_PCM_TRIGGER_STOP); + + /* free PCM in the DSP */ + if (pcm_ops && pcm_ops->hw_free) { + ret = pcm_ops->hw_free(component, substream); + if (ret < 0) + err = ret; + } spcm->prepared[substream->stream] = false; } - /* stop DMA */ + /* reset DMA */ ret = snd_sof_pcm_platform_hw_free(sdev, substream); if (ret < 0) { dev_err(component->dev, "error: platform hw free failed\n"); @@ -362,8 +368,9 @@ static int sof_pcm_trigger(struct snd_soc_component *component, case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: case SNDRV_PCM_TRIGGER_STOP: - /* invoke platform trigger to stop DMA even if pcm_ops failed */ - snd_sof_pcm_platform_trigger(sdev, substream, cmd); + /* invoke platform trigger to stop DMA even if pcm_ops isn't set or if it failed */ + if (!pcm_ops || (pcm_ops && !pcm_ops->platform_stop_during_hw_free)) + snd_sof_pcm_platform_trigger(sdev, substream, cmd); break; default: break; diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c index 7651644fcd62..1cbda595c518 100644 --- a/sound/soc/sof/sof-audio.c +++ b/sound/soc/sof/sof-audio.c @@ -805,16 +805,22 @@ int sof_pcm_stream_free(struct snd_sof_dev *sdev, struct snd_pcm_substream *subs const struct sof_ipc_pcm_ops *pcm_ops = sof_ipc_get_ops(sdev, pcm); int ret; - /* Send PCM_FREE IPC to reset pipeline */ - if (pcm_ops && pcm_ops->hw_free && spcm->prepared[substream->stream]) { - ret = pcm_ops->hw_free(sdev->component, substream); - if (ret < 0) - return ret; + if (spcm->prepared[substream->stream]) { + /* stop DMA first if needed */ + if (pcm_ops && pcm_ops->platform_stop_during_hw_free) + snd_sof_pcm_platform_trigger(sdev, substream, SNDRV_PCM_TRIGGER_STOP); + + /* Send PCM_FREE IPC to reset pipeline */ + if (pcm_ops && pcm_ops->hw_free) { + ret = pcm_ops->hw_free(sdev->component, substream); + if (ret < 0) + return ret; + } + + spcm->prepared[substream->stream] = false; } - spcm->prepared[substream->stream] = false; - - /* stop the DMA */ + /* reset the DMA */ ret = snd_sof_pcm_platform_hw_free(sdev, substream); if (ret < 0) return ret; diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h index 6c64376858b3..a090a9eb4828 100644 --- a/sound/soc/sof/sof-audio.h +++ b/sound/soc/sof/sof-audio.h @@ -108,6 +108,11 @@ struct snd_sof_dai_config_data { * STOP pcm trigger * @ipc_first_on_start: Send IPC before invoking platform trigger during * START/PAUSE_RELEASE triggers + * @platform_stop_during_hw_free: Invoke the platform trigger during hw_free. This is needed for + * IPC4 where a pipeline is only paused during stop/pause/suspend + * triggers. The FW keeps the host DMA running in this case and + * therefore the host must do the same and should stop the DMA during + * hw_free. */ struct sof_ipc_pcm_ops { int (*hw_params)(struct snd_soc_component *component, struct snd_pcm_substream *substream, @@ -123,6 +128,7 @@ struct sof_ipc_pcm_ops { struct snd_pcm_substream *substream); bool reset_hw_params_during_stop; bool ipc_first_on_start; + bool platform_stop_during_hw_free; }; /** From 996b07efe49620325332081afdb0dc0bd6fe5cd0 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Thu, 20 Apr 2023 13:47:14 +0300 Subject: [PATCH 772/778] ASoC: SOF: Intel: Split the set_power_op for IPC3 and IPC4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Suspending to S0iX with IPC3 requires the PM_GATE IPC to be sent again to stop the DMA trace. But with IPC4, this is not needed as the trace is stopped with the LARGE_CONFIG_SET IPC. Also, sending the MOD_D0IX IPC to set the D0I3 state again when the DSP is in D0I3 already results in an imbalance in PM runtime states in the firmware. So split the set_power_state ops for IPC3 and IPC4 to avoid sending the MOD_D0IX IPC when the DSP is already in D0I3 with IPC4. Signed-off-by: Ranjani Sridharan Reviewed-by: Rander Wang Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230420104714.29573-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/apl.c | 4 ++ sound/soc/sof/intel/cnl.c | 4 ++ sound/soc/sof/intel/hda-common-ops.c | 1 - sound/soc/sof/intel/hda-dsp.c | 60 ++++++++++++++++++---------- sound/soc/sof/intel/hda.h | 6 ++- sound/soc/sof/intel/icl.c | 4 ++ sound/soc/sof/intel/mtl.c | 2 + sound/soc/sof/intel/tgl.c | 4 ++ 8 files changed, 60 insertions(+), 25 deletions(-) diff --git a/sound/soc/sof/intel/apl.c b/sound/soc/sof/intel/apl.c index 0e7a7e4ad976..e1f25a8f0c32 100644 --- a/sound/soc/sof/intel/apl.c +++ b/sound/soc/sof/intel/apl.c @@ -48,6 +48,8 @@ int sof_apl_ops_init(struct snd_sof_dev *sdev) /* debug */ sof_apl_ops.ipc_dump = hda_ipc_dump; + + sof_apl_ops.set_power_state = hda_dsp_set_power_state_ipc3; } if (sdev->pdata->ipc_type == SOF_INTEL_IPC4) { @@ -73,6 +75,8 @@ int sof_apl_ops_init(struct snd_sof_dev *sdev) /* debug */ sof_apl_ops.ipc_dump = hda_ipc4_dump; + + sof_apl_ops.set_power_state = hda_dsp_set_power_state_ipc4; } /* set DAI driver ops */ diff --git a/sound/soc/sof/intel/cnl.c b/sound/soc/sof/intel/cnl.c index a08a77fa946b..a95222e53ecf 100644 --- a/sound/soc/sof/intel/cnl.c +++ b/sound/soc/sof/intel/cnl.c @@ -395,6 +395,8 @@ int sof_cnl_ops_init(struct snd_sof_dev *sdev) /* debug */ sof_cnl_ops.ipc_dump = cnl_ipc_dump; + + sof_cnl_ops.set_power_state = hda_dsp_set_power_state_ipc3; } if (sdev->pdata->ipc_type == SOF_INTEL_IPC4) { @@ -420,6 +422,8 @@ int sof_cnl_ops_init(struct snd_sof_dev *sdev) /* debug */ sof_cnl_ops.ipc_dump = cnl_ipc4_dump; + + sof_cnl_ops.set_power_state = hda_dsp_set_power_state_ipc4; } /* set DAI driver ops */ diff --git a/sound/soc/sof/intel/hda-common-ops.c b/sound/soc/sof/intel/hda-common-ops.c index 397303b3ac9d..8e1cd0babd32 100644 --- a/sound/soc/sof/intel/hda-common-ops.c +++ b/sound/soc/sof/intel/hda-common-ops.c @@ -89,7 +89,6 @@ struct snd_sof_dsp_ops sof_hda_common_ops = { .runtime_resume = hda_dsp_runtime_resume, .runtime_idle = hda_dsp_runtime_idle, .set_hw_params_upon_resume = hda_dsp_set_hw_params_upon_resume, - .set_power_state = hda_dsp_set_power_state, /* ALSA HW info flags */ .hw_info = SNDRV_PCM_INFO_MMAP | diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index 77df536cf901..44f39a520bb3 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -574,31 +574,11 @@ static void hda_dsp_state_log(struct snd_sof_dev *sdev) * is called again either because of a new IPC sent to the DSP or * during system suspend/resume. */ -int hda_dsp_set_power_state(struct snd_sof_dev *sdev, - const struct sof_dsp_power_state *target_state) +static int hda_dsp_set_power_state(struct snd_sof_dev *sdev, + const struct sof_dsp_power_state *target_state) { int ret = 0; - /* - * When the DSP is already in D0I3 and the target state is D0I3, - * it could be the case that the DSP is in D0I3 during S0 - * and the system is suspending to S0Ix. Therefore, - * hda_dsp_set_D0_state() must be called to disable trace DMA - * by sending the PM_GATE IPC to the FW. - */ - if (target_state->substate == SOF_HDA_DSP_PM_D0I3 && - sdev->system_suspend_target == SOF_SUSPEND_S0IX) - goto set_state; - - /* - * For all other cases, return without doing anything if - * the DSP is already in the target state. - */ - if (target_state->state == sdev->dsp_power_state.state && - target_state->substate == sdev->dsp_power_state.substate) - return 0; - -set_state: switch (target_state->state) { case SOF_DSP_PM_D0: ret = hda_dsp_set_D0_state(sdev, target_state); @@ -630,6 +610,42 @@ set_state: return ret; } +int hda_dsp_set_power_state_ipc3(struct snd_sof_dev *sdev, + const struct sof_dsp_power_state *target_state) +{ + /* + * When the DSP is already in D0I3 and the target state is D0I3, + * it could be the case that the DSP is in D0I3 during S0 + * and the system is suspending to S0Ix. Therefore, + * hda_dsp_set_D0_state() must be called to disable trace DMA + * by sending the PM_GATE IPC to the FW. + */ + if (target_state->substate == SOF_HDA_DSP_PM_D0I3 && + sdev->system_suspend_target == SOF_SUSPEND_S0IX) + return hda_dsp_set_power_state(sdev, target_state); + + /* + * For all other cases, return without doing anything if + * the DSP is already in the target state. + */ + if (target_state->state == sdev->dsp_power_state.state && + target_state->substate == sdev->dsp_power_state.substate) + return 0; + + return hda_dsp_set_power_state(sdev, target_state); +} + +int hda_dsp_set_power_state_ipc4(struct snd_sof_dev *sdev, + const struct sof_dsp_power_state *target_state) +{ + /* Return without doing anything if the DSP is already in the target state */ + if (target_state->state == sdev->dsp_power_state.state && + target_state->substate == sdev->dsp_power_state.substate) + return 0; + + return hda_dsp_set_power_state(sdev, target_state); +} + /* * Audio DSP states may transform as below:- * diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 0e0cfa81a8f2..c4befacde23e 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -584,8 +584,10 @@ void hda_dsp_ipc_int_enable(struct snd_sof_dev *sdev); void hda_dsp_ipc_int_disable(struct snd_sof_dev *sdev); bool hda_dsp_core_is_enabled(struct snd_sof_dev *sdev, unsigned int core_mask); -int hda_dsp_set_power_state(struct snd_sof_dev *sdev, - const struct sof_dsp_power_state *target_state); +int hda_dsp_set_power_state_ipc3(struct snd_sof_dev *sdev, + const struct sof_dsp_power_state *target_state); +int hda_dsp_set_power_state_ipc4(struct snd_sof_dev *sdev, + const struct sof_dsp_power_state *target_state); int hda_dsp_suspend(struct snd_sof_dev *sdev, u32 target_state); int hda_dsp_resume(struct snd_sof_dev *sdev); diff --git a/sound/soc/sof/intel/icl.c b/sound/soc/sof/intel/icl.c index 435941a1692f..0f249efc6a5a 100644 --- a/sound/soc/sof/intel/icl.c +++ b/sound/soc/sof/intel/icl.c @@ -116,6 +116,8 @@ int sof_icl_ops_init(struct snd_sof_dev *sdev) /* debug */ sof_icl_ops.ipc_dump = cnl_ipc_dump; + + sof_icl_ops.set_power_state = hda_dsp_set_power_state_ipc3; } if (sdev->pdata->ipc_type == SOF_INTEL_IPC4) { @@ -141,6 +143,8 @@ int sof_icl_ops_init(struct snd_sof_dev *sdev) /* debug */ sof_icl_ops.ipc_dump = cnl_ipc4_dump; + + sof_icl_ops.set_power_state = hda_dsp_set_power_state_ipc4; } /* debug */ diff --git a/sound/soc/sof/intel/mtl.c b/sound/soc/sof/intel/mtl.c index 9f969e07fc27..46caf3ccde66 100644 --- a/sound/soc/sof/intel/mtl.c +++ b/sound/soc/sof/intel/mtl.c @@ -668,6 +668,8 @@ int sof_mtl_ops_init(struct snd_sof_dev *sdev) /* set DAI ops */ hda_set_dai_drv_ops(sdev, &sof_mtl_ops); + sof_mtl_ops.set_power_state = hda_dsp_set_power_state_ipc4; + return 0; }; EXPORT_SYMBOL_NS(sof_mtl_ops_init, SND_SOC_SOF_INTEL_HDA_COMMON); diff --git a/sound/soc/sof/intel/tgl.c b/sound/soc/sof/intel/tgl.c index 58ac3a46e6a7..2713b7dc7931 100644 --- a/sound/soc/sof/intel/tgl.c +++ b/sound/soc/sof/intel/tgl.c @@ -71,6 +71,8 @@ int sof_tgl_ops_init(struct snd_sof_dev *sdev) /* debug */ sof_tgl_ops.ipc_dump = cnl_ipc_dump; + + sof_tgl_ops.set_power_state = hda_dsp_set_power_state_ipc3; } if (sdev->pdata->ipc_type == SOF_INTEL_IPC4) { @@ -96,6 +98,8 @@ int sof_tgl_ops_init(struct snd_sof_dev *sdev) /* debug */ sof_tgl_ops.ipc_dump = cnl_ipc4_dump; + + sof_tgl_ops.set_power_state = hda_dsp_set_power_state_ipc4; } /* set DAI driver ops */ From 2cc3fdcddc86644c070223c522e418416cb7b1a2 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 19 Apr 2023 19:45:06 +0100 Subject: [PATCH 773/778] ASoC: es8316: Don't use ranges based register lookup for a single register The es8316 driver uses a register range to specify the single volatile register it has. While the cost will be in the noise this is a bunch of overhead compared to just having a volatile_reg() callback so switch to the callback. Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20230419-asoc-es8316-volatile-v1-1-2074ec93d8f1@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/es8316.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c index f7d7a9c91e04..a27d80956459 100644 --- a/sound/soc/codecs/es8316.c +++ b/sound/soc/codecs/es8316.c @@ -803,14 +803,15 @@ static const struct snd_soc_component_driver soc_component_dev_es8316 = { .endianness = 1, }; -static const struct regmap_range es8316_volatile_ranges[] = { - regmap_reg_range(ES8316_GPIO_FLAG, ES8316_GPIO_FLAG), -}; - -static const struct regmap_access_table es8316_volatile_table = { - .yes_ranges = es8316_volatile_ranges, - .n_yes_ranges = ARRAY_SIZE(es8316_volatile_ranges), -}; +static bool es8316_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case ES8316_GPIO_FLAG: + return true; + default: + return false; + } +} static const struct regmap_config es8316_regmap = { .reg_bits = 8, @@ -818,7 +819,7 @@ static const struct regmap_config es8316_regmap = { .use_single_read = true, .use_single_write = true, .max_register = 0x53, - .volatile_table = &es8316_volatile_table, + .volatile_reg = es8316_volatile_reg, .cache_type = REGCACHE_RBTREE, }; From a9e42d9e8b4be36a1e0dde0285a9ff36b2e06a46 Mon Sep 17 00:00:00 2001 From: Simon Trimmer Date: Thu, 20 Apr 2023 11:20:43 +0100 Subject: [PATCH 774/778] ASoC: cs35l56: Remove duplicate mbox log messages cs35l56_mbox_send() logs a warning when sending a mbox command fails so the callers can be simplified. Signed-off-by: Simon Trimmer Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/20230420102043.1151830-1-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l56.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c index c0a857cfb8cb..46762f7f1449 100644 --- a/sound/soc/codecs/cs35l56.c +++ b/sound/soc/codecs/cs35l56.c @@ -859,10 +859,8 @@ static void cs35l56_dsp_work(struct work_struct *work) } ret = cs35l56_mbox_send(cs35l56, CS35L56_MBOX_CMD_SHUTDOWN); - if (ret) { - dev_dbg(cs35l56->dev, "%s: CS35L56_MBOX_CMD_SHUTDOWN ret %d\n", __func__, ret); + if (ret) goto err; - } if (cs35l56->rev < CS35L56_REVID_B0) reg = CS35L56_DSP1_PM_CUR_STATE_A1; @@ -1033,9 +1031,7 @@ int cs35l56_runtime_suspend(struct device *dev) * Enable auto-hibernate. If it is woken by some other wake source * it will automatically return to hibernate. */ - ret = cs35l56_mbox_send(cs35l56, CS35L56_MBOX_CMD_ALLOW_AUTO_HIBERNATE); - if (ret) - dev_warn(cs35l56->dev, "ALLOW_HIBERNATE failed: %d\n", ret); + cs35l56_mbox_send(cs35l56, CS35L56_MBOX_CMD_ALLOW_AUTO_HIBERNATE); /* * Must enter cache-only first so there can't be any more register From d6e28695dcb6f653c7f2adf38021a5e934a6f416 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 21 Apr 2023 00:10:56 +0000 Subject: [PATCH 775/778] ASoC: fsl: imx-es8328: cleanup platform which is using Generic DMA If CPU is using soc-generic-dmaengine-pcm, Platform Component will be same as CPU Component. In this case, we can use CPU dlc for Platform dlc. This patch shares CPU dlc with Platform, and add comment. Signed-off-by: Kuninori Morimoto Acked-by: Shengjiu Wang Tested-by: Shengjiu Wang Link: https://lore.kernel.org/r/87bkjif628.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/fsl/imx-es8328.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/sound/soc/fsl/imx-es8328.c b/sound/soc/fsl/imx-es8328.c index b80c57362fb8..85bd36fb68a2 100644 --- a/sound/soc/fsl/imx-es8328.c +++ b/sound/soc/fsl/imx-es8328.c @@ -149,7 +149,7 @@ static int imx_es8328_probe(struct platform_device *pdev) goto put_device; } - comp = devm_kzalloc(dev, 3 * sizeof(*comp), GFP_KERNEL); + comp = devm_kzalloc(dev, 2 * sizeof(*comp), GFP_KERNEL); if (!comp) { ret = -ENOMEM; goto put_device; @@ -159,9 +159,13 @@ static int imx_es8328_probe(struct platform_device *pdev) data->jack_gpio = of_get_named_gpio(pdev->dev.of_node, "jack-gpio", 0); - data->dai.cpus = &comp[0]; + /* + * CPU == Platform + * platform is using soc-generic-dmaengine-pcm + */ + data->dai.cpus = + data->dai.platforms = &comp[0]; data->dai.codecs = &comp[1]; - data->dai.platforms = &comp[2]; data->dai.num_cpus = 1; data->dai.num_codecs = 1; @@ -172,7 +176,6 @@ static int imx_es8328_probe(struct platform_device *pdev) data->dai.codecs->dai_name = "es8328-hifi-analog"; data->dai.codecs->of_node = codec_np; data->dai.cpus->of_node = ssi_np; - data->dai.platforms->of_node = ssi_np; data->dai.init = &imx_es8328_dai_init; data->dai.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP; From 2324bc107b0b3d2de351f35032dc5093cbb61493 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 21 Apr 2023 00:11:07 +0000 Subject: [PATCH 776/778] ASoC: fsl: imx-spdif: cleanup platform which is using Generic DMA If CPU is using soc-generic-dmaengine-pcm, Platform Component will be same as CPU Component. In this case, we can use CPU dlc for Platform dlc. This patch shares CPU dlc with Platform, and add comment. Signed-off-by: Kuninori Morimoto Acked-by: Shengjiu Wang Tested-by: Shengjiu Wang Link: https://lore.kernel.org/r/87a5z2f61w.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/fsl/imx-spdif.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/sound/soc/fsl/imx-spdif.c b/sound/soc/fsl/imx-spdif.c index 4446fba755b9..ab978431ac98 100644 --- a/sound/soc/fsl/imx-spdif.c +++ b/sound/soc/fsl/imx-spdif.c @@ -26,15 +26,19 @@ static int imx_spdif_audio_probe(struct platform_device *pdev) } data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); - comp = devm_kzalloc(&pdev->dev, 3 * sizeof(*comp), GFP_KERNEL); + comp = devm_kzalloc(&pdev->dev, 2 * sizeof(*comp), GFP_KERNEL); if (!data || !comp) { ret = -ENOMEM; goto end; } - data->dai.cpus = &comp[0]; + /* + * CPU == Platform + * platform is using soc-generic-dmaengine-pcm + */ + data->dai.cpus = + data->dai.platforms = &comp[0]; data->dai.codecs = &comp[1]; - data->dai.platforms = &comp[2]; data->dai.num_cpus = 1; data->dai.num_codecs = 1; @@ -45,7 +49,6 @@ static int imx_spdif_audio_probe(struct platform_device *pdev) data->dai.codecs->dai_name = "snd-soc-dummy-dai"; data->dai.codecs->name = "snd-soc-dummy"; data->dai.cpus->of_node = spdif_np; - data->dai.platforms->of_node = spdif_np; data->dai.playback_only = true; data->dai.capture_only = true; From 3ce08f85133fc93278801aba3efb4548d3ef3ca0 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 21 Apr 2023 00:11:21 +0000 Subject: [PATCH 777/778] ASoC: fsl: imx-audmix: cleanup platform which is using Generic DMA If CPU is using soc-generic-dmaengine-pcm, Platform Component will be same as CPU Component. In this case, we can use CPU dlc for Platform dlc. This patch shares CPU dlc with Platform, and add comment. Signed-off-by: Kuninori Morimoto Acked-by: Shengjiu Wang Tested-by: Shengjiu Wang Link: https://lore.kernel.org/r/878remf61j.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/fsl/imx-audmix.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/sound/soc/fsl/imx-audmix.c b/sound/soc/fsl/imx-audmix.c index 1292a845c424..cabef0de3891 100644 --- a/sound/soc/fsl/imx-audmix.c +++ b/sound/soc/fsl/imx-audmix.c @@ -207,8 +207,8 @@ static int imx_audmix_probe(struct platform_device *pdev) for (i = 0; i < num_dai; i++) { struct snd_soc_dai_link_component *dlc; - /* for CPU/Codec/Platform x 2 */ - dlc = devm_kcalloc(&pdev->dev, 6, sizeof(*dlc), GFP_KERNEL); + /* for CPU/Codec x 2 + Platform */ + dlc = devm_kcalloc(&pdev->dev, 5, sizeof(*dlc), GFP_KERNEL); if (!dlc) return -ENOMEM; @@ -238,9 +238,13 @@ static int imx_audmix_probe(struct platform_device *pdev) dai_name, "CPU-Capture"); } - priv->dai[i].cpus = &dlc[0]; - priv->dai[i].codecs = &dlc[1]; - priv->dai[i].platforms = &dlc[2]; + /* + * CPU == Platform + * platform is using soc-generic-dmaengine-pcm + */ + priv->dai[i].cpus = + priv->dai[i].platforms = &dlc[0]; + priv->dai[i].codecs = &dlc[1]; priv->dai[i].num_cpus = 1; priv->dai[i].num_codecs = 1; @@ -252,7 +256,6 @@ static int imx_audmix_probe(struct platform_device *pdev) priv->dai[i].codecs->name = "snd-soc-dummy"; priv->dai[i].cpus->of_node = args.np; priv->dai[i].cpus->dai_name = dev_name(&cpu_pdev->dev); - priv->dai[i].platforms->of_node = args.np; priv->dai[i].dynamic = 1; priv->dai[i].dpcm_playback = 1; priv->dai[i].dpcm_capture = (i == 0 ? 1 : 0); @@ -267,9 +270,9 @@ static int imx_audmix_probe(struct platform_device *pdev) be_cp = devm_kasprintf(&pdev->dev, GFP_KERNEL, "AUDMIX-Capture-%d", i); - priv->dai[num_dai + i].cpus = &dlc[3]; - priv->dai[num_dai + i].codecs = &dlc[4]; - priv->dai[num_dai + i].platforms = &dlc[5]; + priv->dai[num_dai + i].cpus = &dlc[2]; + priv->dai[num_dai + i].codecs = &dlc[3]; + priv->dai[num_dai + i].platforms = &dlc[4]; priv->dai[num_dai + i].num_cpus = 1; priv->dai[num_dai + i].num_codecs = 1; From dc801ea8ae37d54706e6f1cef140731ac5981c9c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 21 Apr 2023 00:11:31 +0000 Subject: [PATCH 778/778] ASoC: fsl: imx-audmix: remove dummy dai_link->platform Dummy dai_link->platform is not needed. Signed-off-by: Kuninori Morimoto Acked-by: Shengjiu Wang Tested-by: Shengjiu Wang Link: https://lore.kernel.org/r/877cu6f619.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/fsl/imx-audmix.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/sound/soc/fsl/imx-audmix.c b/sound/soc/fsl/imx-audmix.c index cabef0de3891..b2c5aca92c6b 100644 --- a/sound/soc/fsl/imx-audmix.c +++ b/sound/soc/fsl/imx-audmix.c @@ -207,8 +207,8 @@ static int imx_audmix_probe(struct platform_device *pdev) for (i = 0; i < num_dai; i++) { struct snd_soc_dai_link_component *dlc; - /* for CPU/Codec x 2 + Platform */ - dlc = devm_kcalloc(&pdev->dev, 5, sizeof(*dlc), GFP_KERNEL); + /* for CPU/Codec x 2 */ + dlc = devm_kcalloc(&pdev->dev, 4, sizeof(*dlc), GFP_KERNEL); if (!dlc) return -ENOMEM; @@ -272,18 +272,15 @@ static int imx_audmix_probe(struct platform_device *pdev) priv->dai[num_dai + i].cpus = &dlc[2]; priv->dai[num_dai + i].codecs = &dlc[3]; - priv->dai[num_dai + i].platforms = &dlc[4]; priv->dai[num_dai + i].num_cpus = 1; priv->dai[num_dai + i].num_codecs = 1; - priv->dai[num_dai + i].num_platforms = 1; priv->dai[num_dai + i].name = be_name; priv->dai[num_dai + i].codecs->dai_name = "snd-soc-dummy-dai"; priv->dai[num_dai + i].codecs->name = "snd-soc-dummy"; priv->dai[num_dai + i].cpus->of_node = audmix_np; priv->dai[num_dai + i].cpus->dai_name = be_name; - priv->dai[num_dai + i].platforms->name = "snd-soc-dummy"; priv->dai[num_dai + i].no_pcm = 1; priv->dai[num_dai + i].dpcm_playback = 1; priv->dai[num_dai + i].dpcm_capture = 1;