From 8222d5910dae08213b6d9d4bc9a7f8502855e624 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 9 Feb 2023 09:09:52 +0800 Subject: [PATCH 001/460] xfrm: Zero padding when dumping algos and encap When copying data to user-space we should ensure that only valid data is copied over. Padding in structures may be filled with random (possibly sensitve) data and should never be given directly to user-space. This patch fixes the copying of xfrm algorithms and the encap template in xfrm_user so that padding is zeroed. Reported-by: syzbot+fa5414772d5c445dac3c@syzkaller.appspotmail.com Reported-by: Hyunwoo Kim Signed-off-by: Herbert Xu Reviewed-by: Sabrina Dubroca Signed-off-by: Steffen Klassert --- net/xfrm/xfrm_user.c | 45 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index cf5172d4ce68c..103af2b3e986f 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -1012,7 +1012,9 @@ static int copy_to_user_aead(struct xfrm_algo_aead *aead, struct sk_buff *skb) return -EMSGSIZE; ap = nla_data(nla); - memcpy(ap, aead, sizeof(*aead)); + strscpy_pad(ap->alg_name, aead->alg_name, sizeof(ap->alg_name)); + ap->alg_key_len = aead->alg_key_len; + ap->alg_icv_len = aead->alg_icv_len; if (redact_secret && aead->alg_key_len) memset(ap->alg_key, 0, (aead->alg_key_len + 7) / 8); @@ -1032,7 +1034,8 @@ static int copy_to_user_ealg(struct xfrm_algo *ealg, struct sk_buff *skb) return -EMSGSIZE; ap = nla_data(nla); - memcpy(ap, ealg, sizeof(*ealg)); + strscpy_pad(ap->alg_name, ealg->alg_name, sizeof(ap->alg_name)); + ap->alg_key_len = ealg->alg_key_len; if (redact_secret && ealg->alg_key_len) memset(ap->alg_key, 0, (ealg->alg_key_len + 7) / 8); @@ -1043,6 +1046,40 @@ static int copy_to_user_ealg(struct xfrm_algo *ealg, struct sk_buff *skb) return 0; } +static int copy_to_user_calg(struct xfrm_algo *calg, struct sk_buff *skb) +{ + struct nlattr *nla = nla_reserve(skb, XFRMA_ALG_COMP, sizeof(*calg)); + struct xfrm_algo *ap; + + if (!nla) + return -EMSGSIZE; + + ap = nla_data(nla); + strscpy_pad(ap->alg_name, calg->alg_name, sizeof(ap->alg_name)); + ap->alg_key_len = 0; + + return 0; +} + +static int copy_to_user_encap(struct xfrm_encap_tmpl *ep, struct sk_buff *skb) +{ + struct nlattr *nla = nla_reserve(skb, XFRMA_ENCAP, sizeof(*ep)); + struct xfrm_encap_tmpl *uep; + + if (!nla) + return -EMSGSIZE; + + uep = nla_data(nla); + memset(uep, 0, sizeof(*uep)); + + uep->encap_type = ep->encap_type; + uep->encap_sport = ep->encap_sport; + uep->encap_dport = ep->encap_dport; + uep->encap_oa = ep->encap_oa; + + return 0; +} + static int xfrm_smark_put(struct sk_buff *skb, struct xfrm_mark *m) { int ret = 0; @@ -1098,12 +1135,12 @@ static int copy_to_user_state_extra(struct xfrm_state *x, goto out; } if (x->calg) { - ret = nla_put(skb, XFRMA_ALG_COMP, sizeof(*(x->calg)), x->calg); + ret = copy_to_user_calg(x->calg, skb); if (ret) goto out; } if (x->encap) { - ret = nla_put(skb, XFRMA_ENCAP, sizeof(*x->encap), x->encap); + ret = copy_to_user_encap(x->encap, skb); if (ret) goto out; } From 7245e629dcaaf308f1868aeffa218e9849c77893 Mon Sep 17 00:00:00 2001 From: Alexandr Sapozhnikov Date: Wed, 15 Feb 2023 20:15:49 +0300 Subject: [PATCH 002/460] 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 678c2ef1cae70..ffa7e61dd1835 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 003/460] 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 591c852f326b9..76a6ae5d56526 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 004/460] 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 c5a4f49ee2065..01a22a13b4520 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 bac7dcc4c2c13..0955340cc4218 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 5098f219e3e6f..a7456e7864636 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 5a21b0ae45958..dd476e079fe1c 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 2658481d575b6..14d942e8b857f 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 0e3c0a8f5d716..4d8a286a7a348 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 f517751f94acd..726c30c8bf95d 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 be82af0364ee4..b8803c124c3b2 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 005/460] 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 38e3b287dbb22..d877a0a9731f9 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 006/460] 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 be4bf77103cd7..ac8ed731f76d9 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 007/460] 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 31e1e30cb52a2..dd7d0b965f85f 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 008/460] 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 f3c9600221d48..7f5bc73b20402 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 aae60cbd9164d..6faea5049f765 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 009/460] 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 660ba0db89002..8b2df12d86814 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 010/460] 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 8b2df12d86814..047c5e8c87ff4 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 011/460] 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 7658e89844b46..7e0affd60993f 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 012/460] 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 7e0affd60993f..f58dd564d122b 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 013/460] 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 36f062c7582f9..c5c4c93b3689c 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 014/460] 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 37ff47552bcb7..d3fe82c5d6b66 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 5f6e839ebc951c50f1ca06791d016c256f0285a9 Mon Sep 17 00:00:00 2001 From: Krister Johansen Date: Wed, 22 Feb 2023 09:54:42 -0800 Subject: [PATCH 015/460] xen: update arch/x86/include/asm/xen/cpuid.h Update arch/x86/include/asm/xen/cpuid.h from the Xen tree to get newest definitions. This picks up some TSC mode definitions and comment formatting changes. Signed-off-by: Krister Johansen Reviewed-by: Juergen Gross Link: https://lore.kernel.org/r/94b9046dd0db3794f0633d134b7108508957758d.1677038165.git.kjlx@templeofstupid.com Signed-off-by: Juergen Gross --- arch/x86/include/asm/xen/cpuid.h | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/xen/cpuid.h b/arch/x86/include/asm/xen/cpuid.h index 6daa9b0c8d114..a3c29b1496c83 100644 --- a/arch/x86/include/asm/xen/cpuid.h +++ b/arch/x86/include/asm/xen/cpuid.h @@ -89,11 +89,21 @@ * Sub-leaf 2: EAX: host tsc frequency in kHz */ +#define XEN_CPUID_TSC_EMULATED (1u << 0) +#define XEN_CPUID_HOST_TSC_RELIABLE (1u << 1) +#define XEN_CPUID_RDTSCP_INSTR_AVAIL (1u << 2) + +#define XEN_CPUID_TSC_MODE_DEFAULT (0) +#define XEN_CPUID_TSC_MODE_ALWAYS_EMULATE (1u) +#define XEN_CPUID_TSC_MODE_NEVER_EMULATE (2u) +#define XEN_CPUID_TSC_MODE_PVRDTSCP (3u) + /* * Leaf 5 (0x40000x04) * HVM-specific features * Sub-leaf 0: EAX: Features * Sub-leaf 0: EBX: vcpu id (iff EAX has XEN_HVM_CPUID_VCPU_ID_PRESENT flag) + * Sub-leaf 0: ECX: domain id (iff EAX has XEN_HVM_CPUID_DOMID_PRESENT flag) */ #define XEN_HVM_CPUID_APIC_ACCESS_VIRT (1u << 0) /* Virtualized APIC registers */ #define XEN_HVM_CPUID_X2APIC_VIRT (1u << 1) /* Virtualized x2APIC accesses */ @@ -102,12 +112,16 @@ #define XEN_HVM_CPUID_VCPU_ID_PRESENT (1u << 3) /* vcpu id is present in EBX */ #define XEN_HVM_CPUID_DOMID_PRESENT (1u << 4) /* domid is present in ECX */ /* - * Bits 55:49 from the IO-APIC RTE and bits 11:5 from the MSI address can be - * used to store high bits for the Destination ID. This expands the Destination - * ID field from 8 to 15 bits, allowing to target APIC IDs up 32768. + * With interrupt format set to 0 (non-remappable) bits 55:49 from the + * IO-APIC RTE and bits 11:5 from the MSI address can be used to store + * high bits for the Destination ID. This expands the Destination ID + * field from 8 to 15 bits, allowing to target APIC IDs up 32768. */ #define XEN_HVM_CPUID_EXT_DEST_ID (1u << 5) -/* Per-vCPU event channel upcalls */ +/* + * Per-vCPU event channel upcalls work correctly with physical IRQs + * bound to event channels. + */ #define XEN_HVM_CPUID_UPCALL_VECTOR (1u << 6) /* From 99a7bcafbd0d04555074554573019096a8c10450 Mon Sep 17 00:00:00 2001 From: Krister Johansen Date: Wed, 22 Feb 2023 09:54:56 -0800 Subject: [PATCH 016/460] x86/xen/time: cleanup xen_tsc_safe_clocksource Modifies xen_tsc_safe_clocksource() to use newly defined constants from arch/x86/include/asm/xen/cpuid.h. This replaces a numeric value with XEN_CPUID_TSC_MODE_NEVER_EMULATE, and deletes a comment that is now self explanatory. There should be no change in the function's behavior. Signed-off-by: Krister Johansen Reviewed-by: Juergen Gross Link: https://lore.kernel.org/r/a69ca370fecf85d312d2db633d9438ace2af6e5b.1677038165.git.kjlx@templeofstupid.com Signed-off-by: Juergen Gross --- arch/x86/xen/time.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c index 95140609c8a80..94056013a2a47 100644 --- a/arch/x86/xen/time.c +++ b/arch/x86/xen/time.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -495,11 +496,7 @@ static int __init xen_tsc_safe_clocksource(void) /* Leaf 4, sub-leaf 0 (0x40000x03) */ cpuid_count(xen_cpuid_base() + 3, 0, &eax, &ebx, &ecx, &edx); - /* tsc_mode = no_emulate (2) */ - if (ebx != 2) - return 0; - - return 1; + return ebx == XEN_CPUID_TSC_MODE_NEVER_EMULATE; } static void __init xen_time_init(void) From ce9f1c05d2edfa6cdf2c1a510495d333e11810a8 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Wed, 22 Feb 2023 23:01:55 -0800 Subject: [PATCH 017/460] 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 f8182417b7341..10bb1d494258d 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 018/460] 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 b7f050aa6210c..324fc9e6edd79 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 019/460] 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 d90f8d102eb99..97598d14e5323 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 c276a706ea1f51cf9723ed8484feceaf961b8f89 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Tue, 21 Feb 2023 13:54:00 +0800 Subject: [PATCH 020/460] xfrm: Allow transport-mode states with AF_UNSPEC selector xfrm state selectors are matched against the inner-most flow which can be of any address family. Therefore middle states in nested configurations need to carry a wildcard selector in order to work at all. However, this is currently forbidden for transport-mode states. Fix this by removing the unnecessary check. Fixes: 13996378e658 ("[IPSEC]: Rename mode to outer_mode and add inner_mode") Reported-by: David George Signed-off-by: Herbert Xu Signed-off-by: Steffen Klassert --- net/xfrm/xfrm_state.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 00afe831c71c4..f238048bf786e 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -2815,11 +2815,6 @@ int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload, goto error; } - if (!(inner_mode->flags & XFRM_MODE_FLAG_TUNNEL)) { - NL_SET_ERR_MSG(extack, "Only tunnel modes can accommodate an AF_UNSPEC selector"); - goto error; - } - x->inner_mode = *inner_mode; if (x->props.family == AF_INET) From a54bace095d00e9222161495649688bc43de4dde Mon Sep 17 00:00:00 2001 From: Oleksandr Tyshchenko Date: Fri, 24 Feb 2023 17:34:50 +0200 Subject: [PATCH 021/460] drm/virtio: Pass correct device to dma_sync_sgtable_for_device() The "vdev->dev.parent" should be used instead of "vdev->dev" as a device for which to perform the DMA operation in both virtio_gpu_cmd_transfer_to_host_2d(3d). Because the virtio-gpu device "vdev->dev" doesn't really have DMA OPS assigned to it, but parent (virtio-pci or virtio-mmio) device "vdev->dev.parent" has. The more, the sgtable in question the code is trying to sync here was mapped for the parent device (by using its DMA OPS) previously at: virtio_gpu_object_shmem_init()->drm_gem_shmem_get_pages_sgt()-> dma_map_sgtable(), so should be synced here for the same parent device. Fixes: b5c9ed70d1a9 ("drm/virtio: Improve DMA API usage for shmem BOs") Signed-off-by: Oleksandr Tyshchenko Reviewed-by: Dmitry Osipenko Signed-off-by: Dmitry Osipenko Link: https://patchwork.freedesktop.org/patch/msgid/20230224153450.526222-1-olekstysh@gmail.com --- drivers/gpu/drm/virtio/virtgpu_vq.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c index 9ff8660b50ade..208e9434cb28d 100644 --- a/drivers/gpu/drm/virtio/virtgpu_vq.c +++ b/drivers/gpu/drm/virtio/virtgpu_vq.c @@ -597,7 +597,7 @@ void virtio_gpu_cmd_transfer_to_host_2d(struct virtio_gpu_device *vgdev, bool use_dma_api = !virtio_has_dma_quirk(vgdev->vdev); if (virtio_gpu_is_shmem(bo) && use_dma_api) - dma_sync_sgtable_for_device(&vgdev->vdev->dev, + dma_sync_sgtable_for_device(vgdev->vdev->dev.parent, bo->base.sgt, DMA_TO_DEVICE); cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p)); @@ -1019,7 +1019,7 @@ void virtio_gpu_cmd_transfer_to_host_3d(struct virtio_gpu_device *vgdev, bool use_dma_api = !virtio_has_dma_quirk(vgdev->vdev); if (virtio_gpu_is_shmem(bo) && use_dma_api) - dma_sync_sgtable_for_device(&vgdev->vdev->dev, + dma_sync_sgtable_for_device(vgdev->vdev->dev.parent, bo->base.sgt, DMA_TO_DEVICE); cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p)); From ee9adb7a45516cfa536ca92253d7ae59d56db9e4 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Mon, 9 Jan 2023 00:13:11 +0300 Subject: [PATCH 022/460] drm/shmem-helper: Remove another errant put in error path drm_gem_shmem_mmap() doesn't own reference in error code path, resulting in the dma-buf shmem GEM object getting prematurely freed leading to a later use-after-free. Fixes: f49a51bfdc8e ("drm/shme-helpers: Fix dma_buf_mmap forwarding bug") Cc: stable@vger.kernel.org Signed-off-by: Dmitry Osipenko Reviewed-by: Rob Clark Link: https://patchwork.freedesktop.org/patch/msgid/20230108211311.3950107-1-dmitry.osipenko@collabora.com --- drivers/gpu/drm/drm_gem_shmem_helper.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c b/drivers/gpu/drm/drm_gem_shmem_helper.c index b602cd72a1205..1a681de9a6eab 100644 --- a/drivers/gpu/drm/drm_gem_shmem_helper.c +++ b/drivers/gpu/drm/drm_gem_shmem_helper.c @@ -622,11 +622,14 @@ int drm_gem_shmem_mmap(struct drm_gem_shmem_object *shmem, struct vm_area_struct int ret; if (obj->import_attach) { - /* Drop the reference drm_gem_mmap_obj() acquired.*/ - drm_gem_object_put(obj); vma->vm_private_data = NULL; + ret = dma_buf_mmap(obj->dma_buf, vma, 0); + + /* Drop the reference drm_gem_mmap_obj() acquired.*/ + if (!ret) + drm_gem_object_put(obj); - return dma_buf_mmap(obj->dma_buf, vma, 0); + return ret; } ret = drm_gem_shmem_get_pages(shmem); From 9630b585b607bd26f505d34620b14d75b9a5af7d Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Fri, 4 Nov 2022 19:04:59 +0300 Subject: [PATCH 023/460] drm/msm/gem: Prevent blocking within shrinker loop Consider this scenario: 1. APP1 continuously creates lots of small GEMs 2. APP2 triggers `drop_caches` 3. Shrinker starts to evict APP1 GEMs, while APP1 produces new purgeable GEMs 4. msm_gem_shrinker_scan() returns non-zero number of freed pages and causes shrinker to try shrink more 5. msm_gem_shrinker_scan() returns non-zero number of freed pages again, goto 4 6. The APP2 is blocked in `drop_caches` until APP1 stops producing purgeable GEMs To prevent this blocking scenario, check number of remaining pages that GPU shrinker couldn't release due to a GEM locking contention or shrinking rejection. If there are no remaining pages left to shrink, then there is no need to free up more pages and shrinker may break out from the loop. This problem was found during shrinker/madvise IOCTL testing of virtio-gpu driver. The MSM driver is affected in the same way. Reviewed-by: Rob Clark Reviewed-by: Thomas Zimmermann Fixes: b352ba54a820 ("drm/msm/gem: Convert to using drm_gem_lru") Signed-off-by: Dmitry Osipenko Link: https://lore.kernel.org/all/20230108210445.3948344-2-dmitry.osipenko@collabora.com/ --- drivers/gpu/drm/drm_gem.c | 9 +++++++-- drivers/gpu/drm/msm/msm_gem_shrinker.c | 11 +++++++++-- include/drm/drm_gem.h | 4 +++- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index b8db675e7fb5e..b0246a8480068 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c @@ -1375,10 +1375,13 @@ EXPORT_SYMBOL(drm_gem_lru_move_tail); * * @lru: The LRU to scan * @nr_to_scan: The number of pages to try to reclaim + * @remaining: The number of pages left to reclaim, should be initialized by caller * @shrink: Callback to try to shrink/reclaim the object. */ unsigned long -drm_gem_lru_scan(struct drm_gem_lru *lru, unsigned nr_to_scan, +drm_gem_lru_scan(struct drm_gem_lru *lru, + unsigned int nr_to_scan, + unsigned long *remaining, bool (*shrink)(struct drm_gem_object *obj)) { struct drm_gem_lru still_in_lru; @@ -1417,8 +1420,10 @@ drm_gem_lru_scan(struct drm_gem_lru *lru, unsigned nr_to_scan, * hit shrinker in response to trying to get backing pages * for this obj (ie. while it's lock is already held) */ - if (!dma_resv_trylock(obj->resv)) + if (!dma_resv_trylock(obj->resv)) { + *remaining += obj->size >> PAGE_SHIFT; goto tail; + } if (shrink(obj)) { freed += obj->size >> PAGE_SHIFT; diff --git a/drivers/gpu/drm/msm/msm_gem_shrinker.c b/drivers/gpu/drm/msm/msm_gem_shrinker.c index 051bdbc093cf9..f38296ad87434 100644 --- a/drivers/gpu/drm/msm/msm_gem_shrinker.c +++ b/drivers/gpu/drm/msm/msm_gem_shrinker.c @@ -107,6 +107,7 @@ msm_gem_shrinker_scan(struct shrinker *shrinker, struct shrink_control *sc) bool (*shrink)(struct drm_gem_object *obj); bool cond; unsigned long freed; + unsigned long remaining; } stages[] = { /* Stages of progressively more aggressive/expensive reclaim: */ { &priv->lru.dontneed, purge, true }, @@ -116,14 +117,18 @@ msm_gem_shrinker_scan(struct shrinker *shrinker, struct shrink_control *sc) }; long nr = sc->nr_to_scan; unsigned long freed = 0; + unsigned long remaining = 0; for (unsigned i = 0; (nr > 0) && (i < ARRAY_SIZE(stages)); i++) { if (!stages[i].cond) continue; stages[i].freed = - drm_gem_lru_scan(stages[i].lru, nr, stages[i].shrink); + drm_gem_lru_scan(stages[i].lru, nr, + &stages[i].remaining, + stages[i].shrink); nr -= stages[i].freed; freed += stages[i].freed; + remaining += stages[i].remaining; } if (freed) { @@ -132,7 +137,7 @@ msm_gem_shrinker_scan(struct shrinker *shrinker, struct shrink_control *sc) stages[3].freed); } - return (freed > 0) ? freed : SHRINK_STOP; + return (freed > 0 && remaining > 0) ? freed : SHRINK_STOP; } #ifdef CONFIG_DEBUG_FS @@ -182,10 +187,12 @@ msm_gem_shrinker_vmap(struct notifier_block *nb, unsigned long event, void *ptr) NULL, }; unsigned idx, unmapped = 0; + unsigned long remaining = 0; for (idx = 0; lrus[idx] && unmapped < vmap_shrink_limit; idx++) { unmapped += drm_gem_lru_scan(lrus[idx], vmap_shrink_limit - unmapped, + &remaining, vmap_shrink); } diff --git a/include/drm/drm_gem.h b/include/drm/drm_gem.h index a17c2f903f81e..b46ade8124436 100644 --- a/include/drm/drm_gem.h +++ b/include/drm/drm_gem.h @@ -475,7 +475,9 @@ int drm_gem_dumb_map_offset(struct drm_file *file, struct drm_device *dev, void drm_gem_lru_init(struct drm_gem_lru *lru, struct mutex *lock); void drm_gem_lru_remove(struct drm_gem_object *obj); void drm_gem_lru_move_tail(struct drm_gem_lru *lru, struct drm_gem_object *obj); -unsigned long drm_gem_lru_scan(struct drm_gem_lru *lru, unsigned nr_to_scan, +unsigned long drm_gem_lru_scan(struct drm_gem_lru *lru, + unsigned int nr_to_scan, + unsigned long *remaining, bool (*shrink)(struct drm_gem_object *obj)); #endif /* __DRM_GEM_H__ */ From ba3be66f11c3c49afaa9f49b99e21d88756229ef Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Thu, 17 Nov 2022 04:40:38 +0300 Subject: [PATCH 024/460] drm/panfrost: Don't sync rpm suspension after mmu flushing Lockdep warns about potential circular locking dependency of devfreq with the fs_reclaim caused by immediate device suspension when mapping is released by shrinker. Fix it by doing the suspension asynchronously. Reviewed-by: Steven Price Fixes: ec7eba47da86 ("drm/panfrost: Rework page table flushing and runtime PM interaction") Signed-off-by: Dmitry Osipenko Link: https://lore.kernel.org/all/20230108210445.3948344-3-dmitry.osipenko@collabora.com/ --- drivers/gpu/drm/panfrost/panfrost_mmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c index 4e83a1891f3ed..666a5e53fe193 100644 --- a/drivers/gpu/drm/panfrost/panfrost_mmu.c +++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c @@ -282,7 +282,7 @@ static void panfrost_mmu_flush_range(struct panfrost_device *pfdev, if (pm_runtime_active(pfdev->dev)) mmu_hw_do_operation(pfdev, mmu, iova, size, AS_COMMAND_FLUSH_PT); - pm_runtime_put_sync_autosuspend(pfdev->dev); + pm_runtime_put_autosuspend(pfdev->dev); } static int mmu_map_sg(struct panfrost_device *pfdev, struct panfrost_mmu *mmu, From 77bc762451c2dc72bdbea07b857c916c9e7f4952 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 27 Feb 2023 13:33:30 +0300 Subject: [PATCH 025/460] fbdev: chipsfb: Fix error codes in chipsfb_pci_init() The error codes are not set on these error paths. Fixes: 145eed48de27 ("fbdev: Remove conflicting devices on PCI bus") Signed-off-by: Dan Carpenter Reviewed-by: Thomas Zimmermann Signed-off-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/Y/yG+sm2mhdJeTZW@kili --- drivers/video/fbdev/chipsfb.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/video/fbdev/chipsfb.c b/drivers/video/fbdev/chipsfb.c index cc37ec3f8fc1f..7799d52a651f3 100644 --- a/drivers/video/fbdev/chipsfb.c +++ b/drivers/video/fbdev/chipsfb.c @@ -358,16 +358,21 @@ static int chipsfb_pci_init(struct pci_dev *dp, const struct pci_device_id *ent) if (rc) return rc; - if (pci_enable_device(dp) < 0) { + rc = pci_enable_device(dp); + if (rc < 0) { dev_err(&dp->dev, "Cannot enable PCI device\n"); goto err_out; } - if ((dp->resource[0].flags & IORESOURCE_MEM) == 0) + if ((dp->resource[0].flags & IORESOURCE_MEM) == 0) { + rc = -ENODEV; goto err_disable; + } addr = pci_resource_start(dp, 0); - if (addr == 0) + if (addr == 0) { + rc = -ENODEV; goto err_disable; + } p = framebuffer_alloc(0, &dp->dev); if (p == NULL) { @@ -417,7 +422,8 @@ static int chipsfb_pci_init(struct pci_dev *dp, const struct pci_device_id *ent) init_chips(p, addr); - if (register_framebuffer(p) < 0) { + rc = register_framebuffer(p); + if (rc < 0) { dev_err(&dp->dev,"C&T 65550 framebuffer failed to register\n"); goto err_unmap; } From 0df979f4b93569dfb908d195f8e7d4c3cef4eaeb Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sun, 12 Feb 2023 01:12:10 +0200 Subject: [PATCH 026/460] 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 cf053e8f081e9..84d974458e0de 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 027/460] 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 84d974458e0de..eea026cf3ac2b 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 fcd9531b305288dc2848d38567d466af4ee147b2 Mon Sep 17 00:00:00 2001 From: Boris Burkov Date: Wed, 15 Feb 2023 12:59:49 -0800 Subject: [PATCH 028/460] 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 8c5efa5813b37..37fc58a7f27ed 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 4d8457fe0eb9c80ff7795cf8a30962128b71d853 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 2 Mar 2023 08:47:04 +0100 Subject: [PATCH 029/460] drm/edid: fix info leak when failing to get panel id Make sure to clear the transfer buffer before fetching the EDID to avoid leaking slab data to the logs on errors that leave the buffer unchanged. Fixes: 69c7717c20cc ("drm/edid: Dump the EDID when drm_edid_get_panel_id() has an error") Cc: stable@vger.kernel.org # 6.2 Cc: Douglas Anderson Signed-off-by: Johan Hovold Reviewed-by: Jani Nikula Reviewed-by: Douglas Anderson Signed-off-by: Douglas Anderson Link: https://patchwork.freedesktop.org/patch/msgid/20230302074704.11371-1-johan+linaro@kernel.org --- drivers/gpu/drm/drm_edid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 3841aba17abdc..8707fe72a0283 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -2797,7 +2797,7 @@ u32 drm_edid_get_panel_id(struct i2c_adapter *adapter) * the EDID then we'll just return 0. */ - base_block = kmalloc(EDID_LENGTH, GFP_KERNEL); + base_block = kzalloc(EDID_LENGTH, GFP_KERNEL); if (!base_block) return 0; 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 030/460] 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 f69c168391aa5..80e1df482337d 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 031/460] 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 5d18a5a6f6624..fa7c40956d0fa 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 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx) return err; } - if (stat_config.initial_delay) { + if (target.initial_delay) { pr_info(EVLIST_DISABLED_MSG); } else { err = enable_counters(); @@ -926,8 +921,8 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx) 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 534d36d26fc38..a07473703c6dd 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 b1c29156c560f..bf1794ebc916d 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 daec6cba500d4..880f1af7f6ad6 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 e301195507feb67290ee6c93b7d13e646bb12687 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sun, 12 Feb 2023 01:12:12 +0200 Subject: [PATCH 032/460] 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 eea026cf3ac2b..e8b12788dc94b 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 033/460] 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 e8b12788dc94b..47de609e22799 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 034/460] 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 47de609e22799..192fff9238f94 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 035/460] 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 192fff9238f94..c4e45c4726853 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 036/460] 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 c4e45c4726853..83836cac69e6b 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 037/460] 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 83836cac69e6b..4f6555c042561 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 038/460] 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 4f6555c042561..360ca7b5e507b 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 039/460] 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 360ca7b5e507b..4a26ef7bb0240 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 040/460] 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 4a26ef7bb0240..02bd8334d67c8 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 041/460] 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 02bd8334d67c8..e3460b35058f3 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 042/460] 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 e3460b35058f3..e390be4ef10b5 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 ddab9caebb18c..e6590302b3bfc 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 043/460] 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 b88a2f3724e6d..6c53ea560ffaa 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 044/460] 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 e390be4ef10b5..497c9e1673abb 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 045/460] 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 396429e63756b..66c1b70d244fc 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 046/460] 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 40725cbc6eb0c..90526f46c9b11 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 047/460] 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 5418e2f99834e..a91ac666f7582 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 fc9ffd3ff3b21..6143b1a6fa2ca 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 048/460] 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 a5e06dcbba136..1312a137f7fb8 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 049/460] 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 87d112650dfbb..7c0cf5031abe8 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 6d005a1f5d942..388b212088ea6 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 050/460] 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 2f86b2ad6d7e9..e8c07da58c9f2 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 051/460] 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 a7a857f1784d8..f8129c624b070 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 e48deab8901d4..7f467fe05d42e 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 55155e262646e..d77aef872a0a0 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 052/460] 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 d3fe82c5d6b66..ad35355ee43ea 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 053/460] 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 7dc0db7f5a761..6abcc34fafd8c 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 054/460] 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 41734202796f4..2ef78aa1d3f60 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 03d0f97fdb45c99cf6f808832db8bd5534e22374 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Fri, 3 Mar 2023 10:34:10 +0100 Subject: [PATCH 055/460] ASoC: clarify that SND_SOC_IMX_SGTL5000 is the old driver Both SND_SOC_IMX_SGTL5000 and SND_SOC_FSL_ASOC_CARD implement the fsl,imx-audio-sgtl5000 compatible string, which is confusing. It took a little research to find out that the latter is much newer and it is supposed to be the preferred choice since several years. Add a clarification note to avoid wasting time for future readers. Signed-off-by: Luca Ceresoli Link: https://lore.kernel.org/r/20230303093410.357621-1-luca.ceresoli@bootlin.com Signed-off-by: Mark Brown --- sound/soc/fsl/Kconfig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 614eceda6b9e3..33b67db8794e3 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -294,6 +294,10 @@ config SND_SOC_IMX_SGTL5000 Say Y if you want to add support for SoC audio on an i.MX board with a sgtl5000 codec. + Note that this is an old driver. Consider enabling + SND_SOC_FSL_ASOC_CARD and SND_SOC_SGTL5000 to use the newer + driver. + config SND_SOC_IMX_SPDIF tristate "SoC Audio support for i.MX boards with S/PDIF" select SND_SOC_IMX_PCM_DMA From 65882134bc622a1e57bd5928ac588855ea2e3ddd Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 2 Mar 2023 13:29:08 +0100 Subject: [PATCH 056/460] ASoC: qcom: q6prm: fix incorrect clk_root passed to ADSP The second to last argument is clk_root (root of the clock), however the code called q6prm_request_lpass_clock() with clk_attr instead (copy-paste error). This effectively was passing value of 1 as root clock which worked on some of the SoCs (e.g. SM8450) but fails on others, depending on the ADSP. For example on SM8550 this "1" as root clock is not accepted and results in errors coming from ADSP. Fixes: 2f20640491ed ("ASoC: qdsp6: qdsp6: q6prm: handle clk disable correctly") Cc: Signed-off-by: Krzysztof Kozlowski Reviewed-by: Srinivas Kandagatla Tested-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20230302122908.221398-1-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- sound/soc/qcom/qdsp6/q6prm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/qcom/qdsp6/q6prm.c b/sound/soc/qcom/qdsp6/q6prm.c index 3aa63aac4a68e..81554d2026589 100644 --- a/sound/soc/qcom/qdsp6/q6prm.c +++ b/sound/soc/qcom/qdsp6/q6prm.c @@ -184,9 +184,9 @@ int q6prm_set_lpass_clock(struct device *dev, int clk_id, int clk_attr, int clk_ unsigned int freq) { if (freq) - return q6prm_request_lpass_clock(dev, clk_id, clk_attr, clk_attr, freq); + return q6prm_request_lpass_clock(dev, clk_id, clk_attr, clk_root, freq); - return q6prm_release_lpass_clock(dev, clk_id, clk_attr, clk_attr, freq); + return q6prm_release_lpass_clock(dev, clk_id, clk_attr, clk_root, freq); } EXPORT_SYMBOL_GPL(q6prm_set_lpass_clock); From e5e7e398f6bb7918dab0612eb6991f7bae95520d Mon Sep 17 00:00:00 2001 From: Ravulapati Vishnu Vardhan Rao Date: Sat, 4 Mar 2023 13:37:02 +0530 Subject: [PATCH 057/460] ASoC: codecs: tx-macro: Fix for KASAN: slab-out-of-bounds When we run syzkaller we get below Out of Bound. "KASAN: slab-out-of-bounds Read in regcache_flat_read" Below is the backtrace of the issue: dump_backtrace+0x0/0x4c8 show_stack+0x34/0x44 dump_stack_lvl+0xd8/0x118 print_address_description+0x30/0x2d8 kasan_report+0x158/0x198 __asan_report_load4_noabort+0x44/0x50 regcache_flat_read+0x10c/0x110 regcache_read+0xf4/0x180 _regmap_read+0xc4/0x278 _regmap_update_bits+0x130/0x290 regmap_update_bits_base+0xc0/0x15c snd_soc_component_update_bits+0xa8/0x22c snd_soc_component_write_field+0x68/0xd4 tx_macro_digital_mute+0xec/0x140 Actually There is no need to have decimator with 32 bits. By limiting the variable with short type u8 issue is resolved. Signed-off-by: Ravulapati Vishnu Vardhan Rao Link: https://lore.kernel.org/r/20230304080702.609-1-quic_visr@quicinc.com Signed-off-by: Mark Brown --- sound/soc/codecs/lpass-tx-macro.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/lpass-tx-macro.c b/sound/soc/codecs/lpass-tx-macro.c index bf27bdd5be206..473d3cd395548 100644 --- a/sound/soc/codecs/lpass-tx-macro.c +++ b/sound/soc/codecs/lpass-tx-macro.c @@ -242,7 +242,7 @@ enum { struct tx_mute_work { struct tx_macro *tx; - u32 decimator; + u8 decimator; struct delayed_work dwork; }; @@ -635,7 +635,7 @@ static int tx_macro_mclk_enable(struct tx_macro *tx, return 0; } -static bool is_amic_enabled(struct snd_soc_component *component, int decimator) +static bool is_amic_enabled(struct snd_soc_component *component, u8 decimator) { u16 adc_mux_reg, adc_reg, adc_n; @@ -849,7 +849,7 @@ static int tx_macro_enable_dec(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); - unsigned int decimator; + u8 decimator; u16 tx_vol_ctl_reg, dec_cfg_reg, hpf_gate_reg, tx_gain_ctl_reg; u8 hpf_cut_off_freq; int hpf_delay = TX_MACRO_DMIC_HPF_DELAY_MS; @@ -1064,7 +1064,8 @@ static int tx_macro_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_component *component = dai->component; - u32 decimator, sample_rate; + u32 sample_rate; + u8 decimator; int tx_fs_rate; struct tx_macro *tx = snd_soc_component_get_drvdata(component); @@ -1128,7 +1129,7 @@ static int tx_macro_digital_mute(struct snd_soc_dai *dai, int mute, int stream) { struct snd_soc_component *component = dai->component; struct tx_macro *tx = snd_soc_component_get_drvdata(component); - u16 decimator; + u8 decimator; /* active decimator not set yet */ if (tx->active_decimator[dai->id] == -1) From d0dc41119905f740e8d5594adce277f7c0de8c92 Mon Sep 17 00:00:00 2001 From: Zhang Xiaoxu Date: Wed, 16 Nov 2022 11:11:36 +0800 Subject: [PATCH 058/460] cifs: Move the in_send statistic to __smb_send_rqst() When send SMB_COM_NT_CANCEL and RFC1002_SESSION_REQUEST, the in_send statistic was lost. Let's move the in_send statistic to the send function to avoid this scenario. Fixes: 7ee1af765dfa ("[CIFS]") Signed-off-by: Zhang Xiaoxu Signed-off-by: Steve French --- fs/cifs/transport.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index b42050c68e6c9..24bdd5f4d3bcc 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c @@ -278,7 +278,7 @@ static int __smb_send_rqst(struct TCP_Server_Info *server, int num_rqst, struct smb_rqst *rqst) { - int rc = 0; + int rc; struct kvec *iov; int n_vec; unsigned int send_length = 0; @@ -289,6 +289,7 @@ __smb_send_rqst(struct TCP_Server_Info *server, int num_rqst, struct msghdr smb_msg = {}; __be32 rfc1002_marker; + cifs_in_send_inc(server); if (cifs_rdma_enabled(server)) { /* return -EAGAIN when connecting or reconnecting */ rc = -EAGAIN; @@ -297,14 +298,17 @@ __smb_send_rqst(struct TCP_Server_Info *server, int num_rqst, goto smbd_done; } + rc = -EAGAIN; if (ssocket == NULL) - return -EAGAIN; + goto out; + rc = -ERESTARTSYS; if (fatal_signal_pending(current)) { cifs_dbg(FYI, "signal pending before send request\n"); - return -ERESTARTSYS; + goto out; } + rc = 0; /* cork the socket */ tcp_sock_set_cork(ssocket->sk, true); @@ -407,7 +411,8 @@ __smb_send_rqst(struct TCP_Server_Info *server, int num_rqst, rc); else if (rc > 0) rc = 0; - +out: + cifs_in_send_dec(server); return rc; } @@ -826,9 +831,7 @@ cifs_call_async(struct TCP_Server_Info *server, struct smb_rqst *rqst, * I/O response may come back and free the mid entry on another thread. */ cifs_save_when_sent(mid); - cifs_in_send_inc(server); rc = smb_send_rqst(server, 1, rqst, flags); - cifs_in_send_dec(server); if (rc < 0) { revert_current_mid(server, mid->credits); @@ -1144,9 +1147,7 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses, else midQ[i]->callback = cifs_compound_last_callback; } - cifs_in_send_inc(server); rc = smb_send_rqst(server, num_rqst, rqst, flags); - cifs_in_send_dec(server); for (i = 0; i < num_rqst; i++) cifs_save_when_sent(midQ[i]); @@ -1396,9 +1397,7 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses, midQ->mid_state = MID_REQUEST_SUBMITTED; - cifs_in_send_inc(server); rc = smb_send(server, in_buf, len); - cifs_in_send_dec(server); cifs_save_when_sent(midQ); if (rc < 0) @@ -1539,9 +1538,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon, } midQ->mid_state = MID_REQUEST_SUBMITTED; - cifs_in_send_inc(server); rc = smb_send(server, in_buf, len); - cifs_in_send_dec(server); cifs_save_when_sent(midQ); if (rc < 0) From 5c8cf1664f288098a971a1d1e65716a2b6a279e1 Mon Sep 17 00:00:00 2001 From: Christian Hewitt Date: Fri, 3 Mar 2023 12:33:12 +0000 Subject: [PATCH 059/460] drm/meson: fix 1px pink line on GXM when scaling video overlay Playing media with a resolution smaller than the crtc size requires the video overlay to be scaled for output and GXM boards display a 1px pink line on the bottom of the scaled overlay. Comparing with the downstream vendor driver revealed VPP_DUMMY_DATA not being set [0]. Setting VPP_DUMMY_DATA prevents the 1px pink line from being seen. [0] https://github.com/endlessm/linux-s905x/blob/master/drivers/amlogic/amports/video.c#L7869 Fixes: bbbe775ec5b5 ("drm: Add support for Amlogic Meson Graphic Controller") Suggested-by: Martin Blumenstingl Signed-off-by: Christian Hewitt Acked-by: Martin Blumenstingl Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/20230303123312.155164-1-christianshewitt@gmail.com --- drivers/gpu/drm/meson/meson_vpp.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/meson/meson_vpp.c b/drivers/gpu/drm/meson/meson_vpp.c index 154837688ab0d..5df1957c8e41f 100644 --- a/drivers/gpu/drm/meson/meson_vpp.c +++ b/drivers/gpu/drm/meson/meson_vpp.c @@ -100,6 +100,8 @@ void meson_vpp_init(struct meson_drm *priv) priv->io_base + _REG(VPP_DOLBY_CTRL)); writel_relaxed(0x1020080, priv->io_base + _REG(VPP_DUMMY_DATA1)); + writel_relaxed(0x42020, + priv->io_base + _REG(VPP_DUMMY_DATA)); } else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) writel_relaxed(0xf, priv->io_base + _REG(DOLBY_PATH_CTRL)); 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 060/460] 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 f9f115a7c75b8..92e1b700b51cb 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 d16c893425d07ada1fdd817ec06d322efcf69480 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Fri, 3 Mar 2023 14:48:50 +0100 Subject: [PATCH 061/460] ASoC: Intel: avs: max98357a: Explicitly define codec format MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit max98357a is speaker codec configured in 48000/2/S16_LE format regardless of front end format, so force it to be so. Reviewed-by: Cezary Rojewski Signed-off-by: Amadeusz Sławiński Link: https://lore.kernel.org/r/20230303134854.2277146-2-amadeuszx.slawinski@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/boards/max98357a.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/sound/soc/intel/avs/boards/max98357a.c b/sound/soc/intel/avs/boards/max98357a.c index 921f42caf7e09..183123d08c5a3 100644 --- a/sound/soc/intel/avs/boards/max98357a.c +++ b/sound/soc/intel/avs/boards/max98357a.c @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -24,6 +25,26 @@ static const struct snd_soc_dapm_route card_base_routes[] = { { "Spk", NULL, "Speaker" }, }; +static int +avs_max98357a_be_fixup(struct snd_soc_pcm_runtime *runrime, struct snd_pcm_hw_params *params) +{ + struct snd_interval *rate, *channels; + struct snd_mask *fmt; + + rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); + channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); + fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); + + /* The ADSP will convert the FE rate to 48k, stereo */ + rate->min = rate->max = 48000; + channels->min = channels->max = 2; + + /* set SSP0 to 16 bit */ + snd_mask_none(fmt); + snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE); + return 0; +} + static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port, struct snd_soc_dai_link **dai_link) { @@ -55,6 +76,7 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in dl->num_platforms = 1; dl->id = 0; dl->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS; + dl->be_hw_params_fixup = avs_max98357a_be_fixup; dl->nonatomic = 1; dl->no_pcm = 1; dl->dpcm_playback = 1; From 61f368624fe4d0c25c6e9c917574b8ace51d776e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Fri, 3 Mar 2023 14:48:51 +0100 Subject: [PATCH 062/460] ASoC: Intel: avs: da7219: Explicitly define codec format MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit da7219 is headset codec configured in 48000/2/S24_LE format regardless of front end format, so force it to be so. Reviewed-by: Cezary Rojewski Signed-off-by: Amadeusz Sławiński Link: https://lore.kernel.org/r/20230303134854.2277146-3-amadeuszx.slawinski@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/boards/da7219.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/sound/soc/intel/avs/boards/da7219.c b/sound/soc/intel/avs/boards/da7219.c index acd43b6108e99..1a1d572cc1d02 100644 --- a/sound/soc/intel/avs/boards/da7219.c +++ b/sound/soc/intel/avs/boards/da7219.c @@ -117,6 +117,26 @@ static void avs_da7219_codec_exit(struct snd_soc_pcm_runtime *rtd) snd_soc_component_set_jack(asoc_rtd_to_codec(rtd, 0)->component, NULL, NULL); } +static int +avs_da7219_be_fixup(struct snd_soc_pcm_runtime *runrime, struct snd_pcm_hw_params *params) +{ + struct snd_interval *rate, *channels; + struct snd_mask *fmt; + + rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); + channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); + fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); + + /* The ADSP will convert the FE rate to 48k, stereo */ + rate->min = rate->max = 48000; + channels->min = channels->max = 2; + + /* set SSP0 to 24 bit */ + snd_mask_none(fmt); + snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE); + return 0; +} + static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port, struct snd_soc_dai_link **dai_link) { @@ -148,6 +168,7 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in dl->num_platforms = 1; dl->id = 0; dl->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS; + dl->be_hw_params_fixup = avs_da7219_be_fixup; dl->init = avs_da7219_codec_init; dl->exit = avs_da7219_codec_exit; dl->nonatomic = 1; From d24dbc865c2bd5946bef62bb862a65df092dfc79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Fri, 3 Mar 2023 14:48:52 +0100 Subject: [PATCH 063/460] ASoC: Intel: avs: rt5682: Explicitly define codec format MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit rt5682 is headset codec configured in 48000/2/S24_LE format regardless of front end format, so force it to be so. Reviewed-by: Cezary Rojewski Signed-off-by: Amadeusz Sławiński Link: https://lore.kernel.org/r/20230303134854.2277146-4-amadeuszx.slawinski@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/boards/rt5682.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/sound/soc/intel/avs/boards/rt5682.c b/sound/soc/intel/avs/boards/rt5682.c index 473e9fe5d0bf7..b2c2ba93dcb56 100644 --- a/sound/soc/intel/avs/boards/rt5682.c +++ b/sound/soc/intel/avs/boards/rt5682.c @@ -169,6 +169,27 @@ static const struct snd_soc_ops avs_rt5682_ops = { .hw_params = avs_rt5682_hw_params, }; +static int +avs_rt5682_be_fixup(struct snd_soc_pcm_runtime *runtime, struct snd_pcm_hw_params *params) +{ + struct snd_interval *rate, *channels; + struct snd_mask *fmt; + + rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); + channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); + fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); + + /* The ADSP will convert the FE rate to 48k, stereo */ + rate->min = rate->max = 48000; + channels->min = channels->max = 2; + + /* set SSPN to 24 bit */ + snd_mask_none(fmt); + snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE); + + return 0; +} + static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port, struct snd_soc_dai_link **dai_link) { @@ -201,6 +222,7 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in dl->id = 0; dl->init = avs_rt5682_codec_init; dl->exit = avs_rt5682_codec_exit; + dl->be_hw_params_fixup = avs_rt5682_be_fixup; dl->ops = &avs_rt5682_ops; dl->nonatomic = 1; dl->no_pcm = 1; From 933de2d127281731166cf2880fa1e23c5a0f7faa Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Fri, 3 Mar 2023 14:48:53 +0100 Subject: [PATCH 064/460] ASoC: Intel: avs: ssm4567: Remove nau8825 bits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some of the nau8825 clock control got into the ssm4567, remove it. Signed-off-by: Cezary Rojewski Signed-off-by: Amadeusz Sławiński Link: https://lore.kernel.org/r/20230303134854.2277146-5-amadeuszx.slawinski@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/boards/ssm4567.c | 31 ---------------------------- 1 file changed, 31 deletions(-) diff --git a/sound/soc/intel/avs/boards/ssm4567.c b/sound/soc/intel/avs/boards/ssm4567.c index c5db696127624..2b7f5ad92aca7 100644 --- a/sound/soc/intel/avs/boards/ssm4567.c +++ b/sound/soc/intel/avs/boards/ssm4567.c @@ -15,7 +15,6 @@ #include #include "../../../codecs/nau8825.h" -#define SKL_NUVOTON_CODEC_DAI "nau8825-hifi" #define SKL_SSM_CODEC_DAI "ssm4567-hifi" static struct snd_soc_codec_conf card_codec_conf[] = { @@ -34,41 +33,11 @@ static const struct snd_kcontrol_new card_controls[] = { SOC_DAPM_PIN_SWITCH("Right Speaker"), }; -static int -platform_clock_control(struct snd_soc_dapm_widget *w, struct snd_kcontrol *control, int event) -{ - struct snd_soc_dapm_context *dapm = w->dapm; - struct snd_soc_card *card = dapm->card; - struct snd_soc_dai *codec_dai; - int ret; - - codec_dai = snd_soc_card_get_codec_dai(card, SKL_NUVOTON_CODEC_DAI); - if (!codec_dai) { - dev_err(card->dev, "Codec dai not found\n"); - return -EINVAL; - } - - if (SND_SOC_DAPM_EVENT_ON(event)) { - ret = snd_soc_dai_set_sysclk(codec_dai, NAU8825_CLK_MCLK, 24000000, - SND_SOC_CLOCK_IN); - if (ret < 0) - dev_err(card->dev, "set sysclk err = %d\n", ret); - } else { - ret = snd_soc_dai_set_sysclk(codec_dai, NAU8825_CLK_INTERNAL, 0, SND_SOC_CLOCK_IN); - if (ret < 0) - dev_err(card->dev, "set sysclk err = %d\n", ret); - } - - return ret; -} - static const struct snd_soc_dapm_widget card_widgets[] = { SND_SOC_DAPM_SPK("Left Speaker", NULL), SND_SOC_DAPM_SPK("Right Speaker", NULL), SND_SOC_DAPM_SPK("DP1", NULL), SND_SOC_DAPM_SPK("DP2", 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), }; static const struct snd_soc_dapm_route card_base_routes[] = { From 6206b2e787da2ed567922c37bb588a44f6fb6705 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Fri, 3 Mar 2023 14:48:54 +0100 Subject: [PATCH 065/460] ASoC: Intel: avs: nau8825: Adjust clock control MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Internal clock shall be adjusted also in cases when DAPM event other than 'ON' is triggered. Signed-off-by: Cezary Rojewski Signed-off-by: Amadeusz Sławiński Link: https://lore.kernel.org/r/20230303134854.2277146-6-amadeuszx.slawinski@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/boards/nau8825.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/sound/soc/intel/avs/boards/nau8825.c b/sound/soc/intel/avs/boards/nau8825.c index b31fa931ba8b6..b69fc5567135d 100644 --- a/sound/soc/intel/avs/boards/nau8825.c +++ b/sound/soc/intel/avs/boards/nau8825.c @@ -33,15 +33,15 @@ avs_nau8825_clock_control(struct snd_soc_dapm_widget *w, struct snd_kcontrol *co return -EINVAL; } - if (!SND_SOC_DAPM_EVENT_ON(event)) { + if (SND_SOC_DAPM_EVENT_ON(event)) + ret = snd_soc_dai_set_sysclk(codec_dai, NAU8825_CLK_MCLK, 24000000, + SND_SOC_CLOCK_IN); + else ret = snd_soc_dai_set_sysclk(codec_dai, NAU8825_CLK_INTERNAL, 0, SND_SOC_CLOCK_IN); - if (ret < 0) { - dev_err(card->dev, "set sysclk err = %d\n", ret); - return ret; - } - } + if (ret < 0) + dev_err(card->dev, "Set sysclk failed: %d\n", ret); - return 0; + return ret; } static const struct snd_kcontrol_new card_controls[] = { 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 066/460] 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 61012476d66e0..d53e13048d2ec 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 c44b56f7ffba0..5dfa4fb76f4b2 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 aff774775c678..7ba1726b71c7b 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 067/460] 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 5b10401d803b3..05102a55710c2 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 @@ static int sample_block_group_extent_item(struct btrfs_caching_control *caching_ 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 068/460] 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 8ea557e222527..439a5bf5ebc67 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 b4f0f9531119f..ada0a489bf2b6 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 069/460] 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 0095c6e4c3d1c..6b457b010cbc4 100644 --- a/fs/btrfs/delayed-inode.c +++ b/fs/btrfs/delayed-inode.c @@ -1048,7 +1048,7 @@ static int __btrfs_update_delayed_inode(struct btrfs_trans_handle *trans, * 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 070/460] 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 d8b90f95b1575..726592868e9c5 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 071/460] 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 05102a55710c2..0eec3084fb006 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 072/460] 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 be94030e1dfbf..138afa955370b 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 c28cd1f3433c7e339315d1ddacaeacf0fdfbe252 Mon Sep 17 00:00:00 2001 From: Saravana Kannan Date: Wed, 1 Mar 2023 17:46:38 -0800 Subject: [PATCH 073/460] clk: Mark a fwnode as initialized when using CLK_OF_DECLARE() macro We already mark fwnodes as initialized when they are registered as clock providers. We do this so that fw_devlink can tell when a clock driver doesn't use the driver core framework to probe/initialize its device. This ensures fw_devlink doesn't block the consumers of such a clock provider indefinitely. However, some users of CLK_OF_DECLARE() macros don't use the same node that matches the macro as the node for the clock provider, but they initialize the entire node. To cover these cases, also mark the nodes that match the macros as initialized when the init callback function is called. An example of this is "stericsson,u8500-clks" that's handled using CLK_OF_DECLARE() and looks something like this: clocks { compatible = "stericsson,u8500-clks"; prcmu_clk: prcmu-clock { #clock-cells = <1>; }; prcc_pclk: prcc-periph-clock { #clock-cells = <2>; }; prcc_kclk: prcc-kernel-clock { #clock-cells = <2>; }; prcc_reset: prcc-reset-controller { #reset-cells = <2>; }; ... }; This patch makes sure that "clocks" is marked as initialized so that fw_devlink knows that all nodes under it have been initialized. If the driver creates struct devices for some of the subnodes, fw_devlink is smart enough to know to wait for those devices to probe, so no special handling is required for those cases. Cc: Greg Kroah-Hartman Reported-by: Linus Walleij Link: https://lore.kernel.org/lkml/CACRpkdamxDX6EBVjKX5=D3rkHp17f5pwGdBVhzFU90-0MHY6dQ@mail.gmail.com/ Fixes: 4a032827daa8 ("of: property: Simplify of_link_to_phandle()") Signed-off-by: Saravana Kannan Link: https://lore.kernel.org/r/20230302014639.297514-1-saravanak@google.com Reviewed-by: Linus Walleij Tested-by: Linus Walleij Signed-off-by: Stephen Boyd --- include/linux/clk-provider.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 842e72a5348fa..c9f5276006a09 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -1363,7 +1363,13 @@ struct clk_hw_onecell_data { struct clk_hw *hws[]; }; -#define CLK_OF_DECLARE(name, compat, fn) OF_DECLARE_1(clk, name, compat, fn) +#define CLK_OF_DECLARE(name, compat, fn) \ + static void __init name##_of_clk_init_declare(struct device_node *np) \ + { \ + fn(np); \ + fwnode_dev_initialized(of_fwnode_handle(np), true); \ + } \ + OF_DECLARE_1(clk, name, compat, name##_of_clk_init_declare) /* * Use this macro when you have a driver that requires two initialization From 9d941b8abf863751c1c634d96539c3fab220a99c Mon Sep 17 00:00:00 2001 From: Nick Alcock Date: Wed, 22 Feb 2023 12:14:37 +0000 Subject: [PATCH 074/460] kbuild, clk: bcm2835: remove MODULE_LICENSE in non-modules Since commit 8b41fc4454e ("kbuild: create modules.builtin without Makefile.modbuiltin or tristate.conf"), MODULE_LICENSE declarations are used to identify modules. As a consequence, uses of the macro in non-modules will cause modprobe to misidentify their containing object file as a module when it is not (false positives), and modprobe might succeed rather than failing with a suitable error message. So remove it in the files in this commit, none of which can be built as modules. Signed-off-by: Nick Alcock Suggested-by: Luis Chamberlain Cc: Luis Chamberlain Cc: linux-modules@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: Hitomi Hasegawa Cc: Michael Turquette Cc: Stephen Boyd Cc: Florian Fainelli Cc: Ray Jui Cc: Scott Branden Cc: linux-clk@vger.kernel.org Cc: linux-rpi-kernel@lists.infradead.org Cc: linux-arm-kernel@lists.infradead.org Link: https://lore.kernel.org/r/20230222121453.91915-12-nick.alcock@oracle.com Signed-off-by: Stephen Boyd --- drivers/clk/bcm/clk-bcm2835-aux.c | 1 - drivers/clk/bcm/clk-bcm2835.c | 1 - 2 files changed, 2 deletions(-) diff --git a/drivers/clk/bcm/clk-bcm2835-aux.c b/drivers/clk/bcm/clk-bcm2835-aux.c index 290a2846a86b6..0fafa5cba4427 100644 --- a/drivers/clk/bcm/clk-bcm2835-aux.c +++ b/drivers/clk/bcm/clk-bcm2835-aux.c @@ -69,4 +69,3 @@ builtin_platform_driver(bcm2835_aux_clk_driver); MODULE_AUTHOR("Eric Anholt "); MODULE_DESCRIPTION("BCM2835 auxiliary peripheral clock driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c index e74fe6219d14e..8dc476ef5bf97 100644 --- a/drivers/clk/bcm/clk-bcm2835.c +++ b/drivers/clk/bcm/clk-bcm2835.c @@ -2350,4 +2350,3 @@ builtin_platform_driver(bcm2835_clk_driver); MODULE_AUTHOR("Eric Anholt "); MODULE_DESCRIPTION("BCM2835 clock driver"); -MODULE_LICENSE("GPL"); From 94511ebc6810142eb36c8b935e1713a15db94d28 Mon Sep 17 00:00:00 2001 From: Nick Alcock Date: Wed, 22 Feb 2023 12:14:38 +0000 Subject: [PATCH 075/460] kbuild, clk: remove MODULE_LICENSE in non-modules Since commit 8b41fc4454e ("kbuild: create modules.builtin without Makefile.modbuiltin or tristate.conf"), MODULE_LICENSE declarations are used to identify modules. As a consequence, uses of the macro in non-modules will cause modprobe to misidentify their containing object file as a module when it is not (false positives), and modprobe might succeed rather than failing with a suitable error message. So remove it in the files in this commit, none of which can be built as modules. Signed-off-by: Nick Alcock Suggested-by: Luis Chamberlain Cc: Luis Chamberlain Cc: linux-modules@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: Hitomi Hasegawa Cc: Michael Turquette Cc: Stephen Boyd Cc: linux-clk@vger.kernel.org Link: https://lore.kernel.org/r/20230222121453.91915-13-nick.alcock@oracle.com Acked-by: Conor Dooley Reviewed-by: Conor Dooley Signed-off-by: Stephen Boyd --- drivers/clk/clk-fixed-mmio.c | 1 - drivers/clk/clk-fsl-sai.c | 1 - drivers/clk/hisilicon/clk-hi3559a.c | 1 - drivers/clk/microchip/clk-mpfs-ccc.c | 1 - 4 files changed, 4 deletions(-) diff --git a/drivers/clk/clk-fixed-mmio.c b/drivers/clk/clk-fixed-mmio.c index 5225d17d6b3f3..8609fca29cc4e 100644 --- a/drivers/clk/clk-fixed-mmio.c +++ b/drivers/clk/clk-fixed-mmio.c @@ -99,4 +99,3 @@ module_platform_driver(of_fixed_mmio_clk_driver); MODULE_AUTHOR("Jan Kotas "); MODULE_DESCRIPTION("Memory Mapped IO Fixed clock driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/clk/clk-fsl-sai.c b/drivers/clk/clk-fsl-sai.c index 6238fcea04673..ee5baf993ff21 100644 --- a/drivers/clk/clk-fsl-sai.c +++ b/drivers/clk/clk-fsl-sai.c @@ -88,5 +88,4 @@ module_platform_driver(fsl_sai_clk_driver); MODULE_DESCRIPTION("Freescale SAI bitclock-as-a-clock driver"); MODULE_AUTHOR("Michael Walle "); -MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:fsl-sai-clk"); diff --git a/drivers/clk/hisilicon/clk-hi3559a.c b/drivers/clk/hisilicon/clk-hi3559a.c index 9ea1a80acbe8b..8036bd8cbb0ac 100644 --- a/drivers/clk/hisilicon/clk-hi3559a.c +++ b/drivers/clk/hisilicon/clk-hi3559a.c @@ -841,5 +841,4 @@ static void __exit hi3559av100_crg_exit(void) module_exit(hi3559av100_crg_exit); -MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("HiSilicon Hi3559AV100 CRG Driver"); diff --git a/drivers/clk/microchip/clk-mpfs-ccc.c b/drivers/clk/microchip/clk-mpfs-ccc.c index 0ddc73e07be42..bce61c45e9674 100644 --- a/drivers/clk/microchip/clk-mpfs-ccc.c +++ b/drivers/clk/microchip/clk-mpfs-ccc.c @@ -291,4 +291,3 @@ module_exit(clk_ccc_exit); MODULE_DESCRIPTION("Microchip PolarFire SoC Clock Conditioning Circuitry Driver"); MODULE_AUTHOR("Conor Dooley "); -MODULE_LICENSE("GPL"); From 0ffad67784a097beccf34d297ddd1b0773b3b8a3 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sat, 25 Feb 2023 21:39:47 -0800 Subject: [PATCH 076/460] clk: HI655X: 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: 3a49afb84ca0 ("clk: enable hi655x common clk automatically") Signed-off-by: Randy Dunlap Cc: Riku Voipio Cc: Stephen Boyd Cc: Michael Turquette Cc: linux-clk@vger.kernel.org Link: https://lore.kernel.org/r/20230226053953.4681-3-rdunlap@infradead.org Signed-off-by: Stephen Boyd --- drivers/clk/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index b6c5bf69a2b2c..1eef05bb1f995 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -91,7 +91,7 @@ config COMMON_CLK_RK808 config COMMON_CLK_HI655X tristate "Clock driver for Hi655x" if EXPERT depends on (MFD_HI655X_PMIC || COMPILE_TEST) - depends on REGMAP + select REGMAP default MFD_HI655X_PMIC help This driver supports the hi655x PMIC clock. This From 26243872fe26ec0df7d81766253d00213990e382 Mon Sep 17 00:00:00 2001 From: Conor Dooley Date: Wed, 22 Feb 2023 12:46:11 +0000 Subject: [PATCH 077/460] MAINTAINERS: add missing clock driver coverage for Microchip FPGAs When the CCC support was added, the clock binding coverage was converted to a regex in commit 71c8517e004b ("MAINTAINERS: update polarfire soc clock binding"), but the coverage for the clock drivers themselves was not updated. Rectify that now. Signed-off-by: Conor Dooley Link: https://lore.kernel.org/r/20230222124610.257101-1-conor.dooley@microchip.com Signed-off-by: Stephen Boyd --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 8d5bc223f3053..cfd630ce68e75 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -17989,7 +17989,7 @@ F: Documentation/devicetree/bindings/spi/microchip,mpfs-spi.yaml F: Documentation/devicetree/bindings/usb/microchip,mpfs-musb.yaml F: arch/riscv/boot/dts/microchip/ F: drivers/char/hw_random/mpfs-rng.c -F: drivers/clk/microchip/clk-mpfs.c +F: drivers/clk/microchip/clk-mpfs*.c F: drivers/i2c/busses/i2c-microchip-corei2c.c F: drivers/mailbox/mailbox-mpfs.c F: drivers/pci/controller/pcie-microchip-host.c 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 078/460] 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 ccb7f5dad59be..37675437b7686 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 079/460] 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 66b5d5a51d5b1..8e46fa10a631e 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 6cc55c969b7ce8d85e09a636693d4126c3676c11 Mon Sep 17 00:00:00 2001 From: Maurizio Lombardi Date: Tue, 14 Feb 2023 15:15:56 +0100 Subject: [PATCH 080/460] 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 2317fb077db0e..557516c642c3b 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 081/460] 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 9142df876c733..9aba07c7bde4b 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 1dbc1496ebedd..ec0423ec66817 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 545167627e48e..80c4ee9df2a4f 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 89dc65a7cc8a119c395c0931b12d7a514f9d2bcc Mon Sep 17 00:00:00 2001 From: Conor Dooley Date: Tue, 28 Feb 2023 19:26:55 -0500 Subject: [PATCH 082/460] clk: k210: remove an implicit 64-bit division The K210 clock driver depends on SOC_CANAAN, which is only selectable when !MMU on RISC-V. !MMU is not possible on 32-bit yet, but patches have been sent for its enabling. The kernel test robot reported this implicit 64-bit division there. Replace the implicit division with an explicit one. Reported-by: kernel test robot Link: https://lore.kernel.org/linux-riscv/202301201538.zNlqgE4L-lkp@intel.com/ Signed-off-by: Conor Dooley Signed-off-by: Jesse Taube Link: https://lore.kernel.org/r/20230301002657.352637-2-Mr.Bossman075@gmail.com Reviewed-by: Damien Le Moal Signed-off-by: Stephen Boyd --- drivers/clk/clk-k210.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/clk-k210.c b/drivers/clk/clk-k210.c index 67a7cb3503c36..4eed667eddaf2 100644 --- a/drivers/clk/clk-k210.c +++ b/drivers/clk/clk-k210.c @@ -495,7 +495,7 @@ static unsigned long k210_pll_get_rate(struct clk_hw *hw, f = FIELD_GET(K210_PLL_CLKF, reg) + 1; od = FIELD_GET(K210_PLL_CLKOD, reg) + 1; - return (u64)parent_rate * f / (r * od); + return div_u64((u64)parent_rate * f, r * od); } static const struct clk_ops k210_pll_ops = { From 06d1a90de60208054cca15ef200138cfdbb642a9 Mon Sep 17 00:00:00 2001 From: Kang Chen Date: Mon, 27 Feb 2023 11:10:30 +0800 Subject: [PATCH 083/460] 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 0c3fcb8078062..a63279f55d096 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 084/460] 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 172d25fef740d..05eac965ee275 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 085/460] 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 34fc453f3eb1f..797230ad39396 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 086/460] 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 797230ad39396..2781739a66e00 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 087/460] 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 2781739a66e00..a02cd866e2f8a 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 @@ static int ufs_qcom_mcq_config_resource(struct ufs_hba *hba) 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 088/460] 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 61958a24a43d9..60e4ac2b8a6b3 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 c5b69f313af36..c5ad46fdde817 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 089/460] 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 c5ad46fdde817..cf630aa6734eb 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 090/460] 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 23de2603e71fd..40f238fa80cc1 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 758f7ca9e0ee8..4254e46a20f1a 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_fw.c +++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c @@ -415,7 +415,7 @@ static void mpi3mr_process_admin_reply_desc(struct mpi3mr_ioc *mrioc, 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 6eaeba41072cb..a794cc8a1c0b1 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 091/460] 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 3b61815979dab..b795a325534d3 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 092/460] 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 4254e46a20f1a..fa903a70baac8 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 093/460] 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 fa903a70baac8..29acf6111db30 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_fw.c +++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c @@ -3840,8 +3840,10 @@ int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc) 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 @@ int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc) 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 @@ int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc) 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 @@ int mpi3mr_reinit_ioc(struct mpi3mr_ioc *mrioc, u8 is_resume) 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 @@ int mpi3mr_reinit_ioc(struct mpi3mr_ioc *mrioc, u8 is_resume) 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 094/460] 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 bff6377023979..d10c6afb7f9cd 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 095/460] 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 b795a325534d3..be25f242fa794 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 096/460] 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 4919ea54b8277..2ef9d41fc6f42 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 da1cad1ee1238..4463a538102ad 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 097/460] 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 2ef9d41fc6f42..c2bace65105b1 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 6597e118c805a..84c9a55a5794c 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 098/460] 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 c2bace65105b1..63bac3684c197 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 099/460] 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 33f568b7f54de..d9ce379c4d2e8 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 100/460] 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 4f28dd617ecad..4bb87043e6dba 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 6b3a02d4406c0..22801c24ea193 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 780f6a9afe8b0e303406a39f6968cf1daa6c3d51 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Wed, 4 Jan 2023 13:20:52 -0800 Subject: [PATCH 101/460] lib: zstd: Fix -Wstringop-overflow warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the following -Wstringop-overflow warning when building with GCC 11+: lib/zstd/decompress/huf_decompress.c: In function ‘HUF_readDTableX2_wksp’: lib/zstd/decompress/huf_decompress.c:700:5: warning: ‘HUF_fillDTableX2.constprop’ accessing 624 bytes in a region of size 52 [-Wstringop-overflow=] 700 | HUF_fillDTableX2(dt, maxTableLog, | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 701 | wksp->sortedSymbol, sizeOfSort, | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 702 | wksp->rankStart0, wksp->rankVal, maxW, | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 703 | tableLog+1, | ~~~~~~~~~~~ 704 | wksp->calleeWksp, sizeof(wksp->calleeWksp) / sizeof(U32)); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ lib/zstd/decompress/huf_decompress.c:700:5: note: referencing argument 6 of type ‘U32 (*)[13]’ {aka ‘unsigned int (*)[13]’} lib/zstd/decompress/huf_decompress.c:571:13: note: in a call to function ‘HUF_fillDTableX2.constprop’ 571 | static void HUF_fillDTableX2(HUF_DEltX2* DTable, const U32 targetLog, | ^~~~~~~~~~~~~~~~ by using pointer notation instead of array notation. This is one of the last remaining warnings to be fixed before globally enabling -Wstringop-overflow. Co-developed-by: Gustavo A. R. Silva Signed-off-by: Gustavo A. R. Silva Cc: Nick Terrell Signed-off-by: Kees Cook Signed-off-by: Nick Terrell --- lib/zstd/decompress/huf_decompress.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/zstd/decompress/huf_decompress.c b/lib/zstd/decompress/huf_decompress.c index 89b269a641c7e..60958afebc415 100644 --- a/lib/zstd/decompress/huf_decompress.c +++ b/lib/zstd/decompress/huf_decompress.c @@ -985,7 +985,7 @@ static void HUF_fillDTableX2Level2(HUF_DEltX2* DTable, U32 targetLog, const U32 static void HUF_fillDTableX2(HUF_DEltX2* DTable, const U32 targetLog, const sortedSymbol_t* sortedList, - const U32* rankStart, rankVal_t rankValOrigin, const U32 maxWeight, + const U32* rankStart, rankValCol_t *rankValOrigin, const U32 maxWeight, const U32 nbBitsBaseline) { U32* const rankVal = rankValOrigin[0]; From 038505c41f0aad26ef101f4f7f6e111531c3914f Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Wed, 15 Feb 2023 15:19:17 -0800 Subject: [PATCH 102/460] lib: zstd: Backport fix for in-place decompression Backport the relevant part of upstream commit 5b266196 [0]. This fixes in-place decompression for x86-64 kernel decompression. It uses a bound of 131072 + (uncompressed_size >> 8), which can be violated after upstream commit 6a7ede3d [1], as zstd can use part of the output buffer as temporary storage, and without this patch needs a bound of ~262144. The fix is for zstd to detect that the input and output buffers overlap, so that zstd knows it can't use the overlapping portion of the output buffer as tempoary storage. If the margin is not large enough, this will ensure that zstd will fail the decompression, rather than overwriting part of the input data, and causing corruption. This fix has been landed upstream and is in release v1.5.4. That commit also adds unit and fuzz tests to verify that the margin we use is respected, and correct. That means that the fix is well tested upstream. I have not been able to reproduce the potential bug in x86-64 kernel decompression locally, nor have I recieved reports of failures to decompress the kernel. It is possible that compression saves enough space to make it very hard for the issue to appear. I've boot tested the zstd compressed kernel on x86-64 and i386 with this patch, which uses in-place decompression, and sanity tested zstd compression in btrfs / squashfs to make sure that we don't see any issues, but other uses of zstd shouldn't be affected, because they don't use in-place decompression. Thanks to Vasily Gorbik for debugging a related issue on s390, which was triggered by the same commit, but was a bug in how __decompress() was called [2]. And to Sasha Levin for the CC alerting me of the issue. [0] https://github.com/facebook/zstd/commit/5b266196a41e6a15e21bd4f0eeab43b938db1d90 [1] https://github.com/facebook/zstd/commit/6a7ede3dfccbf3e0a5928b4224a039c260dcff72 [2] https://lore.kernel.org/r/patch-1.thread-41c676.git-41c676c2d153.your-ad-here.call-01675030179-ext-9637@work.hours CC: Vasily Gorbik CC: Heiko Carstens CC: Sasha Levin CC: Yann Collet Signed-off-by: Nick Terrell --- lib/zstd/decompress/zstd_decompress.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/lib/zstd/decompress/zstd_decompress.c b/lib/zstd/decompress/zstd_decompress.c index b9b935a9f5c0d..6b3177c947114 100644 --- a/lib/zstd/decompress/zstd_decompress.c +++ b/lib/zstd/decompress/zstd_decompress.c @@ -798,7 +798,7 @@ static size_t ZSTD_copyRawBlock(void* dst, size_t dstCapacity, if (srcSize == 0) return 0; RETURN_ERROR(dstBuffer_null, ""); } - ZSTD_memcpy(dst, src, srcSize); + ZSTD_memmove(dst, src, srcSize); return srcSize; } @@ -858,6 +858,7 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx, /* Loop on each block */ while (1) { + BYTE* oBlockEnd = oend; size_t decodedSize; blockProperties_t blockProperties; size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSrcSize, &blockProperties); @@ -867,16 +868,34 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx, remainingSrcSize -= ZSTD_blockHeaderSize; RETURN_ERROR_IF(cBlockSize > remainingSrcSize, srcSize_wrong, ""); + if (ip >= op && ip < oBlockEnd) { + /* We are decompressing in-place. Limit the output pointer so that we + * don't overwrite the block that we are currently reading. This will + * fail decompression if the input & output pointers aren't spaced + * far enough apart. + * + * This is important to set, even when the pointers are far enough + * apart, because ZSTD_decompressBlock_internal() can decide to store + * literals in the output buffer, after the block it is decompressing. + * Since we don't want anything to overwrite our input, we have to tell + * ZSTD_decompressBlock_internal to never write past ip. + * + * See ZSTD_allocateLiteralsBuffer() for reference. + */ + oBlockEnd = op + (ip - op); + } + switch(blockProperties.blockType) { case bt_compressed: - decodedSize = ZSTD_decompressBlock_internal(dctx, op, (size_t)(oend-op), ip, cBlockSize, /* frame */ 1, not_streaming); + decodedSize = ZSTD_decompressBlock_internal(dctx, op, (size_t)(oBlockEnd-op), ip, cBlockSize, /* frame */ 1, not_streaming); break; case bt_raw : + /* Use oend instead of oBlockEnd because this function is safe to overlap. It uses memmove. */ decodedSize = ZSTD_copyRawBlock(op, (size_t)(oend-op), ip, cBlockSize); break; case bt_rle : - decodedSize = ZSTD_setRleBlock(op, (size_t)(oend-op), *ip, blockProperties.origSize); + decodedSize = ZSTD_setRleBlock(op, (size_t)(oBlockEnd-op), *ip, blockProperties.origSize); break; case bt_reserved : default: From 6906598f1ce93761716d780b6e3f171e13f0f4ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonathan=20Neusch=C3=A4fer?= Date: Sun, 29 Jan 2023 14:14:36 +0100 Subject: [PATCH 103/460] zstd: Fix definition of assert() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit assert(x) should emit a warning if x is false. WARN_ON(x) emits a warning if x is true. Thus, assert(x) should be defined as WARN_ON(!x) rather than WARN_ON(x). Signed-off-by: Jonathan Neuschäfer Signed-off-by: Nick Terrell --- lib/zstd/common/zstd_deps.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/zstd/common/zstd_deps.h b/lib/zstd/common/zstd_deps.h index 7a5bf44839c9c..f06df065dec01 100644 --- a/lib/zstd/common/zstd_deps.h +++ b/lib/zstd/common/zstd_deps.h @@ -84,7 +84,7 @@ static uint64_t ZSTD_div64(uint64_t dividend, uint32_t divisor) { #include -#define assert(x) WARN_ON((x)) +#define assert(x) WARN_ON(!(x)) #endif /* ZSTD_DEPS_ASSERT */ #endif /* ZSTD_DEPS_NEED_ASSERT */ From e18048da9bc3f87acef4eb67a11b4fc55fe15424 Mon Sep 17 00:00:00 2001 From: Palmer Dabbelt Date: Thu, 23 Feb 2023 14:46:05 -0800 Subject: [PATCH 104/460] 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 6203c33789228..4de83b9b1772d 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 260daf3236d3a..7f34f3c7c8827 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 2da789cda462bda93679f53ee38f9aa2309d47e8 Mon Sep 17 00:00:00 2001 From: Guillaume Tucker Date: Sat, 4 Feb 2023 14:34:54 +0100 Subject: [PATCH 105/460] selftests: amd-pstate: fix TEST_FILES Bring back the Python scripts that were initially added with TEST_GEN_FILES but now with TEST_FILES to avoid having them deleted when doing a clean. Also fix the way the architecture is being determined as they should also be installed when ARCH=x86_64 is provided explicitly. Then also append extra files to TEST_FILES and TEST_PROGS with += so they don't get discarded. Fixes: ba2d788aa873 ("selftests: amd-pstate: Trigger tbench benchmark and test cpus") Fixes: a49fb7218ed8 ("selftests: amd-pstate: Don't delete source files via Makefile") Signed-off-by: Guillaume Tucker Acked-by: Huang Rui Signed-off-by: Shuah Khan --- tools/testing/selftests/amd-pstate/Makefile | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/tools/testing/selftests/amd-pstate/Makefile b/tools/testing/selftests/amd-pstate/Makefile index 5fd1424db37d8..c382f579fe94a 100644 --- a/tools/testing/selftests/amd-pstate/Makefile +++ b/tools/testing/selftests/amd-pstate/Makefile @@ -4,10 +4,15 @@ # No binaries, but make sure arg-less "make" doesn't trigger "run_tests" all: -uname_M := $(shell uname -m 2>/dev/null || echo not) -ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/x86/ -e s/x86_64/x86/) +ARCH ?= $(shell uname -m 2>/dev/null || echo not) +ARCH := $(shell echo $(ARCH) | sed -e s/i.86/x86/ -e s/x86_64/x86/) -TEST_PROGS := run.sh -TEST_FILES := basic.sh tbench.sh gitsource.sh +ifeq (x86,$(ARCH)) +TEST_FILES += ../../../power/x86/amd_pstate_tracer/amd_pstate_trace.py +TEST_FILES += ../../../power/x86/intel_pstate_tracer/intel_pstate_tracer.py +endif + +TEST_PROGS += run.sh +TEST_FILES += basic.sh tbench.sh gitsource.sh include ../lib.mk From c64c67c0748be5afb769a4eedbeb3ce6de36958f Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 6 Mar 2023 19:58:56 -0500 Subject: [PATCH 106/460] 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 612c5eca71bc0..7c08b225261c4 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 107/460] 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 b06254e76d99a..8fc10089e19e8 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 6b0313c2fa3d2cf991c9ffef6fae6e7ef592ce6d Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Sat, 4 Mar 2023 15:41:07 +0800 Subject: [PATCH 108/460] cpuidle: psci: Iterate backwards over list in psci_pd_remove() In case that psci_pd_init_topology() fails for some reason, psci_pd_remove() will be responsible for deleting provider and removing genpd from psci_pd_providers list. There will be a failure when removing the cluster PD, because the cpu (child) PDs haven't been removed. [ 0.050232] CPUidle PSCI: init PM domain cpu0 [ 0.050278] CPUidle PSCI: init PM domain cpu1 [ 0.050329] CPUidle PSCI: init PM domain cpu2 [ 0.050370] CPUidle PSCI: init PM domain cpu3 [ 0.050422] CPUidle PSCI: init PM domain cpu-cluster0 [ 0.050475] PM: genpd_remove: unable to remove cpu-cluster0 [ 0.051412] PM: genpd_remove: removed cpu3 [ 0.051449] PM: genpd_remove: removed cpu2 [ 0.051499] PM: genpd_remove: removed cpu1 [ 0.051546] PM: genpd_remove: removed cpu0 Fix the problem by iterating the provider list reversely, so that parent PD gets removed after child's PDs like below. [ 0.029052] CPUidle PSCI: init PM domain cpu0 [ 0.029076] CPUidle PSCI: init PM domain cpu1 [ 0.029103] CPUidle PSCI: init PM domain cpu2 [ 0.029124] CPUidle PSCI: init PM domain cpu3 [ 0.029151] CPUidle PSCI: init PM domain cpu-cluster0 [ 0.029647] PM: genpd_remove: removed cpu0 [ 0.029666] PM: genpd_remove: removed cpu1 [ 0.029690] PM: genpd_remove: removed cpu2 [ 0.029714] PM: genpd_remove: removed cpu3 [ 0.029738] PM: genpd_remove: removed cpu-cluster0 Fixes: a65a397f2451 ("cpuidle: psci: Add support for PM domains by using genpd") Reviewed-by: Sudeep Holla Reviewed-by: Ulf Hansson Signed-off-by: Shawn Guo Cc: 5.10+ # 5.10+ Signed-off-by: Rafael J. Wysocki --- drivers/cpuidle/cpuidle-psci-domain.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/cpuidle/cpuidle-psci-domain.c b/drivers/cpuidle/cpuidle-psci-domain.c index 6ad2954948a5a..11316c3b14ca4 100644 --- a/drivers/cpuidle/cpuidle-psci-domain.c +++ b/drivers/cpuidle/cpuidle-psci-domain.c @@ -106,7 +106,8 @@ static void psci_pd_remove(void) struct psci_pd_provider *pd_provider, *it; struct generic_pm_domain *genpd; - list_for_each_entry_safe(pd_provider, it, &psci_pd_providers, link) { + list_for_each_entry_safe_reverse(pd_provider, it, + &psci_pd_providers, link) { of_genpd_del_provider(pd_provider->node); genpd = of_genpd_remove_last(pd_provider->node); From c29b97725c91add5021a3257c14ad1ed32eedf76 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 2 Mar 2023 18:12:12 +0200 Subject: [PATCH 109/460] =?UTF-8?q?ACPI:=20docs:=20enumeration:=20Correct?= =?UTF-8?q?=20reference=20to=20the=20I=C2=B2C=20device=20data=20type?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I²C peripheral devices that are connected to the controller are represented in the Linux kernel as objects of the struct i2c_client. Fix this in the documentation. Signed-off-by: Andy Shevchenko Signed-off-by: Rafael J. Wysocki --- Documentation/firmware-guide/acpi/enumeration.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/firmware-guide/acpi/enumeration.rst b/Documentation/firmware-guide/acpi/enumeration.rst index b9dc0c603f367..56d9913a3370c 100644 --- a/Documentation/firmware-guide/acpi/enumeration.rst +++ b/Documentation/firmware-guide/acpi/enumeration.rst @@ -19,7 +19,7 @@ possible we decided to do following: platform devices. - Devices behind real busses where there is a connector resource - are represented as struct spi_device or struct i2c_device. Note + are represented as struct spi_device or struct i2c_client. Note that standard UARTs are not busses so there is no struct uart_device, although some of them may be represented by struct serdev_device. From 89b0411481967a2e8c91190a211a359966cfcf4b Mon Sep 17 00:00:00 2001 From: "Chia-Lin Kao (AceLan)" Date: Thu, 2 Mar 2023 17:33:00 +0800 Subject: [PATCH 110/460] ACPI: video: Add backlight=native DMI quirk for Dell Vostro 15 3535 Sometimes the system boots up with a acpi_video0 backlight interface which doesn't work. So add Dell Vostro 15 3535 into the video_detect_dmi_table to set it to native explicitly. Signed-off-by: Chia-Lin Kao (AceLan) Signed-off-by: Rafael J. Wysocki --- drivers/acpi/video_detect.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index 710ac640267dd..14d6d81e536fe 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -716,6 +716,13 @@ static const struct dmi_system_id video_detect_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Dell G15 5515"), }, }, + { + .callback = video_detect_force_native, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 15 3535"), + }, + }, /* * Desktops which falsely report a backlight and which our heuristics From 5adc409340b1fc82bc1175e602d14ac82ac685e3 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 1 Mar 2023 11:04:34 +0100 Subject: [PATCH 111/460] ACPI: x86: Introduce an acpi_quirk_skip_gpio_event_handlers() helper x86 ACPI boards which ship with only Android as their factory image usually have pretty broken ACPI tables, relying on everything being hardcoded in the factory kernel image and often disabling parts of the ACPI enumeration kernel code to avoid the broken tables causing issues. Part of this broken ACPI code is that sometimes these boards have _AEI ACPI GPIO event handlers which are broken. So far this has been dealt with in the platform/x86/x86-android-tablets.c module, which contains various workarounds for these devices, by it calling acpi_gpiochip_free_interrupts() on gpiochip-s with troublesome handlers to disable the handlers. But in some cases this is too late, if the handlers are of the edge type then gpiolib-acpi.c's code will already have run them at boot. This can cause issues such as GPIOs ending up as owned by "ACPI:OpRegion", making them unavailable for drivers which actually need them. Boards with these broken ACPI tables are already listed in drivers/acpi/x86/utils.c for e.g. acpi_quirk_skip_i2c_client_enumeration(). Extend the quirks mechanism for a new acpi_quirk_skip_gpio_event_handlers() helper, this re-uses the DMI-ids rather then having to duplicate the same DMI table in gpiolib-acpi.c . Also add the new ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS quirk to existing boards with troublesome ACPI gpio event handlers, so that the current acpi_gpiochip_free_interrupts() hack can be removed from x86-android-tablets.c . Signed-off-by: Hans de Goede Acked-by: Andy Shevchenko Signed-off-by: Rafael J. Wysocki --- drivers/acpi/x86/utils.c | 24 +++++++++++++++++++++--- drivers/gpio/gpiolib-acpi.c | 3 +++ include/acpi/acpi_bus.h | 5 +++++ 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/drivers/acpi/x86/utils.c b/drivers/acpi/x86/utils.c index e45285d4e62a4..4bf57cce30bbf 100644 --- a/drivers/acpi/x86/utils.c +++ b/drivers/acpi/x86/utils.c @@ -251,6 +251,7 @@ bool force_storage_d3(void) #define ACPI_QUIRK_UART1_TTY_UART2_SKIP BIT(1) #define ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY BIT(2) #define ACPI_QUIRK_USE_ACPI_AC_AND_BATTERY BIT(3) +#define ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS BIT(4) static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = { /* @@ -286,7 +287,8 @@ static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = { }, .driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS | ACPI_QUIRK_UART1_TTY_UART2_SKIP | - ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY), + ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY | + ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS), }, { .matches = { @@ -294,7 +296,8 @@ static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = { DMI_MATCH(DMI_PRODUCT_NAME, "TF103C"), }, .driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS | - ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY), + ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY | + ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS), }, { /* Lenovo Yoga Tablet 2 1050F/L */ @@ -336,7 +339,8 @@ static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = { DMI_MATCH(DMI_PRODUCT_NAME, "M890BAP"), }, .driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS | - ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY), + ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY | + ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS), }, { /* Whitelabel (sold as various brands) TM800A550L */ @@ -413,6 +417,20 @@ int acpi_quirk_skip_serdev_enumeration(struct device *controller_parent, bool *s return 0; } EXPORT_SYMBOL_GPL(acpi_quirk_skip_serdev_enumeration); + +bool acpi_quirk_skip_gpio_event_handlers(void) +{ + const struct dmi_system_id *dmi_id; + long quirks; + + dmi_id = dmi_first_match(acpi_quirk_skip_dmi_ids); + if (!dmi_id) + return false; + + quirks = (unsigned long)dmi_id->driver_data; + return (quirks & ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS); +} +EXPORT_SYMBOL_GPL(acpi_quirk_skip_gpio_event_handlers); #endif /* Lists of PMIC ACPI HIDs with an (often better) native charger driver */ diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index d8a421ce26a83..31ae0adbb295a 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -536,6 +536,9 @@ void acpi_gpiochip_request_interrupts(struct gpio_chip *chip) if (ACPI_FAILURE(status)) return; + if (acpi_quirk_skip_gpio_event_handlers()) + return; + acpi_walk_resources(handle, METHOD_NAME__AEI, acpi_gpiochip_alloc_event, acpi_gpio); diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 0584e9f6e3397..57acb895c0381 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -657,6 +657,7 @@ static inline bool acpi_quirk_skip_acpi_ac_and_battery(void) #if IS_ENABLED(CONFIG_X86_ANDROID_TABLETS) bool acpi_quirk_skip_i2c_client_enumeration(struct acpi_device *adev); int acpi_quirk_skip_serdev_enumeration(struct device *controller_parent, bool *skip); +bool acpi_quirk_skip_gpio_event_handlers(void); #else static inline bool acpi_quirk_skip_i2c_client_enumeration(struct acpi_device *adev) { @@ -668,6 +669,10 @@ acpi_quirk_skip_serdev_enumeration(struct device *controller_parent, bool *skip) *skip = false; return 0; } +static inline bool acpi_quirk_skip_gpio_event_handlers(void) +{ + return false; +} #endif #ifdef CONFIG_PM From a5cb0695c5f0ac2ab0cedf2c1c0d75826cb73448 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 1 Mar 2023 11:04:35 +0100 Subject: [PATCH 112/460] ACPI: x86: Add skip i2c clients quirk for Acer Iconia One 7 B1-750 The Acer Iconia One 7 B1-750 is a x86 tablet which ships with Android x86 as factory OS. The Android x86 kernel fork ignores I2C devices described in the DSDT, except for the PMIC and Audio codecs. As usual the Acer Iconia One 7 B1-750's DSDT contains a bunch of extra I2C devices which are not actually there, causing various resource conflicts. Add an ACPI_QUIRK_SKIP_I2C_CLIENTS quirk for the Acer Iconia One 7 B1-750 to the acpi_quirk_skip_dmi_ids table to woraround this. The DSDT also contains broken ACPI GPIO event handlers, disable those too. Signed-off-by: Hans de Goede Signed-off-by: Rafael J. Wysocki --- drivers/acpi/x86/utils.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/acpi/x86/utils.c b/drivers/acpi/x86/utils.c index 4bf57cce30bbf..b2b0e2701333a 100644 --- a/drivers/acpi/x86/utils.c +++ b/drivers/acpi/x86/utils.c @@ -280,6 +280,16 @@ static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = { * need the x86-android-tablets module to properly work. */ #if IS_ENABLED(CONFIG_X86_ANDROID_TABLETS) + { + /* Acer Iconia One 7 B1-750 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Insyde"), + DMI_MATCH(DMI_PRODUCT_NAME, "VESPA2"), + }, + .driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS | + ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY | + ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS), + }, { .matches = { DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), From 1a1e7540cf501dd5c8b57a577a155cdd13c7e202 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 1 Mar 2023 11:04:36 +0100 Subject: [PATCH 113/460] ACPI: x86: Add skip i2c clients quirk for Lenovo Yoga Book X90 The Lenovo Yoga Book X90 is a x86 tablet which ships with Android x86 as factory OS. The Android x86 kernel fork ignores I2C devices described in the DSDT, except for the PMIC and Audio codecs. As usual the Lenovo Yoga Book X90's DSDT contains a bunch of extra I2C devices which are not actually there, causing various resource conflicts. Add an ACPI_QUIRK_SKIP_I2C_CLIENTS quirk for the Lenovo Yoga Book X90 to the acpi_quirk_skip_dmi_ids table to woraround this. The DSDT also contains broken ACPI GPIO event handlers, disable those too. Signed-off-by: Hans de Goede Signed-off-by: Rafael J. Wysocki --- drivers/acpi/x86/utils.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/acpi/x86/utils.c b/drivers/acpi/x86/utils.c index b2b0e2701333a..da5727069d851 100644 --- a/drivers/acpi/x86/utils.c +++ b/drivers/acpi/x86/utils.c @@ -300,6 +300,17 @@ static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = { ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY | ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS), }, + { + /* Lenovo Yoga Book X90F/L */ + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "CHERRYVIEW D1 PLATFORM"), + DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "YETI-11"), + }, + .driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS | + ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY | + ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS), + }, { .matches = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), From a659e35ca0af2765f567bdfdccfa247eff0cdab8 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 7 Mar 2023 11:39:11 +0200 Subject: [PATCH 114/460] ASoC: SOF: Intel: MTL: Fix the device description Add the missing ops_free callback. Fixes: 064520e8aeaa ("ASoC: SOF: Intel: Add support for MeteorLake (MTL)") Signed-off-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307093914.25409-2-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 6e4e6d4ef5a56..b183dc0014b4b 100644 --- a/sound/soc/sof/intel/pci-mtl.c +++ b/sound/soc/sof/intel/pci-mtl.c @@ -46,6 +46,7 @@ static const struct sof_dev_desc mtl_desc = { .nocodec_tplg_filename = "sof-mtl-nocodec.tplg", .ops = &sof_mtl_ops, .ops_init = sof_mtl_ops_init, + .ops_free = hda_ops_free, }; /* PCI IDs */ From 9eb2b4cac223095d2079a6d52b8bbddc6e064288 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 7 Mar 2023 11:39:12 +0200 Subject: [PATCH 115/460] ASoC: SOF: Intel: HDA: Fix device description Add the missing ops_free callback for APL/CNL/CML/JSL/TGL/EHL platforms. Fixes: 1da51943725f ("ASoC: SOF: Intel: hda: init NHLT for IPC4") Signed-off-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307093914.25409-3-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/pci-apl.c | 1 + sound/soc/sof/intel/pci-cnl.c | 2 ++ sound/soc/sof/intel/pci-icl.c | 1 + sound/soc/sof/intel/pci-tgl.c | 5 +++++ 4 files changed, 9 insertions(+) diff --git a/sound/soc/sof/intel/pci-apl.c b/sound/soc/sof/intel/pci-apl.c index 69279dcc92dc1..aff6cb573c270 100644 --- a/sound/soc/sof/intel/pci-apl.c +++ b/sound/soc/sof/intel/pci-apl.c @@ -78,6 +78,7 @@ static const struct sof_dev_desc glk_desc = { .nocodec_tplg_filename = "sof-glk-nocodec.tplg", .ops = &sof_apl_ops, .ops_init = sof_apl_ops_init, + .ops_free = hda_ops_free, }; /* PCI IDs */ diff --git a/sound/soc/sof/intel/pci-cnl.c b/sound/soc/sof/intel/pci-cnl.c index 8db3f8d15b55e..4c0c1c369dcd8 100644 --- a/sound/soc/sof/intel/pci-cnl.c +++ b/sound/soc/sof/intel/pci-cnl.c @@ -48,6 +48,7 @@ static const struct sof_dev_desc cnl_desc = { .nocodec_tplg_filename = "sof-cnl-nocodec.tplg", .ops = &sof_cnl_ops, .ops_init = sof_cnl_ops_init, + .ops_free = hda_ops_free, }; static const struct sof_dev_desc cfl_desc = { @@ -111,6 +112,7 @@ static const struct sof_dev_desc cml_desc = { .nocodec_tplg_filename = "sof-cnl-nocodec.tplg", .ops = &sof_cnl_ops, .ops_init = sof_cnl_ops_init, + .ops_free = hda_ops_free, }; /* PCI IDs */ diff --git a/sound/soc/sof/intel/pci-icl.c b/sound/soc/sof/intel/pci-icl.c index d6cf75e357dbf..6785669113b3c 100644 --- a/sound/soc/sof/intel/pci-icl.c +++ b/sound/soc/sof/intel/pci-icl.c @@ -79,6 +79,7 @@ static const struct sof_dev_desc jsl_desc = { .nocodec_tplg_filename = "sof-jsl-nocodec.tplg", .ops = &sof_cnl_ops, .ops_init = sof_cnl_ops_init, + .ops_free = hda_ops_free, }; /* PCI IDs */ diff --git a/sound/soc/sof/intel/pci-tgl.c b/sound/soc/sof/intel/pci-tgl.c index e80c4dfef85a5..adc7314a1b578 100644 --- a/sound/soc/sof/intel/pci-tgl.c +++ b/sound/soc/sof/intel/pci-tgl.c @@ -48,6 +48,7 @@ static const struct sof_dev_desc tgl_desc = { .nocodec_tplg_filename = "sof-tgl-nocodec.tplg", .ops = &sof_tgl_ops, .ops_init = sof_tgl_ops_init, + .ops_free = hda_ops_free, }; static const struct sof_dev_desc tglh_desc = { @@ -110,6 +111,7 @@ static const struct sof_dev_desc ehl_desc = { .nocodec_tplg_filename = "sof-ehl-nocodec.tplg", .ops = &sof_tgl_ops, .ops_init = sof_tgl_ops_init, + .ops_free = hda_ops_free, }; static const struct sof_dev_desc adls_desc = { @@ -141,6 +143,7 @@ static const struct sof_dev_desc adls_desc = { .nocodec_tplg_filename = "sof-adl-nocodec.tplg", .ops = &sof_tgl_ops, .ops_init = sof_tgl_ops_init, + .ops_free = hda_ops_free, }; static const struct sof_dev_desc adl_desc = { @@ -172,6 +175,7 @@ static const struct sof_dev_desc adl_desc = { .nocodec_tplg_filename = "sof-adl-nocodec.tplg", .ops = &sof_tgl_ops, .ops_init = sof_tgl_ops_init, + .ops_free = hda_ops_free, }; static const struct sof_dev_desc adl_n_desc = { @@ -203,6 +207,7 @@ static const struct sof_dev_desc adl_n_desc = { .nocodec_tplg_filename = "sof-adl-nocodec.tplg", .ops = &sof_tgl_ops, .ops_init = sof_tgl_ops_init, + .ops_free = hda_ops_free, }; static const struct sof_dev_desc rpls_desc = { From 1f320bdb29b644a2c9fb301a6fb2d6170e6417e9 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 7 Mar 2023 11:39:13 +0200 Subject: [PATCH 116/460] ASoC: SOF: Intel: SKL: Fix device description Add missing ops_free callback for SKL/KBL platforms. Fixes: 52d7939d10f2 ("ASoC: SOF: Intel: add ops for SKL/KBL") Signed-off-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307093914.25409-4-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 3a99dc444f92e..5b4bccf819658 100644 --- a/sound/soc/sof/intel/pci-skl.c +++ b/sound/soc/sof/intel/pci-skl.c @@ -38,6 +38,7 @@ static struct sof_dev_desc skl_desc = { .nocodec_tplg_filename = "sof-skl-nocodec.tplg", .ops = &sof_skl_ops, .ops_init = sof_skl_ops_init, + .ops_free = hda_ops_free, }; static struct sof_dev_desc kbl_desc = { @@ -61,6 +62,7 @@ static struct sof_dev_desc kbl_desc = { .nocodec_tplg_filename = "sof-kbl-nocodec.tplg", .ops = &sof_skl_ops, .ops_init = sof_skl_ops_init, + .ops_free = hda_ops_free, }; /* PCI IDs */ From 376f79bbf521fc37b871b536276319951b5bef3a Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 7 Mar 2023 11:39:14 +0200 Subject: [PATCH 117/460] ASOC: SOF: Intel: pci-tgl: Fix device description Add the missing ops_free callback. Fixes: 63d375b9f2a9 ("ASoC: SOF: Intel: pci-tgl: use RPL specific firmware definitions") Signed-off-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307093914.25409-5-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/pci-tgl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/sof/intel/pci-tgl.c b/sound/soc/sof/intel/pci-tgl.c index adc7314a1b578..22e769e0831d9 100644 --- a/sound/soc/sof/intel/pci-tgl.c +++ b/sound/soc/sof/intel/pci-tgl.c @@ -239,6 +239,7 @@ static const struct sof_dev_desc rpls_desc = { .nocodec_tplg_filename = "sof-rpl-nocodec.tplg", .ops = &sof_tgl_ops, .ops_init = sof_tgl_ops_init, + .ops_free = hda_ops_free, }; static const struct sof_dev_desc rpl_desc = { @@ -270,6 +271,7 @@ static const struct sof_dev_desc rpl_desc = { .nocodec_tplg_filename = "sof-rpl-nocodec.tplg", .ops = &sof_tgl_ops, .ops_init = sof_tgl_ops_init, + .ops_free = hda_ops_free, }; /* PCI IDs */ From 989a3e4479177d0f4afab8be1960731bc0ffbbd0 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 7 Mar 2023 13:49:17 +0200 Subject: [PATCH 118/460] ASoC: SOF: ipc3: Check for upper size limit for the received message The sof_ipc3_rx_msg() checks for minimum size of a new rx message but it is missing the check for upper limit. Corrupted or compromised firmware might be able to take advantage of this to cause out of bounds reads outside of the message area. Reported-by: Curtis Malainey Signed-off-by: Peter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Curtis Malainey Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307114917.5124-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc3.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/ipc3.c b/sound/soc/sof/ipc3.c index 3de64ea2dc9aa..4493bbd7faf12 100644 --- a/sound/soc/sof/ipc3.c +++ b/sound/soc/sof/ipc3.c @@ -970,8 +970,9 @@ static void sof_ipc3_rx_msg(struct snd_sof_dev *sdev) return; } - if (hdr.size < sizeof(hdr)) { - dev_err(sdev->dev, "The received message size is invalid\n"); + if (hdr.size < sizeof(hdr) || hdr.size > SOF_IPC_MSG_MAX_SIZE) { + dev_err(sdev->dev, "The received message size is invalid: %u\n", + hdr.size); return; } From 9e269e3aa9006440de639597079ee7140ef5b5f3 Mon Sep 17 00:00:00 2001 From: Seppo Ingalsuo Date: Tue, 7 Mar 2023 13:07:51 +0200 Subject: [PATCH 119/460] ASoC: SOF: ipc4-topology: Fix incorrect sample rate print unit This patch fixes the sample rate print unit from KHz to Hz. E.g. 48000KHz becomes 48000Hz. Signed-off-by: Seppo Ingalsuo Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307110751.2053-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index 3e27c7a48ebd3..dc44ba2ec71c2 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -155,7 +155,7 @@ static void sof_ipc4_dbg_audio_format(struct device *dev, for (i = 0; i < num_format; i++, ptr = (u8 *)ptr + object_size) { fmt = ptr; dev_dbg(dev, - " #%d: %uKHz, %ubit (ch_map %#x ch_cfg %u interleaving_style %u fmt_cfg %#x)\n", + " #%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); } From 858a438a6cf919e5727d2a0f5f3f0e68b2d5354e Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 7 Mar 2023 12:07:33 +0200 Subject: [PATCH 120/460] ASoC: Intel: soc-acpi: fix copy-paste issue in topology names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For some reason the convention for topology names was not followed and the name inspired by another unrelated hardware configuration. As a result, the kernel will request a non-existent topology file. Link: https://github.com/thesofproject/sof/pull/6878 Fixes: 2ec8b081d59f ("ASoC: Intel: soc-acpi: Add entry for sof_es8336 in ADL match table") Cc: stable@vger.kernel.org Signed-off-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307100733.15025-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/common/soc-acpi-intel-adl-match.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 56ee5fef66a8b..28dd2046e4ac5 100644 --- a/sound/soc/intel/common/soc-acpi-intel-adl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-adl-match.c @@ -559,7 +559,7 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_machines[] = { { .comp_ids = &essx_83x6, .drv_name = "sof-essx8336", - .sof_tplg_filename = "sof-adl-es83x6", /* the tplg suffix is added at run time */ + .sof_tplg_filename = "sof-adl-es8336", /* the tplg suffix is added at run time */ .tplg_quirk_mask = SND_SOC_ACPI_TPLG_INTEL_SSP_NUMBER | SND_SOC_ACPI_TPLG_INTEL_SSP_MSB | SND_SOC_ACPI_TPLG_INTEL_DMIC_NUMBER, From 6ba8ddf86a3ada463e9952a19b069f978a70a748 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 7 Mar 2023 13:48:15 +0200 Subject: [PATCH 121/460] ASoC: SOF: topology: Fix error handling in sof_widget_ready() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the error paths in sof_widget_ready() to free all allocated memory and prevent memory leaks. Signed-off-by: Ranjani Sridharan Reviewed-by: Péter Ujfalusi Reviewed-by: Bard Liao Reviewed-by: Pierre-Louis Bossart Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307114815.4909-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/topology.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 4a62ccc71fcbf..9f3a038fe21ad 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -1388,14 +1388,15 @@ static int sof_widget_ready(struct snd_soc_component *scomp, int index, if (ret < 0) { dev_err(scomp->dev, "failed to parse component pin tokens for %s\n", w->name); - return ret; + 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); - return -EINVAL; + ret = -EINVAL; + goto widget_free; } if (swidget->num_sink_pins > 1) { @@ -1404,7 +1405,7 @@ static int sof_widget_ready(struct snd_soc_component *scomp, int index, if (ret < 0) { dev_err(scomp->dev, "failed to parse sink pin binding for %s\n", w->name); - return ret; + goto widget_free; } } @@ -1414,7 +1415,7 @@ static int sof_widget_ready(struct snd_soc_component *scomp, int index, if (ret < 0) { dev_err(scomp->dev, "failed to parse source pin binding for %s\n", w->name); - return ret; + goto widget_free; } } @@ -1436,9 +1437,8 @@ static int sof_widget_ready(struct snd_soc_component *scomp, int index, case snd_soc_dapm_dai_out: dai = kzalloc(sizeof(*dai), GFP_KERNEL); if (!dai) { - kfree(swidget); - return -ENOMEM; - + ret = -ENOMEM; + goto widget_free; } ret = sof_widget_parse_tokens(scomp, swidget, tw, token_list, token_list_size); @@ -1496,8 +1496,7 @@ static int sof_widget_ready(struct snd_soc_component *scomp, int index, tw->shift, swidget->id, tw->name, strnlen(tw->sname, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) > 0 ? tw->sname : "none"); - kfree(swidget); - return ret; + goto widget_free; } if (sof_debug_check_flag(SOF_DBG_DISABLE_MULTICORE)) { @@ -1518,10 +1517,7 @@ static int sof_widget_ready(struct snd_soc_component *scomp, int index, if (ret) { dev_err(scomp->dev, "widget event binding failed for %s\n", swidget->widget->name); - kfree(swidget->private); - kfree(swidget->tuples); - kfree(swidget); - return ret; + goto free; } } } @@ -1532,10 +1528,8 @@ static int sof_widget_ready(struct snd_soc_component *scomp, int index, spipe = kzalloc(sizeof(*spipe), GFP_KERNEL); if (!spipe) { - kfree(swidget->private); - kfree(swidget->tuples); - kfree(swidget); - return -ENOMEM; + ret = -ENOMEM; + goto free; } spipe->pipe_widget = swidget; @@ -1546,6 +1540,12 @@ static int sof_widget_ready(struct snd_soc_component *scomp, int index, w->dobj.private = swidget; list_add(&swidget->list, &sdev->widget_list); return ret; +free: + kfree(swidget->private); + kfree(swidget->tuples); +widget_free: + kfree(swidget); + return ret; } static int sof_route_unload(struct snd_soc_component *scomp, From ca09e2a351fbc7836ba9418304ff0c3e72addfe0 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 7 Mar 2023 11:53:41 +0200 Subject: [PATCH 122/460] ASoC: SOF: Intel: pci-tng: revert invalid bar size setting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The logic for the ioremap is to find the resource index 3 (IRAM) and infer the BAR address by subtracting the IRAM offset. The BAR size defined in hardware specifications is 2MB. The commit 5947b2726beb6 ("ASoC: SOF: Intel: Check the bar size before remapping") tried to find the BAR size by querying the resource length instead of a pre-canned value, but by requesting the size for index 3 it only gets the size of the IRAM. That's obviously wrong and prevents the probe from proceeding. This commit attempted to fix an issue in a fuzzing/simulated environment but created another on actual devices, so the best course of action is to revert that change. Reported-by: Ferry Toth Tested-by: Ferry Toth (Intel Edison-Arduino) Link: https://github.com/thesofproject/linux/issues/3901 Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307095341.3222-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/pci-tng.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/sound/soc/sof/intel/pci-tng.c b/sound/soc/sof/intel/pci-tng.c index 5b2b409752c58..8c22a00266c06 100644 --- a/sound/soc/sof/intel/pci-tng.c +++ b/sound/soc/sof/intel/pci-tng.c @@ -75,11 +75,7 @@ static int tangier_pci_probe(struct snd_sof_dev *sdev) /* LPE base */ base = pci_resource_start(pci, desc->resindex_lpe_base) - IRAM_OFFSET; - size = pci_resource_len(pci, desc->resindex_lpe_base); - if (size < PCI_BAR_SIZE) { - dev_err(sdev->dev, "error: I/O region is too small.\n"); - return -ENODEV; - } + size = PCI_BAR_SIZE; dev_dbg(sdev->dev, "LPE PHY base at 0x%x size 0x%x", base, size); sdev->bar[DSP_BAR] = devm_ioremap(sdev->dev, base, size); From b66bfc3a9810caed5d55dd8907110bdc8028b06b Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 7 Mar 2023 13:46:39 +0200 Subject: [PATCH 123/460] ASoC: SOF: sof-audio: Fix broken early bclk feature for SSP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With the removal of widget setup during BE hw_params, the DAI config IPC is never sent with the SOF_DAI_CONFIG_FLAGS_HW_PARAMS. This means that the early bit clock feature required for certain codecs will be broken. Fix this by saving the config flags sent during BE DAI hw_params and reusing it when the DAI_CONFIG IPC is sent after the DAI widget is set up. Also, free the DAI config before the widget is freed. The DAI_CONFIG IPC sent during the sof_widget_free() does not have the DAI index information. So, save the dai_index in the config during hw_params and reuse it during hw_free. For IPC4, do not clear the node ID during hw_free. It will be needed for freeing the group_ida during unprepare. 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/20230307114639.4553-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc3-topology.c | 32 ++++++++++++++++++++++++++++++-- sound/soc/sof/ipc4-topology.c | 15 +++++++++++++-- sound/soc/sof/sof-audio.c | 28 +++++++++++++++++++++++++--- 3 files changed, 68 insertions(+), 7 deletions(-) diff --git a/sound/soc/sof/ipc3-topology.c b/sound/soc/sof/ipc3-topology.c index dceb78bfe17c6..b1f425b39db94 100644 --- a/sound/soc/sof/ipc3-topology.c +++ b/sound/soc/sof/ipc3-topology.c @@ -2081,7 +2081,9 @@ static int sof_ipc3_dai_config(struct snd_sof_dev *sdev, struct snd_sof_widget * break; case SOF_DAI_INTEL_ALH: if (data) { - config->dai_index = data->dai_index; + /* save the dai_index during hw_params and reuse it for hw_free */ + if (flags & SOF_DAI_CONFIG_FLAGS_HW_PARAMS) + config->dai_index = data->dai_index; config->alh.stream_id = data->dai_data; } break; @@ -2089,7 +2091,30 @@ static int sof_ipc3_dai_config(struct snd_sof_dev *sdev, struct snd_sof_widget * break; } - config->flags = flags; + /* + * The dai_config op is invoked several times and the flags argument varies as below: + * BE DAI hw_params: When the op is invoked during the BE DAI hw_params, flags contains + * SOF_DAI_CONFIG_FLAGS_HW_PARAMS along with quirks + * FE DAI hw_params: When invoked during FE DAI hw_params after the DAI widget has + * just been set up in the DSP, flags is set to SOF_DAI_CONFIG_FLAGS_HW_PARAMS with no + * quirks + * BE DAI trigger: When invoked during the BE DAI trigger, flags is set to + * SOF_DAI_CONFIG_FLAGS_PAUSE and contains no quirks + * BE DAI hw_free: When invoked during the BE DAI hw_free, flags is set to + * SOF_DAI_CONFIG_FLAGS_HW_FREE and contains no quirks + * FE DAI hw_free: When invoked during the FE DAI hw_free, flags is set to + * SOF_DAI_CONFIG_FLAGS_HW_FREE and contains no quirks + * + * The DAI_CONFIG IPC is sent to the DSP, only after the widget is set up during the FE + * DAI hw_params. But since the BE DAI hw_params precedes the FE DAI hw_params, the quirks + * need to be preserved when assigning the flags before sending the IPC. + * For the case of PAUSE/HW_FREE, since there are no quirks, flags can be used as is. + */ + + if (flags & SOF_DAI_CONFIG_FLAGS_HW_PARAMS) + config->flags |= flags; + else + config->flags = flags; /* only send the IPC if the widget is set up in the DSP */ if (swidget->use_count > 0) { @@ -2097,6 +2122,9 @@ static int sof_ipc3_dai_config(struct snd_sof_dev *sdev, struct snd_sof_widget * &reply, sizeof(reply)); if (ret < 0) dev_err(sdev->dev, "Failed to set dai config for %s\n", dai->name); + + /* clear the flags once the IPC has been sent even if it fails */ + config->flags = SOF_DAI_CONFIG_FLAGS_NONE; } return ret; diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index dc44ba2ec71c2..ae02cc152f879 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -980,6 +980,7 @@ static void sof_ipc4_unprepare_copier_module(struct snd_sof_widget *swidget) ipc4_copier = dai->private; 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; unsigned int group_id; @@ -989,6 +990,9 @@ static void sof_ipc4_unprepare_copier_module(struct snd_sof_widget *swidget) ALH_MULTI_GTW_BASE; ida_free(&alh_group_ida, group_id); } + + /* clear the node ID */ + copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK; } } @@ -1940,8 +1944,15 @@ static int sof_ipc4_dai_config(struct snd_sof_dev *sdev, struct snd_sof_widget * pipeline->skip_during_fe_trigger = true; fallthrough; case SOF_DAI_INTEL_ALH: - copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK; - copier_data->gtw_cfg.node_id |= SOF_IPC4_NODE_INDEX(data->dai_data); + /* + * Do not clear the node ID when this op is invoked with + * SOF_DAI_CONFIG_FLAGS_HW_FREE. It is needed to free the group_ida during + * unprepare. + */ + if (flags & SOF_DAI_CONFIG_FLAGS_HW_PARAMS) { + copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK; + copier_data->gtw_cfg.node_id |= SOF_IPC4_NODE_INDEX(data->dai_data); + } break; case SOF_DAI_INTEL_DMIC: case SOF_DAI_INTEL_SSP: diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c index 760621bfc8028..d7df29f2ada85 100644 --- a/sound/soc/sof/sof-audio.c +++ b/sound/soc/sof/sof-audio.c @@ -50,9 +50,27 @@ static int sof_widget_free_unlocked(struct snd_sof_dev *sdev, /* reset route setup status for all routes that contain this widget */ sof_reset_route_setup_status(sdev, swidget); + /* free DAI config and continue to free widget even if it fails */ + if (WIDGET_IS_DAI(swidget->id)) { + struct snd_sof_dai_config_data data; + unsigned int flags = SOF_DAI_CONFIG_FLAGS_HW_FREE; + + data.dai_data = DMA_CHAN_INVALID; + + if (tplg_ops && tplg_ops->dai_config) { + err = tplg_ops->dai_config(sdev, swidget, flags, &data); + if (err < 0) + dev_err(sdev->dev, "failed to free config for widget %s\n", + swidget->widget->name); + } + } + /* continue to disable core even if IPC fails */ - if (tplg_ops && tplg_ops->widget_free) - err = tplg_ops->widget_free(sdev, swidget); + if (tplg_ops && tplg_ops->widget_free) { + ret = tplg_ops->widget_free(sdev, swidget); + if (ret < 0 && !err) + err = ret; + } /* * disable widget core. continue to route setup status and complete flag @@ -151,8 +169,12 @@ static int sof_widget_setup_unlocked(struct snd_sof_dev *sdev, /* send config for DAI components */ if (WIDGET_IS_DAI(swidget->id)) { - unsigned int flags = SOF_DAI_CONFIG_FLAGS_NONE; + unsigned int flags = SOF_DAI_CONFIG_FLAGS_HW_PARAMS; + /* + * The config flags saved during BE DAI hw_params will be used for IPC3. IPC4 does + * not use the flags argument. + */ if (tplg_ops && tplg_ops->dai_config) { ret = tplg_ops->dai_config(sdev, swidget, flags, NULL); if (ret < 0) From c99e48f4ce9b986ab7992ec7283a06dae875f668 Mon Sep 17 00:00:00 2001 From: Jaska Uimonen Date: Tue, 7 Mar 2023 13:07:30 +0200 Subject: [PATCH 124/460] ASoC: SOF: ipc4-topology: set dmic dai index from copier MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Dmic dai index was set incorrectly to bits 5-7, when it is actually using just the lowest 3. Fix the macro for setting the bits. Fixes: aa84ffb72158 ("ASoC: SOF: ipc4-topology: Add support for SSP/DMIC DAI's") Signed-off-by: Jaska Uimonen Reviewed-by: Adrian Bonislawski 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/20230307110730.1995-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sof/ipc4-topology.h b/sound/soc/sof/ipc4-topology.h index 72529179ac223..c0e457f7f51ad 100644 --- a/sound/soc/sof/ipc4-topology.h +++ b/sound/soc/sof/ipc4-topology.h @@ -46,7 +46,7 @@ #define SOF_IPC4_NODE_INDEX_INTEL_SSP(x) (((x) & 0xf) << 4) /* Node ID for DMIC type DAI copiers */ -#define SOF_IPC4_NODE_INDEX_INTEL_DMIC(x) (((x) & 0x7) << 5) +#define SOF_IPC4_NODE_INDEX_INTEL_DMIC(x) ((x) & 0x7) #define SOF_IPC4_GAIN_ALL_CHANNELS_MASK 0xffffffff #define SOF_IPC4_VOL_ZERO_DB 0x7fffffff From 52a55779ed14792a150421339664193d6eb8e036 Mon Sep 17 00:00:00 2001 From: Rander Wang Date: Tue, 7 Mar 2023 11:54:52 +0200 Subject: [PATCH 125/460] ASoC: SOF: Intel: hda-dsp: harden D0i3 programming sequence MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add delay between set and wait command according to hardware programming sequence. Also add debug log to detect error. Signed-off-by: Rander Wang Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307095453.3719-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dsp.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index 68eb06f13a1fd..a6f2822401e03 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -392,6 +392,12 @@ static int hda_dsp_update_d0i3c_register(struct snd_sof_dev *sdev, u8 value) snd_sof_dsp_update8(sdev, HDA_DSP_HDA_BAR, chip->d0i3_offset, SOF_HDA_VS_D0I3C_I3, value); + /* + * The value written to the D0I3C::I3 bit may not be taken into account immediately. + * A delay is recommended before checking if D0I3C::CIP is cleared + */ + usleep_range(30, 40); + /* Wait for cmd in progress to be cleared before exiting the function */ ret = hda_dsp_wait_d0i3c_done(sdev); if (ret < 0) { @@ -400,6 +406,12 @@ static int hda_dsp_update_d0i3c_register(struct snd_sof_dev *sdev, u8 value) } reg = snd_sof_dsp_read8(sdev, HDA_DSP_HDA_BAR, chip->d0i3_offset); + /* Confirm d0i3 state changed with paranoia check */ + if ((reg ^ value) & SOF_HDA_VS_D0I3C_I3) { + dev_err(sdev->dev, "failed to update D0I3C!\n"); + return -EIO; + } + trace_sof_intel_D0I3C_updated(sdev, reg); return 0; From 8bac40b8ed17ab1be9133e9620f65fae80262b7e Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 7 Mar 2023 11:54:12 +0200 Subject: [PATCH 126/460] ASoC: SOF: Intel: hda-ctrl: re-add sleep after entering and exiting reset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit a09d82ce0a867 ("ASoC: SOF: Intel: hda-ctrl: remove useless sleep") It was a mistake to remove those delays, in light of comments in the HDaudio spec captured in snd_hdac_bus_reset_link() that the codec needs time for its initialization and PLL lock. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Péter Ujfalusi Reviewed-by: Rander Wang Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307095412.3416-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-ctrl.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/sof/intel/hda-ctrl.c b/sound/soc/sof/intel/hda-ctrl.c index 3aea36c077c9d..f3bdeba284122 100644 --- a/sound/soc/sof/intel/hda-ctrl.c +++ b/sound/soc/sof/intel/hda-ctrl.c @@ -196,12 +196,15 @@ int hda_dsp_ctrl_init_chip(struct snd_sof_dev *sdev) goto err; } + usleep_range(500, 1000); + /* exit HDA controller reset */ ret = hda_dsp_ctrl_link_reset(sdev, false); if (ret < 0) { dev_err(sdev->dev, "error: failed to exit HDA controller reset\n"); goto err; } + usleep_range(1000, 1200); hda_codec_detect_mask(sdev); From c7e328f1cbf22efe23bc3cd7dd6bb14efccc28d0 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 7 Mar 2023 13:46:59 +0200 Subject: [PATCH 127/460] ASoC: SOF: sof-audio: don't squelch errors in WIDGET_SETUP phase When an IPC error happens while setting-up a widget during the FE hw_params phase, the existing logic will unwind all previous configurations but will overwrite the return status. The ALSA/ASoC logic will then proceed with the prepare and trigger phases, even though the firmware resources are not available. Fix by returning the initial error code and ignoring the code returned in the UNPREPARE phase. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Chao Song Reviewed-by: Bard Liao Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307114659.4614-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/sof-audio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c index d7df29f2ada85..6de388a8d0b8d 100644 --- a/sound/soc/sof/sof-audio.c +++ b/sound/soc/sof/sof-audio.c @@ -610,8 +610,8 @@ int sof_widget_list_setup(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm, ret = sof_walk_widgets_in_order(sdev, spcm, fe_params, platform_params, dir, SOF_WIDGET_SETUP); if (ret < 0) { - ret = sof_walk_widgets_in_order(sdev, spcm, fe_params, platform_params, - dir, SOF_WIDGET_UNPREPARE); + sof_walk_widgets_in_order(sdev, spcm, fe_params, platform_params, + dir, SOF_WIDGET_UNPREPARE); return ret; } From e45cd86c3a78bfb9875a5eb8ab5dab459b59bbe2 Mon Sep 17 00:00:00 2001 From: Rander Wang Date: Tue, 7 Mar 2023 13:06:56 +0200 Subject: [PATCH 128/460] ASoC: SOF: IPC4: update gain ipc msg definition to align with fw MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Recent firmware changes modified the curve duration from 32 to 64 bits, which breaks volume ramps. A simple solution would be to change the definition, but unfortunately the ASoC topology framework only supports up to 32 bit tokens. This patch suggests breaking the 64 bit value in low and high parts, with only the low-part extracted from topology and high-part only zeroes. Since the curve duration is represented in hundred of nanoseconds, we can still represent a 400s ramp, which is just fine. The defacto ABI change has no effect on existing users since the IPC4 firmware has not been released just yet. Link: https://github.com/thesofproject/linux/issues/4026 Signed-off-by: Rander Wang Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307110656.1816-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-control.c | 3 ++- sound/soc/sof/ipc4-topology.c | 4 ++-- sound/soc/sof/ipc4-topology.h | 6 ++++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/sound/soc/sof/ipc4-control.c b/sound/soc/sof/ipc4-control.c index 67bd2233fd9a6..9a71af1a613ac 100644 --- a/sound/soc/sof/ipc4-control.c +++ b/sound/soc/sof/ipc4-control.c @@ -97,7 +97,8 @@ sof_ipc4_set_volume_data(struct snd_sof_dev *sdev, struct snd_sof_widget *swidge } /* set curve type and duration from topology */ - data.curve_duration = gain->data.curve_duration; + data.curve_duration_l = gain->data.curve_duration_l; + data.curve_duration_h = gain->data.curve_duration_h; data.curve_type = gain->data.curve_type; msg->data_ptr = &data; diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index ae02cc152f879..a623707c8ffc7 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -107,7 +107,7 @@ static const struct sof_topology_token gain_tokens[] = { get_token_u32, offsetof(struct sof_ipc4_gain_data, curve_type)}, {SOF_TKN_GAIN_RAMP_DURATION, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, - offsetof(struct sof_ipc4_gain_data, curve_duration)}, + offsetof(struct sof_ipc4_gain_data, curve_duration_l)}, {SOF_TKN_GAIN_VAL, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, offsetof(struct sof_ipc4_gain_data, init_val)}, }; @@ -692,7 +692,7 @@ static int sof_ipc4_widget_setup_comp_pga(struct snd_sof_widget *swidget) dev_dbg(scomp->dev, "pga widget %s: ramp type: %d, ramp duration %d, initial gain value: %#x, cpc %d\n", - swidget->widget->name, gain->data.curve_type, gain->data.curve_duration, + swidget->widget->name, gain->data.curve_type, gain->data.curve_duration_l, gain->data.init_val, gain->base_config.cpc); ret = sof_ipc4_widget_setup_msg(swidget, &gain->msg); diff --git a/sound/soc/sof/ipc4-topology.h b/sound/soc/sof/ipc4-topology.h index c0e457f7f51ad..123f1096f3261 100644 --- a/sound/soc/sof/ipc4-topology.h +++ b/sound/soc/sof/ipc4-topology.h @@ -277,14 +277,16 @@ struct sof_ipc4_control_data { * @init_val: Initial value * @curve_type: Curve type * @reserved: reserved for future use - * @curve_duration: Curve duration + * @curve_duration_l: Curve duration low part + * @curve_duration_h: Curve duration high part */ struct sof_ipc4_gain_data { uint32_t channels; uint32_t init_val; uint32_t curve_type; uint32_t reserved; - uint32_t curve_duration; + uint32_t curve_duration_l; + uint32_t curve_duration_h; } __aligned(8); /** From 428913bce1e67ccb4dae317fd0332545bf8c9233 Mon Sep 17 00:00:00 2001 From: Yu Kuai Date: Tue, 7 Mar 2023 18:55:52 +0800 Subject: [PATCH 129/460] 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 3ee5577e15860..02d9cfb9e077a 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 fd9a2e1d513823e840960cb3bc26d8b7749d4ac2 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Mon, 6 Mar 2023 10:43:47 -0500 Subject: [PATCH 130/460] 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 21d5209f6e041..ba34a31a7c702 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 c22f2ff8724b49dce2ae797e9fbf4bc0fa91112f Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 6 Mar 2023 11:32:42 +0100 Subject: [PATCH 131/460] drm/sun4i: fix missing component unbind on bind errors Make sure to unbind all subcomponents when binding the aggregate device fails. Fixes: 9026e0d122ac ("drm: Add Allwinner A10 Display Engine support") Cc: stable@vger.kernel.org # 4.7 Cc: Maxime Ripard Signed-off-by: Johan Hovold Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20230306103242.4775-1-johan+linaro@kernel.org --- drivers/gpu/drm/sun4i/sun4i_drv.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c index cc94efbbf2d4e..d6c741716167a 100644 --- a/drivers/gpu/drm/sun4i/sun4i_drv.c +++ b/drivers/gpu/drm/sun4i/sun4i_drv.c @@ -95,12 +95,12 @@ static int sun4i_drv_bind(struct device *dev) /* drm_vblank_init calls kcalloc, which can fail */ ret = drm_vblank_init(drm, drm->mode_config.num_crtc); if (ret) - goto cleanup_mode_config; + goto unbind_all; /* Remove early framebuffers (ie. simplefb) */ ret = drm_aperture_remove_framebuffers(false, &sun4i_drv_driver); if (ret) - goto cleanup_mode_config; + goto unbind_all; sun4i_framebuffer_init(drm); @@ -119,6 +119,8 @@ static int sun4i_drv_bind(struct device *dev) finish_poll: drm_kms_helper_poll_fini(drm); +unbind_all: + component_unbind_all(dev, NULL); cleanup_mode_config: drm_mode_config_cleanup(drm); of_reserved_mem_device_release(dev); From 5d89176af1ae201c01c10a89b68b27cfc683b76c Mon Sep 17 00:00:00 2001 From: Song Shuai Date: Mon, 27 Feb 2023 18:59:41 +0800 Subject: [PATCH 132/460] sched/doc: supplement CPU capacity with RISC-V This commit 7d2078310cbf ("dt-bindings: arm: move cpu-capacity to a shared loation") updates some references about capacity-dmips-mhz property in this document. The list of architectures using capacity-dmips-mhz omits RISC-V, so supplements it here. Signed-off-by: Song Shuai Reviewed-by: Palmer Dabbelt # English Acked-by: Palmer Dabbelt Reviewed-by: Alex Shi Reviewed-by: Conor Dooley Link: https://lore.kernel.org/r/20230227105941.2749193-1-suagrfillet@gmail.com Signed-off-by: Jonathan Corbet --- Documentation/scheduler/sched-capacity.rst | 2 +- Documentation/translations/zh_CN/scheduler/sched-capacity.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/scheduler/sched-capacity.rst b/Documentation/scheduler/sched-capacity.rst index 8e2b8538bc2b7..e2c1cf7431588 100644 --- a/Documentation/scheduler/sched-capacity.rst +++ b/Documentation/scheduler/sched-capacity.rst @@ -258,7 +258,7 @@ Linux cannot currently figure out CPU capacity on its own, this information thus needs to be handed to it. Architectures must define arch_scale_cpu_capacity() for that purpose. -The arm and arm64 architectures directly map this to the arch_topology driver +The arm, arm64, and RISC-V architectures directly map this to the arch_topology driver CPU scaling data, which is derived from the capacity-dmips-mhz CPU binding; see Documentation/devicetree/bindings/cpu/cpu-capacity.txt. diff --git a/Documentation/translations/zh_CN/scheduler/sched-capacity.rst b/Documentation/translations/zh_CN/scheduler/sched-capacity.rst index e07ffdd391d32..8cba135dcd1a6 100644 --- a/Documentation/translations/zh_CN/scheduler/sched-capacity.rst +++ b/Documentation/translations/zh_CN/scheduler/sched-capacity.rst @@ -231,7 +231,7 @@ CFS调度类基于实体负载跟踪机制(Per-Entity Load Tracking, PELT) 当前,Linux无法凭自身算出CPU算力,因此必须要有把这个信息传递给Linux的方式。每个架构必须为此 定义arch_scale_cpu_capacity()函数。 -arm和arm64架构直接把这个信息映射到arch_topology驱动的CPU scaling数据中(译注:参考 +arm、arm64和RISC-V架构直接把这个信息映射到arch_topology驱动的CPU scaling数据中(译注:参考 arch_topology.h的percpu变量cpu_scale),它是从capacity-dmips-mhz CPU binding中衍生计算 出来的。参见Documentation/devicetree/bindings/cpu/cpu-capacity.txt。 From 74596085796fae0cfce3e42ee46bf4f8acbdac55 Mon Sep 17 00:00:00 2001 From: Glenn Washburn Date: Mon, 27 Feb 2023 12:40:42 -0600 Subject: [PATCH 133/460] docs: Correct missing "d_" prefix for dentry_operations member d_weak_revalidate The details for struct dentry_operations member d_weak_revalidate is missing a "d_" prefix. Fixes: af96c1e304f7 ("docs: filesystems: vfs: Convert vfs.txt to RST") Signed-off-by: Glenn Washburn Reviewed-by: Matthew Wilcox (Oracle) Link: https://lore.kernel.org/r/20230227184042.2375235-1-development@efficientek.com Signed-off-by: Jonathan Corbet --- Documentation/filesystems/vfs.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/filesystems/vfs.rst b/Documentation/filesystems/vfs.rst index c53f30251a660..f3b344f0c0a4b 100644 --- a/Documentation/filesystems/vfs.rst +++ b/Documentation/filesystems/vfs.rst @@ -1222,7 +1222,7 @@ defined: return -ECHILD and it will be called again in ref-walk mode. -``_weak_revalidate`` +``d_weak_revalidate`` called when the VFS needs to revalidate a "jumped" dentry. This is called when a path-walk ends at dentry that was not acquired by doing a lookup in the parent directory. This includes "/", From 38484a1d0c50596c8080a00c269466f60fa4a051 Mon Sep 17 00:00:00 2001 From: Miguel Ojeda Date: Mon, 6 Mar 2023 20:17:11 +0100 Subject: [PATCH 134/460] docs: programming-language: remove mention of the Intel compiler The Intel compiler support has been removed in commit 95207db8166a ("Remove Intel compiler support"). Thus remove its mention in the Documentation too. Signed-off-by: Miguel Ojeda Reviewed-by: Vincenzo Palazzo Reviewed-by: Nick Desaulniers Link: https://lore.kernel.org/r/20230306191712.230658-1-ojeda@kernel.org Signed-off-by: Jonathan Corbet --- Documentation/process/programming-language.rst | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Documentation/process/programming-language.rst b/Documentation/process/programming-language.rst index 5fc9160ca1fa5..10dc772671d84 100644 --- a/Documentation/process/programming-language.rst +++ b/Documentation/process/programming-language.rst @@ -12,10 +12,6 @@ under ``-std=gnu11`` [gcc-c-dialect-options]_: the GNU dialect of ISO C11. This dialect contains many extensions to the language [gnu-extensions]_, and many of them are used within the kernel as a matter of course. -There is some support for compiling the kernel with ``icc`` [icc]_ for several -of the architectures, although at the time of writing it is not completed, -requiring third-party patches. - Attributes ---------- @@ -38,7 +34,6 @@ Please refer to ``include/linux/compiler_attributes.h`` for more information. .. [c-language] http://www.open-std.org/jtc1/sc22/wg14/www/standards .. [gcc] https://gcc.gnu.org .. [clang] https://clang.llvm.org -.. [icc] https://software.intel.com/en-us/c-compilers .. [gcc-c-dialect-options] https://gcc.gnu.org/onlinedocs/gcc/C-Dialect-Options.html .. [gnu-extensions] https://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html .. [gcc-attribute-syntax] https://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html From 0b02076f995332fe1e457da29dd61c3b66c862f7 Mon Sep 17 00:00:00 2001 From: Miguel Ojeda Date: Mon, 6 Mar 2023 20:17:12 +0100 Subject: [PATCH 135/460] docs: programming-language: add Rust programming language section Following the C text in the file, add a mention about the Rust programming language, the currently supported compiler and the edition used (similar to the "dialect" mention for C). Similarly, add a mention about the unstable features used (similar to the "extensions" mentions for C). In addition, add some links to complement the information. Signed-off-by: Miguel Ojeda Link: https://lore.kernel.org/r/20230306191712.230658-2-ojeda@kernel.org Signed-off-by: Jonathan Corbet --- .../process/programming-language.rst | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/Documentation/process/programming-language.rst b/Documentation/process/programming-language.rst index 10dc772671d84..bc56dee6d0bcb 100644 --- a/Documentation/process/programming-language.rst +++ b/Documentation/process/programming-language.rst @@ -31,6 +31,20 @@ in order to feature detect which ones can be used and/or to shorten the code. Please refer to ``include/linux/compiler_attributes.h`` for more information. +Rust +---- + +The kernel has experimental support for the Rust programming language +[rust-language]_ under ``CONFIG_RUST``. It is compiled with ``rustc`` [rustc]_ +under ``--edition=2021`` [rust-editions]_. Editions are a way to introduce +small changes to the language that are not backwards compatible. + +On top of that, some unstable features [rust-unstable-features]_ are used in +the kernel. Unstable features may change in the future, thus it is an important +goal to reach a point where only stable features are used. + +Please refer to Documentation/rust/index.rst for more information. + .. [c-language] http://www.open-std.org/jtc1/sc22/wg14/www/standards .. [gcc] https://gcc.gnu.org .. [clang] https://clang.llvm.org @@ -38,4 +52,7 @@ Please refer to ``include/linux/compiler_attributes.h`` for more information. .. [gnu-extensions] https://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html .. [gcc-attribute-syntax] https://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html .. [n2049] http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2049.pdf - +.. [rust-language] https://www.rust-lang.org +.. [rustc] https://doc.rust-lang.org/rustc/ +.. [rust-editions] https://doc.rust-lang.org/edition-guide/editions/ +.. [rust-unstable-features] https://github.com/Rust-for-Linux/linux/issues/2 From a414684e3b735a4114c19295a07e8cb2eb889dae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Tue, 28 Feb 2023 14:46:57 +0100 Subject: [PATCH 136/460] docs: rebasing-and-merging: Drop wrong statement about git MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The "^0" syntax is no longer needed to fast-forward to a mainline commit; take that out and add --ff-only to force an error if fast-forward is not possible. Signed-off-by: Uwe Kleine-König [jc: rewrote changelog] Link: https://lore.kernel.org/r/20230228134657.1797871-1-u.kleine-koenig@pengutronix.de Signed-off-by: Jonathan Corbet --- Documentation/maintainer/rebasing-and-merging.rst | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Documentation/maintainer/rebasing-and-merging.rst b/Documentation/maintainer/rebasing-and-merging.rst index 09f988e7fa719..85800ce95ae5f 100644 --- a/Documentation/maintainer/rebasing-and-merging.rst +++ b/Documentation/maintainer/rebasing-and-merging.rst @@ -213,11 +213,7 @@ point rather than some random spot. If your upstream-bound branch has emptied entirely into the mainline during the merge window, you can pull it forward with a command like:: - git merge v5.2-rc1^0 - -The "^0" will cause Git to do a fast-forward merge (which should be -possible in this situation), thus avoiding the addition of a spurious merge -commit. + git merge --ff-only v5.2-rc1 The guidelines laid out above are just that: guidelines. There will always be situations that call out for a different solution, and these guidelines From 9a9a8fe26751334b7739193a94eba741073b8a55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Hellstr=C3=B6m?= Date: Tue, 7 Mar 2023 15:46:15 +0100 Subject: [PATCH 137/460] drm/ttm: Fix a NULL pointer dereference MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The LRU mechanism may look up a resource in the process of being removed from an object. The locking rules here are a bit unclear but it looks currently like res->bo assignment is protected by the LRU lock, whereas bo->resource is protected by the object lock, while *clearing* of bo->resource is also protected by the LRU lock. This means that if we check that bo->resource points to the LRU resource under the LRU lock we should be safe. So perform that check before deciding to swap out a bo. That avoids dereferencing a NULL bo->resource in ttm_bo_swapout(). Fixes: 6a9b02899402 ("drm/ttm: move the LRU into resource handling v4") Cc: Christian König Cc: Daniel Vetter Cc: Christian Koenig Cc: Huang Rui Cc: Alex Deucher Cc: Felix Kuehling Cc: Philip Yang Cc: Qiang Yu Cc: Matthew Auld Cc: Nirmoy Das Cc: Tvrtko Ursulin Cc: "Thomas Hellström" Cc: Anshuman Gupta Cc: Arunpravin Paneer Selvam Cc: dri-devel@lists.freedesktop.org Cc: # v5.19+ Signed-off-by: Thomas Hellström Reviewed-by: Christian König Link: https://patchwork.freedesktop.org/patch/msgid/20230307144621.10748-2-thomas.hellstrom@linux.intel.com --- drivers/gpu/drm/ttm/ttm_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/ttm/ttm_device.c b/drivers/gpu/drm/ttm/ttm_device.c index e7147e3046378..b84f74807ca13 100644 --- a/drivers/gpu/drm/ttm/ttm_device.c +++ b/drivers/gpu/drm/ttm/ttm_device.c @@ -158,7 +158,7 @@ int ttm_device_swapout(struct ttm_device *bdev, struct ttm_operation_ctx *ctx, struct ttm_buffer_object *bo = res->bo; uint32_t num_pages; - if (!bo) + if (!bo || bo->resource != res) continue; num_pages = PFN_UP(bo->base.size); From 3b80a03d455143cc9135dac86722bbdd079daff3 Mon Sep 17 00:00:00 2001 From: "Mike Rapoport (IBM)" Date: Fri, 24 Feb 2023 12:03:05 +0200 Subject: [PATCH 138/460] docs/mm: Physical Memory: fix a reference to a file that doesn't exist kbuild reports: >> Warning: Documentation/mm/physical_memory.rst references a file that doesn't exist: Documentation/admin-guide/mm/memory_hotplug.rst Fix the filename to be 'Documentation/admin-guide/mm/memory-hotplug.rst'. Reported-by: kernel test robot Link: https://lore.kernel.org/oe-kbuild-all/202302231311.567PAoS2-lkp@intel.com/ Fixes: 353c7dd636ed ("docs/mm: Physical Memory: remove useless markup") Signed-off-by: Mike Rapoport (IBM) Link: https://lore.kernel.org/r/20230224100306.2287696-1-rppt@kernel.org Signed-off-by: Jonathan Corbet --- Documentation/mm/physical_memory.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/mm/physical_memory.rst b/Documentation/mm/physical_memory.rst index f9d7ea4b9dca7..1bc888d36ea13 100644 --- a/Documentation/mm/physical_memory.rst +++ b/Documentation/mm/physical_memory.rst @@ -66,7 +66,7 @@ one of the types described below. also populated on boot using one of ``kernelcore``, ``movablecore`` and ``movable_node`` kernel command line parameters. See Documentation/mm/page_migration.rst and - Documentation/admin-guide/mm/memory_hotplug.rst for additional details. + Documentation/admin-guide/mm/memory-hotplug.rst for additional details. * ``ZONE_DEVICE`` represents memory residing on devices such as PMEM and GPU. It has different characteristics than RAM zone types and it exists to provide From 87eae260995577d203a70d72d46976521a5687e1 Mon Sep 17 00:00:00 2001 From: "Mike Rapoport (IBM)" Date: Fri, 24 Feb 2023 12:03:06 +0200 Subject: [PATCH 139/460] docs/mm: hugetlbfs_reserv: fix a reference to a file that doesn't exist kbuild reports: >> Warning: Documentation/mm/hugetlbfs_reserv.rst references a file that doesn't exist: Documentation/mm/hugetlbpage.rst >> Warning: Documentation/translations/zh_CN/mm/hugetlbfs_reserv.rst references a file that doesn't exist: Documentation/mm/hugetlbpage.rst Fix the filename to be 'Documentation/admin-guide/mm/hugetlbpage.rst'. Reported-by: kernel test robot Link: https://lore.kernel.org/oe-kbuild-all/202302231854.sKlCmx9K-lkp@intel.com/ Fixes: ee86588960e2 ("docs/mm: remove useless markup") Signed-off-by: Mike Rapoport (IBM) Link: https://lore.kernel.org/r/20230224100306.2287696-2-rppt@kernel.org Signed-off-by: Jonathan Corbet --- Documentation/mm/hugetlbfs_reserv.rst | 8 ++++---- Documentation/translations/zh_CN/mm/hugetlbfs_reserv.rst | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Documentation/mm/hugetlbfs_reserv.rst b/Documentation/mm/hugetlbfs_reserv.rst index 3d05d64de9b46..d9c2b0f01dcd0 100644 --- a/Documentation/mm/hugetlbfs_reserv.rst +++ b/Documentation/mm/hugetlbfs_reserv.rst @@ -5,10 +5,10 @@ Hugetlbfs Reservation Overview ======== -Huge pages as described at Documentation/mm/hugetlbpage.rst are typically -preallocated for application use. These huge pages are instantiated in a -task's address space at page fault time if the VMA indicates huge pages are -to be used. If no huge page exists at page fault time, the task is sent +Huge pages as described at Documentation/admin-guide/mm/hugetlbpage.rst are +typically preallocated for application use. These huge pages are instantiated +in a task's address space at page fault time if the VMA indicates huge pages +are to be used. If no huge page exists at page fault time, the task is sent a SIGBUS and often dies an unhappy death. Shortly after huge page support was added, it was determined that it would be better to detect a shortage of huge pages at mmap() time. The idea is that if there were not enough diff --git a/Documentation/translations/zh_CN/mm/hugetlbfs_reserv.rst b/Documentation/translations/zh_CN/mm/hugetlbfs_reserv.rst index c1fa35315d8b2..b7a0544224ad1 100644 --- a/Documentation/translations/zh_CN/mm/hugetlbfs_reserv.rst +++ b/Documentation/translations/zh_CN/mm/hugetlbfs_reserv.rst @@ -15,7 +15,8 @@ Hugetlbfs 预留 概述 ==== -Documentation/mm/hugetlbpage.rst 中描述的巨页通常是预先分配给应用程序使用的。如果VMA指 +Documentation/admin-guide/mm/hugetlbpage.rst +中描述的巨页通常是预先分配给应用程序使用的 。如果VMA指 示要使用巨页,这些巨页会在缺页异常时被实例化到任务的地址空间。如果在缺页异常 时没有巨页存在,任务就会被发送一个SIGBUS,并经常不高兴地死去。在加入巨页支 持后不久,人们决定,在mmap()时检测巨页的短缺情况会更好。这个想法是,如果 From bf89b7ee52af5a5944fa3539e86089f72475055b Mon Sep 17 00:00:00 2001 From: Conor Dooley Date: Thu, 2 Mar 2023 17:41:55 +0000 Subject: [PATCH 140/460] 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 da55cb247e894..31d2ebea4286e 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 141/460] 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 0264abe552788..faf5e9efa7d33 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 142/460] 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 5457c02ca1abc..fed41800fea73 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 143/460] 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 b719852daa071..1a3cb53d2e0d0 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 f2bf979af5883..36e19336f3b34 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 85e0afc3d4f7f..af7b3ba1ca000 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 25eaf4af5fcf4..c6dfd433fec7b 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 144/460] 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 923a9fb3c8873..27448ffe60a43 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 145/460] 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 24715ca2fa944..01383aac6b419 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 e33062213ff2f9151e0d125e1c00f524c2b7acfe Mon Sep 17 00:00:00 2001 From: Sagi Grimberg Date: Fri, 3 Mar 2023 10:43:23 +0200 Subject: [PATCH 146/460] 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 ac1e519272aa2..282de3680367d 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 147/460] 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 0eec3084fb006..0ef8b8926bfa7 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 63cf584203f3367c8b073d417c8e5cbbfc450506 Mon Sep 17 00:00:00 2001 From: James Houghton Date: Thu, 2 Mar 2023 22:24:04 +0000 Subject: [PATCH 148/460] mm: teach mincore_hugetlb about pte markers By checking huge_pte_none(), we incorrectly classify PTE markers as "present". Instead, check huge_pte_none_mostly(), classifying PTE markers the same as if the PTE were completely blank. PTE markers, unlike other kinds of swap entries, don't reference any physical page and don't indicate that a physical page was mapped previously. As such, treat them as non-present for the sake of mincore(). Link: https://lkml.kernel.org/r/20230302222404.175303-1-jthoughton@google.com Fixes: 5c041f5d1f23 ("mm: teach core mm about pte markers") Signed-off-by: James Houghton Acked-by: Peter Xu Acked-by: David Hildenbrand Cc: Axel Rasmussen Cc: James Houghton Cc: Signed-off-by: Andrew Morton --- mm/mincore.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/mincore.c b/mm/mincore.c index cd69b9db00812..d359650b0f75b 100644 --- a/mm/mincore.c +++ b/mm/mincore.c @@ -33,7 +33,7 @@ static int mincore_hugetlb(pte_t *pte, unsigned long hmask, unsigned long addr, * Hugepages under user process are always in RAM and never * swapped out, but theoretically it needs to be checked. */ - present = pte && !huge_pte_none(huge_ptep_get(pte)); + present = pte && !huge_pte_none_mostly(huge_ptep_get(pte)); for (; addr != end; vec++, addr += PAGE_SIZE) *vec = present; walk->private = vec; From 42b2af2c9b7eede8ef21d0943f84d135e21a32a3 Mon Sep 17 00:00:00 2001 From: David Hildenbrand Date: Thu, 2 Mar 2023 18:54:23 +0100 Subject: [PATCH 149/460] mm/userfaultfd: propagate uffd-wp bit when PTE-mapping the huge zeropage Currently, we'd lose the userfaultfd-wp marker when PTE-mapping a huge zeropage, resulting in the next write faults in the PMD range not triggering uffd-wp events. Various actions (partial MADV_DONTNEED, partial mremap, partial munmap, partial mprotect) could trigger this. However, most importantly, un-protecting a single sub-page from the userfaultfd-wp handler when processing a uffd-wp event will PTE-map the shared huge zeropage and lose the uffd-wp bit for the remainder of the PMD. Let's properly propagate the uffd-wp bit to the PMDs. #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include static size_t pagesize; static int uffd; static volatile bool uffd_triggered; #define barrier() __asm__ __volatile__("": : :"memory") static void uffd_wp_range(char *start, size_t size, bool wp) { struct uffdio_writeprotect uffd_writeprotect; uffd_writeprotect.range.start = (unsigned long) start; uffd_writeprotect.range.len = size; if (wp) { uffd_writeprotect.mode = UFFDIO_WRITEPROTECT_MODE_WP; } else { uffd_writeprotect.mode = 0; } if (ioctl(uffd, UFFDIO_WRITEPROTECT, &uffd_writeprotect)) { fprintf(stderr, "UFFDIO_WRITEPROTECT failed: %d\n", errno); exit(1); } } static void *uffd_thread_fn(void *arg) { static struct uffd_msg msg; ssize_t nread; while (1) { struct pollfd pollfd; int nready; pollfd.fd = uffd; pollfd.events = POLLIN; nready = poll(&pollfd, 1, -1); if (nready == -1) { fprintf(stderr, "poll() failed: %d\n", errno); exit(1); } nread = read(uffd, &msg, sizeof(msg)); if (nread <= 0) continue; if (msg.event != UFFD_EVENT_PAGEFAULT || !(msg.arg.pagefault.flags & UFFD_PAGEFAULT_FLAG_WP)) { printf("FAIL: wrong uffd-wp event fired\n"); exit(1); } /* un-protect the single page. */ uffd_triggered = true; uffd_wp_range((char *)(uintptr_t)msg.arg.pagefault.address, pagesize, false); } return arg; } static int setup_uffd(char *map, size_t size) { struct uffdio_api uffdio_api; struct uffdio_register uffdio_register; pthread_t thread; uffd = syscall(__NR_userfaultfd, O_CLOEXEC | O_NONBLOCK | UFFD_USER_MODE_ONLY); if (uffd < 0) { fprintf(stderr, "syscall() failed: %d\n", errno); return -errno; } uffdio_api.api = UFFD_API; uffdio_api.features = UFFD_FEATURE_PAGEFAULT_FLAG_WP; if (ioctl(uffd, UFFDIO_API, &uffdio_api) < 0) { fprintf(stderr, "UFFDIO_API failed: %d\n", errno); return -errno; } if (!(uffdio_api.features & UFFD_FEATURE_PAGEFAULT_FLAG_WP)) { fprintf(stderr, "UFFD_FEATURE_WRITEPROTECT missing\n"); return -ENOSYS; } uffdio_register.range.start = (unsigned long) map; uffdio_register.range.len = size; uffdio_register.mode = UFFDIO_REGISTER_MODE_WP; if (ioctl(uffd, UFFDIO_REGISTER, &uffdio_register) < 0) { fprintf(stderr, "UFFDIO_REGISTER failed: %d\n", errno); return -errno; } pthread_create(&thread, NULL, uffd_thread_fn, NULL); return 0; } int main(void) { const size_t size = 4 * 1024 * 1024ull; char *map, *cur; pagesize = getpagesize(); map = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0); if (map == MAP_FAILED) { fprintf(stderr, "mmap() failed\n"); return -errno; } if (madvise(map, size, MADV_HUGEPAGE)) { fprintf(stderr, "MADV_HUGEPAGE failed\n"); return -errno; } if (setup_uffd(map, size)) return 1; /* Read the whole range, populating zeropages. */ madvise(map, size, MADV_POPULATE_READ); /* Write-protect the whole range. */ uffd_wp_range(map, size, true); /* Make sure uffd-wp triggers on each page. */ for (cur = map; cur < map + size; cur += pagesize) { uffd_triggered = false; barrier(); /* Trigger a write fault. */ *cur = 1; barrier(); if (!uffd_triggered) { printf("FAIL: uffd-wp did not trigger\n"); return 1; } } printf("PASS: uffd-wp triggered\n"); return 0; } Link: https://lkml.kernel.org/r/20230302175423.589164-1-david@redhat.com Fixes: e06f1e1dd499 ("userfaultfd: wp: enabled write protection in userfaultfd API") Signed-off-by: David Hildenbrand Acked-by: Peter Xu Cc: Mike Rapoport Cc: Andrea Arcangeli Cc: Jerome Glisse Cc: Shaohua Li Cc: Signed-off-by: Andrew Morton --- mm/huge_memory.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 4fc43859e59a3..032fb0ef9cd19 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -2037,7 +2037,7 @@ static void __split_huge_zero_page_pmd(struct vm_area_struct *vma, { struct mm_struct *mm = vma->vm_mm; pgtable_t pgtable; - pmd_t _pmd; + pmd_t _pmd, old_pmd; int i; /* @@ -2048,7 +2048,7 @@ static void __split_huge_zero_page_pmd(struct vm_area_struct *vma, * * See Documentation/mm/mmu_notifier.rst */ - pmdp_huge_clear_flush(vma, haddr, pmd); + old_pmd = pmdp_huge_clear_flush(vma, haddr, pmd); pgtable = pgtable_trans_huge_withdraw(mm, pmd); pmd_populate(mm, &_pmd, pgtable); @@ -2057,6 +2057,8 @@ static void __split_huge_zero_page_pmd(struct vm_area_struct *vma, pte_t *pte, entry; entry = pfn_pte(my_zero_pfn(haddr), vma->vm_page_prot); entry = pte_mkspecial(entry); + if (pmd_uffd_wp(old_pmd)) + entry = pte_mkuffd_wp(entry); pte = pte_offset_map(&_pmd, haddr); VM_BUG_ON(!pte_none(*pte)); set_pte_at(mm, haddr, pte, entry); From af665b40dfa2b49f1e3e11ecd1096506ef40348d Mon Sep 17 00:00:00 2001 From: Jarkko Sakkinen Date: Thu, 2 Mar 2023 01:54:42 +0200 Subject: [PATCH 150/460] mailmap: updates for Jarkko Sakkinen Update to my current employer: https://research.tuni.fi/nisec/ Link: https://lkml.kernel.org/r/20230301235443.6663-1-jarkko@kernel.org Signed-off-by: Jarkko Sakkinen Cc: Arnd Bergmann Cc: Baolin Wang Cc: Ben Widawsky Cc: Bjorn Andersson Cc: Colin Ian King Cc: Kirill Tkhai Cc: Qais Yousef Cc: Vasily Averin Signed-off-by: Andrew Morton --- .mailmap | 1 + 1 file changed, 1 insertion(+) diff --git a/.mailmap b/.mailmap index 5367faaf78312..7581773e1e161 100644 --- a/.mailmap +++ b/.mailmap @@ -191,6 +191,7 @@ Jan Glauber Jan Glauber Jarkko Sakkinen Jarkko Sakkinen +Jarkko Sakkinen Jason Gunthorpe Jason Gunthorpe Jason Gunthorpe From 071ca76d2c1dddc6bf2f4917a016207e00bcc8e3 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Wed, 1 Mar 2023 12:00:12 +0100 Subject: [PATCH 151/460] mailmap: correct Dikshita Agarwal's Qualcomm email address I recently sent a patch to map Dikshita's old CAF address to his current one @ Qualcomm. It turned out however, that he has two of them, with the @quicinc.com one meant for upstream contributions. Fix it. Link: https://lkml.kernel.org/r/20230301110012.1290379-1-konrad.dybcio@linaro.org Signed-off-by: Konrad Dybcio Cc: Dikshita Agarwal Cc: Andy Gross Cc: Arnd Bergmann Cc: Baolin Wang Cc: Bjorn Andersson Cc: Colin Ian King Cc: Kirill Tkhai Cc: Marijn Suijten Cc: Qais Yousef Cc: Vasily Averin Signed-off-by: Andrew Morton --- .mailmap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.mailmap b/.mailmap index 7581773e1e161..16b195032269b 100644 --- a/.mailmap +++ b/.mailmap @@ -121,7 +121,7 @@ Dengcheng Zhu Dengcheng Zhu Dengcheng Zhu -Dikshita Agarwal +Dikshita Agarwal Dmitry Baryshkov Dmitry Baryshkov <[dbaryshkov@gmail.com]> Dmitry Baryshkov From 89a004508081e1d1a498f10ea6d4f7f97a820438 Mon Sep 17 00:00:00 2001 From: Alexandre Ghiti Date: Wed, 1 Mar 2023 10:01:32 +0100 Subject: [PATCH 152/460] .mailmap: add Alexandre Ghiti personal email address I'm no longer employed by Canonical which results in email bouncing so add an entry to my personal email address. Link: https://lkml.kernel.org/r/20230301090132.280475-1-alexghiti@rivosinc.com Signed-off-by: Alexandre Ghiti Reported-by: Conor Dooley Signed-off-by: Andrew Morton --- .mailmap | 1 + 1 file changed, 1 insertion(+) diff --git a/.mailmap b/.mailmap index 16b195032269b..c1def9105d0c7 100644 --- a/.mailmap +++ b/.mailmap @@ -28,6 +28,7 @@ Alexander Lobakin Alexander Mikhalitsyn Alexander Mikhalitsyn Alexandre Belloni +Alexandre Ghiti Alexei Starovoitov Alexei Starovoitov Alexei Starovoitov From fb3592c41a4427601f9643b2a84e55bb99f5cd7c Mon Sep 17 00:00:00 2001 From: Huang Ying Date: Fri, 3 Mar 2023 11:01:53 +0800 Subject: [PATCH 153/460] migrate_pages: fix deadlock in batched migration Patch series "migrate_pages: fix deadlock in batched synchronous migration", v2. Two deadlock bugs were reported for the migrate_pages() batching series. Thanks Hugh and Pengfei. Analysis shows that if we have locked some other folios except the one we are migrating, it's not safe in general to wait synchronously, for example, to wait the writeback to complete or wait to lock the buffer head. So 1/3 fixes the deadlock in a simple way, where the batching support for the synchronous migration is disabled. The change is straightforward and easy to be understood. While 3/3 re-introduce the batching for synchronous migration via trying to migrate asynchronously in batch optimistically, then fall back to migrate synchronously one by one for fail-to-migrate folios. Test shows that this can restore the TLB flushing batching performance for synchronous migration effectively. This patch (of 3): Two deadlock bugs were reported for the migrate_pages() batching series. Thanks Hugh and Pengfei! For example, in the following deadlock trace snippet, INFO: task kworker/u4:0:9 blocked for more than 147 seconds. Not tainted 6.2.0-rc4-kvm+ #1314 "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. task:kworker/u4:0 state:D stack:0 pid:9 ppid:2 flags:0x00004000 Workqueue: loop4 loop_rootcg_workfn Call Trace: __schedule+0x43b/0xd00 schedule+0x6a/0xf0 io_schedule+0x4a/0x80 folio_wait_bit_common+0x1b5/0x4e0 ? __pfx_wake_page_function+0x10/0x10 __filemap_get_folio+0x73d/0x770 shmem_get_folio_gfp+0x1fd/0xc80 shmem_write_begin+0x91/0x220 generic_perform_write+0x10e/0x2e0 __generic_file_write_iter+0x17e/0x290 ? generic_write_checks+0x12b/0x1a0 generic_file_write_iter+0x97/0x180 ? __sanitizer_cov_trace_const_cmp4+0x1a/0x20 do_iter_readv_writev+0x13c/0x210 ? __sanitizer_cov_trace_const_cmp4+0x1a/0x20 do_iter_write+0xf6/0x330 vfs_iter_write+0x46/0x70 loop_process_work+0x723/0xfe0 loop_rootcg_workfn+0x28/0x40 process_one_work+0x3cc/0x8d0 worker_thread+0x66/0x630 ? __pfx_worker_thread+0x10/0x10 kthread+0x153/0x190 ? __pfx_kthread+0x10/0x10 ret_from_fork+0x29/0x50 INFO: task repro:1023 blocked for more than 147 seconds. Not tainted 6.2.0-rc4-kvm+ #1314 "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. task:repro state:D stack:0 pid:1023 ppid:360 flags:0x00004004 Call Trace: __schedule+0x43b/0xd00 schedule+0x6a/0xf0 io_schedule+0x4a/0x80 folio_wait_bit_common+0x1b5/0x4e0 ? compaction_alloc+0x77/0x1150 ? __pfx_wake_page_function+0x10/0x10 folio_wait_bit+0x30/0x40 folio_wait_writeback+0x2e/0x1e0 migrate_pages_batch+0x555/0x1ac0 ? __pfx_compaction_alloc+0x10/0x10 ? __pfx_compaction_free+0x10/0x10 ? __this_cpu_preempt_check+0x17/0x20 ? lock_is_held_type+0xe6/0x140 migrate_pages+0x100e/0x1180 ? __pfx_compaction_free+0x10/0x10 ? __pfx_compaction_alloc+0x10/0x10 compact_zone+0xe10/0x1b50 ? lock_is_held_type+0xe6/0x140 ? check_preemption_disabled+0x80/0xf0 compact_node+0xa3/0x100 ? __sanitizer_cov_trace_const_cmp8+0x1c/0x30 ? _find_first_bit+0x7b/0x90 sysctl_compaction_handler+0x5d/0xb0 proc_sys_call_handler+0x29d/0x420 proc_sys_write+0x2b/0x40 vfs_write+0x3a3/0x780 ksys_write+0xb7/0x180 __x64_sys_write+0x26/0x30 do_syscall_64+0x3b/0x90 entry_SYSCALL_64_after_hwframe+0x72/0xdc RIP: 0033:0x7f3a2471f59d RSP: 002b:00007ffe567f7288 EFLAGS: 00000217 ORIG_RAX: 0000000000000001 RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f3a2471f59d RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000005 RBP: 00007ffe567f72a0 R08: 0000000000000010 R09: 0000000000000010 R10: 0000000000000010 R11: 0000000000000217 R12: 00000000004012e0 R13: 00007ffe567f73e0 R14: 0000000000000000 R15: 0000000000000000 The page migration task has held the lock of the shmem folio A, and is waiting the writeback of the folio B of the file system on the loop block device to complete. While the loop worker task which writes back the folio B is waiting to lock the shmem folio A, because the folio A backs the folio B in the loop device. Thus deadlock is triggered. In general, if we have locked some other folios except the one we are migrating, it's not safe to wait synchronously, for example, to wait the writeback to complete or wait to lock the buffer head. To fix the deadlock, in this patch, we avoid to batch the page migration except for MIGRATE_ASYNC mode. In MIGRATE_ASYNC mode, synchronous waiting is avoided. The fix can be improved further. We will do that as soon as possible. Link: https://lkml.kernel.org/r/20230303030155.160983-1-ying.huang@intel.com Link: https://lore.kernel.org/linux-mm/87a6c8c-c5c1-67dc-1e32-eb30831d6e3d@google.com/ Link: https://lore.kernel.org/linux-mm/874jrg7kke.fsf@yhuang6-desk2.ccr.corp.intel.com/ Link: https://lore.kernel.org/linux-mm/20230227110614.dngdub2j3exr6dfp@quack3/ Link: https://lkml.kernel.org/r/20230303030155.160983-2-ying.huang@intel.com Fixes: 5dfab109d519 ("migrate_pages: batch _unmap and _move") Signed-off-by: "Huang, Ying" Reported-by: Hugh Dickins Reported-by: "Xu, Pengfei" Cc: Jan Kara Cc: Baolin Wang Cc: Christoph Hellwig Cc: Stefan Roesch Cc: Tejun Heo Cc: Xin Hao Cc: Zi Yan Cc: Yang Shi Cc: Matthew Wilcox Cc: Mike Kravetz Signed-off-by: Andrew Morton --- mm/migrate.c | 69 ++++++++++++++++++++-------------------------------- 1 file changed, 26 insertions(+), 43 deletions(-) diff --git a/mm/migrate.c b/mm/migrate.c index 98f1c11197a8c..f348e0a7b1df5 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -1112,7 +1112,7 @@ static void migrate_folio_done(struct folio *src, /* Obtain the lock on page, remove all ptes. */ static int migrate_folio_unmap(new_page_t get_new_page, free_page_t put_new_page, unsigned long private, struct folio *src, - struct folio **dstp, int force, bool avoid_force_lock, + struct folio **dstp, int force, enum migrate_mode mode, enum migrate_reason reason, struct list_head *ret) { @@ -1163,17 +1163,6 @@ static int migrate_folio_unmap(new_page_t get_new_page, free_page_t put_new_page if (current->flags & PF_MEMALLOC) goto out; - /* - * We have locked some folios and are going to wait to lock - * this folio. To avoid a potential deadlock, let's bail - * out and not do that. The locked folios will be moved and - * unlocked, then we can wait to lock this folio. - */ - if (avoid_force_lock) { - rc = -EDEADLOCK; - goto out; - } - folio_lock(src); } locked = true; @@ -1253,7 +1242,7 @@ static int migrate_folio_unmap(new_page_t get_new_page, free_page_t put_new_page /* Establish migration ptes */ VM_BUG_ON_FOLIO(folio_test_anon(src) && !folio_test_ksm(src) && !anon_vma, src); - try_to_migrate(src, TTU_BATCH_FLUSH); + try_to_migrate(src, mode == MIGRATE_ASYNC ? TTU_BATCH_FLUSH : 0); page_was_mapped = 1; } @@ -1267,7 +1256,7 @@ static int migrate_folio_unmap(new_page_t get_new_page, free_page_t put_new_page * A folio that has not been unmapped will be restored to * right list unless we want to retry. */ - if (rc == -EAGAIN || rc == -EDEADLOCK) + if (rc == -EAGAIN) ret = NULL; migrate_folio_undo_src(src, page_was_mapped, anon_vma, locked, ret); @@ -1618,6 +1607,11 @@ static int migrate_hugetlbs(struct list_head *from, new_page_t get_new_page, /* * migrate_pages_batch() first unmaps folios in the from list as many as * possible, then move the unmapped folios. + * + * We only batch migration if mode == MIGRATE_ASYNC to avoid to wait a + * lock or bit when we have locked more than one folio. Which may cause + * deadlock (e.g., for loop device). So, if mode != MIGRATE_ASYNC, the + * length of the from list must be <= 1. */ static int migrate_pages_batch(struct list_head *from, new_page_t get_new_page, free_page_t put_new_page, unsigned long private, @@ -1640,11 +1634,11 @@ static int migrate_pages_batch(struct list_head *from, new_page_t get_new_page, LIST_HEAD(dst_folios); bool nosplit = (reason == MR_NUMA_MISPLACED); bool no_split_folio_counting = false; - bool avoid_force_lock; + VM_WARN_ON_ONCE(mode != MIGRATE_ASYNC && + !list_empty(from) && !list_is_singular(from)); retry: rc_saved = 0; - avoid_force_lock = false; retry = 1; for (pass = 0; pass < NR_MAX_MIGRATE_PAGES_RETRY && (retry || large_retry); @@ -1689,15 +1683,14 @@ static int migrate_pages_batch(struct list_head *from, new_page_t get_new_page, } rc = migrate_folio_unmap(get_new_page, put_new_page, private, - folio, &dst, pass > 2, avoid_force_lock, - mode, reason, ret_folios); + folio, &dst, pass > 2, mode, + reason, ret_folios); /* * The rules are: * Success: folio will be freed * Unmap: folio will be put on unmap_folios list, * dst folio put on dst_folios list * -EAGAIN: stay on the from list - * -EDEADLOCK: stay on the from list * -ENOMEM: stay on the from list * Other errno: put on ret_folios list */ @@ -1749,14 +1742,6 @@ static int migrate_pages_batch(struct list_head *from, new_page_t get_new_page, goto out; else goto move; - case -EDEADLOCK: - /* - * The folio cannot be locked for potential deadlock. - * Go move (and unlock) all locked folios. Then we can - * try again. - */ - rc_saved = rc; - goto move; case -EAGAIN: if (is_large) { large_retry++; @@ -1771,11 +1756,6 @@ static int migrate_pages_batch(struct list_head *from, new_page_t get_new_page, stats->nr_thp_succeeded += is_thp; break; case MIGRATEPAGE_UNMAP: - /* - * We have locked some folios, don't force lock - * to avoid deadlock. - */ - avoid_force_lock = true; list_move_tail(&folio->lru, &unmap_folios); list_add_tail(&dst->lru, &dst_folios); break; @@ -1900,17 +1880,15 @@ static int migrate_pages_batch(struct list_head *from, new_page_t get_new_page, */ list_splice_init(from, ret_folios); list_splice_init(&split_folios, from); + /* + * Force async mode to avoid to wait lock or bit when we have + * locked more than one folios. + */ + mode = MIGRATE_ASYNC; no_split_folio_counting = true; goto retry; } - /* - * We have unlocked all locked folios, so we can force lock now, let's - * try again. - */ - if (rc == -EDEADLOCK) - goto retry; - return rc; } @@ -1945,7 +1923,7 @@ int migrate_pages(struct list_head *from, new_page_t get_new_page, enum migrate_mode mode, int reason, unsigned int *ret_succeeded) { int rc, rc_gather; - int nr_pages; + int nr_pages, batch; struct folio *folio, *folio2; LIST_HEAD(folios); LIST_HEAD(ret_folios); @@ -1959,6 +1937,11 @@ int migrate_pages(struct list_head *from, new_page_t get_new_page, mode, reason, &stats, &ret_folios); if (rc_gather < 0) goto out; + + if (mode == MIGRATE_ASYNC) + batch = NR_MAX_BATCHED_MIGRATION; + else + batch = 1; again: nr_pages = 0; list_for_each_entry_safe(folio, folio2, from, lru) { @@ -1969,11 +1952,11 @@ int migrate_pages(struct list_head *from, new_page_t get_new_page, } nr_pages += folio_nr_pages(folio); - if (nr_pages > NR_MAX_BATCHED_MIGRATION) + if (nr_pages >= batch) break; } - if (nr_pages > NR_MAX_BATCHED_MIGRATION) - list_cut_before(&folios, from, &folio->lru); + if (nr_pages >= batch) + list_cut_before(&folios, from, &folio2->lru); else list_splice_init(from, &folios); rc = migrate_pages_batch(&folios, get_new_page, put_new_page, private, From a21d2133215b58fbf254ea2bb77eb3143ffedf60 Mon Sep 17 00:00:00 2001 From: Huang Ying Date: Fri, 3 Mar 2023 11:01:54 +0800 Subject: [PATCH 154/460] migrate_pages: move split folios processing out of migrate_pages_batch() To simplify the code logic and reduce the line number. Link: https://lkml.kernel.org/r/20230303030155.160983-3-ying.huang@intel.com Fixes: 5dfab109d519 ("migrate_pages: batch _unmap and _move") Signed-off-by: "Huang, Ying" Reviewed-by: Baolin Wang Cc: Hugh Dickins Cc: "Xu, Pengfei" Cc: Christoph Hellwig Cc: Stefan Roesch Cc: Tejun Heo Cc: Xin Hao Cc: Zi Yan Cc: Yang Shi Cc: Matthew Wilcox Cc: Mike Kravetz Signed-off-by: Andrew Morton --- mm/migrate.c | 78 +++++++++++++++++++--------------------------------- 1 file changed, 28 insertions(+), 50 deletions(-) diff --git a/mm/migrate.c b/mm/migrate.c index f348e0a7b1df5..b61abe529107f 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -1616,9 +1616,10 @@ static int migrate_hugetlbs(struct list_head *from, new_page_t get_new_page, static int migrate_pages_batch(struct list_head *from, new_page_t get_new_page, free_page_t put_new_page, unsigned long private, enum migrate_mode mode, int reason, struct list_head *ret_folios, - struct migrate_pages_stats *stats) + struct list_head *split_folios, struct migrate_pages_stats *stats, + int nr_pass) { - int retry; + int retry = 1; int large_retry = 1; int thp_retry = 1; int nr_failed = 0; @@ -1628,21 +1629,15 @@ static int migrate_pages_batch(struct list_head *from, new_page_t get_new_page, bool is_large = false; bool is_thp = false; struct folio *folio, *folio2, *dst = NULL, *dst2; - int rc, rc_saved, nr_pages; - LIST_HEAD(split_folios); + int rc, rc_saved = 0, nr_pages; LIST_HEAD(unmap_folios); LIST_HEAD(dst_folios); bool nosplit = (reason == MR_NUMA_MISPLACED); - bool no_split_folio_counting = false; VM_WARN_ON_ONCE(mode != MIGRATE_ASYNC && !list_empty(from) && !list_is_singular(from)); -retry: - rc_saved = 0; - retry = 1; - for (pass = 0; - pass < NR_MAX_MIGRATE_PAGES_RETRY && (retry || large_retry); - pass++) { + + for (pass = 0; pass < nr_pass && (retry || large_retry); pass++) { retry = 0; large_retry = 0; thp_retry = 0; @@ -1673,7 +1668,7 @@ static int migrate_pages_batch(struct list_head *from, new_page_t get_new_page, if (!thp_migration_supported() && is_thp) { nr_large_failed++; stats->nr_thp_failed++; - if (!try_split_folio(folio, &split_folios)) { + if (!try_split_folio(folio, split_folios)) { stats->nr_thp_split++; continue; } @@ -1705,7 +1700,7 @@ static int migrate_pages_batch(struct list_head *from, new_page_t get_new_page, stats->nr_thp_failed += is_thp; /* Large folio NUMA faulting doesn't split to retry. */ if (!nosplit) { - int ret = try_split_folio(folio, &split_folios); + int ret = try_split_folio(folio, split_folios); if (!ret) { stats->nr_thp_split += is_thp; @@ -1722,18 +1717,11 @@ static int migrate_pages_batch(struct list_head *from, new_page_t get_new_page, break; } } - } else if (!no_split_folio_counting) { + } else { nr_failed++; } stats->nr_failed_pages += nr_pages + nr_retry_pages; - /* - * There might be some split folios of fail-to-migrate large - * folios left in split_folios list. Move them to ret_folios - * list so that they could be put back to the right list by - * the caller otherwise the folio refcnt will be leaked. - */ - list_splice_init(&split_folios, ret_folios); /* nr_failed isn't updated for not used */ nr_large_failed += large_retry; stats->nr_thp_failed += thp_retry; @@ -1746,7 +1734,7 @@ static int migrate_pages_batch(struct list_head *from, new_page_t get_new_page, if (is_large) { large_retry++; thp_retry += is_thp; - } else if (!no_split_folio_counting) { + } else { retry++; } nr_retry_pages += nr_pages; @@ -1769,7 +1757,7 @@ static int migrate_pages_batch(struct list_head *from, new_page_t get_new_page, if (is_large) { nr_large_failed++; stats->nr_thp_failed += is_thp; - } else if (!no_split_folio_counting) { + } else { nr_failed++; } @@ -1787,9 +1775,7 @@ static int migrate_pages_batch(struct list_head *from, new_page_t get_new_page, try_to_unmap_flush(); retry = 1; - for (pass = 0; - pass < NR_MAX_MIGRATE_PAGES_RETRY && (retry || large_retry); - pass++) { + for (pass = 0; pass < nr_pass && (retry || large_retry); pass++) { retry = 0; large_retry = 0; thp_retry = 0; @@ -1818,7 +1804,7 @@ static int migrate_pages_batch(struct list_head *from, new_page_t get_new_page, if (is_large) { large_retry++; thp_retry += is_thp; - } else if (!no_split_folio_counting) { + } else { retry++; } nr_retry_pages += nr_pages; @@ -1831,7 +1817,7 @@ static int migrate_pages_batch(struct list_head *from, new_page_t get_new_page, if (is_large) { nr_large_failed++; stats->nr_thp_failed += is_thp; - } else if (!no_split_folio_counting) { + } else { nr_failed++; } @@ -1868,27 +1854,6 @@ static int migrate_pages_batch(struct list_head *from, new_page_t get_new_page, dst2 = list_next_entry(dst, lru); } - /* - * Try to migrate split folios of fail-to-migrate large folios, no - * nr_failed counting in this round, since all split folios of a - * large folio is counted as 1 failure in the first round. - */ - if (rc >= 0 && !list_empty(&split_folios)) { - /* - * Move non-migrated folios (after NR_MAX_MIGRATE_PAGES_RETRY - * retries) to ret_folios to avoid migrating them again. - */ - list_splice_init(from, ret_folios); - list_splice_init(&split_folios, from); - /* - * Force async mode to avoid to wait lock or bit when we have - * locked more than one folios. - */ - mode = MIGRATE_ASYNC; - no_split_folio_counting = true; - goto retry; - } - return rc; } @@ -1927,6 +1892,7 @@ int migrate_pages(struct list_head *from, new_page_t get_new_page, struct folio *folio, *folio2; LIST_HEAD(folios); LIST_HEAD(ret_folios); + LIST_HEAD(split_folios); struct migrate_pages_stats stats; trace_mm_migrate_pages_start(mode, reason); @@ -1960,12 +1926,24 @@ int migrate_pages(struct list_head *from, new_page_t get_new_page, else list_splice_init(from, &folios); rc = migrate_pages_batch(&folios, get_new_page, put_new_page, private, - mode, reason, &ret_folios, &stats); + mode, reason, &ret_folios, &split_folios, &stats, + NR_MAX_MIGRATE_PAGES_RETRY); list_splice_tail_init(&folios, &ret_folios); if (rc < 0) { rc_gather = rc; + list_splice_tail(&split_folios, &ret_folios); goto out; } + if (!list_empty(&split_folios)) { + /* + * Failure isn't counted since all split folios of a large folio + * is counted as 1 failure already. And, we only try to migrate + * with minimal effort, force MIGRATE_ASYNC mode and retry once. + */ + migrate_pages_batch(&split_folios, get_new_page, put_new_page, private, + MIGRATE_ASYNC, reason, &ret_folios, NULL, &stats, 1); + list_splice_tail_init(&split_folios, &ret_folios); + } rc_gather += rc; if (!list_empty(from)) goto again; From 2ef7dbb269902bde34c82f027806992195d1d1ee Mon Sep 17 00:00:00 2001 From: Huang Ying Date: Fri, 3 Mar 2023 11:01:55 +0800 Subject: [PATCH 155/460] migrate_pages: try migrate in batch asynchronously firstly When we have locked more than one folios, we cannot wait the lock or bit (e.g., page lock, buffer head lock, writeback bit) synchronously. Otherwise deadlock may be triggered. This make it hard to batch the synchronous migration directly. This patch re-enables batching synchronous migration via trying to migrate in batch asynchronously firstly. And any folios that are failed to be migrated asynchronously will be migrated synchronously one by one. Test shows that this can restore the TLB flushing batching performance for synchronous migration effectively. Link: https://lkml.kernel.org/r/20230303030155.160983-4-ying.huang@intel.com Fixes: 5dfab109d519 ("migrate_pages: batch _unmap and _move") Signed-off-by: "Huang, Ying" Tested-by: Hugh Dickins Reviewed-by: Baolin Wang Cc: "Xu, Pengfei" Cc: Christoph Hellwig Cc: Stefan Roesch Cc: Tejun Heo Cc: Xin Hao Cc: Zi Yan Cc: Yang Shi Cc: Matthew Wilcox Cc: Mike Kravetz Signed-off-by: Andrew Morton --- mm/migrate.c | 80 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 62 insertions(+), 18 deletions(-) diff --git a/mm/migrate.c b/mm/migrate.c index b61abe529107f..db3f154446af4 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -1112,9 +1112,8 @@ static void migrate_folio_done(struct folio *src, /* Obtain the lock on page, remove all ptes. */ static int migrate_folio_unmap(new_page_t get_new_page, free_page_t put_new_page, unsigned long private, struct folio *src, - struct folio **dstp, int force, - enum migrate_mode mode, enum migrate_reason reason, - struct list_head *ret) + struct folio **dstp, enum migrate_mode mode, + enum migrate_reason reason, struct list_head *ret) { struct folio *dst; int rc = -EAGAIN; @@ -1144,7 +1143,7 @@ static int migrate_folio_unmap(new_page_t get_new_page, free_page_t put_new_page dst->private = NULL; if (!folio_trylock(src)) { - if (!force || mode == MIGRATE_ASYNC) + if (mode == MIGRATE_ASYNC) goto out; /* @@ -1182,8 +1181,6 @@ static int migrate_folio_unmap(new_page_t get_new_page, free_page_t put_new_page rc = -EBUSY; goto out; } - if (!force) - goto out; folio_wait_writeback(src); } @@ -1497,6 +1494,9 @@ static inline int try_split_folio(struct folio *folio, struct list_head *split_f #define NR_MAX_BATCHED_MIGRATION 512 #endif #define NR_MAX_MIGRATE_PAGES_RETRY 10 +#define NR_MAX_MIGRATE_ASYNC_RETRY 3 +#define NR_MAX_MIGRATE_SYNC_RETRY \ + (NR_MAX_MIGRATE_PAGES_RETRY - NR_MAX_MIGRATE_ASYNC_RETRY) struct migrate_pages_stats { int nr_succeeded; /* Normal and large folios migrated successfully, in @@ -1678,8 +1678,7 @@ static int migrate_pages_batch(struct list_head *from, new_page_t get_new_page, } rc = migrate_folio_unmap(get_new_page, put_new_page, private, - folio, &dst, pass > 2, mode, - reason, ret_folios); + folio, &dst, mode, reason, ret_folios); /* * The rules are: * Success: folio will be freed @@ -1857,6 +1856,51 @@ static int migrate_pages_batch(struct list_head *from, new_page_t get_new_page, return rc; } +static int migrate_pages_sync(struct list_head *from, new_page_t get_new_page, + free_page_t put_new_page, unsigned long private, + enum migrate_mode mode, int reason, struct list_head *ret_folios, + struct list_head *split_folios, struct migrate_pages_stats *stats) +{ + int rc, nr_failed = 0; + LIST_HEAD(folios); + struct migrate_pages_stats astats; + + memset(&astats, 0, sizeof(astats)); + /* Try to migrate in batch with MIGRATE_ASYNC mode firstly */ + rc = migrate_pages_batch(from, get_new_page, put_new_page, private, MIGRATE_ASYNC, + reason, &folios, split_folios, &astats, + NR_MAX_MIGRATE_ASYNC_RETRY); + stats->nr_succeeded += astats.nr_succeeded; + stats->nr_thp_succeeded += astats.nr_thp_succeeded; + stats->nr_thp_split += astats.nr_thp_split; + if (rc < 0) { + stats->nr_failed_pages += astats.nr_failed_pages; + stats->nr_thp_failed += astats.nr_thp_failed; + list_splice_tail(&folios, ret_folios); + return rc; + } + stats->nr_thp_failed += astats.nr_thp_split; + nr_failed += astats.nr_thp_split; + /* + * Fall back to migrate all failed folios one by one synchronously. All + * failed folios except split THPs will be retried, so their failure + * isn't counted + */ + list_splice_tail_init(&folios, from); + while (!list_empty(from)) { + list_move(from->next, &folios); + rc = migrate_pages_batch(&folios, get_new_page, put_new_page, + private, mode, reason, ret_folios, + split_folios, stats, NR_MAX_MIGRATE_SYNC_RETRY); + list_splice_tail_init(&folios, ret_folios); + if (rc < 0) + return rc; + nr_failed += rc; + } + + return nr_failed; +} + /* * migrate_pages - migrate the folios specified in a list, to the free folios * supplied as the target for the page migration @@ -1888,7 +1932,7 @@ int migrate_pages(struct list_head *from, new_page_t get_new_page, enum migrate_mode mode, int reason, unsigned int *ret_succeeded) { int rc, rc_gather; - int nr_pages, batch; + int nr_pages; struct folio *folio, *folio2; LIST_HEAD(folios); LIST_HEAD(ret_folios); @@ -1904,10 +1948,6 @@ int migrate_pages(struct list_head *from, new_page_t get_new_page, if (rc_gather < 0) goto out; - if (mode == MIGRATE_ASYNC) - batch = NR_MAX_BATCHED_MIGRATION; - else - batch = 1; again: nr_pages = 0; list_for_each_entry_safe(folio, folio2, from, lru) { @@ -1918,16 +1958,20 @@ int migrate_pages(struct list_head *from, new_page_t get_new_page, } nr_pages += folio_nr_pages(folio); - if (nr_pages >= batch) + if (nr_pages >= NR_MAX_BATCHED_MIGRATION) break; } - if (nr_pages >= batch) + if (nr_pages >= NR_MAX_BATCHED_MIGRATION) list_cut_before(&folios, from, &folio2->lru); else list_splice_init(from, &folios); - rc = migrate_pages_batch(&folios, get_new_page, put_new_page, private, - mode, reason, &ret_folios, &split_folios, &stats, - NR_MAX_MIGRATE_PAGES_RETRY); + if (mode == MIGRATE_ASYNC) + rc = migrate_pages_batch(&folios, get_new_page, put_new_page, private, + mode, reason, &ret_folios, &split_folios, &stats, + NR_MAX_MIGRATE_PAGES_RETRY); + else + rc = migrate_pages_sync(&folios, get_new_page, put_new_page, private, + mode, reason, &ret_folios, &split_folios, &stats); list_splice_tail_init(&folios, &ret_folios); if (rc < 0) { rc_gather = rc; From 90410bcf873cf05f54a32183afff0161f44f9715 Mon Sep 17 00:00:00 2001 From: Jan Kara via Ocfs2-devel Date: Thu, 2 Mar 2023 16:38:43 +0100 Subject: [PATCH 156/460] ocfs2: fix data corruption after failed write When buffered write fails to copy data into underlying page cache page, ocfs2_write_end_nolock() just zeroes out and dirties the page. This can leave dirty page beyond EOF and if page writeback tries to write this page before write succeeds and expands i_size, page gets into inconsistent state where page dirty bit is clear but buffer dirty bits stay set resulting in page data never getting written and so data copied to the page is lost. Fix the problem by invalidating page beyond EOF after failed write. Link: https://lkml.kernel.org/r/20230302153843.18499-1-jack@suse.cz Fixes: 6dbf7bb55598 ("fs: Don't invalidate page buffers in block_write_full_page()") Signed-off-by: Jan Kara Reviewed-by: Joseph Qi Cc: Mark Fasheh Cc: Joel Becker Cc: Junxiao Bi Cc: Changwei Ge Cc: Gang He Cc: Jun Piao Cc: Signed-off-by: Andrew Morton --- fs/ocfs2/aops.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index 1d65f6ef00ca8..0394505fdce3f 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c @@ -1977,11 +1977,26 @@ int ocfs2_write_end_nolock(struct address_space *mapping, } if (unlikely(copied < len) && wc->w_target_page) { + loff_t new_isize; + if (!PageUptodate(wc->w_target_page)) copied = 0; - ocfs2_zero_new_buffers(wc->w_target_page, start+copied, - start+len); + new_isize = max_t(loff_t, i_size_read(inode), pos + copied); + if (new_isize > page_offset(wc->w_target_page)) + ocfs2_zero_new_buffers(wc->w_target_page, start+copied, + start+len); + else { + /* + * When page is fully beyond new isize (data copy + * failed), do not bother zeroing the page. Invalidate + * it instead so that writeback does not get confused + * put page & buffer dirty bits into inconsistent + * state. + */ + block_invalidate_folio(page_folio(wc->w_target_page), + 0, PAGE_SIZE); + } } if (wc->w_target_page) flush_dcache_page(wc->w_target_page); From 751688b8be9049f558f86982966ecaa61a9cbedf Mon Sep 17 00:00:00 2001 From: SeongJae Park Date: Sat, 4 Mar 2023 19:39:48 +0000 Subject: [PATCH 157/460] mm/damon/paddr: fix folio_size() call after folio_put() in damon_pa_young() Patch series "mm/damon/paddr: Fix folio-use-after-put bugs". There are two folio accesses after folio_put() in mm/damon/paddr.c file. Fix those. This patch (of 2): damon_pa_young() is accessing a folio via folio_size() after folio_put() for the folio has invoked. Fix it. Link: https://lkml.kernel.org/r/20230304193949.296391-1-sj@kernel.org Link: https://lkml.kernel.org/r/20230304193949.296391-2-sj@kernel.org Fixes: 397b0c3a584b ("mm/damon/paddr: remove folio_sz field from damon_pa_access_chk_result") Signed-off-by: SeongJae Park Reviewed-by: Kefeng Wang Reviewed-by: Matthew Wilcox (Oracle) Cc: Vishal Moola (Oracle) Cc: [6.2.x] Signed-off-by: Andrew Morton --- mm/damon/paddr.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mm/damon/paddr.c b/mm/damon/paddr.c index 6c655d9b56391..49b267b033050 100644 --- a/mm/damon/paddr.c +++ b/mm/damon/paddr.c @@ -130,7 +130,6 @@ static bool damon_pa_young(unsigned long paddr, unsigned long *folio_sz) accessed = false; else accessed = true; - folio_put(folio); goto out; } @@ -144,10 +143,10 @@ static bool damon_pa_young(unsigned long paddr, unsigned long *folio_sz) if (need_lock) folio_unlock(folio); - folio_put(folio); out: *folio_sz = folio_size(folio); + folio_put(folio); return accessed; } From dd52a61da0dd8bab8b90e808f0e5ad507b61ad6d Mon Sep 17 00:00:00 2001 From: SeongJae Park Date: Sat, 4 Mar 2023 19:39:49 +0000 Subject: [PATCH 158/460] mm/damon/paddr: fix folio_nr_pages() after folio_put() in damon_pa_mark_accessed_or_deactivate() damon_pa_mark_accessed_or_deactivate() is accessing a folio via folio_nr_pages() after folio_put() for the folio has invoked. Fix it. Link: https://lkml.kernel.org/r/20230304193949.296391-3-sj@kernel.org Fixes: f70da5ee8fe1 ("mm/damon: convert damon_pa_mark_accessed_or_deactivate() to use folios") Signed-off-by: SeongJae Park Reviewed-by: Kefeng Wang Reviewed-by: Matthew Wilcox (Oracle) Cc: Vishal Moola (Oracle) Signed-off-by: Andrew Morton --- mm/damon/paddr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/damon/paddr.c b/mm/damon/paddr.c index 49b267b033050..dd9c33fbe8052 100644 --- a/mm/damon/paddr.c +++ b/mm/damon/paddr.c @@ -280,8 +280,8 @@ static inline unsigned long damon_pa_mark_accessed_or_deactivate( folio_mark_accessed(folio); else folio_deactivate(folio); - folio_put(folio); applied += folio_nr_pages(folio); + folio_put(folio); } return applied * PAGE_SIZE; } From ffec85d53d0f39ee4680a2cf0795255e000e1feb Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 2 Feb 2023 16:55:03 -0800 Subject: [PATCH 159/460] 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 beaec6d81074a..1e4db96a04e63 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 @@ static void io_submit_add_bh(struct ext4_io_submit *io, } 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 160/460] 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 e2b8b3437c589..12d6252e3e226 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 161/460] 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 270fbcba75b6a..e8f429330f3c3 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 162/460] 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 4493ef0c715e9..cdf9bfe10137f 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 163/460] 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 46d78f860623f..ed5a5cac6d40e 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 164/460] 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 6479146140d20..9dec84fff8265 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 d3c57724f1569311e4b81e98fad0931028b9bdcd Mon Sep 17 00:00:00 2001 From: Wenchao Hao Date: Sat, 25 Feb 2023 18:01:36 +0800 Subject: [PATCH 165/460] scsi: mpt3sas: Fix NULL pointer access in mpt3sas_transport_port_add() Port is allocated by sas_port_alloc_num() and rphy is allocated by either sas_end_device_alloc() or sas_expander_alloc(), all of which may return NULL. So we need to check the rphy to avoid possible NULL pointer access. If sas_rphy_add() returned with failure, rphy is set to NULL. We would access the rphy in the following lines which would also result NULL pointer access. Fixes: 78316e9dfc24 ("scsi: mpt3sas: Fix possible resource leaks in mpt3sas_transport_port_add()") Signed-off-by: Wenchao Hao Link: https://lore.kernel.org/r/20230225100135.2109330-1-haowenchao2@huawei.com Acked-by: Sathya Prakash Veerichetty Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_transport.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_transport.c b/drivers/scsi/mpt3sas/mpt3sas_transport.c index e5ecd6ada6cdd..e8a4750f6ec47 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_transport.c +++ b/drivers/scsi/mpt3sas/mpt3sas_transport.c @@ -785,7 +785,7 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle, goto out_fail; } port = sas_port_alloc_num(sas_node->parent_dev); - if ((sas_port_add(port))) { + if (!port || (sas_port_add(port))) { ioc_err(ioc, "failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); goto out_fail; @@ -824,6 +824,12 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle, mpt3sas_port->remote_identify.sas_address; } + if (!rphy) { + ioc_err(ioc, "failure at %s:%d/%s()!\n", + __FILE__, __LINE__, __func__); + goto out_delete_port; + } + rphy->identify = mpt3sas_port->remote_identify; if ((sas_rphy_add(rphy))) { @@ -831,6 +837,7 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle, __FILE__, __LINE__, __func__); sas_rphy_free(rphy); rphy = NULL; + goto out_delete_port; } if (mpt3sas_port->remote_identify.device_type == SAS_END_DEVICE) { @@ -857,7 +864,10 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle, rphy_to_expander_device(rphy), hba_port->port_id); return mpt3sas_port; - out_fail: +out_delete_port: + sas_port_delete(port); + +out_fail: list_for_each_entry_safe(mpt3sas_phy, next, &mpt3sas_port->phy_list, port_siblings) list_del(&mpt3sas_phy->port_siblings); From f305a7b6ca21a665e8d0cf70b5936991a298c93c Mon Sep 17 00:00:00 2001 From: Tomas Henzl Date: Fri, 3 Mar 2023 00:43:31 +0100 Subject: [PATCH 166/460] scsi: mpi3mr: Fix throttle_groups memory leak Add a missing kfree(). Fixes: f10af057325c ("scsi: mpi3mr: Resource Based Metering") Signed-off-by: Tomas Henzl Link: https://lore.kernel.org/r/20230302234336.25456-2-thenzl@redhat.com Acked-by: Sathya Prakash Veerichetty Signed-off-by: Martin K. Petersen --- drivers/scsi/mpi3mr/mpi3mr_fw.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c index 29acf6111db30..514ccf29cd7fa 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_fw.c +++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c @@ -4389,6 +4389,9 @@ void mpi3mr_free_mem(struct mpi3mr_ioc *mrioc) mrioc->pel_seqnum_virt = NULL; } + kfree(mrioc->throttle_groups); + mrioc->throttle_groups = NULL; + kfree(mrioc->logdata_buf); mrioc->logdata_buf = NULL; From 7d2b02172b6a2ae6aecd7ef6480b9c4bf3dc59f4 Mon Sep 17 00:00:00 2001 From: Tomas Henzl Date: Fri, 3 Mar 2023 00:43:32 +0100 Subject: [PATCH 167/460] scsi: mpi3mr: Fix config page DMA memory leak A fix for: DMA-API: pci 0000:83:00.0: device driver has pending DMA allocations while released from device [count=1] Fixes: 32d457d5a2af ("scsi: mpi3mr: Add framework to issue config requests") Signed-off-by: Tomas Henzl Link: https://lore.kernel.org/r/20230302234336.25456-3-thenzl@redhat.com Acked-by: Sathya Prakash Veerichetty Signed-off-by: Martin K. Petersen --- drivers/scsi/mpi3mr/mpi3mr_fw.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c index 514ccf29cd7fa..0736e6a59e81c 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_fw.c +++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c @@ -4382,7 +4382,11 @@ void mpi3mr_free_mem(struct mpi3mr_ioc *mrioc) mrioc->admin_req_base, mrioc->admin_req_dma); mrioc->admin_req_base = NULL; } - + if (mrioc->cfg_page) { + dma_free_coherent(&mrioc->pdev->dev, mrioc->cfg_page_sz, + mrioc->cfg_page, mrioc->cfg_page_dma); + mrioc->cfg_page = NULL; + } if (mrioc->pel_seqnum_virt) { dma_free_coherent(&mrioc->pdev->dev, mrioc->pel_seqnum_sz, mrioc->pel_seqnum_virt, mrioc->pel_seqnum_dma); From d0f3c3728da8af76dfe435f7f0cfa2b9d9e43ef0 Mon Sep 17 00:00:00 2001 From: Tomas Henzl Date: Fri, 3 Mar 2023 00:43:33 +0100 Subject: [PATCH 168/460] scsi: mpi3mr: Fix mpi3mr_hba_port memory leak in mpi3mr_remove() Free mpi3mr_hba_port at .remove. Fixes: 42fc9fee116f ("scsi: mpi3mr: Add helper functions to manage device's port") Signed-off-by: Tomas Henzl Link: https://lore.kernel.org/r/20230302234336.25456-4-thenzl@redhat.com Acked-by: Sathya Prakash Veerichetty Signed-off-by: Martin K. Petersen --- drivers/scsi/mpi3mr/mpi3mr_os.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c index a794cc8a1c0b1..2ad03b993f05e 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_os.c +++ b/drivers/scsi/mpi3mr/mpi3mr_os.c @@ -5078,6 +5078,7 @@ static void mpi3mr_remove(struct pci_dev *pdev) struct workqueue_struct *wq; unsigned long flags; struct mpi3mr_tgt_dev *tgtdev, *tgtdev_next; + struct mpi3mr_hba_port *port, *hba_port_next; if (!shost) return; @@ -5117,6 +5118,16 @@ static void mpi3mr_remove(struct pci_dev *pdev) mpi3mr_free_mem(mrioc); mpi3mr_cleanup_resources(mrioc); + spin_lock_irqsave(&mrioc->sas_node_lock, flags); + list_for_each_entry_safe(port, hba_port_next, &mrioc->hba_port_table_list, list) { + ioc_info(mrioc, + "removing hba_port entry: %p port: %d from hba_port list\n", + port, port->port_id); + list_del(&port->list); + kfree(port); + } + spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); + spin_lock(&mrioc_list_lock); list_del(&mrioc->list); spin_unlock(&mrioc_list_lock); From d4caa1a4255cc44be56bcab3db2c97c632e6cc10 Mon Sep 17 00:00:00 2001 From: Tomas Henzl Date: Fri, 3 Mar 2023 00:43:34 +0100 Subject: [PATCH 169/460] scsi: mpi3mr: Fix sas_hba.phy memory leak in mpi3mr_remove() Free mrioc->sas_hba.phy at .remove. Fixes: 42fc9fee116f ("scsi: mpi3mr: Add helper functions to manage device's port") Signed-off-by: Tomas Henzl Link: https://lore.kernel.org/r/20230302234336.25456-5-thenzl@redhat.com Acked-by: Sathya Prakash Veerichetty Signed-off-by: Martin K. Petersen --- drivers/scsi/mpi3mr/mpi3mr_os.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c index 2ad03b993f05e..2e546c80d98ce 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_os.c +++ b/drivers/scsi/mpi3mr/mpi3mr_os.c @@ -5128,6 +5128,12 @@ static void mpi3mr_remove(struct pci_dev *pdev) } spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); + if (mrioc->sas_hba.num_phys) { + kfree(mrioc->sas_hba.phy); + mrioc->sas_hba.phy = NULL; + mrioc->sas_hba.num_phys = 0; + } + spin_lock(&mrioc_list_lock); list_del(&mrioc->list); spin_unlock(&mrioc_list_lock); From c798304470cab88723d895726d17fcb96472e0e9 Mon Sep 17 00:00:00 2001 From: Tomas Henzl Date: Fri, 3 Mar 2023 00:43:35 +0100 Subject: [PATCH 170/460] scsi: mpi3mr: Fix memory leaks in mpi3mr_init_ioc() Don't allocate memory again when IOC is being reinitialized. Fixes: fe6db6151565 ("scsi: mpi3mr: Handle offline FW activation in graceful manner") Signed-off-by: Tomas Henzl Link: https://lore.kernel.org/r/20230302234336.25456-6-thenzl@redhat.com Acked-by: Sathya Prakash Veerichetty Signed-off-by: Martin K. Petersen --- drivers/scsi/mpi3mr/mpi3mr_fw.c | 41 ++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c index 0736e6a59e81c..a565817aa56d4 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_fw.c +++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c @@ -3837,29 +3837,34 @@ int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc) mpi3mr_print_ioc_info(mrioc); - 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) { - retval = -1; - goto out_failed_noretry; + dprint_init(mrioc, "allocating config page buffers\n"); + mrioc->cfg_page_sz = MPI3MR_DEFAULT_CFG_PAGE_SZ; + mrioc->cfg_page = dma_alloc_coherent(&mrioc->pdev->dev, + mrioc->cfg_page_sz, &mrioc->cfg_page_dma, GFP_KERNEL); + if (!mrioc->cfg_page) { + retval = -1; + goto out_failed_noretry; + } } - mrioc->cfg_page_sz = MPI3MR_DEFAULT_CFG_PAGE_SZ; - - retval = mpi3mr_alloc_reply_sense_bufs(mrioc); - if (retval) { - ioc_err(mrioc, - "%s :Failed to allocated reply sense buffers %d\n", - __func__, retval); - goto out_failed_noretry; + if (!mrioc->init_cmds.reply) { + retval = mpi3mr_alloc_reply_sense_bufs(mrioc); + if (retval) { + ioc_err(mrioc, + "%s :Failed to allocated reply sense buffers %d\n", + __func__, retval); + goto out_failed_noretry; + } } - retval = mpi3mr_alloc_chain_bufs(mrioc); - if (retval) { - ioc_err(mrioc, "Failed to allocated chain buffers %d\n", - retval); - goto out_failed_noretry; + if (!mrioc->chain_sgl_list) { + retval = mpi3mr_alloc_chain_bufs(mrioc); + if (retval) { + ioc_err(mrioc, "Failed to allocated chain buffers %d\n", + retval); + goto out_failed_noretry; + } } retval = mpi3mr_issue_iocinit(mrioc); From ce756daa36e1ba271bb3334267295e447aa57a5c Mon Sep 17 00:00:00 2001 From: Tomas Henzl Date: Fri, 3 Mar 2023 00:43:36 +0100 Subject: [PATCH 171/460] scsi: mpi3mr: Fix expander node leak in mpi3mr_remove() Add a missing resource clean up in .remove. Fixes: e22bae30667a ("scsi: mpi3mr: Add expander devices to STL") Signed-off-by: Tomas Henzl Link: https://lore.kernel.org/r/20230302234336.25456-7-thenzl@redhat.com Acked-by: Sathya Prakash Veerichetty Signed-off-by: Martin K. Petersen --- drivers/scsi/mpi3mr/mpi3mr.h | 2 ++ drivers/scsi/mpi3mr/mpi3mr_os.c | 7 +++++++ drivers/scsi/mpi3mr/mpi3mr_transport.c | 5 +---- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h index 40f238fa80cc1..364fb1b5e45ac 100644 --- a/drivers/scsi/mpi3mr/mpi3mr.h +++ b/drivers/scsi/mpi3mr/mpi3mr.h @@ -1393,4 +1393,6 @@ 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); +void mpi3mr_expander_node_remove(struct mpi3mr_ioc *mrioc, + struct mpi3mr_sas_node *sas_expander); #endif /*MPI3MR_H_INCLUDED*/ diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c index 2e546c80d98ce..6d55698ea4d16 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_os.c +++ b/drivers/scsi/mpi3mr/mpi3mr_os.c @@ -5079,6 +5079,7 @@ static void mpi3mr_remove(struct pci_dev *pdev) unsigned long flags; struct mpi3mr_tgt_dev *tgtdev, *tgtdev_next; struct mpi3mr_hba_port *port, *hba_port_next; + struct mpi3mr_sas_node *sas_expander, *sas_expander_next; if (!shost) return; @@ -5119,6 +5120,12 @@ static void mpi3mr_remove(struct pci_dev *pdev) mpi3mr_cleanup_resources(mrioc); spin_lock_irqsave(&mrioc->sas_node_lock, flags); + list_for_each_entry_safe_reverse(sas_expander, sas_expander_next, + &mrioc->sas_expander_list, list) { + spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); + mpi3mr_expander_node_remove(mrioc, sas_expander); + spin_lock_irqsave(&mrioc->sas_node_lock, flags); + } list_for_each_entry_safe(port, hba_port_next, &mrioc->hba_port_table_list, list) { ioc_info(mrioc, "removing hba_port entry: %p port: %d from hba_port list\n", diff --git a/drivers/scsi/mpi3mr/mpi3mr_transport.c b/drivers/scsi/mpi3mr/mpi3mr_transport.c index be25f242fa794..5748bd9369ff7 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_transport.c +++ b/drivers/scsi/mpi3mr/mpi3mr_transport.c @@ -9,9 +9,6 @@ #include "mpi3mr.h" -static void mpi3mr_expander_node_remove(struct mpi3mr_ioc *mrioc, - struct mpi3mr_sas_node *sas_expander); - /** * mpi3mr_post_transport_req - Issue transport requests and wait * @mrioc: Adapter instance reference @@ -2164,7 +2161,7 @@ int mpi3mr_expander_add(struct mpi3mr_ioc *mrioc, u16 handle) * * Return nothing. */ -static void mpi3mr_expander_node_remove(struct mpi3mr_ioc *mrioc, +void mpi3mr_expander_node_remove(struct mpi3mr_ioc *mrioc, struct mpi3mr_sas_node *sas_expander) { struct mpi3mr_sas_port *mr_sas_port, *next; From 3c92792da8506a295afb6d032b4476e46f979725 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 1 Mar 2023 15:10:04 +0100 Subject: [PATCH 172/460] 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 e8f429330f3c3..7cc3918e2f189 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 @@ static int ext4_rename(struct user_namespace *mnt_userns, struct inode *old_dir, } 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 bbdf904b13a62bb8b1272d92a7dde082dff86fbb Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Mon, 6 Mar 2023 15:41:01 +0800 Subject: [PATCH 173/460] ALSA: hda: intel-dsp-config: add MTL PCI id Use SOF as default audio driver. Signed-off-by: Bard Liao Reviewed-by: Gongjun Song Reviewed-by: Kai Vehmanen Cc: Link: https://lore.kernel.org/r/20230306074101.3906707-1-yung-chuan.liao@linux.intel.com Signed-off-by: Takashi Iwai --- sound/hda/intel-dsp-config.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/sound/hda/intel-dsp-config.c b/sound/hda/intel-dsp-config.c index ae31bb1275940..317bdf6dcbef4 100644 --- a/sound/hda/intel-dsp-config.c +++ b/sound/hda/intel-dsp-config.c @@ -472,6 +472,15 @@ static const struct config_entry config_table[] = { }, #endif +/* Meteor Lake */ +#if IS_ENABLED(CONFIG_SND_SOC_SOF_METEORLAKE) + /* Meteorlake-P */ + { + .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, + .device = 0x7e28, + }, +#endif + }; static const struct config_entry *snd_intel_dsp_find_config From 7bb62340951a9af20235a3bde8c98e2e292915df Mon Sep 17 00:00:00 2001 From: Jeremy Szu Date: Tue, 7 Mar 2023 21:53:16 +0800 Subject: [PATCH 174/460] ALSA: hda/realtek: fix speaker, mute/micmute LEDs not work on a HP platform There is a HP platform needs ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED quirk to make mic-mute/audio-mute/speaker working. Signed-off-by: Jeremy Szu Cc: Link: https://lore.kernel.org/r/20230307135317.37621-1-jeremy.szu@canonical.com Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 3c629f4ae0807..5d530b489c48c 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -9447,6 +9447,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x103c, 0x8b8a, "HP", ALC236_FIXUP_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x8b8b, "HP", ALC236_FIXUP_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x8b8d, "HP", ALC236_FIXUP_HP_GPIO_LED), + SND_PCI_QUIRK(0x103c, 0x8b8f, "HP", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x8b92, "HP", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x8bf0, "HP", ALC236_FIXUP_HP_GPIO_LED), SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC), From a86e79e3015f5dd8e1b01ccfa49bd5c6e41047a1 Mon Sep 17 00:00:00 2001 From: "Hamidreza H. Fard" Date: Tue, 7 Mar 2023 16:37:41 +0000 Subject: [PATCH 175/460] ALSA: hda/realtek: Fix the speaker output on Samsung Galaxy Book2 Pro Samsung Galaxy Book2 Pro (13" 2022 NP930XED-KA1DE) with codec SSID 144d:c868 requires the same workaround for enabling the speaker amp like other Samsung models with ALC298 code. Signed-off-by: Hamidreza H. Fard Cc: Link: https://lore.kernel.org/r/20230307163741.3878-1-nitocris@posteo.net Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 5d530b489c48c..f09a1d7c1b186 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -9540,6 +9540,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x144d, 0xc830, "Samsung Galaxy Book Ion (NT950XCJ-X716A)", ALC298_FIXUP_SAMSUNG_AMP), SND_PCI_QUIRK(0x144d, 0xc832, "Samsung Galaxy Book Flex Alpha (NP730QCJ)", ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET), SND_PCI_QUIRK(0x144d, 0xca03, "Samsung Galaxy Book2 Pro 360 (NP930QED)", ALC298_FIXUP_SAMSUNG_AMP), + SND_PCI_QUIRK(0x144d, 0xc868, "Samsung Galaxy Book2 Pro (NP930XED)", ALC298_FIXUP_SAMSUNG_AMP), SND_PCI_QUIRK(0x1458, 0xfa53, "Gigabyte BXBT-2807", ALC283_FIXUP_HEADSET_MIC), SND_PCI_QUIRK(0x1462, 0xb120, "MSI Cubi MS-B120", ALC283_FIXUP_HEADSET_MIC), SND_PCI_QUIRK(0x1462, 0xb171, "Cubi N 8GL (MS-B171)", ALC283_FIXUP_HEADSET_MIC), From ff447886e675979d66b2bc01810035d3baea1b3a Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 7 Mar 2023 15:40:54 -0600 Subject: [PATCH 176/460] ALSA: hda: Match only Intel devices with CONTROLLER_IN_GPU() CONTROLLER_IN_GPU() is clearly intended to match only Intel devices, but previously it checked only the PCI Device ID, not the Vendor ID, so it could match devices from other vendors that happened to use the same Device ID. Update CONTROLLER_IN_GPU() so it matches only Intel devices. Fixes: 535115b5ff51 ("ALSA: hda - Abort the probe without i915 binding for HSW/B") Signed-off-by: Bjorn Helgaas Link: https://lore.kernel.org/r/20230307214054.886721-1-helgaas@kernel.org Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_intel.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 81c4a45254ff2..77a592f219472 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -328,14 +328,15 @@ enum { #define needs_eld_notify_link(chip) false #endif -#define CONTROLLER_IN_GPU(pci) (((pci)->device == 0x0a0c) || \ +#define CONTROLLER_IN_GPU(pci) (((pci)->vendor == 0x8086) && \ + (((pci)->device == 0x0a0c) || \ ((pci)->device == 0x0c0c) || \ ((pci)->device == 0x0d0c) || \ ((pci)->device == 0x160c) || \ ((pci)->device == 0x490d) || \ ((pci)->device == 0x4f90) || \ ((pci)->device == 0x4f91) || \ - ((pci)->device == 0x4f92)) + ((pci)->device == 0x4f92))) #define IS_BXT(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x5a98) From 03e1d60e177eedbd302b77af4ea5e21b5a7ade31 Mon Sep 17 00:00:00 2001 From: David Disseldorp Date: Tue, 7 Mar 2023 16:21:06 +0100 Subject: [PATCH 177/460] 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 a6f9bdd956c39..f10f403104e7d 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 068d82e75d537b444303b8c449a11e51ea659565 Mon Sep 17 00:00:00 2001 From: Jeremy Sowden Date: Tue, 7 Mar 2023 23:22:56 +0000 Subject: [PATCH 178/460] netfilter: nft_nat: correct length for loading protocol registers The values in the protocol registers are two bytes wide. However, when parsing the register loads, the code currently uses the larger 16-byte size of a `union nf_inet_addr`. Change it to use the (correct) size of a `union nf_conntrack_man_proto` instead. Fixes: d07db9884a5f ("netfilter: nf_tables: introduce nft_validate_register_load()") Signed-off-by: Jeremy Sowden Reviewed-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nft_nat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/netfilter/nft_nat.c b/net/netfilter/nft_nat.c index 0479991503900..5c29915ab0289 100644 --- a/net/netfilter/nft_nat.c +++ b/net/netfilter/nft_nat.c @@ -226,7 +226,7 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr, priv->flags |= NF_NAT_RANGE_MAP_IPS; } - plen = sizeof_field(struct nf_nat_range, min_addr.all); + plen = sizeof_field(struct nf_nat_range, min_proto.all); if (tb[NFTA_NAT_REG_PROTO_MIN]) { err = nft_parse_register_load(tb[NFTA_NAT_REG_PROTO_MIN], &priv->sreg_proto_min, plen); From ec2c5917eb858428b2083d1c74f445aabbe8316b Mon Sep 17 00:00:00 2001 From: Jeremy Sowden Date: Tue, 7 Mar 2023 23:22:57 +0000 Subject: [PATCH 179/460] netfilter: nft_masq: correct length for loading protocol registers The values in the protocol registers are two bytes wide. However, when parsing the register loads, the code currently uses the larger 16-byte size of a `union nf_inet_addr`. Change it to use the (correct) size of a `union nf_conntrack_man_proto` instead. Fixes: 8a6bf5da1aef ("netfilter: nft_masq: support port range") Signed-off-by: Jeremy Sowden Reviewed-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nft_masq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/netfilter/nft_masq.c b/net/netfilter/nft_masq.c index e55e455275c48..9544c2f16998b 100644 --- a/net/netfilter/nft_masq.c +++ b/net/netfilter/nft_masq.c @@ -43,7 +43,7 @@ static int nft_masq_init(const struct nft_ctx *ctx, const struct nft_expr *expr, const struct nlattr * const tb[]) { - u32 plen = sizeof_field(struct nf_nat_range, min_addr.all); + u32 plen = sizeof_field(struct nf_nat_range, min_proto.all); struct nft_masq *priv = nft_expr_priv(expr); int err; From 1f617b6b4c7a3d5ea7a56abb83a4c27733b60c2f Mon Sep 17 00:00:00 2001 From: Jeremy Sowden Date: Tue, 7 Mar 2023 23:22:58 +0000 Subject: [PATCH 180/460] netfilter: nft_redir: correct length for loading protocol registers The values in the protocol registers are two bytes wide. However, when parsing the register loads, the code currently uses the larger 16-byte size of a `union nf_inet_addr`. Change it to use the (correct) size of a `union nf_conntrack_man_proto` instead. Fixes: d07db9884a5f ("netfilter: nf_tables: introduce nft_validate_register_load()") Signed-off-by: Jeremy Sowden Reviewed-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nft_redir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/netfilter/nft_redir.c b/net/netfilter/nft_redir.c index 5f77399875593..dbc642f5d32a3 100644 --- a/net/netfilter/nft_redir.c +++ b/net/netfilter/nft_redir.c @@ -48,7 +48,7 @@ static int nft_redir_init(const struct nft_ctx *ctx, unsigned int plen; int err; - plen = sizeof_field(struct nf_nat_range, min_addr.all); + plen = sizeof_field(struct nf_nat_range, min_proto.all); if (tb[NFTA_REDIR_REG_PROTO_MIN]) { err = nft_parse_register_load(tb[NFTA_REDIR_REG_PROTO_MIN], &priv->sreg_proto_min, plen); From 493924519b1fe3faab13ee621a43b0d0939abab1 Mon Sep 17 00:00:00 2001 From: Jeremy Sowden Date: Tue, 7 Mar 2023 23:22:59 +0000 Subject: [PATCH 181/460] netfilter: nft_redir: correct value of inet type `.maxattrs` `nft_redir_inet_type.maxattrs` was being set, presumably because of a cut-and-paste error, to `NFTA_MASQ_MAX`, instead of `NFTA_REDIR_MAX`. Fixes: 63ce3940f3ab ("netfilter: nft_redir: add inet support") Signed-off-by: Jeremy Sowden Reviewed-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nft_redir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/netfilter/nft_redir.c b/net/netfilter/nft_redir.c index dbc642f5d32a3..67cec56bc84a3 100644 --- a/net/netfilter/nft_redir.c +++ b/net/netfilter/nft_redir.c @@ -236,7 +236,7 @@ static struct nft_expr_type nft_redir_inet_type __read_mostly = { .name = "redir", .ops = &nft_redir_inet_ops, .policy = nft_redir_policy, - .maxattr = NFTA_MASQ_MAX, + .maxattr = NFTA_REDIR_MAX, .owner = THIS_MODULE, }; From a402f1e35313fc7ce2ca60f543c4402c2c7c3544 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Wed, 8 Mar 2023 11:51:26 +0100 Subject: [PATCH 182/460] 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 f68954d05e89d..d8cda4c6de6c7 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 183/460] 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 cd4582129c7d6..4fce46afe6db8 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 9ca6705d9d609441d34f8b853e1e4a6369b3b171 Mon Sep 17 00:00:00 2001 From: Benjamin Coddington Date: Fri, 3 Mar 2023 16:08:32 -0500 Subject: [PATCH 184/460] 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 1fd3f5e572854..fea7ce8fba14e 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 af0f46e5b9a462aaa1d76e82781a5316f03828eb Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Tue, 7 Mar 2023 07:51:11 -0800 Subject: [PATCH 185/460] ASoC: da7219: Initialize jack_det_mutex The following traceback is reported if mutex debugging is enabled. DEBUG_LOCKS_WARN_ON(lock->magic != lock) WARNING: CPU: 0 PID: 17 at kernel/locking/mutex.c:950 __mutex_lock_common+0x31c/0x11d4 Modules linked in: CPU: 0 PID: 17 Comm: kworker/0:1 Not tainted 5.10.172-lockdep-21846-g849884cfca5a #1 fd2de466502012eb58bc8beb467f07d0b925611f Hardware name: MediaTek kakadu rev0/rev1 board (DT) Workqueue: events da7219_aad_jack_det_work pstate: 60400005 (nZCv daif +PAN -UAO -TCO BTYPE=--) pc : __mutex_lock_common+0x31c/0x11d4 lr : __mutex_lock_common+0x31c/0x11d4 sp : ffffff80c0317ae0 x29: ffffff80c0317b50 x28: ffffff80c0317b20 x27: 0000000000000000 x26: 0000000000000000 x25: 0000000000000000 x24: 0000000100000000 x23: ffffffd0121d296c x22: dfffffd000000000 x21: 0000000000000000 x20: 0000000000000000 x19: ffffff80c73d7190 x18: 1ffffff018050f52 x17: 0000000000000000 x16: 0000000000000000 x15: 0000000000000000 x14: 0000000000000000 x13: 0000000000000001 x12: 0000000000000001 x11: 0000000000000000 x10: 0000000000000000 x9 : 83f0d991da544b00 x8 : 83f0d991da544b00 x7 : 0000000000000000 x6 : 0000000000000001 x5 : ffffff80c03176a0 x4 : 0000000000000000 x3 : ffffffd01067fd78 x2 : 0000000100000000 x1 : ffffff80c030ba80 x0 : 0000000000000028 Call trace: __mutex_lock_common+0x31c/0x11d4 mutex_lock_nested+0x98/0xac da7219_aad_jack_det_work+0x54/0xf0 process_one_work+0x6cc/0x19dc worker_thread+0x458/0xddc kthread+0x2fc/0x370 ret_from_fork+0x10/0x30 irq event stamp: 579 hardirqs last enabled at (579): [] exit_to_kernel_mode+0x108/0x138 hardirqs last disabled at (577): [] __do_softirq+0x53c/0x125c softirqs last enabled at (578): [] __irq_exit_rcu+0x264/0x4f4 softirqs last disabled at (573): [] __irq_exit_rcu+0x264/0x4f4 ---[ end trace 26da674636181c40 ]--- Initialize the mutex to fix the problem. Cc: David Rau Fixes: 7fde88eda855 ("ASoC: da7219: Improve the IRQ process to increase the stability") Signed-off-by: Guenter Roeck Link: https://lore.kernel.org/r/20230307155111.1985522-1-linux@roeck-us.net Signed-off-by: Mark Brown --- sound/soc/codecs/da7219-aad.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/codecs/da7219-aad.c b/sound/soc/codecs/da7219-aad.c index 4a4f09f924bc5..e3d398b8f54e4 100644 --- a/sound/soc/codecs/da7219-aad.c +++ b/sound/soc/codecs/da7219-aad.c @@ -968,6 +968,8 @@ int da7219_aad_init(struct snd_soc_component *component) 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, da7219_aad_irq_thread, IRQF_TRIGGER_LOW | IRQF_ONESHOT, From e2f2a39452c43b64ea3191642a2661cb8d03827a Mon Sep 17 00:00:00 2001 From: Yu Kuai Date: Wed, 8 Mar 2023 10:32:08 +0800 Subject: [PATCH 186/460] 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 8a8d4441519ce..d9ed3108c17af 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 5b8e5319affc977d24b8ce7edd295907e969e217 Mon Sep 17 00:00:00 2001 From: Lukas Bulwahn Date: Wed, 8 Mar 2023 15:36:40 +0100 Subject: [PATCH 187/460] 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 8d5bc223f3053..2c2e54e2cd679 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 188/460] 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 411bb2d1acd45..f81c0a7136a58 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 189/460] 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 380753b14cab0..95cdd08c4cbb9 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 190/460] 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 d8455b23e5554..c04eb15c40446 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 191/460] 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 c04eb15c40446..d8408acfc763f 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 192/460] 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 a68b738584623..7587fa8885274 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 54004f846cf0f..3aba4e6eec8a5 100644 --- a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c +++ b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c @@ -711,6 +711,7 @@ static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, struct ieee_pa 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 30374a820496e..40a3157fb7359 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 193/460] 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 3aba4e6eec8a5..84a9f4dd8f954 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 a722511b18268bd1f7084eee243af416b85f288f Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sun, 19 Feb 2023 17:04:28 -0800 Subject: [PATCH 194/460] 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 871870ddf7ec1..949b18a29a554 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 fdf6c2309f425509cddd002f278c650ad0b7e34b Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 8 Mar 2023 14:19:34 +0100 Subject: [PATCH 195/460] 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 8d5bc223f3053..93c5fa40c7726 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 5cfabd5376cc2..f9aef39cac2e9 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 f8c3aa9c24182..ffa70dda481d3 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 f5fe423530f0e..0000000000000 --- 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 fd494c2299e69..0000000000000 --- 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 ab9d5d145b3bc..0000000000000 --- 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 e0ca4b6e17cca..0000000000000 --- 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 a7c67014dde0f..0000000000000 --- 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 ca9e3d4ee7f4b..0000000000000 --- 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 df9534dd25cb6..0000000000000 --- 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 1e4baf74ecd55..0000000000000 --- 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 bc8543ea2e660..0000000000000 --- 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 785c0dba508fa..0000000000000 --- 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 31e196ccd899a..0000000000000 --- 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 48725ce9d369e..0000000000000 --- 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 fb7d0e161fddf..0000000000000 --- 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 dc181e491b342..0000000000000 --- 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 93d3c9c4399cf..0000000000000 --- 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 051cdcb11ff58..0000000000000 --- 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 fc7568cf948b8..0000000000000 --- 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 2d2f0fc4c9420..0000000000000 --- 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 780019ce1b983..0000000000000 --- 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 e1ae1859686ea..0000000000000 --- 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 f1ebb5358cb9a..0000000000000 --- 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 df88b3e29e774..0000000000000 --- 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 1e04de3a6622c..0000000000000 --- 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 23b7205722b5b..0000000000000 --- 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 da71867bcca3b..0000000000000 --- 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 a4c3d3d149f74..0000000000000 --- 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 26e710ef5134d..0000000000000 --- 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 6c0b1368383da..0000000000000 --- 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 33967eb3c0d0e..0000000000000 --- 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 13790e32f11c2..0000000000000 --- 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 94f9b125d8602..0000000000000 --- 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 38f357e8aedaa..0000000000000 --- 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 f3f4074d43167..0000000000000 --- 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 788904d4655c4..0000000000000 --- 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 0399872c45460..0000000000000 --- 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 73855bca76fe0..0000000000000 --- 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 f4edf4a8f5c25..0000000000000 --- 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 1988fb6e780a4..0000000000000 --- 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 d1ac2960f1c44..0000000000000 --- 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 3ffab4953a5c5..0000000000000 --- 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 a1051ac1cac4e..0000000000000 --- 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 9611b19ab55b6..0000000000000 --- 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 4a0b782c33bec..0000000000000 --- 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 da2329be4474a..0000000000000 --- 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 c571ad9478ea8..0000000000000 --- 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 0a290bc31c4d7..0000000000000 --- 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 b3d67c1a80503..0000000000000 --- 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 880feadb43407..0000000000000 --- 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 b75a5d869c56d..0000000000000 --- 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 0886300d26bfb..0000000000000 --- 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 7a530c7d57eb3..0000000000000 --- 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 159990facb8a5..0000000000000 --- 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 cd3f845e146a4..0000000000000 --- 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 296aa5b8268d2..0000000000000 --- 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 e7a4f8af497a4..0000000000000 --- 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 8cea166b7b735..0000000000000 --- 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 3f7185780e879..0000000000000 --- 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 4f16af2485913..0000000000000 --- 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 82a602b39cc70..0000000000000 --- 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 457fb3852a19d..0000000000000 --- 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 f8ed04f32cae3..0000000000000 --- 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 c785cf8ed6830..0000000000000 --- 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 d62cdfc2db208..0000000000000 --- 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 feeb37c228977..0000000000000 --- 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 dc4f358f646d4..0000000000000 --- 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 63ac0acc68fd8..0000000000000 --- 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 25b31417cd581..0000000000000 --- 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 a023dd792da7d..0000000000000 --- 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 89b02c97e041d..0000000000000 --- 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 56772af3bec5d..0000000000000 --- 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 e8eecd52d1d89..0000000000000 --- 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 94d735b1d0db1..0000000000000 --- 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 3d688a0e6dfb3..0000000000000 --- 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 54dc1ea437fc8..0000000000000 --- 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 8f74157ee9ac1..0000000000000 --- 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 2b56b7c38c86b..0000000000000 --- 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 e1718f739cc91..0000000000000 --- 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 c704f3040ac89..0000000000000 --- 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 c3eb2479f27b4..0000000000000 --- 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 099f5a075274c..0000000000000 --- 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 ea5f5edd90131..0000000000000 --- 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 3ff653ff1d816..0000000000000 --- 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 589de7c54d930..0000000000000 --- 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 b91322a1fe104..0000000000000 --- 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 9f5cffd8bfb1d..0000000000000 --- 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 12026431a3d29..0000000000000 --- 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 b7267e75346cb..0000000000000 --- 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 783ae18a122aa..0000000000000 --- 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 feeac85aedb07..0000000000000 --- 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 e42f4b4c6e247..0000000000000 --- 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 5bd8ce37aebf8..0000000000000 --- 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 f271e93e9ab9a..0000000000000 --- 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 254a4bc1a1419..0000000000000 --- 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 ffeafa19ef264..0000000000000 --- 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 e0a8199705466..0000000000000 --- 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 dc419fd1ffa5b..0000000000000 --- 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 88271f956b521..0000000000000 --- 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 74a16d1757ce2..0000000000000 --- 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 ca09f7ed7e4dd..0000000000000 --- 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 196/460] 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 2e76dbb81a8fc..2c3dec2b6dfaf 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 197/460] 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 66b4eef09db57..d82c4cacdfb9f 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 e041a2a550582106cba6a7c862c90dfc2ad14492 Mon Sep 17 00:00:00 2001 From: Emil Abildgaard Svendsen Date: Thu, 9 Mar 2023 06:54:41 +0000 Subject: [PATCH 198/460] ASoC: hdmi-codec: only startup/shutdown on supported streams Currently only one stream is supported. This isn't usally a problem until you have a multi codec audio card. Because the audio card will run startup and shutdown on both capture and playback streams. So if your hdmi-codec only support either playback or capture. Then ALSA can't open for playback and capture. This patch will ignore if startup and shutdown are called with a non supported stream. Thus, allowing an audio card like this: +-+ cpu1 <--@-| |-> codec1 (HDMI-CODEC) | |<- codec2 (NOT HDMI-CODEC) +-+ Signed-off-by: Emil Svendsen Link: https://lore.kernel.org/r/20230309065432.4150700-2-emas@bang-olufsen.dk Signed-off-by: Mark Brown --- sound/soc/codecs/hdmi-codec.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c index 01e8ffda2a4bf..6d980fbc42077 100644 --- a/sound/soc/codecs/hdmi-codec.c +++ b/sound/soc/codecs/hdmi-codec.c @@ -428,8 +428,13 @@ static int hdmi_codec_startup(struct snd_pcm_substream *substream, { struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai); bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; + bool has_capture = !hcp->hcd.no_i2s_capture; + bool has_playback = !hcp->hcd.no_i2s_playback; int ret = 0; + if (!((has_playback && tx) || (has_capture && !tx))) + return 0; + mutex_lock(&hcp->lock); if (hcp->busy) { dev_err(dai->dev, "Only one simultaneous stream supported!\n"); @@ -468,6 +473,12 @@ static void hdmi_codec_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai); + bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; + bool has_capture = !hcp->hcd.no_i2s_capture; + bool has_playback = !hcp->hcd.no_i2s_playback; + + if (!((has_playback && tx) || (has_capture && !tx))) + return; hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN; hcp->hcd.ops->audio_shutdown(dai->dev->parent, hcp->hcd.data); From 11440da77d6020831ee6f9ce4551b545dea789ee Mon Sep 17 00:00:00 2001 From: Francesco Dolcini Date: Mon, 6 Mar 2023 17:27:51 +0100 Subject: [PATCH 199/460] mmc: sdhci_am654: lower power-on failed message severity Lower the power-on failed message severity from warn to info when the controller does not power-up. It's normal to have this situation when the SD card slot is empty, therefore we should not warn the user about it. Fixes: 7ca0f166f5b2 ("mmc: sdhci_am654: Add workaround for card detect debounce timer") Signed-off-by: Francesco Dolcini Acked-by: Adrian Hunter Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20230306162751.163369-1-francesco@dolcini.it Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci_am654.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci_am654.c b/drivers/mmc/host/sdhci_am654.c index 7ef828942df35..89953093e20c7 100644 --- a/drivers/mmc/host/sdhci_am654.c +++ b/drivers/mmc/host/sdhci_am654.c @@ -369,7 +369,7 @@ static void sdhci_am654_write_b(struct sdhci_host *host, u8 val, int reg) MAX_POWER_ON_TIMEOUT, false, host, val, reg); if (ret) - dev_warn(mmc_dev(host->mmc), "Power on failed\n"); + dev_info(mmc_dev(host->mmc), "Power on failed\n"); } } From 92771cdd90de64b15e65f3c88d6c6199bd5f33f5 Mon Sep 17 00:00:00 2001 From: William Qiu Date: Tue, 7 Mar 2023 10:46:46 +0800 Subject: [PATCH 200/460] mmc: dw_mmc-starfive: Fix initialization of prev_err Fix a bug by making sure prev_err doesn't get used when being uninitialized. Signed-off-by: William Qiu Reported-by: Dan Carpenter Reviewed-by: Emil Renner Berthing Fixes: 9e622229bbf4 ("mmc: starfive: Add sdio/emmc driver support") Link: https://lore.kernel.org/r/20230307024646.10216-3-william.qiu@starfivetech.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/dw_mmc-starfive.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/dw_mmc-starfive.c b/drivers/mmc/host/dw_mmc-starfive.c index 40f5969b07a66..dab1508bf83c6 100644 --- a/drivers/mmc/host/dw_mmc-starfive.c +++ b/drivers/mmc/host/dw_mmc-starfive.c @@ -51,7 +51,7 @@ static int dw_mci_starfive_execute_tuning(struct dw_mci_slot *slot, struct dw_mci *host = slot->host; struct starfive_priv *priv = host->priv; int rise_point = -1, fall_point = -1; - int err, prev_err; + int err, prev_err = 0; int i; bool found = 0; u32 regval; From a279adedbb5206ccadb6b2817838cbb1c834133d Mon Sep 17 00:00:00 2001 From: Yangtao Li Date: Fri, 3 Mar 2023 14:37:31 +0800 Subject: [PATCH 201/460] 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 091fd5adf818f..307b37f0b9f57 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 3f3561d37d1b2..1db018f8c2e89 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 a2efd833d1b6c..c7a4b1d77069d 100644 --- a/fs/erofs/pcpubuf.c +++ b/fs/erofs/pcpubuf.c @@ -114,7 +114,7 @@ int erofs_pcpubuf_growsize(unsigned int nrpages) 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 202/460] 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 307b37f0b9f57..d38e19c112704 100644 --- a/fs/erofs/decompressor_lzma.c +++ b/fs/erofs/decompressor_lzma.c @@ -278,7 +278,7 @@ int z_erofs_lzma_decompress(struct z_erofs_decompress_req *rq, } } 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 203/460] 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 3247d2422beae..f1708c77a9912 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 @@ static int z_erofs_decompress_pcluster(struct z_erofs_decompress_backend *be, } 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 @@ static int z_erofs_decompress_pcluster(struct z_erofs_decompress_backend *be, } 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 204/460] 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 8bf6d30518b64..655da4d739cb6 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 205/460] 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 e16545849ea7f..c08c0f578bc69 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 206/460] 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 446a189b78b03..2e4c483075d33 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 207/460] =?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 fd1cc35a1c00b..722624b6d0dca 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 7c198a40d5f11..0eb194817242e 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 b2bda460b1b744a3835ce9d291360b6185e7e305 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 10 Mar 2023 05:24:43 +1000 Subject: [PATCH 208/460] 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 5367faaf78312..4ff64c33a152b 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 209/460] 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 28ffb4377d989..3856d5c04c5fd 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 210/460] 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 5fcefcd0bacac..3e0fff3f129e7 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 211/460] 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 29c94be091596..abad091baeeae 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 212/460] 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 62c44616d8a92..3d8b51316bef0 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 213/460] 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 61906fc54e370..b287c28920a68 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 214/460] 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 a3b524f15d89a..1c80b121e7d6d 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 215/460] 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 cb5fa971d67e2..63253e2b2c1f4 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 500404d85141d..5ba89663ea865 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 216/460] 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 70835825083f5..5a03031519bee 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 09d1d9e67e31f..ce0fb69249a8f 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 3639e6d7304cd..0ccee2ae57204 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 217/460] 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 63253e2b2c1f4..ae3af738b03f5 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 5f25f23c4ff8c..5946c0d0aef99 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 75ee7ebdb614f..a49642bbae4b7 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 cd19546d31fcb..138c3f5e0093a 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 218/460] 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 107623c4cc14a..95a0b63ac560c 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 @@ static int i2cdev_attach_adapter(struct device *dev, void *dummy) 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 @@ static int __init i2c_dev_init(void) 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 219/460] 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 d82c4cacdfb9f..df8b26a425248 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 220/460] 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 f9a5a7c90ff09..64a9c093aef93 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 221/460] 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 9e73922e1e2e5..d47d87c2d7e3d 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 f433121774c01..63c98833d5105 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 5bff37af4770b..03a6434a8cdd0 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 8086d1a281cd3..575e71d6c8ae2 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 e921050022f1f12d5029d1487a7dfc46cde15523 Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Sun, 26 Feb 2023 18:01:36 +0300 Subject: [PATCH 222/460] Revert "riscv: mm: notify remote harts about mmu cache updates" This reverts the remaining bits of commit 4bd1d80efb5a ("riscv: mm: notify remote harts harts about mmu cache updates"). According to bug reports, suggested approach to fix stale TLB entries is not sufficient. It needs to be replaced by a more robust solution. Fixes: 4bd1d80efb5a ("riscv: mm: notify remote harts about mmu cache updates") Reported-by: Zong Li Reported-by: Lad Prabhakar Signed-off-by: Sergey Matyukevich Cc: stable@vger.kernel.org Reviewed-by: Guo Ren Link: https://lore.kernel.org/r/20230226150137.1919750-2-geomatsi@gmail.com Signed-off-by: Palmer Dabbelt --- arch/riscv/include/asm/mmu.h | 2 -- arch/riscv/include/asm/tlbflush.h | 18 ------------------ arch/riscv/mm/context.c | 10 ---------- arch/riscv/mm/tlbflush.c | 28 +++++++++++++++++----------- 4 files changed, 17 insertions(+), 41 deletions(-) diff --git a/arch/riscv/include/asm/mmu.h b/arch/riscv/include/asm/mmu.h index 5ff1f19fd45c2..0099dc1161683 100644 --- a/arch/riscv/include/asm/mmu.h +++ b/arch/riscv/include/asm/mmu.h @@ -19,8 +19,6 @@ typedef struct { #ifdef CONFIG_SMP /* A local icache flush is needed before user execution can resume. */ cpumask_t icache_stale_mask; - /* A local tlb flush is needed before user execution can resume. */ - cpumask_t tlb_stale_mask; #endif } mm_context_t; diff --git a/arch/riscv/include/asm/tlbflush.h b/arch/riscv/include/asm/tlbflush.h index 907b9efd39a87..801019381dea3 100644 --- a/arch/riscv/include/asm/tlbflush.h +++ b/arch/riscv/include/asm/tlbflush.h @@ -22,24 +22,6 @@ static inline void local_flush_tlb_page(unsigned long addr) { ALT_FLUSH_TLB_PAGE(__asm__ __volatile__ ("sfence.vma %0" : : "r" (addr) : "memory")); } - -static inline void local_flush_tlb_all_asid(unsigned long asid) -{ - __asm__ __volatile__ ("sfence.vma x0, %0" - : - : "r" (asid) - : "memory"); -} - -static inline void local_flush_tlb_page_asid(unsigned long addr, - unsigned long asid) -{ - __asm__ __volatile__ ("sfence.vma %0, %1" - : - : "r" (addr), "r" (asid) - : "memory"); -} - #else /* CONFIG_MMU */ #define local_flush_tlb_all() do { } while (0) #define local_flush_tlb_page(addr) do { } while (0) diff --git a/arch/riscv/mm/context.c b/arch/riscv/mm/context.c index 80ce9caba8d22..7acbfbd14557e 100644 --- a/arch/riscv/mm/context.c +++ b/arch/riscv/mm/context.c @@ -196,16 +196,6 @@ static void set_mm_asid(struct mm_struct *mm, unsigned int cpu) if (need_flush_tlb) local_flush_tlb_all(); -#ifdef CONFIG_SMP - else { - cpumask_t *mask = &mm->context.tlb_stale_mask; - - if (cpumask_test_cpu(cpu, mask)) { - cpumask_clear_cpu(cpu, mask); - local_flush_tlb_all_asid(cntx & asid_mask); - } - } -#endif } static void set_mm_noasid(struct mm_struct *mm) diff --git a/arch/riscv/mm/tlbflush.c b/arch/riscv/mm/tlbflush.c index ce7dfc81bb3fe..37ed760d007c3 100644 --- a/arch/riscv/mm/tlbflush.c +++ b/arch/riscv/mm/tlbflush.c @@ -5,7 +5,23 @@ #include #include #include -#include + +static inline void local_flush_tlb_all_asid(unsigned long asid) +{ + __asm__ __volatile__ ("sfence.vma x0, %0" + : + : "r" (asid) + : "memory"); +} + +static inline void local_flush_tlb_page_asid(unsigned long addr, + unsigned long asid) +{ + __asm__ __volatile__ ("sfence.vma %0, %1" + : + : "r" (addr), "r" (asid) + : "memory"); +} void flush_tlb_all(void) { @@ -15,7 +31,6 @@ void flush_tlb_all(void) static void __sbi_tlb_flush_range(struct mm_struct *mm, unsigned long start, unsigned long size, unsigned long stride) { - struct cpumask *pmask = &mm->context.tlb_stale_mask; struct cpumask *cmask = mm_cpumask(mm); unsigned int cpuid; bool broadcast; @@ -29,15 +44,6 @@ static void __sbi_tlb_flush_range(struct mm_struct *mm, unsigned long start, if (static_branch_unlikely(&use_asid_allocator)) { unsigned long asid = atomic_long_read(&mm->context.id); - /* - * TLB will be immediately flushed on harts concurrently - * executing this MM context. TLB flush on other harts - * is deferred until this MM context migrates there. - */ - cpumask_setall(pmask); - cpumask_clear_cpu(cpuid, pmask); - cpumask_andnot(pmask, pmask, cmask); - if (broadcast) { sbi_remote_sfence_vma_asid(cmask, start, size, asid); } else if (size <= stride) { From 82dd33fde0268cc622d3d1ac64971f3f61634142 Mon Sep 17 00:00:00 2001 From: Guo Ren Date: Sun, 26 Feb 2023 18:01:37 +0300 Subject: [PATCH 223/460] riscv: asid: Fixup stale TLB entry cause application crash After use_asid_allocator is enabled, the userspace application will crash by stale TLB entries. Because only using cpumask_clear_cpu without local_flush_tlb_all couldn't guarantee CPU's TLB entries were fresh. Then set_mm_asid would cause the user space application to get a stale value by stale TLB entry, but set_mm_noasid is okay. Here is the symptom of the bug: unhandled signal 11 code 0x1 (coredump) 0x0000003fd6d22524 <+4>: auipc s0,0x70 0x0000003fd6d22528 <+8>: ld s0,-148(s0) # 0x3fd6d92490 => 0x0000003fd6d2252c <+12>: ld a5,0(s0) (gdb) i r s0 s0 0x8082ed1cc3198b21 0x8082ed1cc3198b21 (gdb) x /2x 0x3fd6d92490 0x3fd6d92490: 0xd80ac8a8 0x0000003f The core dump file shows that register s0 is wrong, but the value in memory is correct. Because 'ld s0, -148(s0)' used a stale mapping entry in TLB and got a wrong result from an incorrect physical address. When the task ran on CPU0, which loaded/speculative-loaded the value of address(0x3fd6d92490), then the first version of the mapping entry was PTWed into CPU0's TLB. When the task switched from CPU0 to CPU1 (No local_tlb_flush_all here by asid), it happened to write a value on the address (0x3fd6d92490). It caused do_page_fault -> wp_page_copy -> ptep_clear_flush -> ptep_get_and_clear & flush_tlb_page. The flush_tlb_page used mm_cpumask(mm) to determine which CPUs need TLB flush, but CPU0 had cleared the CPU0's mm_cpumask in the previous switch_mm. So we only flushed the CPU1 TLB and set the second version mapping of the PTE. When the task switched from CPU1 to CPU0 again, CPU0 still used a stale TLB mapping entry which contained a wrong target physical address. It raised a bug when the task happened to read that value. CPU0 CPU1 - switch 'task' in - read addr (Fill stale mapping entry into TLB) - switch 'task' out (no tlb_flush) - switch 'task' in (no tlb_flush) - write addr cause pagefault do_page_fault() (change to new addr mapping) wp_page_copy() ptep_clear_flush() ptep_get_and_clear() & flush_tlb_page() write new value into addr - switch 'task' out (no tlb_flush) - switch 'task' in (no tlb_flush) - read addr again (Use stale mapping entry in TLB) get wrong value from old phyical addr, BUG! The solution is to keep all CPUs' footmarks of cpumask(mm) in switch_mm, which could guarantee to invalidate all stale TLB entries during TLB flush. Fixes: 65d4b9c53017 ("RISC-V: Implement ASID allocator") Signed-off-by: Guo Ren Signed-off-by: Guo Ren Tested-by: Lad Prabhakar Tested-by: Zong Li Tested-by: Sergey Matyukevich Cc: Anup Patel Cc: Palmer Dabbelt Cc: stable@vger.kernel.org Reviewed-by: Andrew Jones Link: https://lore.kernel.org/r/20230226150137.1919750-3-geomatsi@gmail.com Signed-off-by: Palmer Dabbelt --- arch/riscv/mm/context.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/arch/riscv/mm/context.c b/arch/riscv/mm/context.c index 7acbfbd14557e..0f784e3d307bb 100644 --- a/arch/riscv/mm/context.c +++ b/arch/riscv/mm/context.c @@ -205,12 +205,24 @@ static void set_mm_noasid(struct mm_struct *mm) local_flush_tlb_all(); } -static inline void set_mm(struct mm_struct *mm, unsigned int cpu) +static inline void set_mm(struct mm_struct *prev, + struct mm_struct *next, unsigned int cpu) { - if (static_branch_unlikely(&use_asid_allocator)) - set_mm_asid(mm, cpu); - else - set_mm_noasid(mm); + /* + * The mm_cpumask indicates which harts' TLBs contain the virtual + * address mapping of the mm. Compared to noasid, using asid + * can't guarantee that stale TLB entries are invalidated because + * the asid mechanism wouldn't flush TLB for every switch_mm for + * performance. So when using asid, keep all CPUs footmarks in + * cpumask() until mm reset. + */ + cpumask_set_cpu(cpu, mm_cpumask(next)); + if (static_branch_unlikely(&use_asid_allocator)) { + set_mm_asid(next, cpu); + } else { + cpumask_clear_cpu(cpu, mm_cpumask(prev)); + set_mm_noasid(next); + } } static int __init asids_init(void) @@ -264,7 +276,8 @@ static int __init asids_init(void) } early_initcall(asids_init); #else -static inline void set_mm(struct mm_struct *mm, unsigned int cpu) +static inline void set_mm(struct mm_struct *prev, + struct mm_struct *next, unsigned int cpu) { /* Nothing to do here when there is no MMU */ } @@ -317,10 +330,7 @@ void switch_mm(struct mm_struct *prev, struct mm_struct *next, */ cpu = smp_processor_id(); - cpumask_clear_cpu(cpu, mm_cpumask(prev)); - cpumask_set_cpu(cpu, mm_cpumask(next)); - - set_mm(next, cpu); + set_mm(prev, next, cpu); flush_icache_deferred(next, cpu); } From 5cf9d015be160e2d90d29ae74ef1364390e8fce8 Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Wed, 8 Mar 2023 13:47:11 -0700 Subject: [PATCH 224/460] clk: Avoid invalid function names in CLK_OF_DECLARE() After commit c28cd1f3433c ("clk: Mark a fwnode as initialized when using CLK_OF_DECLARE() macro"), drivers/clk/mvebu/kirkwood.c fails to build: drivers/clk/mvebu/kirkwood.c:358:1: error: expected identifier or '(' CLK_OF_DECLARE(98dx1135_clk, "marvell,mv98dx1135-core-clock", ^ include/linux/clk-provider.h:1367:21: note: expanded from macro 'CLK_OF_DECLARE' static void __init name##_of_clk_init_declare(struct device_node *np) \ ^ :124:1: note: expanded from here 98dx1135_clk_of_clk_init_declare ^ drivers/clk/mvebu/kirkwood.c:358:1: error: invalid digit 'd' in decimal constant include/linux/clk-provider.h:1372:34: note: expanded from macro 'CLK_OF_DECLARE' OF_DECLARE_1(clk, name, compat, name##_of_clk_init_declare) ^ :125:3: note: expanded from here 98dx1135_clk_of_clk_init_declare ^ drivers/clk/mvebu/kirkwood.c:358:1: error: invalid digit 'd' in decimal constant include/linux/clk-provider.h:1372:34: note: expanded from macro 'CLK_OF_DECLARE' OF_DECLARE_1(clk, name, compat, name##_of_clk_init_declare) ^ :125:3: note: expanded from here 98dx1135_clk_of_clk_init_declare ^ drivers/clk/mvebu/kirkwood.c:358:1: error: invalid digit 'd' in decimal constant include/linux/clk-provider.h:1372:34: note: expanded from macro 'CLK_OF_DECLARE' OF_DECLARE_1(clk, name, compat, name##_of_clk_init_declare) ^ :125:3: note: expanded from here 98dx1135_clk_of_clk_init_declare ^ C function names must start with either an alphabetic letter or an underscore. To avoid generating invalid function names from clock names, add two underscores to the beginning of the identifier. Fixes: c28cd1f3433c ("clk: Mark a fwnode as initialized when using CLK_OF_DECLARE() macro") Suggested-by: Saravana Kannan Signed-off-by: Nathan Chancellor Link: https://lore.kernel.org/r/20230308-clk_of_declare-fix-v1-1-317b741e2532@kernel.org Reviewed-by: Saravana Kannan Reported-by: Naresh Kamboju Signed-off-by: Stephen Boyd --- include/linux/clk-provider.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index c9f5276006a09..6f3175f0678a8 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -1364,12 +1364,12 @@ struct clk_hw_onecell_data { }; #define CLK_OF_DECLARE(name, compat, fn) \ - static void __init name##_of_clk_init_declare(struct device_node *np) \ + static void __init __##name##_of_clk_init_declare(struct device_node *np) \ { \ fn(np); \ fwnode_dev_initialized(of_fwnode_handle(np), true); \ } \ - OF_DECLARE_1(clk, name, compat, name##_of_clk_init_declare) + OF_DECLARE_1(clk, name, compat, __##name##_of_clk_init_declare) /* * Use this macro when you have a driver that requires two initialization From 4b1a2c2a8e0ddcb89c5f6c5003bd9b53142f69e3 Mon Sep 17 00:00:00 2001 From: Lee Duncan Date: Wed, 28 Sep 2022 11:13:50 -0700 Subject: [PATCH 225/460] scsi: core: Add BLIST_NO_VPD_SIZE for some VDASD Some storage, such as AIX VDASD (virtual storage) and IBM 2076 (front end), fail as a result of commit c92a6b5d6335 ("scsi: core: Query VPD size before getting full page"). That commit changed getting SCSI VPD pages so that we now read just enough of the page to get the actual page size, then read the whole page in a second read. The problem is that the above mentioned hardware returns zero for the page size, because of a firmware error. In such cases, until the firmware is fixed, this new blacklist flag says to revert to the original method of reading the VPD pages, i.e. try to read a whole buffer's worth on the first try. [mkp: reworked somewhat] Fixes: c92a6b5d6335 ("scsi: core: Query VPD size before getting full page") Reported-by: Martin Wilck Suggested-by: Hannes Reinecke Signed-off-by: Lee Duncan Link: https://lore.kernel.org/r/20220928181350.9948-1-leeman.duncan@gmail.com Tested-by: Srikar Dronamraju Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi.c | 3 +++ drivers/scsi/scsi_devinfo.c | 3 ++- drivers/scsi/scsi_scan.c | 3 +++ include/scsi/scsi_device.h | 2 ++ include/scsi/scsi_devinfo.h | 6 +++--- 5 files changed, 13 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 7d2210a006f0d..5cce1ba70fc60 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -326,6 +326,9 @@ static int scsi_get_vpd_size(struct scsi_device *sdev, u8 page) unsigned char vpd_header[SCSI_VPD_HEADER_SIZE] __aligned(4); int result; + if (sdev->no_vpd_size) + return SCSI_DEFAULT_VPD_LEN; + /* * Fetch the VPD page header to find out how big the page * is. This is done to prevent problems on legacy devices diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c index c7080454aea99..bc9d280417f6a 100644 --- a/drivers/scsi/scsi_devinfo.c +++ b/drivers/scsi/scsi_devinfo.c @@ -134,7 +134,7 @@ static struct { {"3PARdata", "VV", NULL, BLIST_REPORTLUN2}, {"ADAPTEC", "AACRAID", NULL, BLIST_FORCELUN}, {"ADAPTEC", "Adaptec 5400S", NULL, BLIST_FORCELUN}, - {"AIX", "VDASD", NULL, BLIST_TRY_VPD_PAGES}, + {"AIX", "VDASD", NULL, BLIST_TRY_VPD_PAGES | BLIST_NO_VPD_SIZE}, {"AFT PRO", "-IX CF", "0.0>", BLIST_FORCELUN}, {"BELKIN", "USB 2 HS-CF", "1.95", BLIST_FORCELUN | BLIST_INQUIRY_36}, {"BROWNIE", "1200U3P", NULL, BLIST_NOREPORTLUN}, @@ -188,6 +188,7 @@ static struct { {"HPE", "OPEN-", "*", BLIST_REPORTLUN2 | BLIST_TRY_VPD_PAGES}, {"IBM", "AuSaV1S2", NULL, BLIST_FORCELUN}, {"IBM", "ProFibre 4000R", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, + {"IBM", "2076", NULL, BLIST_NO_VPD_SIZE}, {"IBM", "2105", NULL, BLIST_RETRY_HWERROR}, {"iomega", "jaz 1GB", "J.86", BLIST_NOTQ | BLIST_NOLUN}, {"IOMEGA", "ZIP", NULL, BLIST_NOTQ | BLIST_NOLUN}, diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 4e842d79de317..d217be323cc69 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -1057,6 +1057,9 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, else if (*bflags & BLIST_SKIP_VPD_PAGES) sdev->skip_vpd_pages = 1; + if (*bflags & BLIST_NO_VPD_SIZE) + sdev->no_vpd_size = 1; + transport_configure_device(&sdev->sdev_gendev); if (sdev->host->hostt->slave_configure) { diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index de310f21406c5..f10a008e5bfa1 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -145,6 +145,7 @@ struct scsi_device { const char * model; /* ... after scan; point to static string */ const char * rev; /* ... "nullnullnullnull" before scan */ +#define SCSI_DEFAULT_VPD_LEN 255 /* default SCSI VPD page size (max) */ struct scsi_vpd __rcu *vpd_pg0; struct scsi_vpd __rcu *vpd_pg83; struct scsi_vpd __rcu *vpd_pg80; @@ -215,6 +216,7 @@ struct scsi_device { * creation time */ unsigned ignore_media_change:1; /* Ignore MEDIA CHANGE on resume */ unsigned silence_suspend:1; /* Do not print runtime PM related messages */ + unsigned no_vpd_size:1; /* No VPD size reported in header */ unsigned int queue_stopped; /* request queue is quiesced */ bool offline_already; /* Device offline message logged */ diff --git a/include/scsi/scsi_devinfo.h b/include/scsi/scsi_devinfo.h index 5d14adae21c78..6b548dc2c4965 100644 --- a/include/scsi/scsi_devinfo.h +++ b/include/scsi/scsi_devinfo.h @@ -32,7 +32,8 @@ #define BLIST_IGN_MEDIA_CHANGE ((__force blist_flags_t)(1ULL << 11)) /* do not do automatic start on add */ #define BLIST_NOSTARTONADD ((__force blist_flags_t)(1ULL << 12)) -#define __BLIST_UNUSED_13 ((__force blist_flags_t)(1ULL << 13)) +/* do not ask for VPD page size first on some broken targets */ +#define BLIST_NO_VPD_SIZE ((__force blist_flags_t)(1ULL << 13)) #define __BLIST_UNUSED_14 ((__force blist_flags_t)(1ULL << 14)) #define __BLIST_UNUSED_15 ((__force blist_flags_t)(1ULL << 15)) #define __BLIST_UNUSED_16 ((__force blist_flags_t)(1ULL << 16)) @@ -74,8 +75,7 @@ #define __BLIST_HIGH_UNUSED (~(__BLIST_LAST_USED | \ (__force blist_flags_t) \ ((__force __u64)__BLIST_LAST_USED - 1ULL))) -#define __BLIST_UNUSED_MASK (__BLIST_UNUSED_13 | \ - __BLIST_UNUSED_14 | \ +#define __BLIST_UNUSED_MASK (__BLIST_UNUSED_14 | \ __BLIST_UNUSED_15 | \ __BLIST_UNUSED_16 | \ __BLIST_UNUSED_24 | \ From be03df3d4bfe7e8866d4aa43d62e648ffe884f5f Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Tue, 7 Mar 2023 13:44:28 -0800 Subject: [PATCH 226/460] scsi: core: Fix a procfs host directory removal regression scsi_proc_hostdir_rm() decreases a reference counter and hence must only be called once per host that is removed. This change does not require a scsi_add_host_with_dma() change since scsi_add_host_with_dma() will return 0 (success) if scsi_proc_host_add() is called. Fixes: fc663711b944 ("scsi: core: Remove the /proc/scsi/${proc_name} directory earlier") Cc: John Garry Reported-by: John Garry Link: https://lore.kernel.org/all/ed6b8027-a9d9-1b45-be8e-df4e8c6c4605@oracle.com/ Reported-by: syzbot+645a4616b87a2f10e398@syzkaller.appspotmail.com Link: https://lore.kernel.org/linux-scsi/000000000000890fab05f65342b6@google.com/ Signed-off-by: Bart Van Assche Link: https://lore.kernel.org/r/20230307214428.3703498-1-bvanassche@acm.org Tested-by: John Garry Tested-by: Shin'ichiro Kawasaki Signed-off-by: Martin K. Petersen --- drivers/scsi/hosts.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index f7f62e56afcae..9b6fbbe15d922 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -341,9 +341,6 @@ static void scsi_host_dev_release(struct device *dev) struct Scsi_Host *shost = dev_to_shost(dev); struct device *parent = dev->parent; - /* In case scsi_remove_host() has not been called. */ - scsi_proc_hostdir_rm(shost->hostt); - /* Wait for functions invoked through call_rcu(&scmd->rcu, ...) */ rcu_barrier(); From c6001025d53ab56d7159cf313313c6b5bd250380 Mon Sep 17 00:00:00 2001 From: Asutosh Das Date: Wed, 8 Mar 2023 15:13:23 -0800 Subject: [PATCH 227/460] scsi: ufs: mcq: Use active_reqs to check busy in clock scaling Multi Circular Queue doesn't use outstanding_reqs. However, the UFS clock scaling functions use outstanding_reqs to determine if there are requests pending. When MCQ is enabled, this check always returns false. Hence use active_reqs to check if there are pending requests. Fixes: eacb139b77ff ("scsi: ufs: core: mcq: Enable multi-circular queue") Signed-off-by: Asutosh Das Reviewed-by: Manivannan Sadhasivam Link: https://lore.kernel.org/r/a24e0d646aac70eae0fc5e05fac0c58bb7e6e680.1678317160.git.quic_asutoshd@quicinc.com Signed-off-by: Martin K. Petersen --- drivers/ufs/core/ufshcd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c index 05eac965ee275..37e178a9ac475 100644 --- a/drivers/ufs/core/ufshcd.c +++ b/drivers/ufs/core/ufshcd.c @@ -1500,7 +1500,7 @@ static int ufshcd_devfreq_get_dev_status(struct device *dev, scaling->window_start_t = curr_t; scaling->tot_busy_t = 0; - if (hba->outstanding_reqs) { + if (scaling->active_reqs) { scaling->busy_start_t = curr_t; scaling->is_busy_started = true; } else { @@ -2118,7 +2118,7 @@ static void ufshcd_clk_scaling_update_busy(struct ufs_hba *hba) spin_lock_irqsave(hba->host->host_lock, flags); hba->clk_scaling.active_reqs--; - if (!hba->outstanding_reqs && scaling->is_busy_started) { + if (!scaling->active_reqs && scaling->is_busy_started) { scaling->tot_busy_t += ktime_to_us(ktime_sub(ktime_get(), scaling->busy_start_t)); scaling->busy_start_t = 0; From 93bb18d2a873d2fa9625c8ea927723660a868b95 Mon Sep 17 00:00:00 2001 From: lyndonli Date: Thu, 2 Mar 2023 14:18:12 +0800 Subject: [PATCH 228/460] 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 e3e1ed4314dd6..6c7d672412b21 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 229/460] 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 4b0d563c6522c..4ef1fa4603c8e 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 230/460] 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 cbef2e147da58..38c9e1ca66913 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 231/460] 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 28fe6d9410540..3f5d13035aff0 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 232/460] 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 7cd17dda32ceb..2eddd7f6cd41e 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 233/460] 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 620f7409825df..9df2236007ab0 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 234/460] 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 d972025f0d20f..855d390c41de1 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 235/460] 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 9df2236007ab0..061793d390ccc 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 e0213434fe3e4a0d118923dc98d31e7ff1cd9e45 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Google)" Date: Wed, 1 Mar 2023 20:00:52 -0500 Subject: [PATCH 236/460] tracing: Do not let histogram values have some modifiers Histogram values can not be strings, stacktraces, graphs, symbols, syscalls, or grouped in buckets or log. Give an error if a value is set to do so. Note, the histogram code was not prepared to handle these modifiers for histograms and caused a bug. Mark Rutland reported: # echo 'p:copy_to_user __arch_copy_to_user n=$arg2' >> /sys/kernel/tracing/kprobe_events # echo 'hist:keys=n:vals=hitcount.buckets=8:sort=hitcount' > /sys/kernel/tracing/events/kprobes/copy_to_user/trigger # cat /sys/kernel/tracing/events/kprobes/copy_to_user/hist [ 143.694628] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000 [ 143.695190] Mem abort info: [ 143.695362] ESR = 0x0000000096000004 [ 143.695604] EC = 0x25: DABT (current EL), IL = 32 bits [ 143.695889] SET = 0, FnV = 0 [ 143.696077] EA = 0, S1PTW = 0 [ 143.696302] FSC = 0x04: level 0 translation fault [ 143.702381] Data abort info: [ 143.702614] ISV = 0, ISS = 0x00000004 [ 143.702832] CM = 0, WnR = 0 [ 143.703087] user pgtable: 4k pages, 48-bit VAs, pgdp=00000000448f9000 [ 143.703407] [0000000000000000] pgd=0000000000000000, p4d=0000000000000000 [ 143.704137] Internal error: Oops: 0000000096000004 [#1] PREEMPT SMP [ 143.704714] Modules linked in: [ 143.705273] CPU: 0 PID: 133 Comm: cat Not tainted 6.2.0-00003-g6fc512c10a7c #3 [ 143.706138] Hardware name: linux,dummy-virt (DT) [ 143.706723] pstate: 80000005 (Nzcv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) [ 143.707120] pc : hist_field_name.part.0+0x14/0x140 [ 143.707504] lr : hist_field_name.part.0+0x104/0x140 [ 143.707774] sp : ffff800008333a30 [ 143.707952] x29: ffff800008333a30 x28: 0000000000000001 x27: 0000000000400cc0 [ 143.708429] x26: ffffd7a653b20260 x25: 0000000000000000 x24: ffff10d303ee5800 [ 143.708776] x23: ffffd7a6539b27b0 x22: ffff10d303fb8c00 x21: 0000000000000001 [ 143.709127] x20: ffff10d303ec2000 x19: 0000000000000000 x18: 0000000000000000 [ 143.709478] x17: 0000000000000000 x16: 0000000000000000 x15: 0000000000000000 [ 143.709824] x14: 0000000000000000 x13: 203a6f666e692072 x12: 6567676972742023 [ 143.710179] x11: 0a230a6d6172676f x10: 000000000000002c x9 : ffffd7a6521e018c [ 143.710584] x8 : 000000000000002c x7 : 7f7f7f7f7f7f7f7f x6 : 000000000000002c [ 143.710915] x5 : ffff10d303b0103e x4 : ffffd7a653b20261 x3 : 000000000000003d [ 143.711239] x2 : 0000000000020001 x1 : 0000000000000001 x0 : 0000000000000000 [ 143.711746] Call trace: [ 143.712115] hist_field_name.part.0+0x14/0x140 [ 143.712642] hist_field_name.part.0+0x104/0x140 [ 143.712925] hist_field_print+0x28/0x140 [ 143.713125] event_hist_trigger_print+0x174/0x4d0 [ 143.713348] hist_show+0xf8/0x980 [ 143.713521] seq_read_iter+0x1bc/0x4b0 [ 143.713711] seq_read+0x8c/0xc4 [ 143.713876] vfs_read+0xc8/0x2a4 [ 143.714043] ksys_read+0x70/0xfc [ 143.714218] __arm64_sys_read+0x24/0x30 [ 143.714400] invoke_syscall+0x50/0x120 [ 143.714587] el0_svc_common.constprop.0+0x4c/0x100 [ 143.714807] do_el0_svc+0x44/0xd0 [ 143.714970] el0_svc+0x2c/0x84 [ 143.715134] el0t_64_sync_handler+0xbc/0x140 [ 143.715334] el0t_64_sync+0x190/0x194 [ 143.715742] Code: a9bd7bfd 910003fd a90153f3 aa0003f3 (f9400000) [ 143.716510] ---[ end trace 0000000000000000 ]--- Segmentation fault Link: https://lkml.kernel.org/r/20230302020810.559462599@goodmis.org Cc: stable@vger.kernel.org Cc: Masami Hiramatsu Cc: Andrew Morton Fixes: c6afad49d127f ("tracing: Add hist trigger 'sym' and 'sym-offset' modifiers") Reported-by: Mark Rutland Tested-by: Mark Rutland Signed-off-by: Steven Rostedt (Google) --- kernel/trace/trace_events_hist.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c index 89877a18f9330..6e8ab726a7b5e 100644 --- a/kernel/trace/trace_events_hist.c +++ b/kernel/trace/trace_events_hist.c @@ -4235,6 +4235,15 @@ static int __create_val_field(struct hist_trigger_data *hist_data, goto out; } + /* Some types cannot be a value */ + if (hist_field->flags & (HIST_FIELD_FL_GRAPH | HIST_FIELD_FL_PERCENT | + HIST_FIELD_FL_BUCKET | HIST_FIELD_FL_LOG2 | + HIST_FIELD_FL_SYM | HIST_FIELD_FL_SYM_OFFSET | + HIST_FIELD_FL_SYSCALL | HIST_FIELD_FL_STACKTRACE)) { + hist_err(file->tr, HIST_ERR_BAD_FIELD_MODIFIER, errpos(field_str)); + ret = -EINVAL; + } + hist_data->fields[val_idx] = hist_field; ++hist_data->n_vals; From 9f116f76fa8c04c81aef33ad870dbf9a158e5b70 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Google)" Date: Wed, 1 Mar 2023 20:00:53 -0500 Subject: [PATCH 237/460] tracing: Check field value in hist_field_name() The function hist_field_name() cannot handle being passed a NULL field parameter. It should never be NULL, but due to a previous bug, NULL was passed to the function and the kernel crashed due to a NULL dereference. Mark Rutland reported this to me on IRC. The bug was fixed, but to prevent future bugs from crashing the kernel, check the field and add a WARN_ON() if it is NULL. Link: https://lkml.kernel.org/r/20230302020810.762384440@goodmis.org Cc: stable@vger.kernel.org Cc: Masami Hiramatsu Cc: Andrew Morton Reported-by: Mark Rutland Fixes: c6afad49d127f ("tracing: Add hist trigger 'sym' and 'sym-offset' modifiers") Tested-by: Mark Rutland Signed-off-by: Steven Rostedt (Google) --- kernel/trace/trace_events_hist.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c index 6e8ab726a7b5e..486cca3c2b754 100644 --- a/kernel/trace/trace_events_hist.c +++ b/kernel/trace/trace_events_hist.c @@ -1331,6 +1331,9 @@ static const char *hist_field_name(struct hist_field *field, { const char *field_name = ""; + if (WARN_ON_ONCE(!field)) + return field_name; + if (level > 1) return field_name; From ee92fa443358f4fc0017c1d0d325c27b37802504 Mon Sep 17 00:00:00 2001 From: Chen Zhongjin Date: Thu, 9 Mar 2023 16:02:30 +0800 Subject: [PATCH 238/460] ftrace: Fix invalid address access in lookup_rec() when index is 0 KASAN reported follow problem: BUG: KASAN: use-after-free in lookup_rec Read of size 8 at addr ffff000199270ff0 by task modprobe CPU: 2 Comm: modprobe Call trace: kasan_report __asan_load8 lookup_rec ftrace_location arch_check_ftrace_location check_kprobe_address_safe register_kprobe When checking pg->records[pg->index - 1].ip in lookup_rec(), it can get a pg which is newly added to ftrace_pages_start in ftrace_process_locs(). Before the first pg->index++, index is 0 and accessing pg->records[-1].ip will cause this problem. Don't check the ip when pg->index is 0. Link: https://lore.kernel.org/linux-trace-kernel/20230309080230.36064-1-chenzhongjin@huawei.com Cc: stable@vger.kernel.org Fixes: 9644302e3315 ("ftrace: Speed up search by skipping pages by address") Suggested-by: Steven Rostedt (Google) Signed-off-by: Chen Zhongjin Signed-off-by: Steven Rostedt (Google) --- kernel/trace/ftrace.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 750aa3f08b25a..a47f7d93e32d2 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -1537,7 +1537,8 @@ static struct dyn_ftrace *lookup_rec(unsigned long start, unsigned long end) key.flags = end; /* overload flags, as it is unsigned long */ for (pg = ftrace_pages_start; pg; pg = pg->next) { - if (end < pg->records[0].ip || + if (pg->index == 0 || + end < pg->records[0].ip || start >= (pg->records[pg->index - 1].ip + MCOUNT_INSN_SIZE)) continue; rec = bsearch(&key, pg->records, pg->index, From aa69f814920d85a2d4cfd5c294757c3d59d2fba6 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 31 Jan 2023 10:36:30 +0100 Subject: [PATCH 239/460] ftrace,kcfi: Define ftrace_stub_graph conditionally When CONFIG_FUNCTION_GRAPH_TRACER is disabled, __kcfi_typeid_ftrace_stub_graph is missing, causing a link failure: ld.lld: error: undefined symbol: __kcfi_typeid_ftrace_stub_graph referenced by arch/x86/kernel/ftrace_64.o:(__cfi_ftrace_stub_graph) in archive vmlinux.a Mark the reference to it as conditional on the same symbol, as is done on arm64. Link: https://lore.kernel.org/linux-trace-kernel/20230131093643.3850272-1-arnd@kernel.org Cc: Peter Zijlstra Cc: Masami Hiramatsu Cc: Mark Rutland Cc: Thomas Gleixner Cc: Ingo Molnar Cc: Borislav Petkov Cc: Dave Hansen Cc: "H. Peter Anvin" Cc: Josh Poimboeuf Fixes: 883bbbffa5a4 ("ftrace,kcfi: Separate ftrace_stub() and ftrace_stub_graph()") See-also: 2598ac6ec493 ("arm64: ftrace: Define ftrace_stub_graph only with FUNCTION_GRAPH_TRACER") Signed-off-by: Arnd Bergmann Signed-off-by: Steven Rostedt (Google) --- arch/x86/kernel/ftrace_64.S | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/kernel/ftrace_64.S b/arch/x86/kernel/ftrace_64.S index 1265ad519249c..fb4f1e01b64a2 100644 --- a/arch/x86/kernel/ftrace_64.S +++ b/arch/x86/kernel/ftrace_64.S @@ -136,10 +136,12 @@ SYM_TYPED_FUNC_START(ftrace_stub) RET SYM_FUNC_END(ftrace_stub) +#ifdef CONFIG_FUNCTION_GRAPH_TRACER SYM_TYPED_FUNC_START(ftrace_stub_graph) CALL_DEPTH_ACCOUNT RET SYM_FUNC_END(ftrace_stub_graph) +#endif #ifdef CONFIG_DYNAMIC_FTRACE From 609d54441493c99f21c1823dfd66fa7f4c512ff4 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Mon, 6 Mar 2023 13:54:50 -0500 Subject: [PATCH 240/460] 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 c942c89ca4cda..7893ea161d770 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 bced3f7db95ff2e6ca29dc4d1c9751ab5e736a09 Mon Sep 17 00:00:00 2001 From: Breno Leitao Date: Wed, 8 Mar 2023 11:07:45 -0800 Subject: [PATCH 241/460] tcp: tcp_make_synack() can be called from process context tcp_rtx_synack() now could be called in process context as explained in 0a375c822497 ("tcp: tcp_rtx_synack() can be called from process context"). tcp_rtx_synack() might call tcp_make_synack(), which will touch per-CPU variables with preemption enabled. This causes the following BUG: BUG: using __this_cpu_add() in preemptible [00000000] code: ThriftIO1/5464 caller is tcp_make_synack+0x841/0xac0 Call Trace: dump_stack_lvl+0x10d/0x1a0 check_preemption_disabled+0x104/0x110 tcp_make_synack+0x841/0xac0 tcp_v6_send_synack+0x5c/0x450 tcp_rtx_synack+0xeb/0x1f0 inet_rtx_syn_ack+0x34/0x60 tcp_check_req+0x3af/0x9e0 tcp_rcv_state_process+0x59b/0x2030 tcp_v6_do_rcv+0x5f5/0x700 release_sock+0x3a/0xf0 tcp_sendmsg+0x33/0x40 ____sys_sendmsg+0x2f2/0x490 __sys_sendmsg+0x184/0x230 do_syscall_64+0x3d/0x90 Avoid calling __TCP_INC_STATS() with will touch per-cpu variables. Use TCP_INC_STATS() which is safe to be called from context switch. Fixes: 8336886f786f ("tcp: TCP Fast Open Server - support TFO listeners") Signed-off-by: Breno Leitao Reviewed-by: Eric Dumazet Link: https://lore.kernel.org/r/20230308190745.780221-1-leitao@debian.org Signed-off-by: Jakub Kicinski --- net/ipv4/tcp_output.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 71d01cf3c13eb..ba839e441450f 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -3605,7 +3605,7 @@ struct sk_buff *tcp_make_synack(const struct sock *sk, struct dst_entry *dst, th->window = htons(min(req->rsk_rcv_wnd, 65535U)); tcp_options_write(th, NULL, &opts); th->doff = (tcp_header_size >> 2); - __TCP_INC_STATS(sock_net(sk), TCP_MIB_OUTSEGS); + TCP_INC_STATS(sock_net(sk), TCP_MIB_OUTSEGS); #ifdef CONFIG_TCP_MD5SIG /* Okay, we have all we need - do the md5 hash if needed */ From aed8efddd39b3434c96718d39009285c52b1cafc Mon Sep 17 00:00:00 2001 From: Cindy Lu Date: Tue, 14 Feb 2023 16:09:24 +0800 Subject: [PATCH 242/460] vp_vdpa: fix the crash in hot unplug with vp_vdpa While unplugging the vp_vdpa device, it triggers a kernel panic The root cause is: vdpa_mgmtdev_unregister() will accesses modern devices which will cause a use after free. So need to change the sequence in vp_vdpa_remove [ 195.003359] BUG: unable to handle page fault for address: ff4e8beb80199014 [ 195.004012] #PF: supervisor read access in kernel mode [ 195.004486] #PF: error_code(0x0000) - not-present page [ 195.004960] PGD 100000067 P4D 1001b6067 PUD 1001b7067 PMD 1001b8067 PTE 0 [ 195.005578] Oops: 0000 1 PREEMPT SMP PTI [ 195.005968] CPU: 13 PID: 164 Comm: kworker/u56:10 Kdump: loaded Not tainted 5.14.0-252.el9.x86_64 #1 [ 195.006792] Hardware name: Red Hat KVM/RHEL, BIOS edk2-20221207gitfff6d81270b5-2.el9 unknown [ 195.007556] Workqueue: kacpi_hotplug acpi_hotplug_work_fn [ 195.008059] RIP: 0010:ioread8+0x31/0x80 [ 195.008418] Code: 77 28 48 81 ff 00 00 01 00 76 0b 89 fa ec 0f b6 c0 c3 cc cc cc cc 8b 15 ad 72 93 01 b8 ff 00 00 00 85 d2 75 0f c3 cc cc cc cc <8a> 07 0f b6 c0 c3 cc cc cc cc 83 ea 01 48 83 ec 08 48 89 fe 48 c7 [ 195.010104] RSP: 0018:ff4e8beb8067bab8 EFLAGS: 00010292 [ 195.010584] RAX: ffffffffc05834a0 RBX: ffffffffc05843c0 RCX: ff4e8beb8067bae0 [ 195.011233] RDX: ff1bcbd580f88000 RSI: 0000000000000246 RDI: ff4e8beb80199014 [ 195.011881] RBP: ff1bcbd587e39000 R08: ffffffff916fa2d0 R09: ff4e8beb8067ba68 [ 195.012527] R10: 000000000000001c R11: 0000000000000000 R12: ff1bcbd5a3de9120 [ 195.013179] R13: ffffffffc062d000 R14: 0000000000000080 R15: ff1bcbe402bc7805 [ 195.013826] FS: 0000000000000000(0000) GS:ff1bcbe402740000(0000) knlGS:0000000000000000 [ 195.014564] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 195.015093] CR2: ff4e8beb80199014 CR3: 0000000107dea002 CR4: 0000000000771ee0 [ 195.015741] PKRU: 55555554 [ 195.016001] Call Trace: [ 195.016233] [ 195.016434] vp_modern_get_status+0x12/0x20 [ 195.016823] vp_vdpa_reset+0x1b/0x50 [vp_vdpa] [ 195.017238] virtio_vdpa_reset+0x3c/0x48 [virtio_vdpa] [ 195.017709] remove_vq_common+0x1f/0x3a0 [virtio_net] [ 195.018178] virtnet_remove+0x5d/0x70 [virtio_net] [ 195.018618] virtio_dev_remove+0x3d/0x90 [ 195.018986] device_release_driver_internal+0x1aa/0x230 [ 195.019466] bus_remove_device+0xd8/0x150 [ 195.019841] device_del+0x18b/0x3f0 [ 195.020167] ? kernfs_find_ns+0x35/0xd0 [ 195.020526] device_unregister+0x13/0x60 [ 195.020894] unregister_virtio_device+0x11/0x20 [ 195.021311] device_release_driver_internal+0x1aa/0x230 [ 195.021790] bus_remove_device+0xd8/0x150 [ 195.022162] device_del+0x18b/0x3f0 [ 195.022487] device_unregister+0x13/0x60 [ 195.022852] ? vdpa_dev_remove+0x30/0x30 [vdpa] [ 195.023270] vp_vdpa_dev_del+0x12/0x20 [vp_vdpa] [ 195.023694] vdpa_match_remove+0x2b/0x40 [vdpa] [ 195.024115] bus_for_each_dev+0x78/0xc0 [ 195.024471] vdpa_mgmtdev_unregister+0x65/0x80 [vdpa] [ 195.024937] vp_vdpa_remove+0x23/0x40 [vp_vdpa] [ 195.025353] pci_device_remove+0x36/0xa0 [ 195.025719] device_release_driver_internal+0x1aa/0x230 [ 195.026201] pci_stop_bus_device+0x6c/0x90 [ 195.026580] pci_stop_and_remove_bus_device+0xe/0x20 [ 195.027039] disable_slot+0x49/0x90 [ 195.027366] acpiphp_disable_and_eject_slot+0x15/0x90 [ 195.027832] hotplug_event+0xea/0x210 [ 195.028171] ? hotplug_event+0x210/0x210 [ 195.028535] acpiphp_hotplug_notify+0x22/0x80 [ 195.028942] ? hotplug_event+0x210/0x210 [ 195.029303] acpi_device_hotplug+0x8a/0x1d0 [ 195.029690] acpi_hotplug_work_fn+0x1a/0x30 [ 195.030077] process_one_work+0x1e8/0x3c0 [ 195.030451] worker_thread+0x50/0x3b0 [ 195.030791] ? rescuer_thread+0x3a0/0x3a0 [ 195.031165] kthread+0xd9/0x100 [ 195.031459] ? kthread_complete_and_exit+0x20/0x20 [ 195.031899] ret_from_fork+0x22/0x30 [ 195.032233] Fixes: ffbda8e9df10 ("vdpa/vp_vdpa : add vdpa tool support in vp_vdpa") Tested-by: Lei Yang Cc: stable@vger.kernel.org Signed-off-by: Cindy Lu Message-Id: <20230214080924.131462-1-lulu@redhat.com> Signed-off-by: Michael S. Tsirkin Acked-by: Jason Wang --- drivers/vdpa/virtio_pci/vp_vdpa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/vdpa/virtio_pci/vp_vdpa.c b/drivers/vdpa/virtio_pci/vp_vdpa.c index 8fe267ca3e76f..281287fae89f1 100644 --- a/drivers/vdpa/virtio_pci/vp_vdpa.c +++ b/drivers/vdpa/virtio_pci/vp_vdpa.c @@ -645,8 +645,8 @@ static void vp_vdpa_remove(struct pci_dev *pdev) struct virtio_pci_modern_device *mdev = NULL; mdev = vp_vdpa_mgtdev->mdev; - vp_modern_remove(mdev); vdpa_mgmtdev_unregister(&vp_vdpa_mgtdev->mgtdev); + vp_modern_remove(mdev); kfree(vp_vdpa_mgtdev->mgtdev.id_table); kfree(mdev); kfree(vp_vdpa_mgtdev); From 09e65ee9059d76b89cb713795748805efd3f50c6 Mon Sep 17 00:00:00 2001 From: Si-Wei Liu Date: Tue, 14 Feb 2023 17:30:40 -0800 Subject: [PATCH 243/460] vdpa/mlx5: should not activate virtq object when suspended Otherwise the virtqueue object to instate could point to invalid address that was unmapped from the MTT: mlx5_core 0000:41:04.2: mlx5_cmd_out_err:782:(pid 8321): CREATE_GENERAL_OBJECT(0xa00) op_mod(0xd) failed, status bad parameter(0x3), syndrome (0x5fa1c), err(-22) Fixes: cae15c2ed8e6 ("vdpa/mlx5: Implement susupend virtqueue callback") Cc: Eli Cohen Signed-off-by: Si-Wei Liu Reviewed-by: Eli Cohen Message-Id: <1676424640-11673-1-git-send-email-si-wei.liu@oracle.com> Signed-off-by: Michael S. Tsirkin Acked-by: Jason Wang --- drivers/vdpa/mlx5/core/mlx5_vdpa.h | 1 + drivers/vdpa/mlx5/net/mlx5_vnet.c | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/vdpa/mlx5/core/mlx5_vdpa.h b/drivers/vdpa/mlx5/core/mlx5_vdpa.h index 058fbe28107e9..25fc4120b618d 100644 --- a/drivers/vdpa/mlx5/core/mlx5_vdpa.h +++ b/drivers/vdpa/mlx5/core/mlx5_vdpa.h @@ -96,6 +96,7 @@ struct mlx5_vdpa_dev { struct mlx5_control_vq cvq; struct workqueue_struct *wq; unsigned int group2asid[MLX5_VDPA_NUMVQ_GROUPS]; + bool suspended; }; int mlx5_vdpa_alloc_pd(struct mlx5_vdpa_dev *dev, u32 *pdn, u16 uid); diff --git a/drivers/vdpa/mlx5/net/mlx5_vnet.c b/drivers/vdpa/mlx5/net/mlx5_vnet.c index 3a0e721aef05f..520646ae7fa01 100644 --- a/drivers/vdpa/mlx5/net/mlx5_vnet.c +++ b/drivers/vdpa/mlx5/net/mlx5_vnet.c @@ -2438,7 +2438,7 @@ static int mlx5_vdpa_change_map(struct mlx5_vdpa_dev *mvdev, if (err) goto err_mr; - if (!(mvdev->status & VIRTIO_CONFIG_S_DRIVER_OK)) + if (!(mvdev->status & VIRTIO_CONFIG_S_DRIVER_OK) || mvdev->suspended) goto err_mr; restore_channels_info(ndev); @@ -2606,6 +2606,7 @@ static int mlx5_vdpa_reset(struct vdpa_device *vdev) clear_vqs_ready(ndev); mlx5_vdpa_destroy_mr(&ndev->mvdev); ndev->mvdev.status = 0; + ndev->mvdev.suspended = false; ndev->cur_num_vqs = 0; ndev->mvdev.cvq.received_desc = 0; ndev->mvdev.cvq.completed_desc = 0; @@ -2852,6 +2853,8 @@ static int mlx5_vdpa_suspend(struct vdpa_device *vdev) struct mlx5_vdpa_virtqueue *mvq; int i; + mlx5_vdpa_info(mvdev, "suspending device\n"); + down_write(&ndev->reslock); ndev->nb_registered = false; mlx5_notifier_unregister(mvdev->mdev, &ndev->nb); @@ -2861,6 +2864,7 @@ static int mlx5_vdpa_suspend(struct vdpa_device *vdev) suspend_vq(ndev, mvq); } mlx5_vdpa_cvq_suspend(mvdev); + mvdev->suspended = true; up_write(&ndev->reslock); return 0; } From f624bb6fad23df3270580b4fcef415c6e7bf7705 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 1 Mar 2023 12:09:29 +0200 Subject: [PATCH 244/460] wifi: nl80211: fix NULL-ptr deref in offchan check If, e.g. in AP mode, the link was already created by userspace but not activated yet, it has a chandef but the chandef isn't valid and has no channel. Check for this and ignore this link. Fixes: 7b0a0e3c3a88 ("wifi: cfg80211: do some rework towards MLO link APIs") Signed-off-by: Johannes Berg Signed-off-by: Gregory Greenman Link: https://lore.kernel.org/r/20230301115906.71bd4803fbb9.Iee39c0f6c2d3a59a8227674dc55d52e38b1090cf@changeid Signed-off-by: Johannes Berg --- net/wireless/nl80211.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 112b4bb009c80..51f6582eff7bc 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -8901,7 +8901,7 @@ static bool cfg80211_off_channel_oper_allowed(struct wireless_dev *wdev, struct cfg80211_chan_def *chandef; chandef = wdev_chandef(wdev, link_id); - if (!chandef) + if (!chandef || !chandef->chan) continue; /* From b27f07c50a73e34eefb6b1030b235192b7ded850 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 24 Feb 2023 13:36:57 +0100 Subject: [PATCH 245/460] wifi: nl80211: fix puncturing bitmap policy This was meant to be a u32, and while applying the patch I tried to use policy validation for it. However, not only did I copy/paste it to u8 instead of u32, but also used the policy range erroneously. Fix both of these issues. Fixes: d7c1a9a0ed18 ("wifi: nl80211: validate and configure puncturing bitmap") Signed-off-by: Johannes Berg --- net/wireless/nl80211.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 51f6582eff7bc..6869781283e28 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -462,6 +462,11 @@ nl80211_sta_wme_policy[NL80211_STA_WME_MAX + 1] = { [NL80211_STA_WME_MAX_SP] = { .type = NLA_U8 }, }; +static struct netlink_range_validation nl80211_punct_bitmap_range = { + .min = 0, + .max = 0xffff, +}; + static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { [0] = { .strict_start_type = NL80211_ATTR_HE_OBSS_PD }, [NL80211_ATTR_WIPHY] = { .type = NLA_U32 }, @@ -805,7 +810,8 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { [NL80211_ATTR_MLD_ADDR] = NLA_POLICY_EXACT_LEN(ETH_ALEN), [NL80211_ATTR_MLO_SUPPORT] = { .type = NLA_FLAG }, [NL80211_ATTR_MAX_NUM_AKM_SUITES] = { .type = NLA_REJECT }, - [NL80211_ATTR_PUNCT_BITMAP] = NLA_POLICY_RANGE(NLA_U8, 0, 0xffff), + [NL80211_ATTR_PUNCT_BITMAP] = + NLA_POLICY_FULL_RANGE(NLA_U32, &nl80211_punct_bitmap_range), }; /* policy for the key attributes */ From ce04abc3fcc62cd5640af981ebfd7c4dc3bded28 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 24 Feb 2023 10:52:19 +0100 Subject: [PATCH 246/460] wifi: mac80211: check basic rates validity When userspace sets basic rates, it might send us some rates list that's empty or consists of invalid values only. We're currently ignoring invalid values and then may end up with a rates bitmap that's empty, which later results in a warning. Reject the call if there were no valid rates. Signed-off-by: Johannes Berg --- net/mac80211/cfg.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 8eb3423008687..d3d861911ed65 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -2611,6 +2611,17 @@ static int ieee80211_change_bss(struct wiphy *wiphy, if (!sband) return -EINVAL; + if (params->basic_rates) { + if (!ieee80211_parse_bitrates(link->conf->chandef.width, + wiphy->bands[sband->band], + params->basic_rates, + params->basic_rates_len, + &link->conf->basic_rates)) + return -EINVAL; + changed |= BSS_CHANGED_BASIC_RATES; + ieee80211_check_rate_mask(link); + } + if (params->use_cts_prot >= 0) { link->conf->use_cts_prot = params->use_cts_prot; changed |= BSS_CHANGED_ERP_CTS_PROT; @@ -2632,16 +2643,6 @@ static int ieee80211_change_bss(struct wiphy *wiphy, changed |= BSS_CHANGED_ERP_SLOT; } - if (params->basic_rates) { - ieee80211_parse_bitrates(link->conf->chandef.width, - wiphy->bands[sband->band], - params->basic_rates, - params->basic_rates_len, - &link->conf->basic_rates); - changed |= BSS_CHANGED_BASIC_RATES; - ieee80211_check_rate_mask(link); - } - if (params->ap_isolate >= 0) { if (params->ap_isolate) sdata->flags |= IEEE80211_SDATA_DONT_BRIDGE_PACKETS; From 96c069508377547f913e7265a80fffe9355de592 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 1 Mar 2023 12:09:33 +0200 Subject: [PATCH 247/460] wifi: cfg80211: fix MLO connection ownership When disconnecting from an MLO connection we need the AP MLD address, not an arbitrary BSSID. Fix the code to do that. Fixes: 9ecff10e82a5 ("wifi: nl80211: refactor BSS lookup in nl80211_associate()") Signed-off-by: Johannes Berg Signed-off-by: Gregory Greenman Link: https://lore.kernel.org/r/20230301115906.4c1b3b18980e.I008f070c7f3b8e8bde9278101ef9e40706a82902@changeid Signed-off-by: Johannes Berg --- net/wireless/nl80211.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 6869781283e28..4f63059efd813 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -10799,8 +10799,7 @@ static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev, static struct cfg80211_bss *nl80211_assoc_bss(struct cfg80211_registered_device *rdev, const u8 *ssid, int ssid_len, - struct nlattr **attrs, - const u8 **bssid_out) + struct nlattr **attrs) { struct ieee80211_channel *chan; struct cfg80211_bss *bss; @@ -10827,7 +10826,6 @@ static struct cfg80211_bss *nl80211_assoc_bss(struct cfg80211_registered_device if (!bss) return ERR_PTR(-ENOENT); - *bssid_out = bssid; return bss; } @@ -10837,7 +10835,7 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) struct net_device *dev = info->user_ptr[1]; struct cfg80211_assoc_request req = {}; struct nlattr **attrs = NULL; - const u8 *bssid, *ssid; + const u8 *ap_addr, *ssid; unsigned int link_id; int err, ssid_len; @@ -10974,6 +10972,7 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) return -EINVAL; req.ap_mld_addr = nla_data(info->attrs[NL80211_ATTR_MLD_ADDR]); + ap_addr = req.ap_mld_addr; attrs = kzalloc(attrsize, GFP_KERNEL); if (!attrs) @@ -10999,8 +10998,7 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) goto free; } req.links[link_id].bss = - nl80211_assoc_bss(rdev, ssid, ssid_len, attrs, - &bssid); + nl80211_assoc_bss(rdev, ssid, ssid_len, attrs); if (IS_ERR(req.links[link_id].bss)) { err = PTR_ERR(req.links[link_id].bss); req.links[link_id].bss = NULL; @@ -11051,10 +11049,10 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) if (req.link_id >= 0) return -EINVAL; - req.bss = nl80211_assoc_bss(rdev, ssid, ssid_len, info->attrs, - &bssid); + req.bss = nl80211_assoc_bss(rdev, ssid, ssid_len, info->attrs); if (IS_ERR(req.bss)) return PTR_ERR(req.bss); + ap_addr = req.bss->bssid; } err = nl80211_crypto_settings(rdev, info, &req.crypto, 1); @@ -11067,7 +11065,7 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) dev->ieee80211_ptr->conn_owner_nlportid = info->snd_portid; memcpy(dev->ieee80211_ptr->disconnect_bssid, - bssid, ETH_ALEN); + ap_addr, ETH_ALEN); } wdev_unlock(dev->ieee80211_ptr); From fe9ae05cfbe587dda724fcf537c00bc2f287da62 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 8 Mar 2023 11:50:12 +0100 Subject: [PATCH 248/460] fbdev: Fix incorrect page mapping clearance at fb_deferred_io_release() The recent fix for the deferred I/O by the commit 3efc61d95259 ("fbdev: Fix invalid page access after closing deferred I/O devices") caused a regression when the same fb device is opened/closed while it's being used. It resulted in a frozen screen even if something is redrawn there after the close. The breakage is because the patch was made under a wrong assumption of a single open; in the current code, fb_deferred_io_release() cleans up the page mapping of the pageref list and it calls cancel_delayed_work_sync() unconditionally, where both are no correct behavior for multiple opens. This patch adds a refcount for the opens of the device, and applies the cleanup only when all files get closed. As both fb_deferred_io_open() and _close() are called always in the fb_info lock (mutex), it's safe to use the normal int for the refcounting. Also, a useless BUG_ON() is dropped. Fixes: 3efc61d95259 ("fbdev: Fix invalid page access after closing deferred I/O devices") Cc: Signed-off-by: Takashi Iwai Reviewed-by: Patrik Jakobsson Signed-off-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/20230308105012.1845-1-tiwai@suse.de --- drivers/video/fbdev/core/fb_defio.c | 17 +++++++++++++---- include/linux/fb.h | 1 + 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/drivers/video/fbdev/core/fb_defio.c b/drivers/video/fbdev/core/fb_defio.c index 583cbcf094467..a3cf1f764f29b 100644 --- a/drivers/video/fbdev/core/fb_defio.c +++ b/drivers/video/fbdev/core/fb_defio.c @@ -309,17 +309,18 @@ void fb_deferred_io_open(struct fb_info *info, struct inode *inode, struct file *file) { + struct fb_deferred_io *fbdefio = info->fbdefio; + file->f_mapping->a_ops = &fb_deferred_io_aops; + fbdefio->open_count++; } EXPORT_SYMBOL_GPL(fb_deferred_io_open); -void fb_deferred_io_release(struct fb_info *info) +static void fb_deferred_io_lastclose(struct fb_info *info) { - struct fb_deferred_io *fbdefio = info->fbdefio; struct page *page; int i; - BUG_ON(!fbdefio); cancel_delayed_work_sync(&info->deferred_work); /* clear out the mapping that we setup */ @@ -328,13 +329,21 @@ void fb_deferred_io_release(struct fb_info *info) page->mapping = NULL; } } + +void fb_deferred_io_release(struct fb_info *info) +{ + struct fb_deferred_io *fbdefio = info->fbdefio; + + if (!--fbdefio->open_count) + fb_deferred_io_lastclose(info); +} EXPORT_SYMBOL_GPL(fb_deferred_io_release); void fb_deferred_io_cleanup(struct fb_info *info) { struct fb_deferred_io *fbdefio = info->fbdefio; - fb_deferred_io_release(info); + fb_deferred_io_lastclose(info); kvfree(info->pagerefs); mutex_destroy(&fbdefio->lock); diff --git a/include/linux/fb.h b/include/linux/fb.h index 73eb1f85ea8e5..05e40fcc76964 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -212,6 +212,7 @@ struct fb_deferred_io { /* delay between mkwrite and deferred handler */ unsigned long delay; bool sort_pagereflist; /* sort pagelist by offset */ + int open_count; /* number of opened files; protected by fb_info lock */ struct mutex lock; /* mutex that protects the pageref list */ struct list_head pagereflist; /* list of pagerefs for touched pages */ /* callback */ From 624c60f326c6e5a80b008e8a5c7feffe8c27dc72 Mon Sep 17 00:00:00 2001 From: Guillaume Tucker Date: Tue, 9 Aug 2022 16:22:31 +0200 Subject: [PATCH 249/460] selftests: fix LLVM build for i386 and x86_64 Add missing cases for the i386 and x86_64 architectures when determining the LLVM target for building kselftest. Fixes: 795285ef2425 ("selftests: Fix clang cross compilation") Signed-off-by: Guillaume Tucker Reviewed-by: Nathan Chancellor Signed-off-by: Shuah Khan --- tools/testing/selftests/lib.mk | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/testing/selftests/lib.mk b/tools/testing/selftests/lib.mk index f7900e75d2306..05400462c7799 100644 --- a/tools/testing/selftests/lib.mk +++ b/tools/testing/selftests/lib.mk @@ -10,12 +10,14 @@ endif CLANG_TARGET_FLAGS_arm := arm-linux-gnueabi CLANG_TARGET_FLAGS_arm64 := aarch64-linux-gnu CLANG_TARGET_FLAGS_hexagon := hexagon-linux-musl +CLANG_TARGET_FLAGS_i386 := i386-linux-gnu CLANG_TARGET_FLAGS_m68k := m68k-linux-gnu CLANG_TARGET_FLAGS_mips := mipsel-linux-gnu CLANG_TARGET_FLAGS_powerpc := powerpc64le-linux-gnu CLANG_TARGET_FLAGS_riscv := riscv64-linux-gnu CLANG_TARGET_FLAGS_s390 := s390x-linux-gnu CLANG_TARGET_FLAGS_x86 := x86_64-linux-gnu +CLANG_TARGET_FLAGS_x86_64 := x86_64-linux-gnu CLANG_TARGET_FLAGS := $(CLANG_TARGET_FLAGS_$(ARCH)) ifeq ($(CROSS_COMPILE),) From 484b7059796e3bc1cb527caa61dfc60da649b4f6 Mon Sep 17 00:00:00 2001 From: Fedor Pchelkin Date: Thu, 9 Mar 2023 19:50:50 +0300 Subject: [PATCH 250/460] nfc: pn533: initialize struct pn533_out_arg properly struct pn533_out_arg used as a temporary context for out_urb is not initialized properly. Its uninitialized 'phy' field can be dereferenced in error cases inside pn533_out_complete() callback function. It causes the following failure: general protection fault, probably for non-canonical address 0xdffffc0000000000: 0000 [#1] PREEMPT SMP KASAN KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007] CPU: 1 PID: 0 Comm: swapper/1 Not tainted 6.2.0-rc3-next-20230110-syzkaller #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/26/2022 RIP: 0010:pn533_out_complete.cold+0x15/0x44 drivers/nfc/pn533/usb.c:441 Call Trace: __usb_hcd_giveback_urb+0x2b6/0x5c0 drivers/usb/core/hcd.c:1671 usb_hcd_giveback_urb+0x384/0x430 drivers/usb/core/hcd.c:1754 dummy_timer+0x1203/0x32d0 drivers/usb/gadget/udc/dummy_hcd.c:1988 call_timer_fn+0x1da/0x800 kernel/time/timer.c:1700 expire_timers+0x234/0x330 kernel/time/timer.c:1751 __run_timers kernel/time/timer.c:2022 [inline] __run_timers kernel/time/timer.c:1995 [inline] run_timer_softirq+0x326/0x910 kernel/time/timer.c:2035 __do_softirq+0x1fb/0xaf6 kernel/softirq.c:571 invoke_softirq kernel/softirq.c:445 [inline] __irq_exit_rcu+0x123/0x180 kernel/softirq.c:650 irq_exit_rcu+0x9/0x20 kernel/softirq.c:662 sysvec_apic_timer_interrupt+0x97/0xc0 arch/x86/kernel/apic/apic.c:1107 Initialize the field with the pn533_usb_phy currently used. Found by Linux Verification Center (linuxtesting.org) with Syzkaller. Fixes: 9dab880d675b ("nfc: pn533: Wait for out_urb's completion in pn533_usb_send_frame()") Reported-by: syzbot+1e608ba4217c96d1952f@syzkaller.appspotmail.com Signed-off-by: Fedor Pchelkin Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/20230309165050.207390-1-pchelkin@ispras.ru Signed-off-by: Jakub Kicinski --- drivers/nfc/pn533/usb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/nfc/pn533/usb.c b/drivers/nfc/pn533/usb.c index ed9c5e2cf3ad4..a187f0e0b0f7d 100644 --- a/drivers/nfc/pn533/usb.c +++ b/drivers/nfc/pn533/usb.c @@ -175,6 +175,7 @@ static int pn533_usb_send_frame(struct pn533 *dev, print_hex_dump_debug("PN533 TX: ", DUMP_PREFIX_NONE, 16, 1, out->data, out->len, false); + arg.phy = phy; init_completion(&arg.done); cntx = phy->out_urb->context; phy->out_urb->context = &arg; From 25074a44ac4e5dae5b4a25dcb9bbfcbd00f15ae2 Mon Sep 17 00:00:00 2001 From: Xuan Zhuo Date: Wed, 8 Mar 2023 10:49:33 +0800 Subject: [PATCH 251/460] virtio_net: reorder some funcs The purpose of this is to facilitate the subsequent addition of new functions without introducing a separate declaration. Signed-off-by: Xuan Zhuo Acked-by: Michael S. Tsirkin Signed-off-by: Jakub Kicinski --- drivers/net/virtio_net.c | 92 ++++++++++++++++++++-------------------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index fb5e68ed3ec27..8b31a04052f2f 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -545,6 +545,52 @@ static struct sk_buff *page_to_skb(struct virtnet_info *vi, return skb; } +static void free_old_xmit_skbs(struct send_queue *sq, bool in_napi) +{ + unsigned int len; + unsigned int packets = 0; + unsigned int bytes = 0; + void *ptr; + + while ((ptr = virtqueue_get_buf(sq->vq, &len)) != NULL) { + if (likely(!is_xdp_frame(ptr))) { + struct sk_buff *skb = ptr; + + pr_debug("Sent skb %p\n", skb); + + bytes += skb->len; + napi_consume_skb(skb, in_napi); + } else { + struct xdp_frame *frame = ptr_to_xdp(ptr); + + bytes += xdp_get_frame_len(frame); + xdp_return_frame(frame); + } + packets++; + } + + /* Avoid overhead when no packets have been processed + * happens when called speculatively from start_xmit. + */ + if (!packets) + return; + + u64_stats_update_begin(&sq->stats.syncp); + sq->stats.bytes += bytes; + sq->stats.packets += packets; + u64_stats_update_end(&sq->stats.syncp); +} + +static bool is_xdp_raw_buffer_queue(struct virtnet_info *vi, int q) +{ + if (q < (vi->curr_queue_pairs - vi->xdp_queue_pairs)) + return false; + else if (q < vi->curr_queue_pairs) + return true; + else + return false; +} + static int __virtnet_xdp_xmit_one(struct virtnet_info *vi, struct send_queue *sq, struct xdp_frame *xdpf) @@ -1714,52 +1760,6 @@ static int virtnet_receive(struct receive_queue *rq, int budget, return stats.packets; } -static void free_old_xmit_skbs(struct send_queue *sq, bool in_napi) -{ - unsigned int len; - unsigned int packets = 0; - unsigned int bytes = 0; - void *ptr; - - while ((ptr = virtqueue_get_buf(sq->vq, &len)) != NULL) { - if (likely(!is_xdp_frame(ptr))) { - struct sk_buff *skb = ptr; - - pr_debug("Sent skb %p\n", skb); - - bytes += skb->len; - napi_consume_skb(skb, in_napi); - } else { - struct xdp_frame *frame = ptr_to_xdp(ptr); - - bytes += xdp_get_frame_len(frame); - xdp_return_frame(frame); - } - packets++; - } - - /* Avoid overhead when no packets have been processed - * happens when called speculatively from start_xmit. - */ - if (!packets) - return; - - u64_stats_update_begin(&sq->stats.syncp); - sq->stats.bytes += bytes; - sq->stats.packets += packets; - u64_stats_update_end(&sq->stats.syncp); -} - -static bool is_xdp_raw_buffer_queue(struct virtnet_info *vi, int q) -{ - if (q < (vi->curr_queue_pairs - vi->xdp_queue_pairs)) - return false; - else if (q < vi->curr_queue_pairs) - return true; - else - return false; -} - static void virtnet_poll_cleantx(struct receive_queue *rq) { struct virtnet_info *vi = rq->vq->vdev->priv; From b8ef4809bc7faa22e63de921ef56de21ed191af0 Mon Sep 17 00:00:00 2001 From: Xuan Zhuo Date: Wed, 8 Mar 2023 10:49:34 +0800 Subject: [PATCH 252/460] virtio_net: separate the logic of checking whether sq is full Separate the logic of checking whether sq is full. The subsequent patch will reuse this func. Signed-off-by: Xuan Zhuo Reviewed-by: Alexander Duyck Acked-by: Michael S. Tsirkin Acked-by: Jason Wang Signed-off-by: Jakub Kicinski --- drivers/net/virtio_net.c | 60 ++++++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 24 deletions(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 8b31a04052f2f..46bbddaadb0d3 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -591,6 +591,41 @@ static bool is_xdp_raw_buffer_queue(struct virtnet_info *vi, int q) return false; } +static void check_sq_full_and_disable(struct virtnet_info *vi, + struct net_device *dev, + struct send_queue *sq) +{ + bool use_napi = sq->napi.weight; + int qnum; + + qnum = sq - vi->sq; + + /* If running out of space, stop queue to avoid getting packets that we + * are then unable to transmit. + * An alternative would be to force queuing layer to requeue the skb by + * returning NETDEV_TX_BUSY. However, NETDEV_TX_BUSY should not be + * returned in a normal path of operation: it means that driver is not + * maintaining the TX queue stop/start state properly, and causes + * the stack to do a non-trivial amount of useless work. + * Since most packets only take 1 or 2 ring slots, stopping the queue + * early means 16 slots are typically wasted. + */ + if (sq->vq->num_free < 2+MAX_SKB_FRAGS) { + netif_stop_subqueue(dev, qnum); + if (use_napi) { + if (unlikely(!virtqueue_enable_cb_delayed(sq->vq))) + virtqueue_napi_schedule(&sq->napi, sq->vq); + } else if (unlikely(!virtqueue_enable_cb_delayed(sq->vq))) { + /* More just got used, free them then recheck. */ + free_old_xmit_skbs(sq, false); + if (sq->vq->num_free >= 2+MAX_SKB_FRAGS) { + netif_start_subqueue(dev, qnum); + virtqueue_disable_cb(sq->vq); + } + } + } +} + static int __virtnet_xdp_xmit_one(struct virtnet_info *vi, struct send_queue *sq, struct xdp_frame *xdpf) @@ -1989,30 +2024,7 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev) nf_reset_ct(skb); } - /* If running out of space, stop queue to avoid getting packets that we - * are then unable to transmit. - * An alternative would be to force queuing layer to requeue the skb by - * returning NETDEV_TX_BUSY. However, NETDEV_TX_BUSY should not be - * returned in a normal path of operation: it means that driver is not - * maintaining the TX queue stop/start state properly, and causes - * the stack to do a non-trivial amount of useless work. - * Since most packets only take 1 or 2 ring slots, stopping the queue - * early means 16 slots are typically wasted. - */ - if (sq->vq->num_free < 2+MAX_SKB_FRAGS) { - netif_stop_subqueue(dev, qnum); - if (use_napi) { - if (unlikely(!virtqueue_enable_cb_delayed(sq->vq))) - virtqueue_napi_schedule(&sq->napi, sq->vq); - } else if (unlikely(!virtqueue_enable_cb_delayed(sq->vq))) { - /* More just got used, free them then recheck. */ - free_old_xmit_skbs(sq, false); - if (sq->vq->num_free >= 2+MAX_SKB_FRAGS) { - netif_start_subqueue(dev, qnum); - virtqueue_disable_cb(sq->vq); - } - } - } + check_sq_full_and_disable(vi, dev, sq); if (kick || netif_xmit_stopped(txq)) { if (virtqueue_kick_prepare(sq->vq) && virtqueue_notify(sq->vq)) { From cd1c604aa1d8c641f5edcb58b76352d4eba06ec1 Mon Sep 17 00:00:00 2001 From: Xuan Zhuo Date: Wed, 8 Mar 2023 10:49:35 +0800 Subject: [PATCH 253/460] virtio_net: add checking sq is full inside xdp xmit If the queue of xdp xmit is not an independent queue, then when the xdp xmit used all the desc, the xmit from the __dev_queue_xmit() may encounter the following error. net ens4: Unexpected TXQ (0) queue failure: -28 This patch adds a check whether sq is full in xdp xmit. Fixes: 56434a01b12e ("virtio_net: add XDP_TX support") Reported-by: Yichun Zhang Signed-off-by: Xuan Zhuo Reviewed-by: Alexander Duyck Acked-by: Michael S. Tsirkin Acked-by: Jason Wang Signed-off-by: Jakub Kicinski --- drivers/net/virtio_net.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 46bbddaadb0d3..1a309cfb4976a 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -767,6 +767,9 @@ static int virtnet_xdp_xmit(struct net_device *dev, } ret = nxmit; + if (!is_xdp_raw_buffer_queue(vi, sq - vi->sq)) + check_sq_full_and_disable(vi, dev, sq); + if (flags & XDP_XMIT_FLUSH) { if (virtqueue_kick_prepare(sq->vq) && virtqueue_notify(sq->vq)) kicks = 1; From 71582371a5ee09272b4b4b0a07fa6eb78c9d2f90 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 9 Mar 2023 12:49:11 +0100 Subject: [PATCH 254/460] MAINTAINERS: make my email address consistent Use jiri@resnulli.us in all MAINTAINERS entries and fixup .mailmap so all other addresses point to that one. Signed-off-by: Jiri Pirko Link: https://lore.kernel.org/r/20230309114911.923460-1-jiri@resnulli.us Signed-off-by: Jakub Kicinski --- .mailmap | 3 +++ MAINTAINERS | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.mailmap b/.mailmap index 66754ca6656d1..438d79c277172 100644 --- a/.mailmap +++ b/.mailmap @@ -210,6 +210,9 @@ Jens Axboe Jens Osterkamp Jernej Skrabec Jessica Zhang +Jiri Pirko +Jiri Pirko +Jiri Pirko Jiri Slaby Jiri Slaby Jiri Slaby diff --git a/MAINTAINERS b/MAINTAINERS index 8d5bc223f3053..d86c7807aa201 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5971,7 +5971,7 @@ F: include/linux/dm-*.h F: include/uapi/linux/dm-*.h DEVLINK -M: Jiri Pirko +M: Jiri Pirko L: netdev@vger.kernel.org S: Supported F: Documentation/networking/devlink @@ -15079,7 +15079,7 @@ F: Documentation/hwmon/nzxt-smart2.rst F: drivers/hwmon/nzxt-smart2.c OBJAGG -M: Jiri Pirko +M: Jiri Pirko L: netdev@vger.kernel.org S: Supported F: include/linux/objagg.h @@ -15853,7 +15853,7 @@ F: drivers/video/logo/logo_parisc* F: include/linux/hp_sdc.h PARMAN -M: Jiri Pirko +M: Jiri Pirko L: netdev@vger.kernel.org S: Supported F: include/linux/parman.h From 8ba572052a4b8fe5b205854d27e54e3486049b71 Mon Sep 17 00:00:00 2001 From: "Radu Pirea (OSS)" Date: Thu, 9 Mar 2023 12:01:11 +0200 Subject: [PATCH 255/460] net: phy: nxp-c45-tja11xx: fix MII_BASIC_CONFIG_REV bit According to the TJA1103 user manual, the bit for the reversed role in MII or RMII modes is bit 4. Cc: # 5.15+ Fixes: b050f2f15e04 ("phy: nxp-c45: add driver for tja1103") Signed-off-by: Radu Pirea (OSS) Link: https://lore.kernel.org/r/20230309100111.1246214-1-radu-nicolae.pirea@oss.nxp.com Signed-off-by: Jakub Kicinski --- drivers/net/phy/nxp-c45-tja11xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/phy/nxp-c45-tja11xx.c b/drivers/net/phy/nxp-c45-tja11xx.c index 047c581457e34..5813b07242ce1 100644 --- a/drivers/net/phy/nxp-c45-tja11xx.c +++ b/drivers/net/phy/nxp-c45-tja11xx.c @@ -79,7 +79,7 @@ #define SGMII_ABILITY BIT(0) #define VEND1_MII_BASIC_CONFIG 0xAFC6 -#define MII_BASIC_CONFIG_REV BIT(8) +#define MII_BASIC_CONFIG_REV BIT(4) #define MII_BASIC_CONFIG_SGMII 0x9 #define MII_BASIC_CONFIG_RGMII 0x7 #define MII_BASIC_CONFIG_RMII 0x5 From 59a0b022aa249e3f5735d93de0849341722c4754 Mon Sep 17 00:00:00 2001 From: Jianguo Wu Date: Thu, 9 Mar 2023 10:03:36 +0800 Subject: [PATCH 256/460] ipvlan: Make skb->skb_iif track skb->dev for l3s mode For l3s mode, skb->dev is set to ipvlan interface in ipvlan_nf_input(): skb->dev = addr->master->dev but, skb->skb_iif remain unchanged, this will cause socket lookup failed if a target socket is bound to a interface, like the following example: ip link add ipvlan0 link eth0 type ipvlan mode l3s ip addr add dev ipvlan0 192.168.124.111/24 ip link set ipvlan0 up ping -c 1 -I ipvlan0 8.8.8.8 100% packet loss This is because there is no match sk in __raw_v4_lookup() as sk->sk_bound_dev_if != dif(skb->skb_iif). Fix this by make skb->skb_iif track skb->dev in ipvlan_nf_input(). Fixes: c675e06a98a4 ("ipvlan: decouple l3s mode dependencies from other modes") Signed-off-by: Jianguo Wu Reviewed-by: Jiri Pirko Link: https://lore.kernel.org/r/29865b1f-6db7-c07a-de89-949d3721ea30@163.com Signed-off-by: Jakub Kicinski --- drivers/net/ipvlan/ipvlan_l3s.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ipvlan/ipvlan_l3s.c b/drivers/net/ipvlan/ipvlan_l3s.c index 943d26cbf39f5..71712ea25403d 100644 --- a/drivers/net/ipvlan/ipvlan_l3s.c +++ b/drivers/net/ipvlan/ipvlan_l3s.c @@ -101,6 +101,7 @@ static unsigned int ipvlan_nf_input(void *priv, struct sk_buff *skb, goto out; skb->dev = addr->master->dev; + skb->skb_iif = skb->dev->ifindex; len = skb->len + ETH_HLEN; ipvlan_count_rx(addr->master, len, true, false); out: From 7e4f8a0c495413a50413e8c9f1032ce1bc633bae Mon Sep 17 00:00:00 2001 From: Ivan Vecera Date: Thu, 9 Mar 2023 10:45:09 -0800 Subject: [PATCH 257/460] i40e: Fix kernel crash during reboot when adapter is in recovery mode If the driver detects during probe that firmware is in recovery mode then i40e_init_recovery_mode() is called and the rest of probe function is skipped including pci_set_drvdata(). Subsequent i40e_shutdown() called during shutdown/reboot dereferences NULL pointer as pci_get_drvdata() returns NULL. To fix call pci_set_drvdata() also during entering to recovery mode. Reproducer: 1) Lets have i40e NIC with firmware in recovery mode 2) Run reboot Result: [ 139.084698] i40e: Intel(R) Ethernet Connection XL710 Network Driver [ 139.090959] i40e: Copyright (c) 2013 - 2019 Intel Corporation. [ 139.108438] i40e 0000:02:00.0: Firmware recovery mode detected. Limiting functionality. [ 139.116439] i40e 0000:02:00.0: Refer to the Intel(R) Ethernet Adapters and Devices User Guide for details on firmware recovery mode. [ 139.129499] i40e 0000:02:00.0: fw 8.3.64775 api 1.13 nvm 8.30 0x8000b78d 1.3106.0 [8086:1583] [15d9:084a] [ 139.215932] i40e 0000:02:00.0 enp2s0f0: renamed from eth0 [ 139.223292] i40e 0000:02:00.1: Firmware recovery mode detected. Limiting functionality. [ 139.231292] i40e 0000:02:00.1: Refer to the Intel(R) Ethernet Adapters and Devices User Guide for details on firmware recovery mode. [ 139.244406] i40e 0000:02:00.1: fw 8.3.64775 api 1.13 nvm 8.30 0x8000b78d 1.3106.0 [8086:1583] [15d9:084a] [ 139.329209] i40e 0000:02:00.1 enp2s0f1: renamed from eth0 ... [ 156.311376] BUG: kernel NULL pointer dereference, address: 00000000000006c2 [ 156.318330] #PF: supervisor write access in kernel mode [ 156.323546] #PF: error_code(0x0002) - not-present page [ 156.328679] PGD 0 P4D 0 [ 156.331210] Oops: 0002 [#1] PREEMPT SMP NOPTI [ 156.335567] CPU: 26 PID: 15119 Comm: reboot Tainted: G E 6.2.0+ #1 [ 156.343126] Hardware name: Abacus electric, s.r.o. - servis@abacus.cz Super Server/H12SSW-iN, BIOS 2.4 04/13/2022 [ 156.353369] RIP: 0010:i40e_shutdown+0x15/0x130 [i40e] [ 156.358430] Code: c1 fc ff ff 90 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 55 48 89 fd 53 48 8b 9f 48 01 00 00 80 8b c2 06 00 00 04 f0 80 8b c0 06 00 00 08 48 8d bb 08 08 00 [ 156.377168] RSP: 0018:ffffb223c8447d90 EFLAGS: 00010282 [ 156.382384] RAX: ffffffffc073ee70 RBX: 0000000000000000 RCX: 0000000000000001 [ 156.389510] RDX: 0000000080000001 RSI: 0000000000000246 RDI: ffff95db49988000 [ 156.396634] RBP: ffff95db49988000 R08: ffffffffffffffff R09: ffffffff8bd17d40 [ 156.403759] R10: 0000000000000001 R11: ffffffff8a5e3d28 R12: ffff95db49988000 [ 156.410882] R13: ffffffff89a6fe17 R14: ffff95db49988150 R15: 0000000000000000 [ 156.418007] FS: 00007fe7c0cc3980(0000) GS:ffff95ea8ee80000(0000) knlGS:0000000000000000 [ 156.426083] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 156.431819] CR2: 00000000000006c2 CR3: 00000003092fc005 CR4: 0000000000770ee0 [ 156.438944] PKRU: 55555554 [ 156.441647] Call Trace: [ 156.444096] [ 156.446199] pci_device_shutdown+0x38/0x60 [ 156.450297] device_shutdown+0x163/0x210 [ 156.454215] kernel_restart+0x12/0x70 [ 156.457872] __do_sys_reboot+0x1ab/0x230 [ 156.461789] ? vfs_writev+0xa6/0x1a0 [ 156.465362] ? __pfx_file_free_rcu+0x10/0x10 [ 156.469635] ? __call_rcu_common.constprop.85+0x109/0x5a0 [ 156.475034] do_syscall_64+0x3e/0x90 [ 156.478611] entry_SYSCALL_64_after_hwframe+0x72/0xdc [ 156.483658] RIP: 0033:0x7fe7bff37ab7 Fixes: 4ff0ee1af016 ("i40e: Introduce recovery mode support") Signed-off-by: Ivan Vecera Tested-by: Arpana Arland (A Contingent worker at Intel) Signed-off-by: Tony Nguyen Link: https://lore.kernel.org/r/20230309184509.984639-1-anthony.l.nguyen@intel.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/intel/i40e/i40e_main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 467001db5070e..228cd502bb48a 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -15525,6 +15525,7 @@ static int i40e_init_recovery_mode(struct i40e_pf *pf, struct i40e_hw *hw) int err; int v_idx; + pci_set_drvdata(pf->pdev, pf); pci_save_state(pf->pdev); /* set up periodic task facility */ From 8f76a4f80fba8096a611b6b60c40a0f4cab3ddfb Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Thu, 9 Mar 2023 13:25:25 +0100 Subject: [PATCH 258/460] tools: ynl: fix render-max for flags definition Properly manage render-max property for flags definition type introducing mask value and setting it to (last_element << 1) - 1 instead of adding max value set to last_element + 1 Fixes: be5bea1cc0bf ("net: add basic C code generators for Netlink") Signed-off-by: Lorenzo Bianconi Signed-off-by: Jakub Kicinski --- tools/net/ynl/ynl-gen-c.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tools/net/ynl/ynl-gen-c.py b/tools/net/ynl/ynl-gen-c.py index 1bcc5354d8000..d47376f19de72 100755 --- a/tools/net/ynl/ynl-gen-c.py +++ b/tools/net/ynl/ynl-gen-c.py @@ -1931,9 +1931,14 @@ def render_uapi(family, cw): if const.get('render-max', False): cw.nl() - max_name = c_upper(name_pfx + 'max') - cw.p('__' + max_name + ',') - cw.p(max_name + ' = (__' + max_name + ' - 1)') + if const['type'] == 'flags': + max_name = c_upper(name_pfx + 'mask') + max_val = f' = {enum.get_mask()},' + cw.p(max_name + max_val) + else: + max_name = c_upper(name_pfx + 'max') + cw.p('__' + max_name + ',') + cw.p(max_name + ' = (__' + max_name + ' - 1)') cw.block_end(line=';') cw.nl() elif const['type'] == 'const': From bf51d27704c963ea52c0843096e23c9f404b13af Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Thu, 9 Mar 2023 13:25:26 +0100 Subject: [PATCH 259/460] tools: ynl: fix get_mask utility routine Fix get_mask utility routine in order to take into account possible gaps in the elements list. Fixes: be5bea1cc0bf ("net: add basic C code generators for Netlink") Signed-off-by: Lorenzo Bianconi Signed-off-by: Jakub Kicinski --- tools/net/ynl/lib/nlspec.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tools/net/ynl/lib/nlspec.py b/tools/net/ynl/lib/nlspec.py index a34d088f67432..960a356e8225e 100644 --- a/tools/net/ynl/lib/nlspec.py +++ b/tools/net/ynl/lib/nlspec.py @@ -138,10 +138,8 @@ def has_doc(self): def get_mask(self): mask = 0 - idx = self.yaml.get('value-start', 0) - for _ in self.entries.values(): - mask |= 1 << idx - idx += 1 + for e in self.entries.values(): + mask += e.user_value() return mask From f85949f98206b3b11d92d695cea4efda6a81f00e Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Thu, 9 Mar 2023 13:25:27 +0100 Subject: [PATCH 260/460] xdp: add xdp_set_features_flag utility routine Introduce xdp_set_features_flag utility routine in order to update dynamically xdp_features according to the dynamic hw configuration via ethtool (e.g. changing number of hw rx/tx queues). Add xdp_clear_features_flag() in order to clear all xdp_feature flag. Reviewed-by: Shay Agroskin Signed-off-by: Lorenzo Bianconi Signed-off-by: Jakub Kicinski --- Documentation/netlink/specs/netdev.yaml | 1 + include/net/xdp.h | 11 +++++++++++ include/uapi/linux/netdev.h | 2 ++ net/core/xdp.c | 26 ++++++++++++++++++------- tools/include/uapi/linux/netdev.h | 2 ++ 5 files changed, 35 insertions(+), 7 deletions(-) diff --git a/Documentation/netlink/specs/netdev.yaml b/Documentation/netlink/specs/netdev.yaml index 24de747b53443..753e5914a8b7c 100644 --- a/Documentation/netlink/specs/netdev.yaml +++ b/Documentation/netlink/specs/netdev.yaml @@ -9,6 +9,7 @@ definitions: - type: flags name: xdp-act + render-max: true entries: - name: basic diff --git a/include/net/xdp.h b/include/net/xdp.h index d517bfac937b0..41c57b8b16714 100644 --- a/include/net/xdp.h +++ b/include/net/xdp.h @@ -428,12 +428,18 @@ MAX_XDP_METADATA_KFUNC, #ifdef CONFIG_NET u32 bpf_xdp_metadata_kfunc_id(int id); bool bpf_dev_bound_kfunc_id(u32 btf_id); +void xdp_set_features_flag(struct net_device *dev, xdp_features_t val); void xdp_features_set_redirect_target(struct net_device *dev, bool support_sg); void xdp_features_clear_redirect_target(struct net_device *dev); #else static inline u32 bpf_xdp_metadata_kfunc_id(int id) { return 0; } static inline bool bpf_dev_bound_kfunc_id(u32 btf_id) { return false; } +static inline void +xdp_set_features_flag(struct net_device *dev, xdp_features_t val) +{ +} + static inline void xdp_features_set_redirect_target(struct net_device *dev, bool support_sg) { @@ -445,4 +451,9 @@ xdp_features_clear_redirect_target(struct net_device *dev) } #endif +static inline void xdp_clear_features_flag(struct net_device *dev) +{ + xdp_set_features_flag(dev, 0); +} + #endif /* __LINUX_NET_XDP_H__ */ diff --git a/include/uapi/linux/netdev.h b/include/uapi/linux/netdev.h index 8c4e3e536c042..ed134fbdfd32d 100644 --- a/include/uapi/linux/netdev.h +++ b/include/uapi/linux/netdev.h @@ -33,6 +33,8 @@ enum netdev_xdp_act { NETDEV_XDP_ACT_HW_OFFLOAD = 16, NETDEV_XDP_ACT_RX_SG = 32, NETDEV_XDP_ACT_NDO_XMIT_SG = 64, + + NETDEV_XDP_ACT_MASK = 127, }; enum { diff --git a/net/core/xdp.c b/net/core/xdp.c index 8c92fc5533177..87e654b7d06c1 100644 --- a/net/core/xdp.c +++ b/net/core/xdp.c @@ -774,20 +774,32 @@ static int __init xdp_metadata_init(void) } late_initcall(xdp_metadata_init); -void xdp_features_set_redirect_target(struct net_device *dev, bool support_sg) +void xdp_set_features_flag(struct net_device *dev, xdp_features_t val) { - dev->xdp_features |= NETDEV_XDP_ACT_NDO_XMIT; - if (support_sg) - dev->xdp_features |= NETDEV_XDP_ACT_NDO_XMIT_SG; + val &= NETDEV_XDP_ACT_MASK; + if (dev->xdp_features == val) + return; + dev->xdp_features = val; call_netdevice_notifiers(NETDEV_XDP_FEAT_CHANGE, dev); } +EXPORT_SYMBOL_GPL(xdp_set_features_flag); + +void xdp_features_set_redirect_target(struct net_device *dev, bool support_sg) +{ + xdp_features_t val = (dev->xdp_features | NETDEV_XDP_ACT_NDO_XMIT); + + if (support_sg) + val |= NETDEV_XDP_ACT_NDO_XMIT_SG; + xdp_set_features_flag(dev, val); +} EXPORT_SYMBOL_GPL(xdp_features_set_redirect_target); void xdp_features_clear_redirect_target(struct net_device *dev) { - dev->xdp_features &= ~(NETDEV_XDP_ACT_NDO_XMIT | - NETDEV_XDP_ACT_NDO_XMIT_SG); - call_netdevice_notifiers(NETDEV_XDP_FEAT_CHANGE, dev); + xdp_features_t val = dev->xdp_features; + + val &= ~(NETDEV_XDP_ACT_NDO_XMIT | NETDEV_XDP_ACT_NDO_XMIT_SG); + xdp_set_features_flag(dev, val); } EXPORT_SYMBOL_GPL(xdp_features_clear_redirect_target); diff --git a/tools/include/uapi/linux/netdev.h b/tools/include/uapi/linux/netdev.h index 8c4e3e536c042..ed134fbdfd32d 100644 --- a/tools/include/uapi/linux/netdev.h +++ b/tools/include/uapi/linux/netdev.h @@ -33,6 +33,8 @@ enum netdev_xdp_act { NETDEV_XDP_ACT_HW_OFFLOAD = 16, NETDEV_XDP_ACT_RX_SG = 32, NETDEV_XDP_ACT_NDO_XMIT_SG = 64, + + NETDEV_XDP_ACT_MASK = 127, }; enum { From 3c249fe4de1608a9af56563606d4f6eb3a64a47f Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Thu, 9 Mar 2023 13:25:28 +0100 Subject: [PATCH 261/460] net: thunderx: take into account xdp_features setting tx/rx queues thunderx nic allows xdp just if enough hw queues are available for XDP. Take into account queues configuration setting xdp_features. Fixes: 66c0e13ad236 ("drivers: net: turn on XDP features") Signed-off-by: Lorenzo Bianconi Signed-off-by: Jakub Kicinski --- .../net/ethernet/cavium/thunder/nicvf_ethtool.c | 17 +++++++++++------ .../net/ethernet/cavium/thunder/nicvf_main.c | 4 +++- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c b/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c index e5c71f9078523..d8d71bf97983b 100644 --- a/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c +++ b/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c @@ -735,12 +735,17 @@ static int nicvf_set_channels(struct net_device *dev, if (channel->tx_count > nic->max_queues) return -EINVAL; - if (nic->xdp_prog && - ((channel->tx_count + channel->rx_count) > nic->max_queues)) { - netdev_err(nic->netdev, - "XDP mode, RXQs + TXQs > Max %d\n", - nic->max_queues); - return -EINVAL; + if (channel->tx_count + channel->rx_count > nic->max_queues) { + if (nic->xdp_prog) { + netdev_err(nic->netdev, + "XDP mode, RXQs + TXQs > Max %d\n", + nic->max_queues); + return -EINVAL; + } + + xdp_clear_features_flag(nic->netdev); + } else if (!pass1_silicon(nic->pdev)) { + xdp_set_features_flag(dev, NETDEV_XDP_ACT_BASIC); } if (if_up) diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c index 8b25313c7f6b8..eff350e0bc2a8 100644 --- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c +++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c @@ -2218,7 +2218,9 @@ static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) netdev->netdev_ops = &nicvf_netdev_ops; netdev->watchdog_timeo = NICVF_TX_TIMEOUT; - netdev->xdp_features = NETDEV_XDP_ACT_BASIC; + if (!pass1_silicon(nic->pdev) && + nic->rx_queues + nic->tx_queues <= nic->max_queues) + netdev->xdp_features = NETDEV_XDP_ACT_BASIC; /* MTU range: 64 - 9200 */ netdev->min_mtu = NIC_HW_MIN_FRS; From 7aa6dc351b92abbfead9ebe25ce7a7ac0384ea6d Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Thu, 9 Mar 2023 13:25:29 +0100 Subject: [PATCH 262/460] net: ena: take into account xdp_features setting tx/rx queues ena nic allows xdp just if enough hw queues are available for XDP. Take into account queues configuration setting xdp_features. Fixes: 66c0e13ad236 ("drivers: net: turn on XDP features") Reviewed-by: Shay Agroskin Signed-off-by: Lorenzo Bianconi Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/amazon/ena/ena_ethtool.c | 15 ++++++++++++--- drivers/net/ethernet/amazon/ena/ena_netdev.c | 6 ++++-- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/amazon/ena/ena_ethtool.c b/drivers/net/ethernet/amazon/ena/ena_ethtool.c index 8da79eedc057c..1d4f2f4d10f29 100644 --- a/drivers/net/ethernet/amazon/ena/ena_ethtool.c +++ b/drivers/net/ethernet/amazon/ena/ena_ethtool.c @@ -850,11 +850,20 @@ static int ena_set_channels(struct net_device *netdev, struct ena_adapter *adapter = netdev_priv(netdev); u32 count = channels->combined_count; /* The check for max value is already done in ethtool */ - if (count < ENA_MIN_NUM_IO_QUEUES || - (ena_xdp_present(adapter) && - !ena_xdp_legal_queue_count(adapter, count))) + if (count < ENA_MIN_NUM_IO_QUEUES) return -EINVAL; + if (!ena_xdp_legal_queue_count(adapter, count)) { + if (ena_xdp_present(adapter)) + return -EINVAL; + + xdp_clear_features_flag(netdev); + } else { + xdp_set_features_flag(netdev, + NETDEV_XDP_ACT_BASIC | + NETDEV_XDP_ACT_REDIRECT); + } + return ena_update_queue_count(adapter, count); } diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c index d3999db7c6a29..cbfe7f977270f 100644 --- a/drivers/net/ethernet/amazon/ena/ena_netdev.c +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c @@ -4105,8 +4105,6 @@ static void ena_set_conf_feat_params(struct ena_adapter *adapter, /* Set offload features */ ena_set_dev_offloads(feat, netdev); - netdev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT; - adapter->max_mtu = feat->dev_attr.max_mtu; netdev->max_mtu = adapter->max_mtu; netdev->min_mtu = ENA_MIN_MTU; @@ -4393,6 +4391,10 @@ static int ena_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ena_config_debug_area(adapter); + if (ena_xdp_legal_queue_count(adapter, adapter->num_io_queues)) + netdev->xdp_features = NETDEV_XDP_ACT_BASIC | + NETDEV_XDP_ACT_REDIRECT; + memcpy(adapter->netdev->perm_addr, adapter->mac_addr, netdev->addr_len); netif_carrier_off(netdev); From fccca038f3003daa8f28a5e5d97efe50f04b8d9d Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Thu, 9 Mar 2023 13:25:30 +0100 Subject: [PATCH 263/460] veth: take into account device reconfiguration for xdp_features flag Take into account tx/rx queues reconfiguration setting device xdp_features flag. Moreover consider NETIF_F_GRO flag in order to enable ndo_xdp_xmit callback. Fixes: 66c0e13ad236 ("drivers: net: turn on XDP features") Signed-off-by: Lorenzo Bianconi Signed-off-by: Jakub Kicinski --- drivers/net/veth.c | 42 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/drivers/net/veth.c b/drivers/net/veth.c index 1bb54de7124d9..293dc3b2c84a6 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c @@ -1257,6 +1257,26 @@ static int veth_enable_range_safe(struct net_device *dev, int start, int end) return 0; } +static void veth_set_xdp_features(struct net_device *dev) +{ + struct veth_priv *priv = netdev_priv(dev); + struct net_device *peer; + + peer = rcu_dereference(priv->peer); + if (peer && peer->real_num_tx_queues <= dev->real_num_rx_queues) { + xdp_features_t val = NETDEV_XDP_ACT_BASIC | + NETDEV_XDP_ACT_REDIRECT | + NETDEV_XDP_ACT_RX_SG; + + if (priv->_xdp_prog || veth_gro_requested(dev)) + val |= NETDEV_XDP_ACT_NDO_XMIT | + NETDEV_XDP_ACT_NDO_XMIT_SG; + xdp_set_features_flag(dev, val); + } else { + xdp_clear_features_flag(dev); + } +} + static int veth_set_channels(struct net_device *dev, struct ethtool_channels *ch) { @@ -1323,6 +1343,12 @@ static int veth_set_channels(struct net_device *dev, if (peer) netif_carrier_on(peer); } + + /* update XDP supported features */ + veth_set_xdp_features(dev); + if (peer) + veth_set_xdp_features(peer); + return err; revert: @@ -1489,7 +1515,10 @@ static int veth_set_features(struct net_device *dev, err = veth_napi_enable(dev); if (err) return err; + + xdp_features_set_redirect_target(dev, true); } else { + xdp_features_clear_redirect_target(dev); veth_napi_del(dev); } return 0; @@ -1570,10 +1599,15 @@ static int veth_xdp_set(struct net_device *dev, struct bpf_prog *prog, peer->hw_features &= ~NETIF_F_GSO_SOFTWARE; peer->max_mtu = max_mtu; } + + xdp_features_set_redirect_target(dev, true); } if (old_prog) { if (!prog) { + if (!veth_gro_requested(dev)) + xdp_features_clear_redirect_target(dev); + if (dev->flags & IFF_UP) veth_disable_xdp(dev); @@ -1686,10 +1720,6 @@ static void veth_setup(struct net_device *dev) dev->hw_enc_features = VETH_FEATURES; dev->mpls_features = NETIF_F_HW_CSUM | NETIF_F_GSO_SOFTWARE; netif_set_tso_max_size(dev, GSO_MAX_SIZE); - - dev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT | - NETDEV_XDP_ACT_NDO_XMIT | NETDEV_XDP_ACT_RX_SG | - NETDEV_XDP_ACT_NDO_XMIT_SG; } /* @@ -1857,6 +1887,10 @@ static int veth_newlink(struct net *src_net, struct net_device *dev, goto err_queues; veth_disable_gro(dev); + /* update XDP supported features */ + veth_set_xdp_features(dev); + veth_set_xdp_features(peer); + return 0; err_queues: From 4d5ab0ad964df178beba031b89429a601893ff61 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Thu, 9 Mar 2023 13:25:31 +0100 Subject: [PATCH 264/460] net/mlx5e: take into account device reconfiguration for xdp_features flag Take into account LRO and GRO configuration setting device xdp_features flag. Consider channel rq_wq_type enabling rx scatter-gatter support in xdp_features flag and disable NETDEV_XDP_ACT_NDO_XMIT_SG since it is not supported yet by the driver. Moreover always enable NETDEV_XDP_ACT_NDO_XMIT as the ndo_xdp_xmit callback does not require to load a dummy xdp program on the NIC. Fixes: 66c0e13ad236 ("drivers: net: turn on XDP features") Co-developed-by: Tariq Toukan Signed-off-by: Tariq Toukan Signed-off-by: Lorenzo Bianconi Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlx5/core/en.h | 1 + .../ethernet/mellanox/mlx5/core/en_ethtool.c | 10 ++++- .../net/ethernet/mellanox/mlx5/core/en_main.c | 37 +++++++++++++------ .../net/ethernet/mellanox/mlx5/core/en_rep.c | 3 ++ 4 files changed, 39 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index 88460b7796e55..4276c6eb68201 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -1243,6 +1243,7 @@ void mlx5e_build_nic_params(struct mlx5e_priv *priv, struct mlx5e_xsk *xsk, u16 void mlx5e_rx_dim_work(struct work_struct *work); void mlx5e_tx_dim_work(struct work_struct *work); +void mlx5e_set_xdp_feature(struct net_device *netdev); netdev_features_t mlx5e_features_check(struct sk_buff *skb, struct net_device *netdev, netdev_features_t features); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c index 7708acc9b2ab3..79fd21ecb9cbc 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c @@ -1985,6 +1985,7 @@ static int set_pflag_rx_striding_rq(struct net_device *netdev, bool enable) struct mlx5e_priv *priv = netdev_priv(netdev); struct mlx5_core_dev *mdev = priv->mdev; struct mlx5e_params new_params; + int err; if (enable) { /* Checking the regular RQ here; mlx5e_validate_xsk_param called @@ -2005,7 +2006,14 @@ static int set_pflag_rx_striding_rq(struct net_device *netdev, bool enable) MLX5E_SET_PFLAG(&new_params, MLX5E_PFLAG_RX_STRIDING_RQ, enable); mlx5e_set_rq_type(mdev, &new_params); - return mlx5e_safe_switch_params(priv, &new_params, NULL, NULL, true); + err = mlx5e_safe_switch_params(priv, &new_params, NULL, NULL, true); + if (err) + return err; + + /* update XDP supported features */ + mlx5e_set_xdp_feature(netdev); + + return 0; } static int set_pflag_rx_no_csum_complete(struct net_device *netdev, bool enable) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 76a9c5194a704..51b5f3cca5047 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -4004,6 +4004,25 @@ static int mlx5e_handle_feature(struct net_device *netdev, return 0; } +void mlx5e_set_xdp_feature(struct net_device *netdev) +{ + struct mlx5e_priv *priv = netdev_priv(netdev); + struct mlx5e_params *params = &priv->channels.params; + xdp_features_t val; + + if (params->packet_merge.type != MLX5E_PACKET_MERGE_NONE) { + xdp_clear_features_flag(netdev); + return; + } + + val = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT | + NETDEV_XDP_ACT_XSK_ZEROCOPY | + NETDEV_XDP_ACT_NDO_XMIT; + if (params->rq_wq_type == MLX5_WQ_TYPE_CYCLIC) + val |= NETDEV_XDP_ACT_RX_SG; + xdp_set_features_flag(netdev, val); +} + int mlx5e_set_features(struct net_device *netdev, netdev_features_t features) { netdev_features_t oper_features = features; @@ -4030,6 +4049,9 @@ int mlx5e_set_features(struct net_device *netdev, netdev_features_t features) return -EINVAL; } + /* update XDP supported features */ + mlx5e_set_xdp_feature(netdev); + return 0; } @@ -4761,13 +4783,6 @@ static int mlx5e_xdp_set(struct net_device *netdev, struct bpf_prog *prog) if (old_prog) bpf_prog_put(old_prog); - if (reset) { - if (prog) - xdp_features_set_redirect_target(netdev, true); - else - xdp_features_clear_redirect_target(netdev); - } - if (!test_bit(MLX5E_STATE_OPENED, &priv->state) || reset) goto unlock; @@ -5163,13 +5178,10 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev) netdev->features |= NETIF_F_HIGHDMA; netdev->features |= NETIF_F_HW_VLAN_STAG_FILTER; - netdev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT | - NETDEV_XDP_ACT_XSK_ZEROCOPY | - NETDEV_XDP_ACT_RX_SG; - netdev->priv_flags |= IFF_UNICAST_FLT; netif_set_tso_max_size(netdev, GSO_MAX_SIZE); + mlx5e_set_xdp_feature(netdev); mlx5e_set_netdev_dev_addr(netdev); mlx5e_macsec_build_netdev(priv); mlx5e_ipsec_build_netdev(priv); @@ -5241,6 +5253,9 @@ static int mlx5e_nic_init(struct mlx5_core_dev *mdev, mlx5_core_err(mdev, "TLS initialization failed, %d\n", err); mlx5e_health_create_reporters(priv); + /* update XDP supported features */ + mlx5e_set_xdp_feature(netdev); + return 0; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index 9b92034430854..43fd12fb87b87 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -747,6 +747,9 @@ static void mlx5e_build_rep_params(struct net_device *netdev) /* RQ */ mlx5e_build_rq_params(mdev, params); + /* update XDP supported features */ + mlx5e_set_xdp_feature(netdev); + /* CQ moderation params */ params->rx_dim_enabled = MLX5_CAP_GEN(mdev, cq_moderation); mlx5e_set_rx_cq_mode_params(params, cq_period_mode); From 481e96fc1307eb52c0c449608e629921ecbbaf15 Mon Sep 17 00:00:00 2001 From: Matteo Croce Date: Thu, 9 Mar 2023 13:25:32 +0100 Subject: [PATCH 265/460] mvpp2: take care of xdp_features when reconfiguring queues XDP is supported only if enough queues are present, so when reconfiguring the queues set xdp_features accordingly. Fixes: 66c0e13ad236 ("drivers: net: turn on XDP features") Suggested-by: Lorenzo Bianconi Signed-off-by: Matteo Croce Signed-off-by: Lorenzo Bianconi Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index 9b4ecbe4f36d4..3ea00bc9b91ca 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c @@ -4996,6 +4996,14 @@ static int mvpp2_bm_switch_buffers(struct mvpp2 *priv, bool percpu) for (i = 0; i < priv->port_count; i++) { port = priv->port_list[i]; + if (percpu && port->ntxqs >= num_possible_cpus() * 2) + xdp_set_features_flag(port->dev, + NETDEV_XDP_ACT_BASIC | + NETDEV_XDP_ACT_REDIRECT | + NETDEV_XDP_ACT_NDO_XMIT); + else + xdp_clear_features_flag(port->dev); + mvpp2_swf_bm_pool_init(port); if (status[i]) mvpp2_open(port->dev); @@ -6863,13 +6871,14 @@ static int mvpp2_port_probe(struct platform_device *pdev, if (!port->priv->percpu_pools) mvpp2_set_hw_csum(port, port->pool_long->id); + else if (port->ntxqs >= num_possible_cpus() * 2) + dev->xdp_features = NETDEV_XDP_ACT_BASIC | + NETDEV_XDP_ACT_REDIRECT | + NETDEV_XDP_ACT_NDO_XMIT; dev->vlan_features |= features; netif_set_tso_max_segs(dev, MVPP2_MAX_TSO_SEGS); - dev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT | - NETDEV_XDP_ACT_NDO_XMIT; - dev->priv_flags |= IFF_UNICAST_FLT; /* MTU range: 68 - 9704 */ From b7a679ba7c652587b85294f4953f33ac0b756d40 Mon Sep 17 00:00:00 2001 From: Paolo Abeni Date: Thu, 9 Mar 2023 15:49:57 +0100 Subject: [PATCH 266/460] mptcp: fix possible deadlock in subflow_error_report Christoph reported a possible deadlock while the TCP stack destroys an unaccepted subflow due to an incoming reset: the MPTCP socket error path tries to acquire the msk-level socket lock while TCP still owns the listener socket accept queue spinlock, and the reverse dependency already exists in the TCP stack. Note that the above is actually a lockdep false positive, as the chain involves two separate sockets. A different per-socket lockdep key will address the issue, but such a change will be quite invasive. Instead, we can simply stop earlier the socket error handling for orphaned or unaccepted subflows, breaking the critical lockdep chain. Error handling in such a scenario is a no-op. Reported-and-tested-by: Christoph Paasch Fixes: 15cc10453398 ("mptcp: deliver ssk errors to msk") Cc: stable@vger.kernel.org Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/355 Signed-off-by: Paolo Abeni Reviewed-by: Matthieu Baerts Signed-off-by: Matthieu Baerts Signed-off-by: Jakub Kicinski --- net/mptcp/subflow.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c index 4ae1a7304cf0d..5070dc33675dd 100644 --- a/net/mptcp/subflow.c +++ b/net/mptcp/subflow.c @@ -1432,6 +1432,13 @@ static void subflow_error_report(struct sock *ssk) { struct sock *sk = mptcp_subflow_ctx(ssk)->conn; + /* bail early if this is a no-op, so that we avoid introducing a + * problematic lockdep dependency between TCP accept queue lock + * and msk socket spinlock + */ + if (!sk->sk_socket) + return; + mptcp_data_lock(sk); if (!sock_owned_by_user(sk)) __mptcp_error_report(sk); From 3a236aef280ed5122b2d47087eb514d0921ae033 Mon Sep 17 00:00:00 2001 From: Paolo Abeni Date: Thu, 9 Mar 2023 15:49:58 +0100 Subject: [PATCH 267/460] mptcp: refactor passive socket initialization After commit 30e51b923e43 ("mptcp: fix unreleased socket in accept queue") unaccepted msk sockets go throu complete shutdown, we don't need anymore to delay inserting the first subflow into the subflow lists. The reference counting deserve some extra care, as __mptcp_close() is unaware of the request socket linkage to the first subflow. Please note that this is more a refactoring than a fix but because this modification is needed to include other corrections, see the following commits. Then a Fixes tag has been added here to help the stable team. Fixes: 30e51b923e43 ("mptcp: fix unreleased socket in accept queue") Cc: stable@vger.kernel.org Signed-off-by: Paolo Abeni Reviewed-by: Matthieu Baerts Tested-by: Christoph Paasch Signed-off-by: Matthieu Baerts Signed-off-by: Jakub Kicinski --- net/mptcp/protocol.c | 17 ----------------- net/mptcp/subflow.c | 27 +++++++++++++++++++++------ 2 files changed, 21 insertions(+), 23 deletions(-) diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index 3ad9c46202fc6..447641d34c2c5 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -825,7 +825,6 @@ static bool __mptcp_finish_join(struct mptcp_sock *msk, struct sock *ssk) if (sk->sk_socket && !ssk->sk_socket) mptcp_sock_graft(ssk, sk->sk_socket); - mptcp_propagate_sndbuf((struct sock *)msk, ssk); mptcp_sockopt_sync_locked(msk, ssk); return true; } @@ -3708,22 +3707,6 @@ static int mptcp_stream_accept(struct socket *sock, struct socket *newsock, lock_sock(newsk); - /* PM/worker can now acquire the first subflow socket - * lock without racing with listener queue cleanup, - * we can notify it, if needed. - * - * Even if remote has reset the initial subflow by now - * the refcnt is still at least one. - */ - subflow = mptcp_subflow_ctx(msk->first); - list_add(&subflow->node, &msk->conn_list); - sock_hold(msk->first); - if (mptcp_is_fully_established(newsk)) - mptcp_pm_fully_established(msk, msk->first, GFP_KERNEL); - - mptcp_rcv_space_init(msk, msk->first); - mptcp_propagate_sndbuf(newsk, msk->first); - /* set ssk->sk_socket of accept()ed flows to mptcp socket. * This is needed so NOSPACE flag can be set from tcp stack. */ diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c index 5070dc33675dd..a631a5e6fc7b5 100644 --- a/net/mptcp/subflow.c +++ b/net/mptcp/subflow.c @@ -397,6 +397,12 @@ void mptcp_subflow_reset(struct sock *ssk) struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk); struct sock *sk = subflow->conn; + /* mptcp_mp_fail_no_response() can reach here on an already closed + * socket + */ + if (ssk->sk_state == TCP_CLOSE) + return; + /* must hold: tcp_done() could drop last reference on parent */ sock_hold(sk); @@ -750,6 +756,7 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk, struct mptcp_options_received mp_opt; bool fallback, fallback_is_fatal; struct sock *new_msk = NULL; + struct mptcp_sock *owner; struct sock *child; pr_debug("listener=%p, req=%p, conn=%p", listener, req, listener->conn); @@ -824,6 +831,8 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk, ctx->setsockopt_seq = listener->setsockopt_seq; if (ctx->mp_capable) { + owner = mptcp_sk(new_msk); + /* this can't race with mptcp_close(), as the msk is * not yet exposted to user-space */ @@ -832,14 +841,14 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk, /* record the newly created socket as the first msk * subflow, but don't link it yet into conn_list */ - WRITE_ONCE(mptcp_sk(new_msk)->first, child); + WRITE_ONCE(owner->first, child); /* new mpc subflow takes ownership of the newly * created mptcp socket */ mptcp_sk(new_msk)->setsockopt_seq = ctx->setsockopt_seq; - mptcp_pm_new_connection(mptcp_sk(new_msk), child, 1); - mptcp_token_accept(subflow_req, mptcp_sk(new_msk)); + mptcp_pm_new_connection(owner, child, 1); + mptcp_token_accept(subflow_req, owner); ctx->conn = new_msk; new_msk = NULL; @@ -847,15 +856,21 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk, * uses the correct data */ mptcp_copy_inaddrs(ctx->conn, child); + mptcp_propagate_sndbuf(ctx->conn, child); + + mptcp_rcv_space_init(owner, child); + list_add(&ctx->node, &owner->conn_list); + sock_hold(child); /* with OoO packets we can reach here without ingress * mpc option */ - if (mp_opt.suboptions & OPTION_MPTCP_MPC_ACK) + if (mp_opt.suboptions & OPTION_MPTCP_MPC_ACK) { mptcp_subflow_fully_established(ctx, &mp_opt); + mptcp_pm_fully_established(owner, child, GFP_ATOMIC); + ctx->pm_notified = 1; + } } else if (ctx->mp_join) { - struct mptcp_sock *owner; - owner = subflow_req->msk; if (!owner) { subflow_add_reset_reason(skb, MPTCP_RST_EPROHIBIT); From b6985b9b82954caa53f862d6059d06c0526254f0 Mon Sep 17 00:00:00 2001 From: Paolo Abeni Date: Thu, 9 Mar 2023 15:49:59 +0100 Subject: [PATCH 268/460] mptcp: use the workqueue to destroy unaccepted sockets Christoph reported a UaF at token lookup time after having refactored the passive socket initialization part: BUG: KASAN: use-after-free in __token_bucket_busy+0x253/0x260 Read of size 4 at addr ffff88810698d5b0 by task syz-executor653/3198 CPU: 1 PID: 3198 Comm: syz-executor653 Not tainted 6.2.0-rc59af4eaa31c1f6c00c8f1e448ed99a45c66340dd5 #6 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.13.0-0-gf21b5a4aeb02-prebuilt.qemu.org 04/01/2014 Call Trace: dump_stack_lvl+0x6e/0x91 print_report+0x16a/0x46f kasan_report+0xad/0x130 __token_bucket_busy+0x253/0x260 mptcp_token_new_connect+0x13d/0x490 mptcp_connect+0x4ed/0x860 __inet_stream_connect+0x80e/0xd90 tcp_sendmsg_fastopen+0x3ce/0x710 mptcp_sendmsg+0xff1/0x1a20 inet_sendmsg+0x11d/0x140 __sys_sendto+0x405/0x490 __x64_sys_sendto+0xdc/0x1b0 do_syscall_64+0x3b/0x90 entry_SYSCALL_64_after_hwframe+0x72/0xdc We need to properly clean-up all the paired MPTCP-level resources and be sure to release the msk last, even when the unaccepted subflow is destroyed by the TCP internals via inet_child_forget(). We can re-use the existing MPTCP_WORK_CLOSE_SUBFLOW infra, explicitly checking that for the critical scenario: the closed subflow is the MPC one, the msk is not accepted and eventually going through full cleanup. With such change, __mptcp_destroy_sock() is always called on msk sockets, even on accepted ones. We don't need anymore to transiently drop one sk reference at msk clone time. Please note this commit depends on the parent one: mptcp: refactor passive socket initialization Fixes: 58b09919626b ("mptcp: create msk early") Cc: stable@vger.kernel.org Reported-and-tested-by: Christoph Paasch Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/347 Signed-off-by: Paolo Abeni Reviewed-by: Matthieu Baerts Signed-off-by: Matthieu Baerts Signed-off-by: Jakub Kicinski --- net/mptcp/protocol.c | 40 ++++++++++++++++++++++++++++++---------- net/mptcp/protocol.h | 5 ++++- net/mptcp/subflow.c | 17 ++++++++++++----- 3 files changed, 46 insertions(+), 16 deletions(-) diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index 447641d34c2c5..2a2093d61835c 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -2342,7 +2342,6 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk, goto out; } - sock_orphan(ssk); subflow->disposable = 1; /* if ssk hit tcp_done(), tcp_cleanup_ulp() cleared the related ops @@ -2350,7 +2349,20 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk, * reference owned by msk; */ if (!inet_csk(ssk)->icsk_ulp_ops) { + WARN_ON_ONCE(!sock_flag(ssk, SOCK_DEAD)); kfree_rcu(subflow, rcu); + } else if (msk->in_accept_queue && msk->first == ssk) { + /* if the first subflow moved to a close state, e.g. due to + * incoming reset and we reach here before inet_child_forget() + * the TCP stack could later try to close it via + * inet_csk_listen_stop(), or deliver it to the user space via + * accept(). + * We can't delete the subflow - or risk a double free - nor let + * the msk survive - or will be leaked in the non accept scenario: + * fallback and let TCP cope with the subflow cleanup. + */ + WARN_ON_ONCE(sock_flag(ssk, SOCK_DEAD)); + mptcp_subflow_drop_ctx(ssk); } else { /* otherwise tcp will dispose of the ssk and subflow ctx */ if (ssk->sk_state == TCP_LISTEN) { @@ -2398,9 +2410,10 @@ static unsigned int mptcp_sync_mss(struct sock *sk, u32 pmtu) return 0; } -static void __mptcp_close_subflow(struct mptcp_sock *msk) +static void __mptcp_close_subflow(struct sock *sk) { struct mptcp_subflow_context *subflow, *tmp; + struct mptcp_sock *msk = mptcp_sk(sk); might_sleep(); @@ -2414,7 +2427,15 @@ static void __mptcp_close_subflow(struct mptcp_sock *msk) if (!skb_queue_empty_lockless(&ssk->sk_receive_queue)) continue; - mptcp_close_ssk((struct sock *)msk, ssk, subflow); + mptcp_close_ssk(sk, ssk, subflow); + } + + /* if the MPC subflow has been closed before the msk is accepted, + * msk will never be accept-ed, close it now + */ + if (!msk->first && msk->in_accept_queue) { + sock_set_flag(sk, SOCK_DEAD); + inet_sk_state_store(sk, TCP_CLOSE); } } @@ -2623,6 +2644,9 @@ static void mptcp_worker(struct work_struct *work) __mptcp_check_send_data_fin(sk); mptcp_check_data_fin(sk); + if (test_and_clear_bit(MPTCP_WORK_CLOSE_SUBFLOW, &msk->flags)) + __mptcp_close_subflow(sk); + /* There is no point in keeping around an orphaned sk timedout or * closed, but we need the msk around to reply to incoming DATA_FIN, * even if it is orphaned and in FIN_WAIT2 state @@ -2638,9 +2662,6 @@ static void mptcp_worker(struct work_struct *work) } } - if (test_and_clear_bit(MPTCP_WORK_CLOSE_SUBFLOW, &msk->flags)) - __mptcp_close_subflow(msk); - if (test_and_clear_bit(MPTCP_WORK_RTX, &msk->flags)) __mptcp_retrans(sk); @@ -3078,6 +3099,7 @@ struct sock *mptcp_sk_clone(const struct sock *sk, msk->local_key = subflow_req->local_key; msk->token = subflow_req->token; msk->subflow = NULL; + msk->in_accept_queue = 1; WRITE_ONCE(msk->fully_established, false); if (mp_opt->suboptions & OPTION_MPTCP_CSUMREQD) WRITE_ONCE(msk->csum_enabled, true); @@ -3095,8 +3117,7 @@ struct sock *mptcp_sk_clone(const struct sock *sk, security_inet_csk_clone(nsk, req); bh_unlock_sock(nsk); - /* keep a single reference */ - __sock_put(nsk); + /* note: the newly allocated socket refcount is 2 now */ return nsk; } @@ -3152,8 +3173,6 @@ static struct sock *mptcp_accept(struct sock *sk, int flags, int *err, goto out; } - /* acquire the 2nd reference for the owning socket */ - sock_hold(new_mptcp_sock); newsk = new_mptcp_sock; MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPCAPABLEPASSIVEACK); } else { @@ -3704,6 +3723,7 @@ static int mptcp_stream_accept(struct socket *sock, struct socket *newsock, struct sock *newsk = newsock->sk; set_bit(SOCK_CUSTOM_SOCKOPT, &newsock->flags); + msk->in_accept_queue = 0; lock_sock(newsk); diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h index 61fd8eabfca20..3a2db1b862dd7 100644 --- a/net/mptcp/protocol.h +++ b/net/mptcp/protocol.h @@ -295,7 +295,8 @@ struct mptcp_sock { u8 recvmsg_inq:1, cork:1, nodelay:1, - fastopening:1; + fastopening:1, + in_accept_queue:1; int connect_flags; struct work_struct work; struct sk_buff *ooo_last_skb; @@ -666,6 +667,8 @@ void mptcp_subflow_set_active(struct mptcp_subflow_context *subflow); bool mptcp_subflow_active(struct mptcp_subflow_context *subflow); +void mptcp_subflow_drop_ctx(struct sock *ssk); + static inline void mptcp_subflow_tcp_fallback(struct sock *sk, struct mptcp_subflow_context *ctx) { diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c index a631a5e6fc7b5..932a3e0eb22de 100644 --- a/net/mptcp/subflow.c +++ b/net/mptcp/subflow.c @@ -699,9 +699,10 @@ static bool subflow_hmac_valid(const struct request_sock *req, static void mptcp_force_close(struct sock *sk) { - /* the msk is not yet exposed to user-space */ + /* the msk is not yet exposed to user-space, and refcount is 2 */ inet_sk_state_store(sk, TCP_CLOSE); sk_common_release(sk); + sock_put(sk); } static void subflow_ulp_fallback(struct sock *sk, @@ -717,7 +718,7 @@ static void subflow_ulp_fallback(struct sock *sk, mptcp_subflow_ops_undo_override(sk); } -static void subflow_drop_ctx(struct sock *ssk) +void mptcp_subflow_drop_ctx(struct sock *ssk) { struct mptcp_subflow_context *ctx = mptcp_subflow_ctx(ssk); @@ -823,7 +824,7 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk, if (new_msk) mptcp_copy_inaddrs(new_msk, child); - subflow_drop_ctx(child); + mptcp_subflow_drop_ctx(child); goto out; } @@ -914,7 +915,7 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk, return child; dispose_child: - subflow_drop_ctx(child); + mptcp_subflow_drop_ctx(child); tcp_rsk(req)->drop_req = true; inet_csk_prepare_for_destroy_sock(child); tcp_done(child); @@ -1866,7 +1867,6 @@ void mptcp_subflow_queue_clean(struct sock *listener_sk, struct sock *listener_s struct sock *sk = (struct sock *)msk; bool do_cancel_work; - sock_hold(sk); lock_sock_nested(sk, SINGLE_DEPTH_NESTING); next = msk->dl_next; msk->first = NULL; @@ -1954,6 +1954,13 @@ static void subflow_ulp_release(struct sock *ssk) * when the subflow is still unaccepted */ release = ctx->disposable || list_empty(&ctx->node); + + /* inet_child_forget() does not call sk_state_change(), + * explicitly trigger the socket close machinery + */ + if (!release && !test_and_set_bit(MPTCP_WORK_CLOSE_SUBFLOW, + &mptcp_sk(sk)->flags)) + mptcp_schedule_work(sk); sock_put(sk); } From 0a3f4f1f9c27215e4ddcd312558342e57b93e518 Mon Sep 17 00:00:00 2001 From: Paolo Abeni Date: Thu, 9 Mar 2023 15:50:00 +0100 Subject: [PATCH 269/460] mptcp: fix UaF in listener shutdown As reported by Christoph after having refactored the passive socket initialization, the mptcp listener shutdown path is prone to an UaF issue. BUG: KASAN: use-after-free in _raw_spin_lock_bh+0x73/0xe0 Write of size 4 at addr ffff88810cb23098 by task syz-executor731/1266 CPU: 1 PID: 1266 Comm: syz-executor731 Not tainted 6.2.0-rc59af4eaa31c1f6c00c8f1e448ed99a45c66340dd5 #6 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.13.0-0-gf21b5a4aeb02-prebuilt.qemu.org 04/01/2014 Call Trace: dump_stack_lvl+0x6e/0x91 print_report+0x16a/0x46f kasan_report+0xad/0x130 kasan_check_range+0x14a/0x1a0 _raw_spin_lock_bh+0x73/0xe0 subflow_error_report+0x6d/0x110 sk_error_report+0x3b/0x190 tcp_disconnect+0x138c/0x1aa0 inet_child_forget+0x6f/0x2e0 inet_csk_listen_stop+0x209/0x1060 __mptcp_close_ssk+0x52d/0x610 mptcp_destroy_common+0x165/0x640 mptcp_destroy+0x13/0x80 __mptcp_destroy_sock+0xe7/0x270 __mptcp_close+0x70e/0x9b0 mptcp_close+0x2b/0x150 inet_release+0xe9/0x1f0 __sock_release+0xd2/0x280 sock_close+0x15/0x20 __fput+0x252/0xa20 task_work_run+0x169/0x250 exit_to_user_mode_prepare+0x113/0x120 syscall_exit_to_user_mode+0x1d/0x40 do_syscall_64+0x48/0x90 entry_SYSCALL_64_after_hwframe+0x72/0xdc The msk grace period can legitly expire in between the last reference count dropped in mptcp_subflow_queue_clean() and the later eventual access in inet_csk_listen_stop() After the previous patch we don't need anymore special-casing msk listener socket cleanup: the mptcp worker will process each of the unaccepted msk sockets. Just drop the now unnecessary code. Please note this commit depends on the two parent ones: mptcp: refactor passive socket initialization mptcp: use the workqueue to destroy unaccepted sockets Fixes: 6aeed9045071 ("mptcp: fix race on unaccepted mptcp sockets") Cc: stable@vger.kernel.org Reported-and-tested-by: Christoph Paasch Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/346 Signed-off-by: Paolo Abeni Reviewed-by: Matthieu Baerts Signed-off-by: Matthieu Baerts Signed-off-by: Jakub Kicinski --- net/mptcp/protocol.c | 7 ++--- net/mptcp/protocol.h | 1 - net/mptcp/subflow.c | 72 -------------------------------------------- 3 files changed, 2 insertions(+), 78 deletions(-) diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index 2a2093d61835c..60b23b2716c40 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -2365,12 +2365,9 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk, mptcp_subflow_drop_ctx(ssk); } else { /* otherwise tcp will dispose of the ssk and subflow ctx */ - if (ssk->sk_state == TCP_LISTEN) { - tcp_set_state(ssk, TCP_CLOSE); - mptcp_subflow_queue_clean(sk, ssk); - inet_csk_listen_stop(ssk); + if (ssk->sk_state == TCP_LISTEN) mptcp_event_pm_listener(ssk, MPTCP_EVENT_LISTENER_CLOSED); - } + __tcp_close(ssk, 0); /* close acquired an extra ref */ diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h index 3a2db1b862dd7..339a6f0729898 100644 --- a/net/mptcp/protocol.h +++ b/net/mptcp/protocol.h @@ -629,7 +629,6 @@ void mptcp_close_ssk(struct sock *sk, struct sock *ssk, struct mptcp_subflow_context *subflow); void __mptcp_subflow_send_ack(struct sock *ssk); void mptcp_subflow_reset(struct sock *ssk); -void mptcp_subflow_queue_clean(struct sock *sk, struct sock *ssk); void mptcp_sock_graft(struct sock *sk, struct socket *parent); struct socket *__mptcp_nmpc_socket(const struct mptcp_sock *msk); bool __mptcp_close(struct sock *sk, long timeout); diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c index 932a3e0eb22de..9c57575df84c4 100644 --- a/net/mptcp/subflow.c +++ b/net/mptcp/subflow.c @@ -1826,78 +1826,6 @@ static void subflow_state_change(struct sock *sk) } } -void mptcp_subflow_queue_clean(struct sock *listener_sk, struct sock *listener_ssk) -{ - struct request_sock_queue *queue = &inet_csk(listener_ssk)->icsk_accept_queue; - struct mptcp_sock *msk, *next, *head = NULL; - struct request_sock *req; - - /* build a list of all unaccepted mptcp sockets */ - spin_lock_bh(&queue->rskq_lock); - for (req = queue->rskq_accept_head; req; req = req->dl_next) { - struct mptcp_subflow_context *subflow; - struct sock *ssk = req->sk; - struct mptcp_sock *msk; - - if (!sk_is_mptcp(ssk)) - continue; - - subflow = mptcp_subflow_ctx(ssk); - if (!subflow || !subflow->conn) - continue; - - /* skip if already in list */ - msk = mptcp_sk(subflow->conn); - if (msk->dl_next || msk == head) - continue; - - msk->dl_next = head; - head = msk; - } - spin_unlock_bh(&queue->rskq_lock); - if (!head) - return; - - /* can't acquire the msk socket lock under the subflow one, - * or will cause ABBA deadlock - */ - release_sock(listener_ssk); - - for (msk = head; msk; msk = next) { - struct sock *sk = (struct sock *)msk; - bool do_cancel_work; - - lock_sock_nested(sk, SINGLE_DEPTH_NESTING); - next = msk->dl_next; - msk->first = NULL; - msk->dl_next = NULL; - - do_cancel_work = __mptcp_close(sk, 0); - release_sock(sk); - if (do_cancel_work) { - /* lockdep will report a false positive ABBA deadlock - * between cancel_work_sync and the listener socket. - * The involved locks belong to different sockets WRT - * the existing AB chain. - * Using a per socket key is problematic as key - * deregistration requires process context and must be - * performed at socket disposal time, in atomic - * context. - * Just tell lockdep to consider the listener socket - * released here. - */ - mutex_release(&listener_sk->sk_lock.dep_map, _RET_IP_); - mptcp_cancel_work(sk); - mutex_acquire(&listener_sk->sk_lock.dep_map, - SINGLE_DEPTH_NESTING, 0, _RET_IP_); - } - sock_put(sk); - } - - /* we are still under the listener msk socket lock */ - lock_sock_nested(listener_ssk, SINGLE_DEPTH_NESTING); -} - static int subflow_ulp_init(struct sock *sk) { struct inet_connection_sock *icsk = inet_csk(sk); From 840742b7ed0e123e47af9c5c3902746f3d6b64a2 Mon Sep 17 00:00:00 2001 From: Matthieu Baerts Date: Thu, 9 Mar 2023 15:50:01 +0100 Subject: [PATCH 270/460] selftests: mptcp: userspace pm: fix printed values In case of errors, the printed message had the expected and the seen value inverted. This patch simply correct the order: first the expected value, then the one that has been seen. Fixes: 10d4273411be ("selftests: mptcp: userspace: print error details if any") Cc: stable@vger.kernel.org Acked-by: Geliang Tang Signed-off-by: Matthieu Baerts Signed-off-by: Jakub Kicinski --- tools/testing/selftests/net/mptcp/userspace_pm.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/testing/selftests/net/mptcp/userspace_pm.sh b/tools/testing/selftests/net/mptcp/userspace_pm.sh index 66c5be25c13d0..48e52f995a98c 100755 --- a/tools/testing/selftests/net/mptcp/userspace_pm.sh +++ b/tools/testing/selftests/net/mptcp/userspace_pm.sh @@ -240,7 +240,7 @@ check_expected_one() fi stdbuf -o0 -e0 printf "\tExpected value for '%s': '%s', got '%s'.\n" \ - "${var}" "${!var}" "${!exp}" + "${var}" "${!exp}" "${!var}" return 1 } From 822467a48e938e661965d09df5fcac66f7291050 Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Thu, 9 Mar 2023 15:50:02 +0100 Subject: [PATCH 271/460] mptcp: add ro_after_init for tcp{,v6}_prot_override Add __ro_after_init labels for the variables tcp_prot_override and tcpv6_prot_override, just like other variables adjacent to them, to indicate that they are initialised from the init hooks and no writes occur afterwards. Fixes: b19bc2945b40 ("mptcp: implement delegated actions") Cc: stable@vger.kernel.org Fixes: 51fa7f8ebf0e ("mptcp: mark ops structures as ro_after_init") Signed-off-by: Geliang Tang Reviewed-by: Matthieu Baerts Signed-off-by: Matthieu Baerts Signed-off-by: Jakub Kicinski --- net/mptcp/subflow.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c index 9c57575df84c4..2aadc87333690 100644 --- a/net/mptcp/subflow.c +++ b/net/mptcp/subflow.c @@ -628,7 +628,7 @@ static struct request_sock_ops mptcp_subflow_v6_request_sock_ops __ro_after_init static struct tcp_request_sock_ops subflow_request_sock_ipv6_ops __ro_after_init; static struct inet_connection_sock_af_ops subflow_v6_specific __ro_after_init; static struct inet_connection_sock_af_ops subflow_v6m_specific __ro_after_init; -static struct proto tcpv6_prot_override; +static struct proto tcpv6_prot_override __ro_after_init; static int subflow_v6_conn_request(struct sock *sk, struct sk_buff *skb) { @@ -926,7 +926,7 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk, } static struct inet_connection_sock_af_ops subflow_specific __ro_after_init; -static struct proto tcp_prot_override; +static struct proto tcp_prot_override __ro_after_init; enum mapping_status { MAPPING_OK, From 3ba14528684f528566fb7d956bfbfb958b591d86 Mon Sep 17 00:00:00 2001 From: Matthieu Baerts Date: Thu, 9 Mar 2023 15:50:03 +0100 Subject: [PATCH 272/460] mptcp: avoid setting TCP_CLOSE state twice tcp_set_state() is called from tcp_done() already. There is then no need to first set the state to TCP_CLOSE, then call tcp_done(). Fixes: d582484726c4 ("mptcp: fix fallback for MP_JOIN subflows") Cc: stable@vger.kernel.org Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/362 Acked-by: Paolo Abeni Signed-off-by: Matthieu Baerts Signed-off-by: Jakub Kicinski --- net/mptcp/subflow.c | 1 - 1 file changed, 1 deletion(-) diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c index 2aadc87333690..a0041360ee9d9 100644 --- a/net/mptcp/subflow.c +++ b/net/mptcp/subflow.c @@ -406,7 +406,6 @@ void mptcp_subflow_reset(struct sock *ssk) /* must hold: tcp_done() could drop last reference on parent */ sock_hold(sk); - tcp_set_state(ssk, TCP_CLOSE); tcp_send_active_reset(ssk, GFP_ATOMIC); tcp_done(ssk); if (!test_and_set_bit(MPTCP_WORK_CLOSE_SUBFLOW, &mptcp_sk(sk)->flags) && From cee4034a3db1d30c3243dd51506a9d4ab1a849fa Mon Sep 17 00:00:00 2001 From: Paolo Abeni Date: Thu, 9 Mar 2023 15:50:04 +0100 Subject: [PATCH 273/460] mptcp: fix lockdep false positive in mptcp_pm_nl_create_listen_socket() Christoph reports a lockdep splat in the mptcp_subflow_create_socket() error path, when such function is invoked by mptcp_pm_nl_create_listen_socket(). Such code path acquires two separates, nested socket lock, with the internal lock operation lacking the "nested" annotation. Adding that in sock_release() for mptcp's sake only could be confusing. Instead just add a new lockclass to the in-kernel msk socket, re-initializing the lockdep infra after the socket creation. Fixes: ad2171009d96 ("mptcp: fix locking for in-kernel listener creation") Cc: stable@vger.kernel.org Reported-by: Christoph Paasch Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/354 Signed-off-by: Paolo Abeni Reviewed-by: Matthieu Baerts Tested-by: Christoph Paasch Signed-off-by: Matthieu Baerts Signed-off-by: Jakub Kicinski --- net/mptcp/pm_netlink.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/net/mptcp/pm_netlink.c b/net/mptcp/pm_netlink.c index 56628b52d1001..5c8dea49626c3 100644 --- a/net/mptcp/pm_netlink.c +++ b/net/mptcp/pm_netlink.c @@ -997,9 +997,13 @@ static int mptcp_pm_nl_append_new_local_addr(struct pm_nl_pernet *pernet, return ret; } +static struct lock_class_key mptcp_slock_keys[2]; +static struct lock_class_key mptcp_keys[2]; + static int mptcp_pm_nl_create_listen_socket(struct sock *sk, struct mptcp_pm_addr_entry *entry) { + bool is_ipv6 = sk->sk_family == AF_INET6; int addrlen = sizeof(struct sockaddr_in); struct sockaddr_storage addr; struct socket *ssock; @@ -1016,6 +1020,18 @@ static int mptcp_pm_nl_create_listen_socket(struct sock *sk, if (!newsk) return -EINVAL; + /* The subflow socket lock is acquired in a nested to the msk one + * in several places, even by the TCP stack, and this msk is a kernel + * socket: lockdep complains. Instead of propagating the _nested + * modifiers in several places, re-init the lock class for the msk + * socket to an mptcp specific one. + */ + sock_lock_init_class_and_name(newsk, + is_ipv6 ? "mlock-AF_INET6" : "mlock-AF_INET", + &mptcp_slock_keys[is_ipv6], + is_ipv6 ? "msk_lock-AF_INET6" : "msk_lock-AF_INET", + &mptcp_keys[is_ipv6]); + lock_sock(newsk); ssock = __mptcp_nmpc_socket(mptcp_sk(newsk)); release_sock(newsk); From 1dcdce5919115a471bf4921a57f20050c545a236 Mon Sep 17 00:00:00 2001 From: Ye Bin Date: Tue, 7 Mar 2023 09:52:52 +0800 Subject: [PATCH 274/460] 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 2b42ececa46d8..1602d74b5eeb3 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 b65dadfe3b453..530e420ae0e8c 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 275/460] 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 863c15388848a..2a006e4db4671 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c @@ -2851,6 +2851,9 @@ int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize, (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 276/460] 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 2192b41114427..46b7345d2b6a9 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 2696f43e7239f..c84f588fdcd03 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 2170e0cc279d5..6ffa34c51a11b 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 277/460] 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 46b7345d2b6a9..effe5e5bab715 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 278/460] 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 effe5e5bab715..a7495f4ef3e14 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 279/460] 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 2e8c340363138..cc17205f7f496 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 47053904e18282af4525a02e3e0f519f014fc7f9 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Fri, 24 Feb 2023 19:16:40 +0000 Subject: [PATCH 280/460] KVM: arm64: timers: Convert per-vcpu virtual offset to a global value Having a per-vcpu virtual offset is a pain. It needs to be synchronized on each update, and expands badly to a setup where different timers can have different offsets, or have composite offsets (as with NV). So let's start by replacing the use of the CNTVOFF_EL2 shadow register (which we want to reclaim for NV anyway), and make the virtual timer carry a pointer to a VM-wide offset. This simplifies the code significantly. It also addresses two terrible bugs: - The use of CNTVOFF_EL2 leads to some nice offset corruption when the sysreg gets reset, as reported by Joey. - The kvm mutex is taken from a vcpu ioctl, which goes against the locking rules... Reported-by: Joey Gouly Reviewed-by: Reiji Watanabe Signed-off-by: Marc Zyngier Link: https://lore.kernel.org/r/20230224173915.GA17407@e124191.cambridge.arm.com Tested-by: Joey Gouly Link: https://lore.kernel.org/r/20230224191640.3396734-1-maz@kernel.org Signed-off-by: Oliver Upton --- arch/arm64/include/asm/kvm_host.h | 3 +++ arch/arm64/kvm/arch_timer.c | 45 +++++++------------------------ arch/arm64/kvm/hypercalls.c | 2 +- include/kvm/arm_arch_timer.h | 15 +++++++++++ 4 files changed, 29 insertions(+), 36 deletions(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index a1892a8f60323..bcd774d74f349 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -193,6 +193,9 @@ struct kvm_arch { /* Interrupt controller */ struct vgic_dist vgic; + /* Timers */ + struct arch_timer_vm_data timer_data; + /* Mandated version of PSCI */ u32 psci_version; diff --git a/arch/arm64/kvm/arch_timer.c b/arch/arm64/kvm/arch_timer.c index 00610477ec7bd..e1af4301b913d 100644 --- a/arch/arm64/kvm/arch_timer.c +++ b/arch/arm64/kvm/arch_timer.c @@ -84,14 +84,10 @@ u64 timer_get_cval(struct arch_timer_context *ctxt) static u64 timer_get_offset(struct arch_timer_context *ctxt) { - struct kvm_vcpu *vcpu = ctxt->vcpu; + if (ctxt->offset.vm_offset) + return *ctxt->offset.vm_offset; - switch(arch_timer_ctx_index(ctxt)) { - case TIMER_VTIMER: - return __vcpu_sys_reg(vcpu, CNTVOFF_EL2); - default: - return 0; - } + return 0; } static void timer_set_ctl(struct arch_timer_context *ctxt, u32 ctl) @@ -128,15 +124,12 @@ static void timer_set_cval(struct arch_timer_context *ctxt, u64 cval) static void timer_set_offset(struct arch_timer_context *ctxt, u64 offset) { - struct kvm_vcpu *vcpu = ctxt->vcpu; - - switch(arch_timer_ctx_index(ctxt)) { - case TIMER_VTIMER: - __vcpu_sys_reg(vcpu, CNTVOFF_EL2) = offset; - break; - default: + if (!ctxt->offset.vm_offset) { WARN(offset, "timer %ld\n", arch_timer_ctx_index(ctxt)); + return; } + + WRITE_ONCE(*ctxt->offset.vm_offset, offset); } u64 kvm_phys_timer_read(void) @@ -765,25 +758,6 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu) return 0; } -/* Make the updates of cntvoff for all vtimer contexts atomic */ -static void update_vtimer_cntvoff(struct kvm_vcpu *vcpu, u64 cntvoff) -{ - unsigned long i; - struct kvm *kvm = vcpu->kvm; - struct kvm_vcpu *tmp; - - mutex_lock(&kvm->lock); - kvm_for_each_vcpu(i, tmp, kvm) - timer_set_offset(vcpu_vtimer(tmp), cntvoff); - - /* - * When called from the vcpu create path, the CPU being created is not - * included in the loop above, so we just set it here as well. - */ - timer_set_offset(vcpu_vtimer(vcpu), cntvoff); - mutex_unlock(&kvm->lock); -} - void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu) { struct arch_timer_cpu *timer = vcpu_timer(vcpu); @@ -791,10 +765,11 @@ void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu) struct arch_timer_context *ptimer = vcpu_ptimer(vcpu); vtimer->vcpu = vcpu; + vtimer->offset.vm_offset = &vcpu->kvm->arch.timer_data.voffset; ptimer->vcpu = vcpu; /* Synchronize cntvoff across all vtimers of a VM. */ - update_vtimer_cntvoff(vcpu, kvm_phys_timer_read()); + timer_set_offset(vtimer, kvm_phys_timer_read()); timer_set_offset(ptimer, 0); hrtimer_init(&timer->bg_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_HARD); @@ -840,7 +815,7 @@ int kvm_arm_timer_set_reg(struct kvm_vcpu *vcpu, u64 regid, u64 value) break; case KVM_REG_ARM_TIMER_CNT: timer = vcpu_vtimer(vcpu); - update_vtimer_cntvoff(vcpu, kvm_phys_timer_read() - value); + timer_set_offset(timer, kvm_phys_timer_read() - value); break; case KVM_REG_ARM_TIMER_CVAL: timer = vcpu_vtimer(vcpu); diff --git a/arch/arm64/kvm/hypercalls.c b/arch/arm64/kvm/hypercalls.c index 64c086c02c603..5da884e11337a 100644 --- a/arch/arm64/kvm/hypercalls.c +++ b/arch/arm64/kvm/hypercalls.c @@ -44,7 +44,7 @@ static void kvm_ptp_get_time(struct kvm_vcpu *vcpu, u64 *val) feature = smccc_get_arg1(vcpu); switch (feature) { case KVM_PTP_VIRT_COUNTER: - cycles = systime_snapshot.cycles - vcpu_read_sys_reg(vcpu, CNTVOFF_EL2); + cycles = systime_snapshot.cycles - vcpu->kvm->arch.timer_data.voffset; break; case KVM_PTP_PHYS_COUNTER: cycles = systime_snapshot.cycles; diff --git a/include/kvm/arm_arch_timer.h b/include/kvm/arm_arch_timer.h index 71916de7c6c4d..c52a6e6839da9 100644 --- a/include/kvm/arm_arch_timer.h +++ b/include/kvm/arm_arch_timer.h @@ -23,6 +23,19 @@ enum kvm_arch_timer_regs { TIMER_REG_CTL, }; +struct arch_timer_offset { + /* + * If set, pointer to one of the offsets in the kvm's offset + * structure. If NULL, assume a zero offset. + */ + u64 *vm_offset; +}; + +struct arch_timer_vm_data { + /* Offset applied to the virtual timer/counter */ + u64 voffset; +}; + struct arch_timer_context { struct kvm_vcpu *vcpu; @@ -32,6 +45,8 @@ struct arch_timer_context { /* Emulated Timer (may be unused) */ struct hrtimer hrtimer; + /* Offset for this counter/timer */ + struct arch_timer_offset offset; /* * We have multiple paths which can save/restore the timer state onto * the hardware, so we need some way of keeping track of where the From e25c54d17914b0df4f902d1f25cd52f54e20cfbf Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Sat, 11 Mar 2023 10:29:29 +0100 Subject: [PATCH 281/460] 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 1de87062c67b9..3711d7f746003 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 282/460] 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 63d637d18e799..d4901ca8883c3 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 283/460] 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 40360e599bc36..bd757d836c5cf 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 284/460] 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 b99f55f2d4fd2..0601e6e5e3263 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 24ee4e1cc452a..830014a266090 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 285/460] 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 28ce13840a889..7bdeb8eea92dc 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 286/460] Linux 6.3-rc2 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index d7bd0eb9b3463..c933ceb4f21db 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 5a522150093a0eabae9470a70a37a6e436bfad08 Mon Sep 17 00:00:00 2001 From: Gautam Dawar Date: Wed, 1 Mar 2023 22:02:01 +0530 Subject: [PATCH 287/460] vhost-vdpa: free iommu domain after last use during cleanup Currently vhost_vdpa_cleanup() unmaps the DMA mappings by calling `iommu_unmap(v->domain, map->start, map->size);` from vhost_vdpa_general_unmap() when the parent vDPA driver doesn't provide DMA config operations. However, the IOMMU domain referred to by `v->domain` is freed in vhost_vdpa_free_domain() before vhost_vdpa_cleanup() in vhost_vdpa_release() which results in NULL pointer de-reference. Accordingly, moving the call to vhost_vdpa_free_domain() in vhost_vdpa_cleanup() would makes sense. This will also help detaching the dma device in error handling of vhost_vdpa_alloc_domain(). This issue was observed on terminating QEMU with SIGQUIT. Fixes: 037d4305569a ("vhost-vdpa: call vhost_vdpa_cleanup during the release") Signed-off-by: Gautam Dawar Message-Id: <20230301163203.29883-1-gautam.dawar@amd.com> Signed-off-by: Michael S. Tsirkin Acked-by: Jason Wang Reviewed-by: Stefano Garzarella --- drivers/vhost/vdpa.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c index dc12dbd5b43ba..7be9d9d8f01c8 100644 --- a/drivers/vhost/vdpa.c +++ b/drivers/vhost/vdpa.c @@ -1169,6 +1169,7 @@ static int vhost_vdpa_alloc_domain(struct vhost_vdpa *v) err_attach: iommu_domain_free(v->domain); + v->domain = NULL; return ret; } @@ -1213,6 +1214,7 @@ static void vhost_vdpa_cleanup(struct vhost_vdpa *v) vhost_vdpa_remove_as(v, asid); } + vhost_vdpa_free_domain(v); vhost_dev_cleanup(&v->vdev); kfree(v->vdev.vqs); } @@ -1285,7 +1287,6 @@ static int vhost_vdpa_release(struct inode *inode, struct file *filep) vhost_vdpa_clean_irq(v); vhost_vdpa_reset(v); vhost_dev_stop(&v->vdev); - vhost_vdpa_free_domain(v); vhost_vdpa_config_put(v); vhost_vdpa_cleanup(v); mutex_unlock(&d->mutex); From b4cca6d48eb3fa6f0d9caba4329b1a2b0ff67a77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= Date: Thu, 2 Mar 2023 19:18:57 +0100 Subject: [PATCH 288/460] vdpa_sim: set last_used_idx as last_avail_idx in vdpasim_queue_ready MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Starting from an used_idx different than 0 is needed in use cases like virtual machine migration. Not doing so and letting the caller set an avail idx different than 0 causes destination device to try to use old buffers that source driver already recover and are not available anymore. Since vdpa_sim does not support receive inflight descriptors as a destination of a migration, let's set both avail_idx and used_idx the same at vq start. This is how vhost-user works in a VHOST_SET_VRING_BASE call. Although the simple fix is to set last_used_idx at vdpasim_set_vq_state, it would be reset at vdpasim_queue_ready. The last_avail_idx case is fixed with commit 0e84f918fac8 ("vdpa_sim: not reset state in vdpasim_queue_ready"). Since the only option is to make it equal to last_avail_idx, adding the only change needed here. This was discovered and tested live migrating the vdpa_sim_net device. Fixes: 2c53d0f64c06 ("vdpasim: vDPA device simulator") Reviewed-by: Stefano Garzarella Signed-off-by: Eugenio Pérez Message-Id: <20230302181857.925374-1-eperezma@redhat.com> Signed-off-by: Michael S. Tsirkin --- drivers/vdpa/vdpa_sim/vdpa_sim.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/vdpa/vdpa_sim/vdpa_sim.c b/drivers/vdpa/vdpa_sim/vdpa_sim.c index 6a0a658146269..eea23c630f7c0 100644 --- a/drivers/vdpa/vdpa_sim/vdpa_sim.c +++ b/drivers/vdpa/vdpa_sim/vdpa_sim.c @@ -68,6 +68,17 @@ static void vdpasim_queue_ready(struct vdpasim *vdpasim, unsigned int idx) (uintptr_t)vq->device_addr); vq->vring.last_avail_idx = last_avail_idx; + + /* + * Since vdpa_sim does not support receive inflight descriptors as a + * destination of a migration, let's set both avail_idx and used_idx + * the same at vq start. This is how vhost-user works in a + * VHOST_SET_VRING_BASE call. + * + * Although the simple fix is to set last_used_idx at + * vdpasim_set_vq_state, it would be reset at vdpasim_queue_ready. + */ + vq->vring.last_used_idx = last_avail_idx; vq->vring.notify = vdpasim_vq_notify; } From ae43c20da2a77c508715a9c77845b4e87e6a1e25 Mon Sep 17 00:00:00 2001 From: Rong Tao Date: Thu, 9 Mar 2023 14:13:07 +0800 Subject: [PATCH 289/460] tools/virtio: Ignore virtio-trace/trace-agent since commit 108fc82596e3("tools: Add guest trace agent as a user tool") introduce virtio-trace/trace-agent, it should be ignored in the git tree. Signed-off-by: Rong Tao Message-Id: Signed-off-by: Michael S. Tsirkin --- tools/virtio/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/virtio/.gitignore b/tools/virtio/.gitignore index 075588c4da081..9934d48d9a557 100644 --- a/tools/virtio/.gitignore +++ b/tools/virtio/.gitignore @@ -2,3 +2,4 @@ *.d virtio_test vringh_test +virtio-trace/trace-agent From a52e5cdbe8016d4e3e6322fd93d71afddb9a5af9 Mon Sep 17 00:00:00 2001 From: Sven Schnelle Date: Tue, 7 Mar 2023 14:35:23 +0100 Subject: [PATCH 290/460] s390/ipl: add missing intersection check to ipl_report handling The code which handles the ipl report is searching for a free location in memory where it could copy the component and certificate entries to. It checks for intersection between the sections required for the kernel and the component/certificate data area, but fails to check whether the data structures linking these data areas together intersect. This might cause the iplreport copy code to overwrite the iplreport itself. Fix this by adding two addtional intersection checks. Cc: Fixes: 9641b8cc733f ("s390/ipl: read IPL report at early boot") Signed-off-by: Sven Schnelle Reviewed-by: Vasily Gorbik Signed-off-by: Vasily Gorbik --- arch/s390/boot/ipl_report.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/s390/boot/ipl_report.c b/arch/s390/boot/ipl_report.c index 9b14045065b6e..74b5cd2648622 100644 --- a/arch/s390/boot/ipl_report.c +++ b/arch/s390/boot/ipl_report.c @@ -57,11 +57,19 @@ static unsigned long find_bootdata_space(struct ipl_rb_components *comps, if (IS_ENABLED(CONFIG_BLK_DEV_INITRD) && initrd_data.start && initrd_data.size && intersects(initrd_data.start, initrd_data.size, safe_addr, size)) safe_addr = initrd_data.start + initrd_data.size; + if (intersects(safe_addr, size, (unsigned long)comps, comps->len)) { + safe_addr = (unsigned long)comps + comps->len; + goto repeat; + } for_each_rb_entry(comp, comps) if (intersects(safe_addr, size, comp->addr, comp->len)) { safe_addr = comp->addr + comp->len; goto repeat; } + if (intersects(safe_addr, size, (unsigned long)certs, certs->len)) { + safe_addr = (unsigned long)certs + certs->len; + goto repeat; + } for_each_rb_entry(cert, certs) if (intersects(safe_addr, size, cert->addr, cert->len)) { safe_addr = cert->addr + cert->len; From ab909509850b27fd39b8ba99e44cda39dbc3858c Mon Sep 17 00:00:00 2001 From: Niklas Schnelle Date: Mon, 6 Mar 2023 16:10:11 +0100 Subject: [PATCH 291/460] PCI: s390: Fix use-after-free of PCI resources with per-function hotplug On s390 PCI functions may be hotplugged individually even when they belong to a multi-function device. In particular on an SR-IOV device VFs may be removed and later re-added. In commit a50297cf8235 ("s390/pci: separate zbus creation from scanning") it was missed however that struct pci_bus and struct zpci_bus's resource list retained a reference to the PCI functions MMIO resources even though those resources are released and freed on hot-unplug. These stale resources may subsequently be claimed when the PCI function re-appears resulting in use-after-free. One idea of fixing this use-after-free in s390 specific code that was investigated was to simply keep resources around from the moment a PCI function first appeared until the whole virtual PCI bus created for a multi-function device disappears. The problem with this however is that due to the requirement of artificial MMIO addreesses (address cookies) extra logic is then needed to keep the address cookies compatible on re-plug. At the same time the MMIO resources semantically belong to the PCI function so tying their lifecycle to the function seems more logical. Instead a simpler approach is to remove the resources of an individually hot-unplugged PCI function from the PCI bus's resource list while keeping the resources of other PCI functions on the PCI bus untouched. This is done by introducing pci_bus_remove_resource() to remove an individual resource. Similarly the resource also needs to be removed from the struct zpci_bus's resource list. It turns out however, that there is really no need to add the MMIO resources to the struct zpci_bus's resource list at all and instead we can simply use the zpci_bar_struct's resource pointer directly. Fixes: a50297cf8235 ("s390/pci: separate zbus creation from scanning") Signed-off-by: Niklas Schnelle Reviewed-by: Matthew Rosato Acked-by: Bjorn Helgaas Link: https://lore.kernel.org/r/20230306151014.60913-2-schnelle@linux.ibm.com Signed-off-by: Vasily Gorbik --- arch/s390/pci/pci.c | 16 ++++++++++------ arch/s390/pci/pci_bus.c | 12 +++++------- arch/s390/pci/pci_bus.h | 3 +-- drivers/pci/bus.c | 21 +++++++++++++++++++++ include/linux/pci.h | 1 + 5 files changed, 38 insertions(+), 15 deletions(-) diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c index ef38b1514c77a..e16afacc8fd1b 100644 --- a/arch/s390/pci/pci.c +++ b/arch/s390/pci/pci.c @@ -544,8 +544,7 @@ static struct resource *__alloc_res(struct zpci_dev *zdev, unsigned long start, return r; } -int zpci_setup_bus_resources(struct zpci_dev *zdev, - struct list_head *resources) +int zpci_setup_bus_resources(struct zpci_dev *zdev) { unsigned long addr, size, flags; struct resource *res; @@ -581,7 +580,6 @@ int zpci_setup_bus_resources(struct zpci_dev *zdev, return -ENOMEM; } zdev->bars[i].res = res; - pci_add_resource(resources, res); } zdev->has_resources = 1; @@ -590,17 +588,23 @@ int zpci_setup_bus_resources(struct zpci_dev *zdev, static void zpci_cleanup_bus_resources(struct zpci_dev *zdev) { + struct resource *res; int i; + pci_lock_rescan_remove(); for (i = 0; i < PCI_STD_NUM_BARS; i++) { - if (!zdev->bars[i].size || !zdev->bars[i].res) + res = zdev->bars[i].res; + if (!res) continue; + release_resource(res); + pci_bus_remove_resource(zdev->zbus->bus, res); zpci_free_iomap(zdev, zdev->bars[i].map_idx); - release_resource(zdev->bars[i].res); - kfree(zdev->bars[i].res); + zdev->bars[i].res = NULL; + kfree(res); } zdev->has_resources = 0; + pci_unlock_rescan_remove(); } int pcibios_device_add(struct pci_dev *pdev) diff --git a/arch/s390/pci/pci_bus.c b/arch/s390/pci/pci_bus.c index 6a8da1b742ae5..a99926af2b69a 100644 --- a/arch/s390/pci/pci_bus.c +++ b/arch/s390/pci/pci_bus.c @@ -41,9 +41,7 @@ static int zpci_nb_devices; */ static int zpci_bus_prepare_device(struct zpci_dev *zdev) { - struct resource_entry *window, *n; - struct resource *res; - int rc; + int rc, i; if (!zdev_enabled(zdev)) { rc = zpci_enable_device(zdev); @@ -57,10 +55,10 @@ static int zpci_bus_prepare_device(struct zpci_dev *zdev) } if (!zdev->has_resources) { - zpci_setup_bus_resources(zdev, &zdev->zbus->resources); - resource_list_for_each_entry_safe(window, n, &zdev->zbus->resources) { - res = window->res; - pci_bus_add_resource(zdev->zbus->bus, res, 0); + zpci_setup_bus_resources(zdev); + for (i = 0; i < PCI_STD_NUM_BARS; i++) { + if (zdev->bars[i].res) + pci_bus_add_resource(zdev->zbus->bus, zdev->bars[i].res, 0); } } diff --git a/arch/s390/pci/pci_bus.h b/arch/s390/pci/pci_bus.h index e96c9860e0644..af9f0ac79a1b1 100644 --- a/arch/s390/pci/pci_bus.h +++ b/arch/s390/pci/pci_bus.h @@ -30,8 +30,7 @@ static inline void zpci_zdev_get(struct zpci_dev *zdev) int zpci_alloc_domain(int domain); void zpci_free_domain(int domain); -int zpci_setup_bus_resources(struct zpci_dev *zdev, - struct list_head *resources); +int zpci_setup_bus_resources(struct zpci_dev *zdev); static inline struct zpci_dev *zdev_from_bus(struct pci_bus *bus, unsigned int devfn) diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index 83ae838ceb5f0..549c4bd5caeca 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c @@ -76,6 +76,27 @@ struct resource *pci_bus_resource_n(const struct pci_bus *bus, int n) } EXPORT_SYMBOL_GPL(pci_bus_resource_n); +void pci_bus_remove_resource(struct pci_bus *bus, struct resource *res) +{ + struct pci_bus_resource *bus_res, *tmp; + int i; + + for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; i++) { + if (bus->resource[i] == res) { + bus->resource[i] = NULL; + return; + } + } + + list_for_each_entry_safe(bus_res, tmp, &bus->resources, list) { + if (bus_res->res == res) { + list_del(&bus_res->list); + kfree(bus_res); + return; + } + } +} + void pci_bus_remove_resources(struct pci_bus *bus) { int i; diff --git a/include/linux/pci.h b/include/linux/pci.h index fafd8020c6d7f..b50e5c79f7e32 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1438,6 +1438,7 @@ void pci_bus_add_resource(struct pci_bus *bus, struct resource *res, unsigned int flags); struct resource *pci_bus_resource_n(const struct pci_bus *bus, int n); void pci_bus_remove_resources(struct pci_bus *bus); +void pci_bus_remove_resource(struct pci_bus *bus, struct resource *res); int devm_request_pci_bus_resources(struct device *dev, struct list_head *resources); From d7a0bdbf17276b757d2b89f5351bbee9ecf58fe6 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 10 Mar 2023 14:19:55 +0100 Subject: [PATCH 292/460] s390: update defconfigs Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/configs/debug_defconfig | 13 ++++--------- arch/s390/configs/defconfig | 12 +++--------- arch/s390/configs/zfcpdump_defconfig | 2 +- 3 files changed, 8 insertions(+), 19 deletions(-) diff --git a/arch/s390/configs/debug_defconfig b/arch/s390/configs/debug_defconfig index 3c68fe49042c2..4ccf66d29fc24 100644 --- a/arch/s390/configs/debug_defconfig +++ b/arch/s390/configs/debug_defconfig @@ -23,7 +23,6 @@ CONFIG_NUMA_BALANCING=y CONFIG_MEMCG=y CONFIG_BLK_CGROUP=y CONFIG_CFS_BANDWIDTH=y -CONFIG_RT_GROUP_SCHED=y CONFIG_CGROUP_PIDS=y CONFIG_CGROUP_RDMA=y CONFIG_CGROUP_FREEZER=y @@ -90,7 +89,6 @@ CONFIG_MINIX_SUBPARTITION=y CONFIG_SOLARIS_X86_PARTITION=y CONFIG_UNIXWARE_DISKLABEL=y CONFIG_IOSCHED_BFQ=y -CONFIG_BFQ_GROUP_IOSCHED=y CONFIG_BINFMT_MISC=m CONFIG_ZSWAP=y CONFIG_ZSMALLOC_STAT=y @@ -298,7 +296,6 @@ CONFIG_IP_NF_TARGET_REJECT=m CONFIG_IP_NF_NAT=m CONFIG_IP_NF_TARGET_MASQUERADE=m CONFIG_IP_NF_MANGLE=m -CONFIG_IP_NF_TARGET_CLUSTERIP=m CONFIG_IP_NF_TARGET_ECN=m CONFIG_IP_NF_TARGET_TTL=m CONFIG_IP_NF_RAW=m @@ -340,7 +337,6 @@ CONFIG_BRIDGE_MRP=y CONFIG_VLAN_8021Q=m CONFIG_VLAN_8021Q_GVRP=y CONFIG_NET_SCHED=y -CONFIG_NET_SCH_CBQ=m CONFIG_NET_SCH_HTB=m CONFIG_NET_SCH_HFSC=m CONFIG_NET_SCH_PRIO=m @@ -351,7 +347,6 @@ CONFIG_NET_SCH_SFQ=m CONFIG_NET_SCH_TEQL=m CONFIG_NET_SCH_TBF=m CONFIG_NET_SCH_GRED=m -CONFIG_NET_SCH_DSMARK=m CONFIG_NET_SCH_NETEM=m CONFIG_NET_SCH_DRR=m CONFIG_NET_SCH_MQPRIO=m @@ -363,14 +358,11 @@ CONFIG_NET_SCH_INGRESS=m CONFIG_NET_SCH_PLUG=m CONFIG_NET_SCH_ETS=m CONFIG_NET_CLS_BASIC=m -CONFIG_NET_CLS_TCINDEX=m CONFIG_NET_CLS_ROUTE4=m CONFIG_NET_CLS_FW=m CONFIG_NET_CLS_U32=m CONFIG_CLS_U32_PERF=y CONFIG_CLS_U32_MARK=y -CONFIG_NET_CLS_RSVP=m -CONFIG_NET_CLS_RSVP6=m CONFIG_NET_CLS_FLOW=m CONFIG_NET_CLS_CGROUP=y CONFIG_NET_CLS_BPF=m @@ -584,7 +576,7 @@ CONFIG_DIAG288_WATCHDOG=m CONFIG_FB=y CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y -# CONFIG_HID is not set +# CONFIG_HID_SUPPORT is not set # CONFIG_USB_SUPPORT is not set CONFIG_INFINIBAND=m CONFIG_INFINIBAND_USER_ACCESS=m @@ -828,6 +820,7 @@ CONFIG_PANIC_ON_OOPS=y CONFIG_DETECT_HUNG_TASK=y CONFIG_WQ_WATCHDOG=y CONFIG_TEST_LOCKUP=m +CONFIG_DEBUG_PREEMPT=y CONFIG_PROVE_LOCKING=y CONFIG_LOCK_STAT=y CONFIG_DEBUG_ATOMIC_SLEEP=y @@ -843,6 +836,7 @@ CONFIG_RCU_CPU_STALL_TIMEOUT=300 # CONFIG_RCU_TRACE is not set CONFIG_LATENCYTOP=y CONFIG_BOOTTIME_TRACING=y +CONFIG_FPROBE=y CONFIG_FUNCTION_PROFILER=y CONFIG_STACK_TRACER=y CONFIG_IRQSOFF_TRACER=y @@ -857,6 +851,7 @@ CONFIG_SAMPLES=y CONFIG_SAMPLE_TRACE_PRINTK=m CONFIG_SAMPLE_FTRACE_DIRECT=m CONFIG_SAMPLE_FTRACE_DIRECT_MULTI=m +CONFIG_SAMPLE_FTRACE_OPS=m CONFIG_DEBUG_ENTRY=y CONFIG_CIO_INJECT=y CONFIG_KUNIT=m diff --git a/arch/s390/configs/defconfig b/arch/s390/configs/defconfig index 9ab91632f74cc..693297a2e8973 100644 --- a/arch/s390/configs/defconfig +++ b/arch/s390/configs/defconfig @@ -21,7 +21,6 @@ CONFIG_NUMA_BALANCING=y CONFIG_MEMCG=y CONFIG_BLK_CGROUP=y CONFIG_CFS_BANDWIDTH=y -CONFIG_RT_GROUP_SCHED=y CONFIG_CGROUP_PIDS=y CONFIG_CGROUP_RDMA=y CONFIG_CGROUP_FREEZER=y @@ -85,7 +84,6 @@ CONFIG_MINIX_SUBPARTITION=y CONFIG_SOLARIS_X86_PARTITION=y CONFIG_UNIXWARE_DISKLABEL=y CONFIG_IOSCHED_BFQ=y -CONFIG_BFQ_GROUP_IOSCHED=y CONFIG_BINFMT_MISC=m CONFIG_ZSWAP=y CONFIG_ZSMALLOC_STAT=y @@ -289,7 +287,6 @@ CONFIG_IP_NF_TARGET_REJECT=m CONFIG_IP_NF_NAT=m CONFIG_IP_NF_TARGET_MASQUERADE=m CONFIG_IP_NF_MANGLE=m -CONFIG_IP_NF_TARGET_CLUSTERIP=m CONFIG_IP_NF_TARGET_ECN=m CONFIG_IP_NF_TARGET_TTL=m CONFIG_IP_NF_RAW=m @@ -330,7 +327,6 @@ CONFIG_BRIDGE_MRP=y CONFIG_VLAN_8021Q=m CONFIG_VLAN_8021Q_GVRP=y CONFIG_NET_SCHED=y -CONFIG_NET_SCH_CBQ=m CONFIG_NET_SCH_HTB=m CONFIG_NET_SCH_HFSC=m CONFIG_NET_SCH_PRIO=m @@ -341,7 +337,6 @@ CONFIG_NET_SCH_SFQ=m CONFIG_NET_SCH_TEQL=m CONFIG_NET_SCH_TBF=m CONFIG_NET_SCH_GRED=m -CONFIG_NET_SCH_DSMARK=m CONFIG_NET_SCH_NETEM=m CONFIG_NET_SCH_DRR=m CONFIG_NET_SCH_MQPRIO=m @@ -353,14 +348,11 @@ CONFIG_NET_SCH_INGRESS=m CONFIG_NET_SCH_PLUG=m CONFIG_NET_SCH_ETS=m CONFIG_NET_CLS_BASIC=m -CONFIG_NET_CLS_TCINDEX=m CONFIG_NET_CLS_ROUTE4=m CONFIG_NET_CLS_FW=m CONFIG_NET_CLS_U32=m CONFIG_CLS_U32_PERF=y CONFIG_CLS_U32_MARK=y -CONFIG_NET_CLS_RSVP=m -CONFIG_NET_CLS_RSVP6=m CONFIG_NET_CLS_FLOW=m CONFIG_NET_CLS_CGROUP=y CONFIG_NET_CLS_BPF=m @@ -573,7 +565,7 @@ CONFIG_DIAG288_WATCHDOG=m CONFIG_FB=y CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y -# CONFIG_HID is not set +# CONFIG_HID_SUPPORT is not set # CONFIG_USB_SUPPORT is not set CONFIG_INFINIBAND=m CONFIG_INFINIBAND_USER_ACCESS=m @@ -795,6 +787,7 @@ CONFIG_RCU_REF_SCALE_TEST=m CONFIG_RCU_CPU_STALL_TIMEOUT=60 CONFIG_LATENCYTOP=y CONFIG_BOOTTIME_TRACING=y +CONFIG_FPROBE=y CONFIG_FUNCTION_PROFILER=y CONFIG_STACK_TRACER=y CONFIG_SCHED_TRACER=y @@ -805,6 +798,7 @@ CONFIG_SAMPLES=y CONFIG_SAMPLE_TRACE_PRINTK=m CONFIG_SAMPLE_FTRACE_DIRECT=m CONFIG_SAMPLE_FTRACE_DIRECT_MULTI=m +CONFIG_SAMPLE_FTRACE_OPS=m CONFIG_KUNIT=m CONFIG_KUNIT_DEBUGFS=y CONFIG_LKDTM=m diff --git a/arch/s390/configs/zfcpdump_defconfig b/arch/s390/configs/zfcpdump_defconfig index a9c0c81d1de99..33a232bb68af9 100644 --- a/arch/s390/configs/zfcpdump_defconfig +++ b/arch/s390/configs/zfcpdump_defconfig @@ -58,7 +58,7 @@ CONFIG_ZFCP=y # CONFIG_VMCP is not set # CONFIG_MONWRITER is not set # CONFIG_S390_VMUR is not set -# CONFIG_HID is not set +# CONFIG_HID_SUPPORT is not set # CONFIG_VIRTIO_MENU is not set # CONFIG_VHOST_MENU is not set # CONFIG_IOMMU_SUPPORT is not set From ee892ea83d99610fa33bea612de058e0955eec3a Mon Sep 17 00:00:00 2001 From: Ashutosh Dixit Date: Fri, 3 Feb 2023 07:53:09 -0800 Subject: [PATCH 293/460] drm/i915/hwmon: Enable PL1 power limit Previous documentation suggested that PL1 power limit is always enabled. However we now find this not to be the case on some platforms (such as ATSM). Therefore enable PL1 power limit during hwmon initialization. Bspec: 51864 v2: Add Bspec reference (Gwan-gyeong) v3: Add Fixes tag Fixes: 99f55efb79114 ("drm/i915/hwmon: Power PL1 limit and TDP setting") Signed-off-by: Ashutosh Dixit Reviewed-by: Gwan-gyeong Mun Signed-off-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20230203155309.1042297-1-ashutosh.dixit@intel.com (cherry picked from commit 0349c41b05968befaffa5fbb7e73d0ee6004f610) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/i915_hwmon.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_hwmon.c b/drivers/gpu/drm/i915/i915_hwmon.c index 1225bc432f0d5..4683a5b96eff1 100644 --- a/drivers/gpu/drm/i915/i915_hwmon.c +++ b/drivers/gpu/drm/i915/i915_hwmon.c @@ -687,6 +687,11 @@ hwm_get_preregistration_info(struct drm_i915_private *i915) for_each_gt(gt, i915, i) hwm_energy(&hwmon->ddat_gt[i], &energy); } + + /* Enable PL1 power limit */ + if (i915_mmio_reg_valid(hwmon->rg.pkg_rapl_limit)) + hwm_locked_with_pm_intel_uncore_rmw(ddat, hwmon->rg.pkg_rapl_limit, + PKG_PWR_LIM_1_EN, PKG_PWR_LIM_1_EN); } void i915_hwmon_register(struct drm_i915_private *i915) From 897f453c106380e57600c19a0a0485ceb4f3b0d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 20 Feb 2023 17:17:30 +0200 Subject: [PATCH 294/460] drm/i915: Fix audio ELD handling for DP MST MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I forgot to call intel_audio_compute_config() on DP MST, which means ELD doesn't get populated and passed to the audio driver. References: https://gitlab.freedesktop.org/drm/intel/-/issues/8097 Fixes: 5d986635e296 ("drm/i915/audio: Precompute the ELD") Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20230220151731.6852-1-ville.syrjala@linux.intel.com Reviewed-by: Uma Shankar (cherry picked from commit 518b761a7b0e2bb2fac2518f041c71b461adf761) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dp_mst.c | 25 +++++++++++++-------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 054a009e800d7..2106b3de225a0 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -265,6 +265,19 @@ static int intel_dp_mst_update_slots(struct intel_encoder *encoder, return 0; } +static bool intel_dp_mst_has_audio(const struct drm_connector_state *conn_state) +{ + const struct intel_digital_connector_state *intel_conn_state = + to_intel_digital_connector_state(conn_state); + struct intel_connector *connector = + to_intel_connector(conn_state->connector); + + if (intel_conn_state->force_audio == HDMI_AUDIO_AUTO) + return connector->port->has_audio; + else + return intel_conn_state->force_audio == HDMI_AUDIO_ON; +} + static int intel_dp_mst_compute_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config, struct drm_connector_state *conn_state) @@ -272,10 +285,6 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder, struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder); struct intel_dp *intel_dp = &intel_mst->primary->dp; - struct intel_connector *connector = - to_intel_connector(conn_state->connector); - struct intel_digital_connector_state *intel_conn_state = - to_intel_digital_connector_state(conn_state); const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; struct link_config_limits limits; @@ -287,11 +296,9 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder, pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB; pipe_config->has_pch_encoder = false; - if (intel_conn_state->force_audio == HDMI_AUDIO_AUTO) - pipe_config->has_audio = connector->port->has_audio; - else - pipe_config->has_audio = - intel_conn_state->force_audio == HDMI_AUDIO_ON; + pipe_config->has_audio = + intel_dp_mst_has_audio(conn_state) && + intel_audio_compute_config(encoder, pipe_config, conn_state); /* * for MST we always configure max link bw - the spec doesn't From 71c602103c74b277bef3d20a308874a33ec8326d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jouni=20H=C3=B6gander?= Date: Tue, 21 Feb 2023 10:53:04 +0200 Subject: [PATCH 295/460] drm/i915/psr: Use calculated io and fast wake lines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently we are using hardcoded 7 for io and fast wake lines. According to Bspec io and fast wake times are both 42us for DISPLAY_VER >= 12 and 50us and 32us for older platforms. Calculate line counts for these and configure them into PSR2_CTL accordingly Use 45 us for the fast wake calculation as 42 seems to be too tight based on testing. Bspec: 49274, 4289 Cc: Mika Kahola Cc: José Roberto de Souza Fixes: 64cf40a125ff ("drm/i915/psr: Program default IO buffer Wake and Fast Wake") Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/7725 Signed-off-by: Jouni Högander Reviewed-by: Stanislav Lisovskiy Link: https://patchwork.freedesktop.org/patch/msgid/20230221085304.3382297-1-jouni.hogander@intel.com (cherry picked from commit cb42e8ede5b475c096e473b86c356b1158b4bc3b) Signed-off-by: Jani Nikula --- .../drm/i915/display/intel_display_types.h | 2 + drivers/gpu/drm/i915/display/intel_psr.c | 78 +++++++++++++++---- 2 files changed, 63 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 54c517ca9632f..582234f0c49ac 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1631,6 +1631,8 @@ struct intel_psr { bool psr2_sel_fetch_cff_enabled; bool req_psr2_sdp_prior_scanline; u8 sink_sync_latency; + u8 io_wake_lines; + u8 fast_wake_lines; ktime_t last_entry_attempt; ktime_t last_exit; bool sink_not_reliable; diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index 7a72e15e68369..9f1a0bebae240 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -542,6 +542,14 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp) val |= EDP_PSR2_FRAME_BEFORE_SU(max_t(u8, intel_dp->psr.sink_sync_latency + 1, 2)); val |= intel_psr2_get_tp_time(intel_dp); + if (DISPLAY_VER(dev_priv) >= 12) { + if (intel_dp->psr.io_wake_lines < 9 && + intel_dp->psr.fast_wake_lines < 9) + val |= TGL_EDP_PSR2_BLOCK_COUNT_NUM_2; + else + val |= TGL_EDP_PSR2_BLOCK_COUNT_NUM_3; + } + /* Wa_22012278275:adl-p */ if (IS_ADLP_DISPLAY_STEP(dev_priv, STEP_A0, STEP_E0)) { static const u8 map[] = { @@ -558,31 +566,21 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp) * Still using the default IO_BUFFER_WAKE and FAST_WAKE, see * comments bellow for more information */ - u32 tmp, lines = 7; - - val |= TGL_EDP_PSR2_BLOCK_COUNT_NUM_2; + u32 tmp; - tmp = map[lines - TGL_EDP_PSR2_IO_BUFFER_WAKE_MIN_LINES]; + tmp = map[intel_dp->psr.io_wake_lines - TGL_EDP_PSR2_IO_BUFFER_WAKE_MIN_LINES]; tmp = tmp << TGL_EDP_PSR2_IO_BUFFER_WAKE_SHIFT; val |= tmp; - tmp = map[lines - TGL_EDP_PSR2_FAST_WAKE_MIN_LINES]; + tmp = map[intel_dp->psr.fast_wake_lines - TGL_EDP_PSR2_FAST_WAKE_MIN_LINES]; tmp = tmp << TGL_EDP_PSR2_FAST_WAKE_MIN_SHIFT; val |= tmp; } else if (DISPLAY_VER(dev_priv) >= 12) { - /* - * TODO: 7 lines of IO_BUFFER_WAKE and FAST_WAKE are default - * values from BSpec. In order to setting an optimal power - * consumption, lower than 4k resolution mode needs to decrease - * IO_BUFFER_WAKE and FAST_WAKE. And higher than 4K resolution - * mode needs to increase IO_BUFFER_WAKE and FAST_WAKE. - */ - val |= TGL_EDP_PSR2_BLOCK_COUNT_NUM_2; - val |= TGL_EDP_PSR2_IO_BUFFER_WAKE(7); - val |= TGL_EDP_PSR2_FAST_WAKE(7); + val |= TGL_EDP_PSR2_IO_BUFFER_WAKE(intel_dp->psr.io_wake_lines); + val |= TGL_EDP_PSR2_FAST_WAKE(intel_dp->psr.fast_wake_lines); } else if (DISPLAY_VER(dev_priv) >= 9) { - val |= EDP_PSR2_IO_BUFFER_WAKE(7); - val |= EDP_PSR2_FAST_WAKE(7); + val |= EDP_PSR2_IO_BUFFER_WAKE(intel_dp->psr.io_wake_lines); + val |= EDP_PSR2_FAST_WAKE(intel_dp->psr.fast_wake_lines); } if (intel_dp->psr.req_psr2_sdp_prior_scanline) @@ -842,6 +840,46 @@ static bool _compute_psr2_sdp_prior_scanline_indication(struct intel_dp *intel_d return true; } +static bool _compute_psr2_wake_times(struct intel_dp *intel_dp, + struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *i915 = dp_to_i915(intel_dp); + int io_wake_lines, io_wake_time, fast_wake_lines, fast_wake_time; + u8 max_wake_lines; + + if (DISPLAY_VER(i915) >= 12) { + io_wake_time = 42; + /* + * According to Bspec it's 42us, but based on testing + * it is not enough -> use 45 us. + */ + fast_wake_time = 45; + max_wake_lines = 12; + } else { + io_wake_time = 50; + fast_wake_time = 32; + max_wake_lines = 8; + } + + io_wake_lines = intel_usecs_to_scanlines( + &crtc_state->uapi.adjusted_mode, io_wake_time); + fast_wake_lines = intel_usecs_to_scanlines( + &crtc_state->uapi.adjusted_mode, fast_wake_time); + + if (io_wake_lines > max_wake_lines || + fast_wake_lines > max_wake_lines) + return false; + + if (i915->params.psr_safest_params) + io_wake_lines = fast_wake_lines = max_wake_lines; + + /* According to Bspec lower limit should be set as 7 lines. */ + intel_dp->psr.io_wake_lines = max(io_wake_lines, 7); + intel_dp->psr.fast_wake_lines = max(fast_wake_lines, 7); + + return true; +} + static bool intel_psr2_config_valid(struct intel_dp *intel_dp, struct intel_crtc_state *crtc_state) { @@ -936,6 +974,12 @@ static bool intel_psr2_config_valid(struct intel_dp *intel_dp, return false; } + if (!_compute_psr2_wake_times(intel_dp, crtc_state)) { + drm_dbg_kms(&dev_priv->drm, + "PSR2 not enabled, Unable to use long enough wake times\n"); + return false; + } + if (HAS_PSR2_SEL_FETCH(dev_priv)) { if (!intel_psr2_sel_fetch_config_valid(intel_dp, crtc_state) && !HAS_PSR_HW_TRACKING(dev_priv)) { From 46bc23dcd94569270d02c4c1f7e62ae01ebd53bb Mon Sep 17 00:00:00 2001 From: Ankit Nautiyal Date: Thu, 23 Feb 2023 10:06:19 +0530 Subject: [PATCH 296/460] drm/i915/dg2: Add HDMI pixel clock frequencies 267.30 and 319.89 MHz Add snps phy table values for HDMI pixel clocks 267.30 MHz and 319.89 MHz. Values are based on the Bspec algorithm for PLL programming for HDMI. Cc: stable@vger.kernel.org Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/8008 Signed-off-by: Ankit Nautiyal Reviewed-by: Uma Shankar Signed-off-by: Uma Shankar Link: https://patchwork.freedesktop.org/patch/msgid/20230223043619.3941382-1-ankit.k.nautiyal@intel.com (cherry picked from commit d46746b8b13cbd377ffc733e465d25800459a31b) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_snps_phy.c | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_snps_phy.c b/drivers/gpu/drm/i915/display/intel_snps_phy.c index c65c771f5c461..1cfb94b5cedbd 100644 --- a/drivers/gpu/drm/i915/display/intel_snps_phy.c +++ b/drivers/gpu/drm/i915/display/intel_snps_phy.c @@ -1419,6 +1419,36 @@ static const struct intel_mpllb_state dg2_hdmi_262750 = { REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), }; +static const struct intel_mpllb_state dg2_hdmi_267300 = { + .clock = 267300, + .ref_control = + REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), + .mpllb_cp = + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 7) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), + .mpllb_div = + REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 3), + .mpllb_div2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 74) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), + .mpllb_fracn1 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), + .mpllb_fracn2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 30146) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 36699), + .mpllb_sscen = + REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), +}; + static const struct intel_mpllb_state dg2_hdmi_268500 = { .clock = 268500, .ref_control = @@ -1509,6 +1539,36 @@ static const struct intel_mpllb_state dg2_hdmi_241500 = { REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), }; +static const struct intel_mpllb_state dg2_hdmi_319890 = { + .clock = 319890, + .ref_control = + REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), + .mpllb_cp = + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), + .mpllb_div = + REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 2), + .mpllb_div2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 94) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), + .mpllb_fracn1 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), + .mpllb_fracn2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 64094) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 13631), + .mpllb_sscen = + REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), +}; + static const struct intel_mpllb_state dg2_hdmi_497750 = { .clock = 497750, .ref_control = @@ -1696,8 +1756,10 @@ static const struct intel_mpllb_state * const dg2_hdmi_tables[] = { &dg2_hdmi_209800, &dg2_hdmi_241500, &dg2_hdmi_262750, + &dg2_hdmi_267300, &dg2_hdmi_268500, &dg2_hdmi_296703, + &dg2_hdmi_319890, &dg2_hdmi_497750, &dg2_hdmi_592000, &dg2_hdmi_593407, From 193c41926d152761764894f46e23b53c00186a82 Mon Sep 17 00:00:00 2001 From: Andrea Righi Date: Mon, 20 Feb 2023 18:18:58 +0100 Subject: [PATCH 297/460] drm/i915/sseu: fix max_subslices array-index-out-of-bounds access It seems that commit bc3c5e0809ae ("drm/i915/sseu: Don't try to store EU mask internally in UAPI format") exposed a potential out-of-bounds access, reported by UBSAN as following on a laptop with a gen 11 i915 card: UBSAN: array-index-out-of-bounds in drivers/gpu/drm/i915/gt/intel_sseu.c:65:27 index 6 is out of range for type 'u16 [6]' CPU: 2 PID: 165 Comm: systemd-udevd Not tainted 6.2.0-9-generic #9-Ubuntu Hardware name: Dell Inc. XPS 13 9300/077Y9N, BIOS 1.11.0 03/22/2022 Call Trace: show_stack+0x4e/0x61 dump_stack_lvl+0x4a/0x6f dump_stack+0x10/0x18 ubsan_epilogue+0x9/0x3a __ubsan_handle_out_of_bounds.cold+0x42/0x47 gen11_compute_sseu_info+0x121/0x130 [i915] intel_sseu_info_init+0x15d/0x2b0 [i915] intel_gt_init_mmio+0x23/0x40 [i915] i915_driver_mmio_probe+0x129/0x400 [i915] ? intel_gt_probe_all+0x91/0x2e0 [i915] i915_driver_probe+0xe1/0x3f0 [i915] ? drm_privacy_screen_get+0x16d/0x190 [drm] ? acpi_dev_found+0x64/0x80 i915_pci_probe+0xac/0x1b0 [i915] ... According to the definition of sseu_dev_info, eu_mask->hsw is limited to a maximum of GEN_MAX_SS_PER_HSW_SLICE (6) sub-slices, but gen11_sseu_info_init() can potentially set 8 sub-slices, in the !IS_JSL_EHL(gt->i915) case. Fix this by reserving up to 8 slots for max_subslices in the eu_mask struct. Reported-by: Emil Renner Berthing Signed-off-by: Andrea Righi Fixes: bc3c5e0809ae ("drm/i915/sseu: Don't try to store EU mask internally in UAPI format") Reviewed-by: Matt Roper Signed-off-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20230220171858.131416-1-andrea.righi@canonical.com (cherry picked from commit 3cba09a6ac86ea1d456909626eb2685596c07822) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/gt/intel_sseu.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/intel_sseu.h b/drivers/gpu/drm/i915/gt/intel_sseu.h index aa87d3832d60d..d7e8c374f153e 100644 --- a/drivers/gpu/drm/i915/gt/intel_sseu.h +++ b/drivers/gpu/drm/i915/gt/intel_sseu.h @@ -27,7 +27,7 @@ struct drm_printer; * is only relevant to pre-Xe_HP platforms (Xe_HP and beyond use the * I915_MAX_SS_FUSE_BITS value below). */ -#define GEN_MAX_SS_PER_HSW_SLICE 6 +#define GEN_MAX_SS_PER_HSW_SLICE 8 /* * Maximum number of 32-bit registers used by hardware to express the From e0e6b416b25ee14716f3549e0cbec1011b193809 Mon Sep 17 00:00:00 2001 From: Janusz Krzysztofik Date: Thu, 2 Mar 2023 13:08:20 +0100 Subject: [PATCH 298/460] drm/i915/active: Fix misuse of non-idle barriers as fence trackers Users reported oopses on list corruptions when using i915 perf with a number of concurrently running graphics applications. Root cause analysis pointed at an issue in barrier processing code -- a race among perf open / close replacing active barriers with perf requests on kernel context and concurrent barrier preallocate / acquire operations performed during user context first pin / last unpin. When adding a request to a composite tracker, we try to reuse an existing fence tracker, already allocated and registered with that composite. The tracker we obtain may already track another fence, may be an idle barrier, or an active barrier. If the tracker we get occurs a non-idle barrier then we try to delete that barrier from a list of barrier tasks it belongs to. However, while doing that we don't respect return value from a function that performs the barrier deletion. Should the deletion ever fail, we would end up reusing the tracker still registered as a barrier task. Since the same structure field is reused with both fence callback lists and barrier tasks list, list corruptions would likely occur. Barriers are now deleted from a barrier tasks list by temporarily removing the list content, traversing that content with skip over the node to be deleted, then populating the list back with the modified content. Should that intentionally racy concurrent deletion attempts be not serialized, one or more of those may fail because of the list being temporary empty. Related code that ignores the results of barrier deletion was initially introduced in v5.4 by commit d8af05ff38ae ("drm/i915: Allow sharing the idle-barrier from other kernel requests"). However, all users of the barrier deletion routine were apparently serialized at that time, then the issue didn't exhibit itself. Results of git bisect with help of a newly developed igt@gem_barrier_race@remote-request IGT test indicate that list corruptions might start to appear after commit 311770173fac ("drm/i915/gt: Schedule request retirement when timeline idles"), introduced in v5.5. Respect results of barrier deletion attempts -- mark the barrier as idle only if successfully deleted from the list. Then, before proceeding with setting our fence as the one currently tracked, make sure that the tracker we've got is not a non-idle barrier. If that check fails then don't use that tracker but go back and try to acquire a new, usable one. v3: use unlikely() to document what outcome we expect (Andi), - fix bad grammar in commit description. v2: no code changes, - blame commit 311770173fac ("drm/i915/gt: Schedule request retirement when timeline idles"), v5.5, not commit d8af05ff38ae ("drm/i915: Allow sharing the idle-barrier from other kernel requests"), v5.4, - reword commit description. Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/6333 Fixes: 311770173fac ("drm/i915/gt: Schedule request retirement when timeline idles") Cc: Chris Wilson Cc: stable@vger.kernel.org # v5.5 Cc: Andi Shyti Signed-off-by: Janusz Krzysztofik Reviewed-by: Andi Shyti Signed-off-by: Andi Shyti Link: https://patchwork.freedesktop.org/patch/msgid/20230302120820.48740-1-janusz.krzysztofik@linux.intel.com (cherry picked from commit 506006055769b10d1b2b4e22f636f3b45e0e9fc7) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/i915_active.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_active.c b/drivers/gpu/drm/i915/i915_active.c index 7412abf166a8c..a9fea115f2d26 100644 --- a/drivers/gpu/drm/i915/i915_active.c +++ b/drivers/gpu/drm/i915/i915_active.c @@ -422,12 +422,12 @@ replace_barrier(struct i915_active *ref, struct i915_active_fence *active) * we can use it to substitute for the pending idle-barrer * request that we want to emit on the kernel_context. */ - __active_del_barrier(ref, node_from_active(active)); - return true; + return __active_del_barrier(ref, node_from_active(active)); } int i915_active_add_request(struct i915_active *ref, struct i915_request *rq) { + u64 idx = i915_request_timeline(rq)->fence_context; struct dma_fence *fence = &rq->fence; struct i915_active_fence *active; int err; @@ -437,16 +437,19 @@ int i915_active_add_request(struct i915_active *ref, struct i915_request *rq) if (err) return err; - active = active_instance(ref, i915_request_timeline(rq)->fence_context); - if (!active) { - err = -ENOMEM; - goto out; - } + do { + active = active_instance(ref, idx); + if (!active) { + err = -ENOMEM; + goto out; + } + + if (replace_barrier(ref, active)) { + RCU_INIT_POINTER(active->fence, NULL); + atomic_dec(&ref->count); + } + } while (unlikely(is_barrier(active))); - if (replace_barrier(ref, active)) { - RCU_INIT_POINTER(active->fence, NULL); - atomic_dec(&ref->count); - } if (!__i915_active_fence_set(active, fence)) __i915_active_acquire(ref); From 2cde14b187b458b7dcf99360fe4435dae1645a1f Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 1 Mar 2023 17:25:08 +0100 Subject: [PATCH 299/460] accel: Build sub-directories based on config options When accel drivers are disabled do not process into sub-directories and create built-in archives: AR drivers/accel/habanalabs/built-in.a AR drivers/accel/ivpu/built-in.a Fixes: 35b137630f08 ("accel/ivpu: Introduce a new DRM driver for Intel VPU") Signed-off-by: Stanislaw Gruszka Reviewed-by: Jeffrey Hugo Link: https://patchwork.freedesktop.org/patch/msgid/20230301162508.3963484-1-stanislaw.gruszka@linux.intel.com (cherry picked from commit dd61bbd0d1fba48cd9464e047a7f90b70a463e39) Signed-off-by: Jacek Lawrynowicz --- drivers/accel/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/accel/Makefile b/drivers/accel/Makefile index 07aa77aed1c8d..f22fd44d586b2 100644 --- a/drivers/accel/Makefile +++ b/drivers/accel/Makefile @@ -1,4 +1,4 @@ # SPDX-License-Identifier: GPL-2.0-only -obj-y += habanalabs/ -obj-y += ivpu/ +obj-$(CONFIG_DRM_ACCEL_HABANALABS) += habanalabs/ +obj-$(CONFIG_DRM_ACCEL_IVPU) += ivpu/ From 3e453522593d74a87cf68a38e14aa36ebca1dbcd Mon Sep 17 00:00:00 2001 From: Xiao Ni Date: Wed, 22 Feb 2023 11:59:16 +0800 Subject: [PATCH 300/460] md: Free resources in __md_stop If md_run() fails after ->active_io is initialized, then percpu_ref_exit is called in error path. However, later md_free_disk will call percpu_ref_exit again which leads to a panic because of null pointer dereference. It can also trigger this bug when resources are initialized but are freed in error path, then will be freed again in md_free_disk. BUG: kernel NULL pointer dereference, address: 0000000000000038 Oops: 0000 [#1] PREEMPT SMP Workqueue: md_misc mddev_delayed_delete RIP: 0010:free_percpu+0x110/0x630 Call Trace: __percpu_ref_exit+0x44/0x70 percpu_ref_exit+0x16/0x90 md_free_disk+0x2f/0x80 disk_release+0x101/0x180 device_release+0x84/0x110 kobject_put+0x12a/0x380 kobject_put+0x160/0x380 mddev_delayed_delete+0x19/0x30 process_one_work+0x269/0x680 worker_thread+0x266/0x640 kthread+0x151/0x1b0 ret_from_fork+0x1f/0x30 For creating raid device, md raid calls do_md_run->md_run, dm raid calls md_run. We alloc those memory in md_run. For stopping raid device, md raid calls do_md_stop->__md_stop, dm raid calls md_stop->__md_stop. So we can free those memory resources in __md_stop. Fixes: 72adae23a72c ("md: Change active_io to percpu") Reported-and-tested-by: Yu Kuai Signed-off-by: Xiao Ni Signed-off-by: Song Liu --- drivers/md/md.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index 927a43db5dfbb..f5480778e2f7c 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -6256,6 +6256,11 @@ static void __md_stop(struct mddev *mddev) mddev->to_remove = &md_redundancy_group; module_put(pers->owner); clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery); + + percpu_ref_exit(&mddev->writes_pending); + percpu_ref_exit(&mddev->active_io); + bioset_exit(&mddev->bio_set); + bioset_exit(&mddev->sync_set); } void md_stop(struct mddev *mddev) @@ -6265,10 +6270,6 @@ void md_stop(struct mddev *mddev) */ __md_stop_writes(mddev); __md_stop(mddev); - percpu_ref_exit(&mddev->writes_pending); - percpu_ref_exit(&mddev->active_io); - bioset_exit(&mddev->bio_set); - bioset_exit(&mddev->sync_set); } EXPORT_SYMBOL_GPL(md_stop); @@ -7839,11 +7840,6 @@ static void md_free_disk(struct gendisk *disk) { struct mddev *mddev = disk->private_data; - percpu_ref_exit(&mddev->writes_pending); - percpu_ref_exit(&mddev->active_io); - bioset_exit(&mddev->bio_set); - bioset_exit(&mddev->sync_set); - mddev_free(mddev); } From 3bc57292278a0b6ac4656cad94c14f2453344b57 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 6 Mar 2023 09:36:25 +1100 Subject: [PATCH 301/460] md: avoid signed overflow in slot_store() slot_store() uses kstrtouint() to get a slot number, but stores the result in an "int" variable (by casting a pointer). This can result in a negative slot number if the unsigned int value is very large. A negative number means that the slot is empty, but setting a negative slot number this way will not remove the device from the array. I don't think this is a serious problem, but it could cause confusion and it is best to fix it. Reported-by: Dan Carpenter Signed-off-by: NeilBrown Signed-off-by: Song Liu --- drivers/md/md.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/md/md.c b/drivers/md/md.c index f5480778e2f7c..39e49e5d71823 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -3128,6 +3128,9 @@ slot_store(struct md_rdev *rdev, const char *buf, size_t len) err = kstrtouint(buf, 10, (unsigned int *)&slot); if (err < 0) return err; + if (slot < 0) + /* overflow */ + return -ENOSPC; } if (rdev->mddev->pers && slot == -1) { /* Setting 'slot' on an active array requires also From 131db499162274858bdbd7b5323a639da4aab86c Mon Sep 17 00:00:00 2001 From: Vadim Fedorenko Date: Fri, 10 Mar 2023 07:13:56 -0800 Subject: [PATCH 302/460] bnxt_en: reset PHC frequency in free-running mode When using a PHC in shared between multiple hosts, the previous frequency value may not be reset and could lead to host being unable to compensate the offset with timecounter adjustments. To avoid such state reset the hardware frequency of PHC to zero on init. Some refactoring is needed to make code readable. Fixes: 85036aee1938 ("bnxt_en: Add a non-real time mode to access NIC clock") Signed-off-by: Vadim Fedorenko Reviewed-by: Pavan Chebbi Link: https://lore.kernel.org/r/20230310151356.678059-1-vadfed@meta.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 6 +- drivers/net/ethernet/broadcom/bnxt/bnxt.h | 2 + drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c | 56 ++++++++++--------- 3 files changed, 35 insertions(+), 29 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 808236dc898b8..e2e2c986c82b7 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -6990,11 +6990,9 @@ static int bnxt_hwrm_func_qcfg(struct bnxt *bp) if (flags & FUNC_QCFG_RESP_FLAGS_FW_DCBX_AGENT_ENABLED) bp->fw_cap |= BNXT_FW_CAP_DCBX_AGENT; } - if (BNXT_PF(bp) && (flags & FUNC_QCFG_RESP_FLAGS_MULTI_HOST)) { + if (BNXT_PF(bp) && (flags & FUNC_QCFG_RESP_FLAGS_MULTI_HOST)) bp->flags |= BNXT_FLAG_MULTI_HOST; - if (bp->fw_cap & BNXT_FW_CAP_PTP_RTC) - bp->fw_cap &= ~BNXT_FW_CAP_PTP_RTC; - } + if (flags & FUNC_QCFG_RESP_FLAGS_RING_MONITOR_ENABLED) bp->fw_cap |= BNXT_FW_CAP_RING_MONITOR; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h index dcb09fbe40078..c0628ac1b798a 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h @@ -2000,6 +2000,8 @@ struct bnxt { u32 fw_dbg_cap; #define BNXT_NEW_RM(bp) ((bp)->fw_cap & BNXT_FW_CAP_NEW_RM) +#define BNXT_PTP_USE_RTC(bp) (!BNXT_MH(bp) && \ + ((bp)->fw_cap & BNXT_FW_CAP_PTP_RTC)) u32 hwrm_spec_code; u16 hwrm_cmd_seq; u16 hwrm_cmd_kong_seq; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c index 4ec8bba18cdd2..a3a3978a4d1c2 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c @@ -63,7 +63,7 @@ static int bnxt_ptp_settime(struct ptp_clock_info *ptp_info, ptp_info); u64 ns = timespec64_to_ns(ts); - if (ptp->bp->fw_cap & BNXT_FW_CAP_PTP_RTC) + if (BNXT_PTP_USE_RTC(ptp->bp)) return bnxt_ptp_cfg_settime(ptp->bp, ns); spin_lock_bh(&ptp->ptp_lock); @@ -196,7 +196,7 @@ static int bnxt_ptp_adjtime(struct ptp_clock_info *ptp_info, s64 delta) struct bnxt_ptp_cfg *ptp = container_of(ptp_info, struct bnxt_ptp_cfg, ptp_info); - if (ptp->bp->fw_cap & BNXT_FW_CAP_PTP_RTC) + if (BNXT_PTP_USE_RTC(ptp->bp)) return bnxt_ptp_adjphc(ptp, delta); spin_lock_bh(&ptp->ptp_lock); @@ -205,34 +205,39 @@ static int bnxt_ptp_adjtime(struct ptp_clock_info *ptp_info, s64 delta) return 0; } +static int bnxt_ptp_adjfine_rtc(struct bnxt *bp, long scaled_ppm) +{ + s32 ppb = scaled_ppm_to_ppb(scaled_ppm); + struct hwrm_port_mac_cfg_input *req; + int rc; + + rc = hwrm_req_init(bp, req, HWRM_PORT_MAC_CFG); + if (rc) + return rc; + + req->ptp_freq_adj_ppb = cpu_to_le32(ppb); + req->enables = cpu_to_le32(PORT_MAC_CFG_REQ_ENABLES_PTP_FREQ_ADJ_PPB); + rc = hwrm_req_send(bp, req); + if (rc) + netdev_err(bp->dev, + "ptp adjfine failed. rc = %d\n", rc); + return rc; +} + static int bnxt_ptp_adjfine(struct ptp_clock_info *ptp_info, long scaled_ppm) { struct bnxt_ptp_cfg *ptp = container_of(ptp_info, struct bnxt_ptp_cfg, ptp_info); - struct hwrm_port_mac_cfg_input *req; struct bnxt *bp = ptp->bp; - int rc = 0; - if (!(ptp->bp->fw_cap & BNXT_FW_CAP_PTP_RTC)) { - spin_lock_bh(&ptp->ptp_lock); - timecounter_read(&ptp->tc); - ptp->cc.mult = adjust_by_scaled_ppm(ptp->cmult, scaled_ppm); - spin_unlock_bh(&ptp->ptp_lock); - } else { - s32 ppb = scaled_ppm_to_ppb(scaled_ppm); - - rc = hwrm_req_init(bp, req, HWRM_PORT_MAC_CFG); - if (rc) - return rc; + if (BNXT_PTP_USE_RTC(bp)) + return bnxt_ptp_adjfine_rtc(bp, scaled_ppm); - req->ptp_freq_adj_ppb = cpu_to_le32(ppb); - req->enables = cpu_to_le32(PORT_MAC_CFG_REQ_ENABLES_PTP_FREQ_ADJ_PPB); - rc = hwrm_req_send(ptp->bp, req); - if (rc) - netdev_err(ptp->bp->dev, - "ptp adjfine failed. rc = %d\n", rc); - } - return rc; + spin_lock_bh(&ptp->ptp_lock); + timecounter_read(&ptp->tc); + ptp->cc.mult = adjust_by_scaled_ppm(ptp->cmult, scaled_ppm); + spin_unlock_bh(&ptp->ptp_lock); + return 0; } void bnxt_ptp_pps_event(struct bnxt *bp, u32 data1, u32 data2) @@ -879,7 +884,7 @@ int bnxt_ptp_init_rtc(struct bnxt *bp, bool phc_cfg) u64 ns; int rc; - if (!bp->ptp_cfg || !(bp->fw_cap & BNXT_FW_CAP_PTP_RTC)) + if (!bp->ptp_cfg || !BNXT_PTP_USE_RTC(bp)) return -ENODEV; if (!phc_cfg) { @@ -932,13 +937,14 @@ int bnxt_ptp_init(struct bnxt *bp, bool phc_cfg) atomic_set(&ptp->tx_avail, BNXT_MAX_TX_TS); spin_lock_init(&ptp->ptp_lock); - if (bp->fw_cap & BNXT_FW_CAP_PTP_RTC) { + if (BNXT_PTP_USE_RTC(bp)) { bnxt_ptp_timecounter_init(bp, false); rc = bnxt_ptp_init_rtc(bp, phc_cfg); if (rc) goto out; } else { bnxt_ptp_timecounter_init(bp, true); + bnxt_ptp_adjfine_rtc(bp, 0); } ptp->ptp_info = bnxt_ptp_caps; From 22a825c541d775c1dbe7b2402786025acad6727b Mon Sep 17 00:00:00 2001 From: "D. Wythe" Date: Wed, 8 Mar 2023 16:17:12 +0800 Subject: [PATCH 303/460] net/smc: fix NULL sndbuf_desc in smc_cdc_tx_handler() When performing a stress test on SMC-R by rmmod mlx5_ib driver during the wrk/nginx test, we found that there is a probability of triggering a panic while terminating all link groups. This issue dues to the race between smc_smcr_terminate_all() and smc_buf_create(). smc_smcr_terminate_all smc_buf_create /* init */ conn->sndbuf_desc = NULL; ... __smc_lgr_terminate smc_conn_kill smc_close_abort smc_cdc_get_slot_and_msg_send __softirqentry_text_start smc_wr_tx_process_cqe smc_cdc_tx_handler READ(conn->sndbuf_desc->len); /* panic dues to NULL sndbuf_desc */ conn->sndbuf_desc = xxx; This patch tries to fix the issue by always to check the sndbuf_desc before send any cdc msg, to make sure that no null pointer is seen during cqe processing. Fixes: 0b29ec643613 ("net/smc: immediate termination for SMCR link groups") Signed-off-by: D. Wythe Reviewed-by: Tony Lu Reviewed-by: Wenjia Zhang Link: https://lore.kernel.org/r/1678263432-17329-1-git-send-email-alibuda@linux.alibaba.com Signed-off-by: Jakub Kicinski --- net/smc/smc_cdc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/smc/smc_cdc.c b/net/smc/smc_cdc.c index 53f63bfbaf5f9..89105e95b4523 100644 --- a/net/smc/smc_cdc.c +++ b/net/smc/smc_cdc.c @@ -114,6 +114,9 @@ int smc_cdc_msg_send(struct smc_connection *conn, union smc_host_cursor cfed; int rc; + if (unlikely(!READ_ONCE(conn->sndbuf_desc))) + return -ENOBUFS; + smc_cdc_add_pending_send(conn, pend); conn->tx_cdc_seq++; From 1a9dc5610ef89d807acdcfbff93a558f341a44da Mon Sep 17 00:00:00 2001 From: Daniil Tatianin Date: Thu, 9 Mar 2023 23:15:56 +0300 Subject: [PATCH 304/460] qed/qed_dev: guard against a possible division by zero Previously we would divide total_left_rate by zero if num_vports happened to be 1 because non_requested_count is calculated as num_vports - req_count. Guard against this by validating num_vports at the beginning and returning an error otherwise. Found by Linux Verification Center (linuxtesting.org) with the SVACE static analysis tool. Fixes: bcd197c81f63 ("qed: Add vport WFQ configuration APIs") Signed-off-by: Daniil Tatianin Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/20230309201556.191392-1-d-tatianin@yandex-team.ru Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/qlogic/qed/qed_dev.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c b/drivers/net/ethernet/qlogic/qed/qed_dev.c index d61cd32ec3b65..86a93cac26470 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_dev.c +++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c @@ -5083,6 +5083,11 @@ static int qed_init_wfq_param(struct qed_hwfn *p_hwfn, num_vports = p_hwfn->qm_info.num_vports; + if (num_vports < 2) { + DP_NOTICE(p_hwfn, "Unexpected num_vports: %d\n", num_vports); + return -EINVAL; + } + /* Accounting for the vports which are configured for WFQ explicitly */ for (i = 0; i < num_vports; i++) { u32 tmp_speed; From feb03fd11c5616f3a47e4714d2f9917d0f1a2edd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= Date: Fri, 10 Mar 2023 10:33:37 +0300 Subject: [PATCH 305/460] net: dsa: mt7530: remove now incorrect comment regarding port 5 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove now incorrect comment regarding port 5 as GMAC5. This is supposed to be supported since commit 38f790a80560 ("net: dsa: mt7530: Add support for port 5") under mt7530_setup_port5(). Fixes: 38f790a80560 ("net: dsa: mt7530: Add support for port 5") Signed-off-by: Arınç ÜNAL Link: https://lore.kernel.org/r/20230310073338.5836-1-arinc.unal@arinc9.com Signed-off-by: Jakub Kicinski --- drivers/net/dsa/mt7530.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c index a508402c4ecbf..b1a79460df0e7 100644 --- a/drivers/net/dsa/mt7530.c +++ b/drivers/net/dsa/mt7530.c @@ -2201,7 +2201,7 @@ mt7530_setup(struct dsa_switch *ds) mt7530_pll_setup(priv); - /* Enable Port 6 only; P5 as GMAC5 which currently is not supported */ + /* Enable port 6 */ val = mt7530_read(priv, MT7530_MHWTRAP); val &= ~MHWTRAP_P6_DIS & ~MHWTRAP_PHY_ACCESS; val |= MHWTRAP_MANUAL; From 0b086d76e7b011772b0ac214c6e5fd5816eff2df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= Date: Fri, 10 Mar 2023 10:33:38 +0300 Subject: [PATCH 306/460] net: dsa: mt7530: set PLL frequency and trgmii only when trgmii is used MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As my testing on the MCM MT7530 switch on MT7621 SoC shows, setting the PLL frequency does not affect MII modes other than trgmii on port 5 and port 6. So the assumption is that the operation here called "setting the PLL frequency" actually sets the frequency of the TRGMII TX clock. Make it so that it and the rest of the trgmii setup run only when the trgmii mode is used. Tested rgmii and trgmii modes of port 6 on MCM MT7530 on MT7621AT Unielec U7621-06 and standalone MT7530 on MT7623NI Bananapi BPI-R2. Fixes: b8f126a8d543 ("net-next: dsa: add dsa support for Mediatek MT7530 switch") Tested-by: Arınç ÜNAL Signed-off-by: Arınç ÜNAL Link: https://lore.kernel.org/r/20230310073338.5836-2-arinc.unal@arinc9.com Signed-off-by: Jakub Kicinski --- drivers/net/dsa/mt7530.c | 62 ++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c index b1a79460df0e7..c2d81b7a429dc 100644 --- a/drivers/net/dsa/mt7530.c +++ b/drivers/net/dsa/mt7530.c @@ -430,8 +430,6 @@ mt7530_pad_clk_setup(struct dsa_switch *ds, phy_interface_t interface) switch (interface) { case PHY_INTERFACE_MODE_RGMII: trgint = 0; - /* PLL frequency: 125MHz */ - ncpo1 = 0x0c80; break; case PHY_INTERFACE_MODE_TRGMII: trgint = 1; @@ -462,38 +460,40 @@ mt7530_pad_clk_setup(struct dsa_switch *ds, phy_interface_t interface) mt7530_rmw(priv, MT7530_P6ECR, P6_INTF_MODE_MASK, P6_INTF_MODE(trgint)); - /* Lower Tx Driving for TRGMII path */ - for (i = 0 ; i < NUM_TRGMII_CTRL ; i++) - mt7530_write(priv, MT7530_TRGMII_TD_ODT(i), - TD_DM_DRVP(8) | TD_DM_DRVN(8)); - - /* Disable MT7530 core and TRGMII Tx clocks */ - core_clear(priv, CORE_TRGMII_GSW_CLK_CG, - REG_GSWCK_EN | REG_TRGMIICK_EN); - - /* 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)); - core_write(priv, CORE_PLL_GROUP10, RG_LCDDS_SSC_DELTA(ssc_delta)); - core_write(priv, CORE_PLL_GROUP11, RG_LCDDS_SSC_DELTA1(ssc_delta)); - core_write(priv, CORE_PLL_GROUP4, - RG_SYSPLL_DDSFBK_EN | RG_SYSPLL_BIAS_EN | - RG_SYSPLL_BIAS_LPF_EN); - core_write(priv, CORE_PLL_GROUP2, - RG_SYSPLL_EN_NORMAL | RG_SYSPLL_VODEN | - RG_SYSPLL_POSDIV(1)); - core_write(priv, CORE_PLL_GROUP7, - RG_LCDDS_PCW_NCPO_CHG | RG_LCCDS_C(3) | - RG_LCDDS_PWDB | RG_LCDDS_ISO_EN); - - /* Enable MT7530 core and TRGMII Tx clocks */ - core_set(priv, CORE_TRGMII_GSW_CLK_CG, - REG_GSWCK_EN | REG_TRGMIICK_EN); - - if (!trgint) + if (trgint) { + /* Lower Tx Driving for TRGMII path */ + for (i = 0 ; i < NUM_TRGMII_CTRL ; i++) + mt7530_write(priv, MT7530_TRGMII_TD_ODT(i), + TD_DM_DRVP(8) | TD_DM_DRVN(8)); + + /* Disable MT7530 core and TRGMII Tx clocks */ + core_clear(priv, CORE_TRGMII_GSW_CLK_CG, + REG_GSWCK_EN | REG_TRGMIICK_EN); + + /* 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)); + core_write(priv, CORE_PLL_GROUP10, RG_LCDDS_SSC_DELTA(ssc_delta)); + core_write(priv, CORE_PLL_GROUP11, RG_LCDDS_SSC_DELTA1(ssc_delta)); + core_write(priv, CORE_PLL_GROUP4, + RG_SYSPLL_DDSFBK_EN | RG_SYSPLL_BIAS_EN | + RG_SYSPLL_BIAS_LPF_EN); + core_write(priv, CORE_PLL_GROUP2, + RG_SYSPLL_EN_NORMAL | RG_SYSPLL_VODEN | + RG_SYSPLL_POSDIV(1)); + core_write(priv, CORE_PLL_GROUP7, + RG_LCDDS_PCW_NCPO_CHG | RG_LCCDS_C(3) | + RG_LCDDS_PWDB | RG_LCDDS_ISO_EN); + + /* Enable MT7530 core and TRGMII Tx clocks */ + core_set(priv, CORE_TRGMII_GSW_CLK_CG, + REG_GSWCK_EN | REG_TRGMIICK_EN); + } else { for (i = 0 ; i < NUM_TRGMII_CTRL; i++) mt7530_rmw(priv, MT7530_TRGMII_RD(i), RD_TAP_MASK, RD_TAP(16)); + } + return 0; } From 512dd354718b98c60d4ff6017ff8c9f66c10d03f Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 10 Mar 2023 13:37:09 -0600 Subject: [PATCH 307/460] net: ipa: fix a surprising number of bad offsets A recent commit eliminated a hack that adjusted the offset used for many GSI registers. It became possible because we now specify all GSI register offsets explicitly for every version of IPA. Unfortunately, a large number of register offsets were *not* updated as they should have been in that commit. For IPA v4.5+, the offset for every GSI register *except* the two inter-EE interrupt masking registers were supposed to have been reduced by 0xd000. Tested-by: Luca Weiss Tested-by: Dmitry Baryshkov # SM8350-HDK Fixes: 59b12b1d27f3 ("net: ipa: kill gsi->virt_raw") Signed-off-by: Alex Elder Link: https://lore.kernel.org/r/20230310193709.1477102-1-elder@linaro.org Signed-off-by: Jakub Kicinski --- drivers/net/ipa/reg/gsi_reg-v4.5.c | 56 +++++++++++++++--------------- drivers/net/ipa/reg/gsi_reg-v4.9.c | 44 +++++++++++------------ 2 files changed, 50 insertions(+), 50 deletions(-) diff --git a/drivers/net/ipa/reg/gsi_reg-v4.5.c b/drivers/net/ipa/reg/gsi_reg-v4.5.c index 648b51b88d4e8..2900e5c3ff888 100644 --- a/drivers/net/ipa/reg/gsi_reg-v4.5.c +++ b/drivers/net/ipa/reg/gsi_reg-v4.5.c @@ -137,17 +137,17 @@ REG_STRIDE(EV_CH_E_SCRATCH_1, ev_ch_e_scratch_1, 0x0001004c + 0x4000 * GSI_EE_AP, 0x80); REG_STRIDE(CH_C_DOORBELL_0, ch_c_doorbell_0, - 0x0001e000 + 0x4000 * GSI_EE_AP, 0x08); + 0x00011000 + 0x4000 * GSI_EE_AP, 0x08); REG_STRIDE(EV_CH_E_DOORBELL_0, ev_ch_e_doorbell_0, - 0x0001e100 + 0x4000 * GSI_EE_AP, 0x08); + 0x00011100 + 0x4000 * GSI_EE_AP, 0x08); static const u32 reg_gsi_status_fmask[] = { [ENABLED] = BIT(0), /* Bits 1-31 reserved */ }; -REG_FIELDS(GSI_STATUS, gsi_status, 0x0001f000 + 0x4000 * GSI_EE_AP); +REG_FIELDS(GSI_STATUS, gsi_status, 0x00012000 + 0x4000 * GSI_EE_AP); static const u32 reg_ch_cmd_fmask[] = { [CH_CHID] = GENMASK(7, 0), @@ -155,7 +155,7 @@ static const u32 reg_ch_cmd_fmask[] = { [CH_OPCODE] = GENMASK(31, 24), }; -REG_FIELDS(CH_CMD, ch_cmd, 0x0001f008 + 0x4000 * GSI_EE_AP); +REG_FIELDS(CH_CMD, ch_cmd, 0x00012008 + 0x4000 * GSI_EE_AP); static const u32 reg_ev_ch_cmd_fmask[] = { [EV_CHID] = GENMASK(7, 0), @@ -163,7 +163,7 @@ static const u32 reg_ev_ch_cmd_fmask[] = { [EV_OPCODE] = GENMASK(31, 24), }; -REG_FIELDS(EV_CH_CMD, ev_ch_cmd, 0x0001f010 + 0x4000 * GSI_EE_AP); +REG_FIELDS(EV_CH_CMD, ev_ch_cmd, 0x00012010 + 0x4000 * GSI_EE_AP); static const u32 reg_generic_cmd_fmask[] = { [GENERIC_OPCODE] = GENMASK(4, 0), @@ -172,7 +172,7 @@ static const u32 reg_generic_cmd_fmask[] = { /* Bits 14-31 reserved */ }; -REG_FIELDS(GENERIC_CMD, generic_cmd, 0x0001f018 + 0x4000 * GSI_EE_AP); +REG_FIELDS(GENERIC_CMD, generic_cmd, 0x00012018 + 0x4000 * GSI_EE_AP); static const u32 reg_hw_param_2_fmask[] = { [IRAM_SIZE] = GENMASK(2, 0), @@ -188,58 +188,58 @@ static const u32 reg_hw_param_2_fmask[] = { [GSI_USE_INTER_EE] = BIT(31), }; -REG_FIELDS(HW_PARAM_2, hw_param_2, 0x0001f040 + 0x4000 * GSI_EE_AP); +REG_FIELDS(HW_PARAM_2, hw_param_2, 0x00012040 + 0x4000 * GSI_EE_AP); -REG(CNTXT_TYPE_IRQ, cntxt_type_irq, 0x0001f080 + 0x4000 * GSI_EE_AP); +REG(CNTXT_TYPE_IRQ, cntxt_type_irq, 0x00012080 + 0x4000 * GSI_EE_AP); -REG(CNTXT_TYPE_IRQ_MSK, cntxt_type_irq_msk, 0x0001f088 + 0x4000 * GSI_EE_AP); +REG(CNTXT_TYPE_IRQ_MSK, cntxt_type_irq_msk, 0x00012088 + 0x4000 * GSI_EE_AP); -REG(CNTXT_SRC_CH_IRQ, cntxt_src_ch_irq, 0x0001f090 + 0x4000 * GSI_EE_AP); +REG(CNTXT_SRC_CH_IRQ, cntxt_src_ch_irq, 0x00012090 + 0x4000 * GSI_EE_AP); -REG(CNTXT_SRC_EV_CH_IRQ, cntxt_src_ev_ch_irq, 0x0001f094 + 0x4000 * GSI_EE_AP); +REG(CNTXT_SRC_EV_CH_IRQ, cntxt_src_ev_ch_irq, 0x00012094 + 0x4000 * GSI_EE_AP); REG(CNTXT_SRC_CH_IRQ_MSK, cntxt_src_ch_irq_msk, - 0x0001f098 + 0x4000 * GSI_EE_AP); + 0x00012098 + 0x4000 * GSI_EE_AP); REG(CNTXT_SRC_EV_CH_IRQ_MSK, cntxt_src_ev_ch_irq_msk, - 0x0001f09c + 0x4000 * GSI_EE_AP); + 0x0001209c + 0x4000 * GSI_EE_AP); REG(CNTXT_SRC_CH_IRQ_CLR, cntxt_src_ch_irq_clr, - 0x0001f0a0 + 0x4000 * GSI_EE_AP); + 0x000120a0 + 0x4000 * GSI_EE_AP); REG(CNTXT_SRC_EV_CH_IRQ_CLR, cntxt_src_ev_ch_irq_clr, - 0x0001f0a4 + 0x4000 * GSI_EE_AP); + 0x000120a4 + 0x4000 * GSI_EE_AP); -REG(CNTXT_SRC_IEOB_IRQ, cntxt_src_ieob_irq, 0x0001f0b0 + 0x4000 * GSI_EE_AP); +REG(CNTXT_SRC_IEOB_IRQ, cntxt_src_ieob_irq, 0x000120b0 + 0x4000 * GSI_EE_AP); REG(CNTXT_SRC_IEOB_IRQ_MSK, cntxt_src_ieob_irq_msk, - 0x0001f0b8 + 0x4000 * GSI_EE_AP); + 0x000120b8 + 0x4000 * GSI_EE_AP); REG(CNTXT_SRC_IEOB_IRQ_CLR, cntxt_src_ieob_irq_clr, - 0x0001f0c0 + 0x4000 * GSI_EE_AP); + 0x000120c0 + 0x4000 * GSI_EE_AP); -REG(CNTXT_GLOB_IRQ_STTS, cntxt_glob_irq_stts, 0x0001f100 + 0x4000 * GSI_EE_AP); +REG(CNTXT_GLOB_IRQ_STTS, cntxt_glob_irq_stts, 0x00012100 + 0x4000 * GSI_EE_AP); -REG(CNTXT_GLOB_IRQ_EN, cntxt_glob_irq_en, 0x0001f108 + 0x4000 * GSI_EE_AP); +REG(CNTXT_GLOB_IRQ_EN, cntxt_glob_irq_en, 0x00012108 + 0x4000 * GSI_EE_AP); -REG(CNTXT_GLOB_IRQ_CLR, cntxt_glob_irq_clr, 0x0001f110 + 0x4000 * GSI_EE_AP); +REG(CNTXT_GLOB_IRQ_CLR, cntxt_glob_irq_clr, 0x00012110 + 0x4000 * GSI_EE_AP); -REG(CNTXT_GSI_IRQ_STTS, cntxt_gsi_irq_stts, 0x0001f118 + 0x4000 * GSI_EE_AP); +REG(CNTXT_GSI_IRQ_STTS, cntxt_gsi_irq_stts, 0x00012118 + 0x4000 * GSI_EE_AP); -REG(CNTXT_GSI_IRQ_EN, cntxt_gsi_irq_en, 0x0001f120 + 0x4000 * GSI_EE_AP); +REG(CNTXT_GSI_IRQ_EN, cntxt_gsi_irq_en, 0x00012120 + 0x4000 * GSI_EE_AP); -REG(CNTXT_GSI_IRQ_CLR, cntxt_gsi_irq_clr, 0x0001f128 + 0x4000 * GSI_EE_AP); +REG(CNTXT_GSI_IRQ_CLR, cntxt_gsi_irq_clr, 0x00012128 + 0x4000 * GSI_EE_AP); static const u32 reg_cntxt_intset_fmask[] = { [INTYPE] = BIT(0) /* Bits 1-31 reserved */ }; -REG_FIELDS(CNTXT_INTSET, cntxt_intset, 0x0001f180 + 0x4000 * GSI_EE_AP); +REG_FIELDS(CNTXT_INTSET, cntxt_intset, 0x00012180 + 0x4000 * GSI_EE_AP); -REG_FIELDS(ERROR_LOG, error_log, 0x0001f200 + 0x4000 * GSI_EE_AP); +REG_FIELDS(ERROR_LOG, error_log, 0x00012200 + 0x4000 * GSI_EE_AP); -REG(ERROR_LOG_CLR, error_log_clr, 0x0001f210 + 0x4000 * GSI_EE_AP); +REG(ERROR_LOG_CLR, error_log_clr, 0x00012210 + 0x4000 * GSI_EE_AP); static const u32 reg_cntxt_scratch_0_fmask[] = { [INTER_EE_RESULT] = GENMASK(2, 0), @@ -248,7 +248,7 @@ static const u32 reg_cntxt_scratch_0_fmask[] = { /* Bits 8-31 reserved */ }; -REG_FIELDS(CNTXT_SCRATCH_0, cntxt_scratch_0, 0x0001f400 + 0x4000 * GSI_EE_AP); +REG_FIELDS(CNTXT_SCRATCH_0, cntxt_scratch_0, 0x00012400 + 0x4000 * GSI_EE_AP); static const struct reg *reg_array[] = { [INTER_EE_SRC_CH_IRQ_MSK] = ®_inter_ee_src_ch_irq_msk, diff --git a/drivers/net/ipa/reg/gsi_reg-v4.9.c b/drivers/net/ipa/reg/gsi_reg-v4.9.c index 4bf45d264d6b9..8b5d95425a766 100644 --- a/drivers/net/ipa/reg/gsi_reg-v4.9.c +++ b/drivers/net/ipa/reg/gsi_reg-v4.9.c @@ -27,7 +27,7 @@ static const u32 reg_ch_c_cntxt_0_fmask[] = { }; REG_STRIDE_FIELDS(CH_C_CNTXT_0, ch_c_cntxt_0, - 0x0001c000 + 0x4000 * GSI_EE_AP, 0x80); + 0x0000f000 + 0x4000 * GSI_EE_AP, 0x80); static const u32 reg_ch_c_cntxt_1_fmask[] = { [CH_R_LENGTH] = GENMASK(19, 0), @@ -35,11 +35,11 @@ static const u32 reg_ch_c_cntxt_1_fmask[] = { }; REG_STRIDE_FIELDS(CH_C_CNTXT_1, ch_c_cntxt_1, - 0x0001c004 + 0x4000 * GSI_EE_AP, 0x80); + 0x0000f004 + 0x4000 * GSI_EE_AP, 0x80); -REG_STRIDE(CH_C_CNTXT_2, ch_c_cntxt_2, 0x0001c008 + 0x4000 * GSI_EE_AP, 0x80); +REG_STRIDE(CH_C_CNTXT_2, ch_c_cntxt_2, 0x0000f008 + 0x4000 * GSI_EE_AP, 0x80); -REG_STRIDE(CH_C_CNTXT_3, ch_c_cntxt_3, 0x0001c00c + 0x4000 * GSI_EE_AP, 0x80); +REG_STRIDE(CH_C_CNTXT_3, ch_c_cntxt_3, 0x0000f00c + 0x4000 * GSI_EE_AP, 0x80); static const u32 reg_ch_c_qos_fmask[] = { [WRR_WEIGHT] = GENMASK(3, 0), @@ -53,7 +53,7 @@ static const u32 reg_ch_c_qos_fmask[] = { /* Bits 25-31 reserved */ }; -REG_STRIDE_FIELDS(CH_C_QOS, ch_c_qos, 0x0001c05c + 0x4000 * GSI_EE_AP, 0x80); +REG_STRIDE_FIELDS(CH_C_QOS, ch_c_qos, 0x0000f05c + 0x4000 * GSI_EE_AP, 0x80); static const u32 reg_error_log_fmask[] = { [ERR_ARG3] = GENMASK(3, 0), @@ -67,16 +67,16 @@ static const u32 reg_error_log_fmask[] = { }; REG_STRIDE(CH_C_SCRATCH_0, ch_c_scratch_0, - 0x0001c060 + 0x4000 * GSI_EE_AP, 0x80); + 0x0000f060 + 0x4000 * GSI_EE_AP, 0x80); REG_STRIDE(CH_C_SCRATCH_1, ch_c_scratch_1, - 0x0001c064 + 0x4000 * GSI_EE_AP, 0x80); + 0x0000f064 + 0x4000 * GSI_EE_AP, 0x80); REG_STRIDE(CH_C_SCRATCH_2, ch_c_scratch_2, - 0x0001c068 + 0x4000 * GSI_EE_AP, 0x80); + 0x0000f068 + 0x4000 * GSI_EE_AP, 0x80); REG_STRIDE(CH_C_SCRATCH_3, ch_c_scratch_3, - 0x0001c06c + 0x4000 * GSI_EE_AP, 0x80); + 0x0000f06c + 0x4000 * GSI_EE_AP, 0x80); static const u32 reg_ev_ch_e_cntxt_0_fmask[] = { [EV_CHTYPE] = GENMASK(3, 0), @@ -89,23 +89,23 @@ static const u32 reg_ev_ch_e_cntxt_0_fmask[] = { }; REG_STRIDE_FIELDS(EV_CH_E_CNTXT_0, ev_ch_e_cntxt_0, - 0x0001d000 + 0x4000 * GSI_EE_AP, 0x80); + 0x00010000 + 0x4000 * GSI_EE_AP, 0x80); static const u32 reg_ev_ch_e_cntxt_1_fmask[] = { [R_LENGTH] = GENMASK(15, 0), }; REG_STRIDE_FIELDS(EV_CH_E_CNTXT_1, ev_ch_e_cntxt_1, - 0x0001d004 + 0x4000 * GSI_EE_AP, 0x80); + 0x00010004 + 0x4000 * GSI_EE_AP, 0x80); REG_STRIDE(EV_CH_E_CNTXT_2, ev_ch_e_cntxt_2, - 0x0001d008 + 0x4000 * GSI_EE_AP, 0x80); + 0x00010008 + 0x4000 * GSI_EE_AP, 0x80); REG_STRIDE(EV_CH_E_CNTXT_3, ev_ch_e_cntxt_3, - 0x0001d00c + 0x4000 * GSI_EE_AP, 0x80); + 0x0001000c + 0x4000 * GSI_EE_AP, 0x80); REG_STRIDE(EV_CH_E_CNTXT_4, ev_ch_e_cntxt_4, - 0x0001d010 + 0x4000 * GSI_EE_AP, 0x80); + 0x00010010 + 0x4000 * GSI_EE_AP, 0x80); static const u32 reg_ev_ch_e_cntxt_8_fmask[] = { [EV_MODT] = GENMASK(15, 0), @@ -114,28 +114,28 @@ static const u32 reg_ev_ch_e_cntxt_8_fmask[] = { }; REG_STRIDE_FIELDS(EV_CH_E_CNTXT_8, ev_ch_e_cntxt_8, - 0x0001d020 + 0x4000 * GSI_EE_AP, 0x80); + 0x00010020 + 0x4000 * GSI_EE_AP, 0x80); REG_STRIDE(EV_CH_E_CNTXT_9, ev_ch_e_cntxt_9, - 0x0001d024 + 0x4000 * GSI_EE_AP, 0x80); + 0x00010024 + 0x4000 * GSI_EE_AP, 0x80); REG_STRIDE(EV_CH_E_CNTXT_10, ev_ch_e_cntxt_10, - 0x0001d028 + 0x4000 * GSI_EE_AP, 0x80); + 0x00010028 + 0x4000 * GSI_EE_AP, 0x80); REG_STRIDE(EV_CH_E_CNTXT_11, ev_ch_e_cntxt_11, - 0x0001d02c + 0x4000 * GSI_EE_AP, 0x80); + 0x0001002c + 0x4000 * GSI_EE_AP, 0x80); REG_STRIDE(EV_CH_E_CNTXT_12, ev_ch_e_cntxt_12, - 0x0001d030 + 0x4000 * GSI_EE_AP, 0x80); + 0x00010030 + 0x4000 * GSI_EE_AP, 0x80); REG_STRIDE(EV_CH_E_CNTXT_13, ev_ch_e_cntxt_13, - 0x0001d034 + 0x4000 * GSI_EE_AP, 0x80); + 0x00010034 + 0x4000 * GSI_EE_AP, 0x80); REG_STRIDE(EV_CH_E_SCRATCH_0, ev_ch_e_scratch_0, - 0x0001d048 + 0x4000 * GSI_EE_AP, 0x80); + 0x00010048 + 0x4000 * GSI_EE_AP, 0x80); REG_STRIDE(EV_CH_E_SCRATCH_1, ev_ch_e_scratch_1, - 0x0001d04c + 0x4000 * GSI_EE_AP, 0x80); + 0x0001004c + 0x4000 * GSI_EE_AP, 0x80); REG_STRIDE(CH_C_DOORBELL_0, ch_c_doorbell_0, 0x00011000 + 0x4000 * GSI_EE_AP, 0x08); From 6175b70df95ed3b8fe177cb20b9b00b1f9008cc4 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 22 Feb 2023 23:01:15 -0800 Subject: [PATCH 308/460] powerpc/pseries: RTAS work area requires GENERIC_ALLOCATOR The RTAS work area allocator uses code that is built by GENERIC_ALLOCATOR, so the PSERIES Kconfig should select the required Kconfig symbol to fix multiple build errors. powerpc64-linux-ld: arch/powerpc/platforms/pseries/rtas-work-area.o: in function `.rtas_work_area_allocator_init': rtas-work-area.c:(.init.text+0x288): undefined reference to `.gen_pool_create' powerpc64-linux-ld: rtas-work-area.c:(.init.text+0x2dc): undefined reference to `.gen_pool_set_algo' powerpc64-linux-ld: rtas-work-area.c:(.init.text+0x310): undefined reference to `.gen_pool_add_owner' powerpc64-linux-ld: rtas-work-area.c:(.init.text+0x43c): undefined reference to `.gen_pool_destroy' powerpc64-linux-ld: arch/powerpc/platforms/pseries/rtas-work-area.o:(.toc+0x0): undefined reference to `gen_pool_first_fit_order_align' powerpc64-linux-ld: arch/powerpc/platforms/pseries/rtas-work-area.o: in function `.__rtas_work_area_alloc': rtas-work-area.c:(.ref.text+0x14c): undefined reference to `.gen_pool_alloc_algo_owner' powerpc64-linux-ld: rtas-work-area.c:(.ref.text+0x238): undefined reference to `.gen_pool_alloc_algo_owner' powerpc64-linux-ld: arch/powerpc/platforms/pseries/rtas-work-area.o: in function `.rtas_work_area_free': rtas-work-area.c:(.ref.text+0x44c): undefined reference to `.gen_pool_free_owner' Fixes: 43033bc62d34 ("powerpc/pseries: add RTAS work area allocator") Signed-off-by: Randy Dunlap Reviewed-by: Nathan Lynch Signed-off-by: Michael Ellerman Link: https://msgid.link/20230223070116.660-2-rdunlap@infradead.org --- arch/powerpc/platforms/pseries/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig index b481c5c8bae11..21b22bf16ce66 100644 --- a/arch/powerpc/platforms/pseries/Kconfig +++ b/arch/powerpc/platforms/pseries/Kconfig @@ -7,6 +7,7 @@ config PPC_PSERIES select OF_DYNAMIC select FORCE_PCI select PCI_MSI + select GENERIC_ALLOCATOR select PPC_XICS select PPC_XIVE_SPAPR select PPC_ICP_NATIVE From 112e66017bff7f2837030f34c2bc19501e9212d5 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 10 Mar 2023 11:10:56 -0500 Subject: [PATCH 309/460] KVM: nVMX: add missing consistency checks for CR0 and CR4 The effective values of the guest CR0 and CR4 registers may differ from those included in the VMCS12. In particular, disabling EPT forces CR4.PAE=1 and disabling unrestricted guest mode forces CR0.PG=CR0.PE=1. Therefore, checks on these bits cannot be delegated to the processor and must be performed by KVM. Reported-by: Reima ISHII Cc: stable@vger.kernel.org Signed-off-by: Paolo Bonzini --- arch/x86/kvm/vmx/nested.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c index 7c4f5ca405c75..fd7af786b7248 100644 --- a/arch/x86/kvm/vmx/nested.c +++ b/arch/x86/kvm/vmx/nested.c @@ -3022,7 +3022,7 @@ static int nested_vmx_check_guest_state(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12, enum vm_entry_failure_code *entry_failure_code) { - bool ia32e; + bool ia32e = !!(vmcs12->vm_entry_controls & VM_ENTRY_IA32E_MODE); *entry_failure_code = ENTRY_FAIL_DEFAULT; @@ -3048,6 +3048,13 @@ static int nested_vmx_check_guest_state(struct kvm_vcpu *vcpu, vmcs12->guest_ia32_perf_global_ctrl))) return -EINVAL; + if (CC((vmcs12->guest_cr0 & (X86_CR0_PG | X86_CR0_PE)) == X86_CR0_PG)) + return -EINVAL; + + if (CC(ia32e && !(vmcs12->guest_cr4 & X86_CR4_PAE)) || + CC(ia32e && !(vmcs12->guest_cr0 & X86_CR0_PG))) + return -EINVAL; + /* * If the load IA32_EFER VM-entry control is 1, the following checks * are performed on the field for the IA32_EFER MSR: @@ -3059,7 +3066,6 @@ static int nested_vmx_check_guest_state(struct kvm_vcpu *vcpu, */ if (to_vmx(vcpu)->nested.nested_run_pending && (vmcs12->vm_entry_controls & VM_ENTRY_LOAD_IA32_EFER)) { - ia32e = (vmcs12->vm_entry_controls & VM_ENTRY_IA32E_MODE) != 0; if (CC(!kvm_valid_efer(vcpu, vmcs12->guest_ia32_efer)) || CC(ia32e != !!(vmcs12->guest_ia32_efer & EFER_LMA)) || CC(((vmcs12->guest_cr0 & X86_CR0_PG) && From 77900bffed14894476969042718a9ca05eb1f477 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 14 Mar 2023 07:40:56 -0400 Subject: [PATCH 310/460] KVM: nVMX: remove unnecessary #ifdef nested_vmx_check_controls() has already run by the time KVM checks host state, so the "host address space size" exit control can only be set on x86-64 hosts. Simplify the condition at the cost of adding some dead code to 32-bit kernels. Signed-off-by: Paolo Bonzini --- arch/x86/kvm/vmx/nested.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c index fd7af786b7248..1bc2b80273c97 100644 --- a/arch/x86/kvm/vmx/nested.c +++ b/arch/x86/kvm/vmx/nested.c @@ -2903,7 +2903,7 @@ static int nested_vmx_check_address_space_size(struct kvm_vcpu *vcpu, static int nested_vmx_check_host_state(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12) { - bool ia32e; + bool ia32e = !!(vmcs12->vm_exit_controls & VM_EXIT_HOST_ADDR_SPACE_SIZE); if (CC(!nested_host_cr0_valid(vcpu, vmcs12->host_cr0)) || CC(!nested_host_cr4_valid(vcpu, vmcs12->host_cr4)) || @@ -2923,12 +2923,6 @@ static int nested_vmx_check_host_state(struct kvm_vcpu *vcpu, vmcs12->host_ia32_perf_global_ctrl))) return -EINVAL; -#ifdef CONFIG_X86_64 - ia32e = !!(vmcs12->vm_exit_controls & VM_EXIT_HOST_ADDR_SPACE_SIZE); -#else - ia32e = false; -#endif - if (ia32e) { if (CC(!(vmcs12->host_cr4 & X86_CR4_PAE))) return -EINVAL; From 06e18547286068be803ba28c6d1c377e94f8745b Mon Sep 17 00:00:00 2001 From: Rong Tao Date: Wed, 21 Dec 2022 20:24:32 +0800 Subject: [PATCH 311/460] KVM: VMX: Fix indentation coding style issue Code indentation should use tabs where possible. Signed-off-by: Rong Tao Message-Id: Signed-off-by: Paolo Bonzini --- arch/x86/kvm/vmx/vmx.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index bcac3efcde412..d2d6e1b6c7882 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -874,7 +874,7 @@ void vmx_update_exception_bitmap(struct kvm_vcpu *vcpu) */ if (is_guest_mode(vcpu)) eb |= get_vmcs12(vcpu)->exception_bitmap; - else { + else { int mask = 0, match = 0; if (enable_ept && (eb & (1u << PF_VECTOR))) { @@ -1282,7 +1282,7 @@ void vmx_prepare_switch_to_guest(struct kvm_vcpu *vcpu) } } - if (vmx->nested.need_vmcs12_to_shadow_sync) + if (vmx->nested.need_vmcs12_to_shadow_sync) nested_sync_vmcs12_to_shadow(vcpu); if (vmx->guest_state_loaded) @@ -5049,10 +5049,10 @@ static int vmx_interrupt_allowed(struct kvm_vcpu *vcpu, bool for_injection) if (to_vmx(vcpu)->nested.nested_run_pending) return -EBUSY; - /* - * An IRQ must not be injected into L2 if it's supposed to VM-Exit, - * e.g. if the IRQ arrived asynchronously after checking nested events. - */ + /* + * An IRQ must not be injected into L2 if it's supposed to VM-Exit, + * e.g. if the IRQ arrived asynchronously after checking nested events. + */ if (for_injection && is_guest_mode(vcpu) && nested_exit_on_intr(vcpu)) return -EBUSY; From 53293cb81be6db06306666d51e85778725934be5 Mon Sep 17 00:00:00 2001 From: Rong Tao Date: Wed, 21 Dec 2022 20:28:49 +0800 Subject: [PATCH 312/460] KVM: VMX: Use tabs instead of spaces for indentation Code indentation should use tabs where possible and miss a '*'. Signed-off-by: Rong Tao Message-Id: Signed-off-by: Paolo Bonzini --- arch/x86/kvm/vmx/vmenter.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/vmx/vmenter.S b/arch/x86/kvm/vmx/vmenter.S index f550540ed54ee..631fd7da2bc36 100644 --- a/arch/x86/kvm/vmx/vmenter.S +++ b/arch/x86/kvm/vmx/vmenter.S @@ -262,7 +262,7 @@ SYM_INNER_LABEL(vmx_vmexit, SYM_L_GLOBAL) * eIBRS has its own protection against poisoned RSB, so it doesn't * need the RSB filling sequence. But it does need to be enabled, and a * single call to retire, before the first unbalanced RET. - */ + */ FILL_RETURN_BUFFER %_ASM_CX, RSB_CLEAR_LOOPS, X86_FEATURE_RSB_VMEXIT,\ X86_FEATURE_RSB_VMEXIT_LITE @@ -311,7 +311,7 @@ SYM_FUNC_END(vmx_do_nmi_irqoff) * vmread_error_trampoline - Trampoline from inline asm to vmread_error() * @field: VMCS field encoding that failed * @fault: %true if the VMREAD faulted, %false if it failed - + * * Save and restore volatile registers across a call to vmread_error(). Note, * all parameters are passed on the stack. */ From 3dc40cf89b9b763910cb0540a35f9d66a067475d Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 14 Mar 2023 08:35:16 -0400 Subject: [PATCH 313/460] selftests: KVM: skip hugetlb tests if huge pages are not available Right now, if KVM memory stress tests are run with hugetlb sources but hugetlb is not available (either in the kernel or because /proc/sys/vm/nr_hugepages is 0) the test will fail with a memory allocation error. This makes it impossible to add tests that default to hugetlb-backed memory, because on a machine with a default configuration they will fail. Therefore, check HugePages_Total as well and, if zero, direct the user to enable hugepages in procfs. Furthermore, return KSFT_SKIP whenever hugetlb is not available. Signed-off-by: Paolo Bonzini --- tools/testing/selftests/kvm/lib/test_util.c | 25 +++++++++++++-------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/tools/testing/selftests/kvm/lib/test_util.c b/tools/testing/selftests/kvm/lib/test_util.c index 5c22fa4c2825e..b772193f6c186 100644 --- a/tools/testing/selftests/kvm/lib/test_util.c +++ b/tools/testing/selftests/kvm/lib/test_util.c @@ -165,26 +165,33 @@ size_t get_trans_hugepagesz(void) size_t get_def_hugetlb_pagesz(void) { char buf[64]; - const char *tag = "Hugepagesize:"; + const char *hugepagesize = "Hugepagesize:"; + const char *hugepages_total = "HugePages_Total:"; FILE *f; f = fopen("/proc/meminfo", "r"); TEST_ASSERT(f != NULL, "Error in opening /proc/meminfo"); while (fgets(buf, sizeof(buf), f) != NULL) { - if (strstr(buf, tag) == buf) { + if (strstr(buf, hugepages_total) == buf) { + unsigned long long total = strtoull(buf + strlen(hugepages_total), NULL, 10); + if (!total) { + fprintf(stderr, "HUGETLB is not enabled in /proc/sys/vm/nr_hugepages\n"); + exit(KSFT_SKIP); + } + } + if (strstr(buf, hugepagesize) == buf) { fclose(f); - return strtoull(buf + strlen(tag), NULL, 10) << 10; + return strtoull(buf + strlen(hugepagesize), NULL, 10) << 10; } } - if (feof(f)) - TEST_FAIL("HUGETLB is not configured in host kernel"); - else - TEST_FAIL("Error in reading /proc/meminfo"); + if (feof(f)) { + fprintf(stderr, "HUGETLB is not configured in host kernel"); + exit(KSFT_SKIP); + } - fclose(f); - return 0; + TEST_FAIL("Error in reading /proc/meminfo"); } #define ANON_FLAGS (MAP_PRIVATE | MAP_ANONYMOUS) From 3ec7a1b2743c07c45f4a0c508114f6cb410ddef3 Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Tue, 7 Feb 2023 00:21:54 +0000 Subject: [PATCH 314/460] KVM: SVM: Fix a benign off-by-one bug in AVIC physical table mask Define the "physical table max index mask" as bits 8:0, not 9:0. x2AVIC currently supports a max of 512 entries, i.e. the max index is 511, and the inputs to GENMASK_ULL() are inclusive. The bug is benign as bit 9 is reserved and never set by KVM, i.e. KVM is just clearing bits that are guaranteed to be zero. Note, as of this writing, APM "Rev. 3.39-October 2022" incorrectly states that bits 11:8 are reserved in Table B-1. VMCB Layout, Control Area. I.e. that table wasn't updated when x2AVIC support was added. Opportunistically fix the comment for the max AVIC ID to align with the code, and clean up comment formatting too. Fixes: 4d1d7942e36a ("KVM: SVM: Introduce logic to (de)activate x2AVIC mode") Cc: stable@vger.kernel.org Cc: Alejandro Jimenez Cc: Suravee Suthikulpanit Signed-off-by: Sean Christopherson Reviewed-by: Suravee Suthikulpanit Tested-by: Suravee Suthikulpanit Message-Id: <20230207002156.521736-2-seanjc@google.com> Signed-off-by: Paolo Bonzini --- arch/x86/include/asm/svm.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/arch/x86/include/asm/svm.h b/arch/x86/include/asm/svm.h index cb1ee53ad3b18..770dcf75eaa97 100644 --- a/arch/x86/include/asm/svm.h +++ b/arch/x86/include/asm/svm.h @@ -261,20 +261,22 @@ enum avic_ipi_failure_cause { AVIC_IPI_FAILURE_INVALID_BACKING_PAGE, }; -#define AVIC_PHYSICAL_MAX_INDEX_MASK GENMASK_ULL(9, 0) +#define AVIC_PHYSICAL_MAX_INDEX_MASK GENMASK_ULL(8, 0) /* - * For AVIC, the max index allowed for physical APIC ID - * table is 0xff (255). + * For AVIC, the max index allowed for physical APIC ID table is 0xfe (254), as + * 0xff is a broadcast to all CPUs, i.e. can't be targeted individually. */ #define AVIC_MAX_PHYSICAL_ID 0XFEULL /* - * For x2AVIC, the max index allowed for physical APIC ID - * table is 0x1ff (511). + * For x2AVIC, the max index allowed for physical APIC ID table is 0x1ff (511). */ #define X2AVIC_MAX_PHYSICAL_ID 0x1FFUL +static_assert((AVIC_MAX_PHYSICAL_ID & AVIC_PHYSICAL_MAX_INDEX_MASK) == AVIC_MAX_PHYSICAL_ID); +static_assert((X2AVIC_MAX_PHYSICAL_ID & AVIC_PHYSICAL_MAX_INDEX_MASK) == X2AVIC_MAX_PHYSICAL_ID); + #define AVIC_HPA_MASK ~((0xFFFULL << 52) | 0xFFF) #define VMCB_AVIC_APIC_BAR_MASK 0xFFFFFFFFFF000ULL From 5999715922c5a3ede5d8fe2a6b17aba58a157d41 Mon Sep 17 00:00:00 2001 From: Suravee Suthikulpanit Date: Tue, 7 Feb 2023 00:21:55 +0000 Subject: [PATCH 315/460] KVM: SVM: Modify AVIC GATag to support max number of 512 vCPUs Define AVIC_VCPU_ID_MASK based on AVIC_PHYSICAL_MAX_INDEX, i.e. the mask that effectively controls the largest guest physical APIC ID supported by x2AVIC, instead of hardcoding the number of bits to 8 (and the number of VM bits to 24). The AVIC GATag is programmed into the AMD IOMMU IRTE to provide a reference back to KVM in case the IOMMU cannot inject an interrupt into a non-running vCPU. In such a case, the IOMMU notifies software by creating a GALog entry with the corresponded GATag, and KVM then uses the GATag to find the correct VM+vCPU to kick. Dropping bit 8 from the GATag results in kicking the wrong vCPU when targeting vCPUs with x2APIC ID > 255. Fixes: 4d1d7942e36a ("KVM: SVM: Introduce logic to (de)activate x2AVIC mode") Cc: stable@vger.kernel.org Reported-by: Alejandro Jimenez Signed-off-by: Suravee Suthikulpanit Co-developed-by: Sean Christopherson Signed-off-by: Sean Christopherson Reviewed-by: Suravee Suthikulpanit Tested-by: Suravee Suthikulpanit Message-Id: <20230207002156.521736-3-seanjc@google.com> Signed-off-by: Paolo Bonzini --- arch/x86/kvm/svm/avic.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/arch/x86/kvm/svm/avic.c b/arch/x86/kvm/svm/avic.c index ca684979e90d6..326341a221536 100644 --- a/arch/x86/kvm/svm/avic.c +++ b/arch/x86/kvm/svm/avic.c @@ -27,19 +27,29 @@ #include "irq.h" #include "svm.h" -/* AVIC GATAG is encoded using VM and VCPU IDs */ -#define AVIC_VCPU_ID_BITS 8 -#define AVIC_VCPU_ID_MASK ((1 << AVIC_VCPU_ID_BITS) - 1) +/* + * Encode the arbitrary VM ID and the vCPU's default APIC ID, i.e the vCPU ID, + * into the GATag so that KVM can retrieve the correct vCPU from a GALog entry + * if an interrupt can't be delivered, e.g. because the vCPU isn't running. + * + * For the vCPU ID, use however many bits are currently allowed for the max + * guest physical APIC ID (limited by the size of the physical ID table), and + * use whatever bits remain to assign arbitrary AVIC IDs to VMs. Note, the + * size of the GATag is defined by hardware (32 bits), but is an opaque value + * as far as hardware is concerned. + */ +#define AVIC_VCPU_ID_MASK AVIC_PHYSICAL_MAX_INDEX_MASK -#define AVIC_VM_ID_BITS 24 -#define AVIC_VM_ID_NR (1 << AVIC_VM_ID_BITS) -#define AVIC_VM_ID_MASK ((1 << AVIC_VM_ID_BITS) - 1) +#define AVIC_VM_ID_SHIFT HWEIGHT32(AVIC_PHYSICAL_MAX_INDEX_MASK) +#define AVIC_VM_ID_MASK (GENMASK(31, AVIC_VM_ID_SHIFT) >> AVIC_VM_ID_SHIFT) -#define AVIC_GATAG(x, y) (((x & AVIC_VM_ID_MASK) << AVIC_VCPU_ID_BITS) | \ +#define AVIC_GATAG(x, y) (((x & AVIC_VM_ID_MASK) << AVIC_VM_ID_SHIFT) | \ (y & AVIC_VCPU_ID_MASK)) -#define AVIC_GATAG_TO_VMID(x) ((x >> AVIC_VCPU_ID_BITS) & AVIC_VM_ID_MASK) +#define AVIC_GATAG_TO_VMID(x) ((x >> AVIC_VM_ID_SHIFT) & AVIC_VM_ID_MASK) #define AVIC_GATAG_TO_VCPUID(x) (x & AVIC_VCPU_ID_MASK) +static_assert(AVIC_GATAG(AVIC_VM_ID_MASK, AVIC_VCPU_ID_MASK) == -1u); + static bool force_avic; module_param_unsafe(force_avic, bool, 0444); From c281794eaa5c635c0edf39c6a9a3b0171000e92f Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Tue, 7 Feb 2023 00:21:56 +0000 Subject: [PATCH 316/460] KVM: SVM: WARN if GATag generation drops VM or vCPU ID information WARN if generating a GATag given a VM ID and vCPU ID doesn't yield the same IDs when pulling the IDs back out of the tag. Don't bother adding error handling to callers, this is very much a paranoid sanity check as KVM fully controls the VM ID and is supposed to reject too-big vCPU IDs. Signed-off-by: Sean Christopherson Reviewed-by: Suravee Suthikulpanit Tested-by: Suravee Suthikulpanit Message-Id: <20230207002156.521736-4-seanjc@google.com> Signed-off-by: Paolo Bonzini --- arch/x86/kvm/svm/avic.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/arch/x86/kvm/svm/avic.c b/arch/x86/kvm/svm/avic.c index 326341a221536..cfc8ab7730250 100644 --- a/arch/x86/kvm/svm/avic.c +++ b/arch/x86/kvm/svm/avic.c @@ -43,12 +43,21 @@ #define AVIC_VM_ID_SHIFT HWEIGHT32(AVIC_PHYSICAL_MAX_INDEX_MASK) #define AVIC_VM_ID_MASK (GENMASK(31, AVIC_VM_ID_SHIFT) >> AVIC_VM_ID_SHIFT) -#define AVIC_GATAG(x, y) (((x & AVIC_VM_ID_MASK) << AVIC_VM_ID_SHIFT) | \ - (y & AVIC_VCPU_ID_MASK)) #define AVIC_GATAG_TO_VMID(x) ((x >> AVIC_VM_ID_SHIFT) & AVIC_VM_ID_MASK) #define AVIC_GATAG_TO_VCPUID(x) (x & AVIC_VCPU_ID_MASK) -static_assert(AVIC_GATAG(AVIC_VM_ID_MASK, AVIC_VCPU_ID_MASK) == -1u); +#define __AVIC_GATAG(vm_id, vcpu_id) ((((vm_id) & AVIC_VM_ID_MASK) << AVIC_VM_ID_SHIFT) | \ + ((vcpu_id) & AVIC_VCPU_ID_MASK)) +#define AVIC_GATAG(vm_id, vcpu_id) \ +({ \ + u32 ga_tag = __AVIC_GATAG(vm_id, vcpu_id); \ + \ + WARN_ON_ONCE(AVIC_GATAG_TO_VCPUID(ga_tag) != (vcpu_id)); \ + WARN_ON_ONCE(AVIC_GATAG_TO_VMID(ga_tag) != (vm_id)); \ + ga_tag; \ +}) + +static_assert(__AVIC_GATAG(AVIC_VM_ID_MASK, AVIC_VCPU_ID_MASK) == -1u); static bool force_avic; module_param_unsafe(force_avic, bool, 0444); From 4009e0bb7b83d967a14e108d271f003b378f9af9 Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Sat, 4 Feb 2023 02:41:48 +0000 Subject: [PATCH 317/460] KVM: selftests: Move the guts of kvm_hypercall() to a separate macro Extract the guts of kvm_hypercall() to a macro so that Xen hypercalls, which have a different register ABI, can reuse the VMCALL vs. VMMCALL logic. No functional change intended. Signed-off-by: Sean Christopherson Message-Id: <20230204024151.1373296-2-seanjc@google.com> Signed-off-by: Paolo Bonzini --- .../selftests/kvm/lib/x86_64/processor.c | 29 +++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/tools/testing/selftests/kvm/lib/x86_64/processor.c b/tools/testing/selftests/kvm/lib/x86_64/processor.c index ae1e573d94ce7..ff901cb47ffca 100644 --- a/tools/testing/selftests/kvm/lib/x86_64/processor.c +++ b/tools/testing/selftests/kvm/lib/x86_64/processor.c @@ -1139,21 +1139,26 @@ const struct kvm_cpuid_entry2 *get_cpuid_entry(const struct kvm_cpuid2 *cpuid, return NULL; } +#define X86_HYPERCALL(inputs...) \ +({ \ + uint64_t r; \ + \ + asm volatile("test %[use_vmmcall], %[use_vmmcall]\n\t" \ + "jnz 1f\n\t" \ + "vmcall\n\t" \ + "jmp 2f\n\t" \ + "1: vmmcall\n\t" \ + "2:" \ + : "=a"(r) \ + : [use_vmmcall] "r" (host_cpu_is_amd), inputs); \ + \ + r; \ +}) + uint64_t kvm_hypercall(uint64_t nr, uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3) { - uint64_t r; - - asm volatile("test %[use_vmmcall], %[use_vmmcall]\n\t" - "jnz 1f\n\t" - "vmcall\n\t" - "jmp 2f\n\t" - "1: vmmcall\n\t" - "2:" - : "=a"(r) - : "a"(nr), "b"(a0), "c"(a1), "d"(a2), "S"(a3), - [use_vmmcall] "r" (host_cpu_is_amd)); - return r; + return X86_HYPERCALL("a"(nr), "b"(a0), "c"(a1), "d"(a2), "S"(a3)); } const struct kvm_cpuid2 *kvm_get_supported_hv_cpuid(void) From c0c76d99939cb4ac28cbc5ce542cff2b9e1e1b02 Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Sat, 4 Feb 2023 02:41:49 +0000 Subject: [PATCH 318/460] KVM: selftests: Add helpers to make Xen-style VMCALL/VMMCALL hypercalls Add wrappers to do hypercalls using VMCALL/VMMCALL and Xen's register ABI (as opposed to full Xen-style hypercalls through a hypervisor provided page). Using the common helpers dedups a pile of code, and uses the native hypercall instruction when running on AMD. Signed-off-by: Sean Christopherson Message-Id: <20230204024151.1373296-3-seanjc@google.com> Signed-off-by: Paolo Bonzini --- .../selftests/kvm/include/x86_64/processor.h | 2 + .../selftests/kvm/lib/x86_64/processor.c | 10 +++ .../selftests/kvm/x86_64/xen_shinfo_test.c | 63 +++---------------- 3 files changed, 21 insertions(+), 54 deletions(-) diff --git a/tools/testing/selftests/kvm/include/x86_64/processor.h b/tools/testing/selftests/kvm/include/x86_64/processor.h index 53ffa43c90db1..90387ddcb2a9d 100644 --- a/tools/testing/selftests/kvm/include/x86_64/processor.h +++ b/tools/testing/selftests/kvm/include/x86_64/processor.h @@ -1063,6 +1063,8 @@ uint64_t *vm_get_page_table_entry(struct kvm_vm *vm, uint64_t vaddr); uint64_t kvm_hypercall(uint64_t nr, uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3); +uint64_t __xen_hypercall(uint64_t nr, uint64_t a0, void *a1); +void xen_hypercall(uint64_t nr, uint64_t a0, void *a1); void __vm_xsave_require_permission(int bit, const char *name); diff --git a/tools/testing/selftests/kvm/lib/x86_64/processor.c b/tools/testing/selftests/kvm/lib/x86_64/processor.c index ff901cb47ffca..c39a4353ba194 100644 --- a/tools/testing/selftests/kvm/lib/x86_64/processor.c +++ b/tools/testing/selftests/kvm/lib/x86_64/processor.c @@ -1161,6 +1161,16 @@ uint64_t kvm_hypercall(uint64_t nr, uint64_t a0, uint64_t a1, uint64_t a2, return X86_HYPERCALL("a"(nr), "b"(a0), "c"(a1), "d"(a2), "S"(a3)); } +uint64_t __xen_hypercall(uint64_t nr, uint64_t a0, void *a1) +{ + return X86_HYPERCALL("a"(nr), "D"(a0), "S"(a1)); +} + +void xen_hypercall(uint64_t nr, uint64_t a0, void *a1) +{ + GUEST_ASSERT(!__xen_hypercall(nr, a0, a1)); +} + const struct kvm_cpuid2 *kvm_get_supported_hv_cpuid(void) { static struct kvm_cpuid2 *cpuid; diff --git a/tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c b/tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c index 5a3bf8f614176..827b8e126f2f7 100644 --- a/tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c +++ b/tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c @@ -225,15 +225,8 @@ static void guest_code(void) /* Our turn. Deliver event channel (to ourselves) with * EVTCHNOP_send hypercall. */ - unsigned long rax; struct evtchn_send s = { .port = 127 }; - __asm__ __volatile__ ("vmcall" : - "=a" (rax) : - "a" (__HYPERVISOR_event_channel_op), - "D" (EVTCHNOP_send), - "S" (&s)); - - GUEST_ASSERT(rax == 0); + xen_hypercall(__HYPERVISOR_event_channel_op, EVTCHNOP_send, &s); guest_wait_for_irq(); @@ -242,24 +235,15 @@ static void guest_code(void) /* Deliver "outbound" event channel to an eventfd which * happens to be one of our own irqfds. */ s.port = 197; - __asm__ __volatile__ ("vmcall" : - "=a" (rax) : - "a" (__HYPERVISOR_event_channel_op), - "D" (EVTCHNOP_send), - "S" (&s)); - - GUEST_ASSERT(rax == 0); + xen_hypercall(__HYPERVISOR_event_channel_op, EVTCHNOP_send, &s); guest_wait_for_irq(); GUEST_SYNC(13); /* Set a timer 100ms in the future. */ - __asm__ __volatile__ ("vmcall" : - "=a" (rax) : - "a" (__HYPERVISOR_set_timer_op), - "D" (rs->state_entry_time + 100000000)); - GUEST_ASSERT(rax == 0); + xen_hypercall(__HYPERVISOR_set_timer_op, + rs->state_entry_time + 100000000, NULL); GUEST_SYNC(14); @@ -281,37 +265,19 @@ static void guest_code(void) .timeout = 0, }; - __asm__ __volatile__ ("vmcall" : - "=a" (rax) : - "a" (__HYPERVISOR_sched_op), - "D" (SCHEDOP_poll), - "S" (&p)); - - GUEST_ASSERT(rax == 0); + xen_hypercall(__HYPERVISOR_sched_op, SCHEDOP_poll, &p); GUEST_SYNC(17); /* Poll for an unset port and wait for the timeout. */ p.timeout = 100000000; - __asm__ __volatile__ ("vmcall" : - "=a" (rax) : - "a" (__HYPERVISOR_sched_op), - "D" (SCHEDOP_poll), - "S" (&p)); - - GUEST_ASSERT(rax == 0); + xen_hypercall(__HYPERVISOR_sched_op, SCHEDOP_poll, &p); GUEST_SYNC(18); /* A timer will wake the masked port we're waiting on, while we poll */ p.timeout = 0; - __asm__ __volatile__ ("vmcall" : - "=a" (rax) : - "a" (__HYPERVISOR_sched_op), - "D" (SCHEDOP_poll), - "S" (&p)); - - GUEST_ASSERT(rax == 0); + xen_hypercall(__HYPERVISOR_sched_op, SCHEDOP_poll, &p); GUEST_SYNC(19); @@ -319,13 +285,7 @@ static void guest_code(void) * actual interrupt, while we're polling on a different port. */ ports[0]++; p.timeout = 0; - __asm__ __volatile__ ("vmcall" : - "=a" (rax) : - "a" (__HYPERVISOR_sched_op), - "D" (SCHEDOP_poll), - "S" (&p)); - - GUEST_ASSERT(rax == 0); + xen_hypercall(__HYPERVISOR_sched_op, SCHEDOP_poll, &p); guest_wait_for_irq(); @@ -360,12 +320,7 @@ static void guest_code(void) * timer IRQ is dropped due to an invalid event channel. */ for (i = 0; i < 100 && !guest_saw_irq; i++) - asm volatile("vmcall" - : "=a" (rax) - : "a" (__HYPERVISOR_sched_op), - "D" (SCHEDOP_poll), - "S" (&p) - : "memory"); + __xen_hypercall(__HYPERVISOR_sched_op, SCHEDOP_poll, &p); /* * Re-send the timer IRQ if it was (likely) dropped due to the timer From e7062a98d0b3e0b42089f4c5da633a1ce41b807f Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Sat, 4 Feb 2023 02:41:50 +0000 Subject: [PATCH 319/460] KVM: selftests: Use enum for test numbers in xen_shinfo_test The xen_shinfo_test started off with very few iterations, and the numbers we used in GUEST_SYNC() were precisely mapped to the RUNSTATE_xxx values anyway to start with. It has since grown quite a few more tests, and it's kind of awful to be handling them all as bare numbers. Especially when I want to add a new test in the middle. Define an enum for the test stages, and use it both in the guest code and the host switch statement. No functional change, if I can count to 24. Signed-off-by: David Woodhouse Signed-off-by: Sean Christopherson Message-Id: <20230204024151.1373296-4-seanjc@google.com> Signed-off-by: Paolo Bonzini --- .../selftests/kvm/x86_64/xen_shinfo_test.c | 133 +++++++++++------- 1 file changed, 82 insertions(+), 51 deletions(-) diff --git a/tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c b/tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c index 827b8e126f2f7..1a3d2d51fef01 100644 --- a/tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c +++ b/tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c @@ -41,6 +41,36 @@ #define EVTCHN_TEST2 66 #define EVTCHN_TIMER 13 +enum { + TEST_INJECT_VECTOR = 0, + TEST_RUNSTATE_runnable, + TEST_RUNSTATE_blocked, + TEST_RUNSTATE_offline, + TEST_RUNSTATE_ADJUST, + TEST_RUNSTATE_DATA, + TEST_STEAL_TIME, + TEST_EVTCHN_MASKED, + TEST_EVTCHN_UNMASKED, + TEST_EVTCHN_SLOWPATH, + TEST_EVTCHN_SEND_IOCTL, + TEST_EVTCHN_HCALL, + TEST_EVTCHN_HCALL_EVENTFD, + TEST_TIMER_SETUP, + TEST_TIMER_WAIT, + TEST_TIMER_RESTORE, + TEST_POLL_READY, + TEST_POLL_TIMEOUT, + TEST_POLL_MASKED, + TEST_POLL_WAKE, + TEST_TIMER_PAST, + TEST_LOCKING_SEND_RACE, + TEST_LOCKING_POLL_RACE, + TEST_LOCKING_POLL_TIMEOUT, + TEST_DONE, + + TEST_GUEST_SAW_IRQ, +}; + #define XEN_HYPERCALL_MSR 0x40000000 #define MIN_STEAL_TIME 50000 @@ -144,7 +174,7 @@ static void evtchn_handler(struct ex_regs *regs) vi->evtchn_pending_sel = 0; guest_saw_irq = true; - GUEST_SYNC(0x20); + GUEST_SYNC(TEST_GUEST_SAW_IRQ); } static void guest_wait_for_irq(void) @@ -165,41 +195,41 @@ static void guest_code(void) ); /* Trigger an interrupt injection */ - GUEST_SYNC(0); + GUEST_SYNC(TEST_INJECT_VECTOR); guest_wait_for_irq(); /* Test having the host set runstates manually */ - GUEST_SYNC(RUNSTATE_runnable); + GUEST_SYNC(TEST_RUNSTATE_runnable); GUEST_ASSERT(rs->time[RUNSTATE_runnable] != 0); GUEST_ASSERT(rs->state == 0); - GUEST_SYNC(RUNSTATE_blocked); + GUEST_SYNC(TEST_RUNSTATE_blocked); GUEST_ASSERT(rs->time[RUNSTATE_blocked] != 0); GUEST_ASSERT(rs->state == 0); - GUEST_SYNC(RUNSTATE_offline); + GUEST_SYNC(TEST_RUNSTATE_offline); GUEST_ASSERT(rs->time[RUNSTATE_offline] != 0); GUEST_ASSERT(rs->state == 0); /* Test runstate time adjust */ - GUEST_SYNC(4); + GUEST_SYNC(TEST_RUNSTATE_ADJUST); GUEST_ASSERT(rs->time[RUNSTATE_blocked] == 0x5a); GUEST_ASSERT(rs->time[RUNSTATE_offline] == 0x6b6b); /* Test runstate time set */ - GUEST_SYNC(5); + GUEST_SYNC(TEST_RUNSTATE_DATA); GUEST_ASSERT(rs->state_entry_time >= 0x8000); GUEST_ASSERT(rs->time[RUNSTATE_runnable] == 0); GUEST_ASSERT(rs->time[RUNSTATE_blocked] == 0x6b6b); GUEST_ASSERT(rs->time[RUNSTATE_offline] == 0x5a); /* sched_yield() should result in some 'runnable' time */ - GUEST_SYNC(6); + GUEST_SYNC(TEST_STEAL_TIME); GUEST_ASSERT(rs->time[RUNSTATE_runnable] >= MIN_STEAL_TIME); /* Attempt to deliver a *masked* interrupt */ - GUEST_SYNC(7); + GUEST_SYNC(TEST_EVTCHN_MASKED); /* Wait until we see the bit set */ struct shared_info *si = (void *)SHINFO_VADDR; @@ -207,21 +237,21 @@ static void guest_code(void) __asm__ __volatile__ ("rep nop" : : : "memory"); /* Now deliver an *unmasked* interrupt */ - GUEST_SYNC(8); + GUEST_SYNC(TEST_EVTCHN_UNMASKED); guest_wait_for_irq(); /* Change memslots and deliver an interrupt */ - GUEST_SYNC(9); + GUEST_SYNC(TEST_EVTCHN_SLOWPATH); guest_wait_for_irq(); /* Deliver event channel with KVM_XEN_HVM_EVTCHN_SEND */ - GUEST_SYNC(10); + GUEST_SYNC(TEST_EVTCHN_SEND_IOCTL); guest_wait_for_irq(); - GUEST_SYNC(11); + GUEST_SYNC(TEST_EVTCHN_HCALL); /* Our turn. Deliver event channel (to ourselves) with * EVTCHNOP_send hypercall. */ @@ -230,7 +260,7 @@ static void guest_code(void) guest_wait_for_irq(); - GUEST_SYNC(12); + GUEST_SYNC(TEST_EVTCHN_HCALL_EVENTFD); /* Deliver "outbound" event channel to an eventfd which * happens to be one of our own irqfds. */ @@ -239,23 +269,23 @@ static void guest_code(void) guest_wait_for_irq(); - GUEST_SYNC(13); + GUEST_SYNC(TEST_TIMER_SETUP); /* Set a timer 100ms in the future. */ xen_hypercall(__HYPERVISOR_set_timer_op, rs->state_entry_time + 100000000, NULL); - GUEST_SYNC(14); + GUEST_SYNC(TEST_TIMER_WAIT); /* Now wait for the timer */ guest_wait_for_irq(); - GUEST_SYNC(15); + GUEST_SYNC(TEST_TIMER_RESTORE); /* The host has 'restored' the timer. Just wait for it. */ guest_wait_for_irq(); - GUEST_SYNC(16); + GUEST_SYNC(TEST_POLL_READY); /* Poll for an event channel port which is already set */ u32 ports[1] = { EVTCHN_TIMER }; @@ -267,19 +297,19 @@ static void guest_code(void) xen_hypercall(__HYPERVISOR_sched_op, SCHEDOP_poll, &p); - GUEST_SYNC(17); + GUEST_SYNC(TEST_POLL_TIMEOUT); /* Poll for an unset port and wait for the timeout. */ p.timeout = 100000000; xen_hypercall(__HYPERVISOR_sched_op, SCHEDOP_poll, &p); - GUEST_SYNC(18); + GUEST_SYNC(TEST_POLL_MASKED); /* A timer will wake the masked port we're waiting on, while we poll */ p.timeout = 0; xen_hypercall(__HYPERVISOR_sched_op, SCHEDOP_poll, &p); - GUEST_SYNC(19); + GUEST_SYNC(TEST_POLL_WAKE); /* A timer wake an *unmasked* port which should wake us with an * actual interrupt, while we're polling on a different port. */ @@ -289,17 +319,17 @@ static void guest_code(void) guest_wait_for_irq(); - GUEST_SYNC(20); + GUEST_SYNC(TEST_TIMER_PAST); /* Timer should have fired already */ guest_wait_for_irq(); - GUEST_SYNC(21); + GUEST_SYNC(TEST_LOCKING_SEND_RACE); /* Racing host ioctls */ guest_wait_for_irq(); - GUEST_SYNC(22); + GUEST_SYNC(TEST_LOCKING_POLL_RACE); /* Racing vmcall against host ioctl */ ports[0] = 0; @@ -327,12 +357,12 @@ static void guest_code(void) * expiring while the event channel was invalid. */ if (!guest_saw_irq) { - GUEST_SYNC(23); + GUEST_SYNC(TEST_LOCKING_POLL_TIMEOUT); goto wait_for_timer; } guest_saw_irq = false; - GUEST_SYNC(24); + GUEST_SYNC(TEST_DONE); } static int cmp_timespec(struct timespec *a, struct timespec *b) @@ -602,25 +632,26 @@ int main(int argc, char *argv[]) "runstate times don't add up"); switch (uc.args[1]) { - case 0: + case TEST_INJECT_VECTOR: if (verbose) printf("Delivering evtchn upcall\n"); evtchn_irq_expected = true; vinfo->evtchn_upcall_pending = 1; break; - case RUNSTATE_runnable...RUNSTATE_offline: + case TEST_RUNSTATE_runnable...TEST_RUNSTATE_offline: TEST_ASSERT(!evtchn_irq_expected, "Event channel IRQ not seen"); if (!do_runstate_tests) goto done; if (verbose) printf("Testing runstate %s\n", runstate_names[uc.args[1]]); rst.type = KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_CURRENT; - rst.u.runstate.state = uc.args[1]; + rst.u.runstate.state = uc.args[1] + RUNSTATE_runnable - + TEST_RUNSTATE_runnable; vcpu_ioctl(vcpu, KVM_XEN_VCPU_SET_ATTR, &rst); break; - case 4: + case TEST_RUNSTATE_ADJUST: if (verbose) printf("Testing RUNSTATE_ADJUST\n"); rst.type = KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_ADJUST; @@ -635,7 +666,7 @@ int main(int argc, char *argv[]) vcpu_ioctl(vcpu, KVM_XEN_VCPU_SET_ATTR, &rst); break; - case 5: + case TEST_RUNSTATE_DATA: if (verbose) printf("Testing RUNSTATE_DATA\n"); rst.type = KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_DATA; @@ -647,7 +678,7 @@ int main(int argc, char *argv[]) vcpu_ioctl(vcpu, KVM_XEN_VCPU_SET_ATTR, &rst); break; - case 6: + case TEST_STEAL_TIME: if (verbose) printf("Testing steal time\n"); /* Yield until scheduler delay exceeds target */ @@ -657,7 +688,7 @@ int main(int argc, char *argv[]) } while (get_run_delay() < rundelay); break; - case 7: + case TEST_EVTCHN_MASKED: if (!do_eventfd_tests) goto done; if (verbose) @@ -667,7 +698,7 @@ int main(int argc, char *argv[]) alarm(1); break; - case 8: + case TEST_EVTCHN_UNMASKED: if (verbose) printf("Testing unmasked event channel\n"); /* Unmask that, but deliver the other one */ @@ -678,7 +709,7 @@ int main(int argc, char *argv[]) alarm(1); break; - case 9: + case TEST_EVTCHN_SLOWPATH: TEST_ASSERT(!evtchn_irq_expected, "Expected event channel IRQ but it didn't happen"); shinfo->evtchn_pending[1] = 0; @@ -691,7 +722,7 @@ int main(int argc, char *argv[]) alarm(1); break; - case 10: + case TEST_EVTCHN_SEND_IOCTL: TEST_ASSERT(!evtchn_irq_expected, "Expected event channel IRQ but it didn't happen"); if (!do_evtchn_tests) @@ -711,7 +742,7 @@ int main(int argc, char *argv[]) alarm(1); break; - case 11: + case TEST_EVTCHN_HCALL: TEST_ASSERT(!evtchn_irq_expected, "Expected event channel IRQ but it didn't happen"); shinfo->evtchn_pending[1] = 0; @@ -722,7 +753,7 @@ int main(int argc, char *argv[]) alarm(1); break; - case 12: + case TEST_EVTCHN_HCALL_EVENTFD: TEST_ASSERT(!evtchn_irq_expected, "Expected event channel IRQ but it didn't happen"); shinfo->evtchn_pending[0] = 0; @@ -733,7 +764,7 @@ int main(int argc, char *argv[]) alarm(1); break; - case 13: + case TEST_TIMER_SETUP: TEST_ASSERT(!evtchn_irq_expected, "Expected event channel IRQ but it didn't happen"); shinfo->evtchn_pending[1] = 0; @@ -742,7 +773,7 @@ int main(int argc, char *argv[]) printf("Testing guest oneshot timer\n"); break; - case 14: + case TEST_TIMER_WAIT: memset(&tmr, 0, sizeof(tmr)); tmr.type = KVM_XEN_VCPU_ATTR_TYPE_TIMER; vcpu_ioctl(vcpu, KVM_XEN_VCPU_GET_ATTR, &tmr); @@ -756,7 +787,7 @@ int main(int argc, char *argv[]) alarm(1); break; - case 15: + case TEST_TIMER_RESTORE: TEST_ASSERT(!evtchn_irq_expected, "Expected event channel IRQ but it didn't happen"); shinfo->evtchn_pending[0] = 0; @@ -770,7 +801,7 @@ int main(int argc, char *argv[]) alarm(1); break; - case 16: + case TEST_POLL_READY: TEST_ASSERT(!evtchn_irq_expected, "Expected event channel IRQ but it didn't happen"); @@ -780,14 +811,14 @@ int main(int argc, char *argv[]) alarm(1); break; - case 17: + case TEST_POLL_TIMEOUT: if (verbose) printf("Testing SCHEDOP_poll timeout\n"); shinfo->evtchn_pending[0] = 0; alarm(1); break; - case 18: + case TEST_POLL_MASKED: if (verbose) printf("Testing SCHEDOP_poll wake on masked event\n"); @@ -796,7 +827,7 @@ int main(int argc, char *argv[]) alarm(1); break; - case 19: + case TEST_POLL_WAKE: shinfo->evtchn_pending[0] = shinfo->evtchn_mask[0] = 0; if (verbose) printf("Testing SCHEDOP_poll wake on unmasked event\n"); @@ -813,7 +844,7 @@ int main(int argc, char *argv[]) alarm(1); break; - case 20: + case TEST_TIMER_PAST: TEST_ASSERT(!evtchn_irq_expected, "Expected event channel IRQ but it didn't happen"); /* Read timer and check it is no longer pending */ @@ -830,7 +861,7 @@ int main(int argc, char *argv[]) alarm(1); break; - case 21: + case TEST_LOCKING_SEND_RACE: TEST_ASSERT(!evtchn_irq_expected, "Expected event channel IRQ but it didn't happen"); alarm(0); @@ -852,7 +883,7 @@ int main(int argc, char *argv[]) __vm_ioctl(vm, KVM_XEN_HVM_EVTCHN_SEND, &uxe); break; - case 22: + case TEST_LOCKING_POLL_RACE: TEST_ASSERT(!evtchn_irq_expected, "Expected event channel IRQ but it didn't happen"); @@ -867,7 +898,7 @@ int main(int argc, char *argv[]) vcpu_ioctl(vcpu, KVM_XEN_VCPU_SET_ATTR, &tmr); break; - case 23: + case TEST_LOCKING_POLL_TIMEOUT: /* * Optional and possibly repeated sync point. * Injecting the timer IRQ may fail if the @@ -889,7 +920,7 @@ int main(int argc, char *argv[]) SHINFO_RACE_TIMEOUT * 1000000000ULL; vcpu_ioctl(vcpu, KVM_XEN_VCPU_SET_ATTR, &tmr); break; - case 24: + case TEST_DONE: TEST_ASSERT(!evtchn_irq_expected, "Expected event channel IRQ but it didn't happen"); @@ -900,7 +931,7 @@ int main(int argc, char *argv[]) TEST_ASSERT(ret == 0, "pthread_join() failed: %s", strerror(ret)); goto done; - case 0x20: + case TEST_GUEST_SAW_IRQ: TEST_ASSERT(evtchn_irq_expected, "Unexpected event channel IRQ"); evtchn_irq_expected = false; break; From e6239a4ec5c51e4d5ee4d1604f741f490c32054c Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Sat, 4 Feb 2023 02:41:51 +0000 Subject: [PATCH 320/460] KVM: selftests: Add EVTCHNOP_send slow path test to xen_shinfo_test When kvm_xen_evtchn_send() takes the slow path because the shinfo GPC needs to be revalidated, it used to violate the SRCU vs. kvm->lock locking rules and potentially cause a deadlock. Now that lockdep is learning to catch such things, make sure that code path is exercised by the selftest. Link: https://lore.kernel.org/all/20230113124606.10221-2-dwmw2@infradead.org Signed-off-by: David Woodhouse Signed-off-by: Sean Christopherson Message-Id: <20230204024151.1373296-5-seanjc@google.com> Signed-off-by: Paolo Bonzini --- .../selftests/kvm/x86_64/xen_shinfo_test.c | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c b/tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c index 1a3d2d51fef01..d42701dfbd83a 100644 --- a/tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c +++ b/tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c @@ -26,6 +26,9 @@ #define DUMMY_REGION_GPA (SHINFO_REGION_GPA + (3 * PAGE_SIZE)) #define DUMMY_REGION_SLOT 11 +#define DUMMY_REGION_GPA_2 (SHINFO_REGION_GPA + (4 * PAGE_SIZE)) +#define DUMMY_REGION_SLOT_2 12 + #define SHINFO_ADDR (SHINFO_REGION_GPA) #define VCPU_INFO_ADDR (SHINFO_REGION_GPA + 0x40) #define PVTIME_ADDR (SHINFO_REGION_GPA + PAGE_SIZE) @@ -54,6 +57,7 @@ enum { TEST_EVTCHN_SLOWPATH, TEST_EVTCHN_SEND_IOCTL, TEST_EVTCHN_HCALL, + TEST_EVTCHN_HCALL_SLOWPATH, TEST_EVTCHN_HCALL_EVENTFD, TEST_TIMER_SETUP, TEST_TIMER_WAIT, @@ -260,6 +264,16 @@ static void guest_code(void) guest_wait_for_irq(); + GUEST_SYNC(TEST_EVTCHN_HCALL_SLOWPATH); + + /* + * Same again, but this time the host has messed with memslots so it + * should take the slow path in kvm_xen_set_evtchn(). + */ + xen_hypercall(__HYPERVISOR_event_channel_op, EVTCHNOP_send, &s); + + guest_wait_for_irq(); + GUEST_SYNC(TEST_EVTCHN_HCALL_EVENTFD); /* Deliver "outbound" event channel to an eventfd which @@ -753,6 +767,19 @@ int main(int argc, char *argv[]) alarm(1); break; + case TEST_EVTCHN_HCALL_SLOWPATH: + TEST_ASSERT(!evtchn_irq_expected, + "Expected event channel IRQ but it didn't happen"); + shinfo->evtchn_pending[0] = 0; + + if (verbose) + printf("Testing guest EVTCHNOP_send direct to evtchn after memslot change\n"); + vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS, + DUMMY_REGION_GPA_2, DUMMY_REGION_SLOT_2, 1, 0); + evtchn_irq_expected = true; + alarm(1); + break; + case TEST_EVTCHN_HCALL_EVENTFD: TEST_ASSERT(!evtchn_irq_expected, "Expected event channel IRQ but it didn't happen"); From c96f57b08012805da323c6bdf929bab1b88d250c Mon Sep 17 00:00:00 2001 From: Vipin Sharma Date: Fri, 3 Feb 2023 17:45:44 -0800 Subject: [PATCH 321/460] KVM: selftests: Make vCPU exit reason test assertion common Make TEST_ASSERT_KVM_EXIT_REASON() macro and replace all exit reason test assert statements with it. No functional changes intended. Signed-off-by: Vipin Sharma Reviewed-by: David Matlack Message-Id: <20230204014547.583711-2-vipinsh@google.com> Signed-off-by: Paolo Bonzini --- .../testing/selftests/kvm/aarch64/psci_test.c | 4 +-- .../testing/selftests/kvm/include/test_util.h | 8 ++++++ .../kvm/lib/s390x/diag318_test_handler.c | 3 +-- .../selftests/kvm/s390x/sync_regs_test.c | 15 +++-------- .../selftests/kvm/set_memory_region_test.c | 6 +---- tools/testing/selftests/kvm/x86_64/amx_test.c | 8 +----- .../kvm/x86_64/cr4_cpuid_sync_test.c | 8 +----- .../testing/selftests/kvm/x86_64/debug_regs.c | 2 +- .../selftests/kvm/x86_64/flds_emulation.h | 5 +--- .../selftests/kvm/x86_64/hyperv_clock.c | 7 +----- .../selftests/kvm/x86_64/hyperv_evmcs.c | 8 +----- .../selftests/kvm/x86_64/hyperv_features.c | 14 ++--------- .../testing/selftests/kvm/x86_64/hyperv_ipi.c | 6 +---- .../selftests/kvm/x86_64/hyperv_svm_test.c | 7 +----- .../selftests/kvm/x86_64/hyperv_tlb_flush.c | 14 ++--------- .../selftests/kvm/x86_64/kvm_clock_test.c | 5 +--- .../selftests/kvm/x86_64/kvm_pv_test.c | 5 +--- .../selftests/kvm/x86_64/monitor_mwait_test.c | 9 +------ .../kvm/x86_64/nested_exceptions_test.c | 5 +--- .../selftests/kvm/x86_64/platform_info_test.c | 14 +++-------- .../kvm/x86_64/pmu_event_filter_test.c | 6 +---- tools/testing/selftests/kvm/x86_64/smm_test.c | 9 +------ .../testing/selftests/kvm/x86_64/state_test.c | 8 +----- .../selftests/kvm/x86_64/svm_int_ctl_test.c | 8 +----- .../kvm/x86_64/svm_nested_shutdown_test.c | 7 +----- .../kvm/x86_64/svm_nested_soft_inject_test.c | 6 +---- .../selftests/kvm/x86_64/svm_vmcall_test.c | 6 +---- .../selftests/kvm/x86_64/sync_regs_test.c | 25 ++++--------------- .../kvm/x86_64/triple_fault_event_test.c | 9 ++----- .../selftests/kvm/x86_64/tsc_scaling_sync.c | 6 +---- .../kvm/x86_64/ucna_injection_test.c | 22 +++------------- .../selftests/kvm/x86_64/userspace_io_test.c | 6 +---- .../kvm/x86_64/userspace_msr_exit_test.c | 22 +++------------- .../kvm/x86_64/vmx_apic_access_test.c | 11 ++------ .../kvm/x86_64/vmx_close_while_nested_test.c | 5 +--- .../selftests/kvm/x86_64/vmx_dirty_log_test.c | 7 +----- .../vmx_exception_with_invalid_guest_state.c | 4 +-- .../x86_64/vmx_invalid_nested_guest_state.c | 4 +-- .../kvm/x86_64/vmx_nested_tsc_scaling_test.c | 6 +---- .../kvm/x86_64/vmx_preemption_timer_test.c | 8 +----- .../kvm/x86_64/vmx_tsc_adjust_test.c | 6 +---- .../selftests/kvm/x86_64/xapic_ipi_test.c | 6 +---- .../selftests/kvm/x86_64/xen_shinfo_test.c | 7 +----- .../selftests/kvm/x86_64/xen_vmcall_test.c | 5 +--- 44 files changed, 69 insertions(+), 293 deletions(-) diff --git a/tools/testing/selftests/kvm/aarch64/psci_test.c b/tools/testing/selftests/kvm/aarch64/psci_test.c index cfa36f3879484..9b004905d1d31 100644 --- a/tools/testing/selftests/kvm/aarch64/psci_test.c +++ b/tools/testing/selftests/kvm/aarch64/psci_test.c @@ -180,9 +180,7 @@ static void host_test_system_suspend(void) enter_guest(source); - TEST_ASSERT(run->exit_reason == KVM_EXIT_SYSTEM_EVENT, - "Unhandled exit reason: %u (%s)", - run->exit_reason, exit_reason_str(run->exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(source, KVM_EXIT_SYSTEM_EVENT); TEST_ASSERT(run->system_event.type == KVM_SYSTEM_EVENT_SUSPEND, "Unhandled system event: %u (expected: %u)", run->system_event.type, KVM_SYSTEM_EVENT_SUSPEND); diff --git a/tools/testing/selftests/kvm/include/test_util.h b/tools/testing/selftests/kvm/include/test_util.h index 80d6416f3012e..a13663557e2b0 100644 --- a/tools/testing/selftests/kvm/include/test_util.h +++ b/tools/testing/selftests/kvm/include/test_util.h @@ -63,6 +63,14 @@ void test_assert(bool exp, const char *exp_str, #a, #b, #a, (unsigned long) __a, #b, (unsigned long) __b); \ } while (0) +#define TEST_ASSERT_KVM_EXIT_REASON(vcpu, expected) do { \ + __u32 exit_reason = (vcpu)->run->exit_reason; \ + \ + TEST_ASSERT(exit_reason == (expected), \ + "Unexpected exit reason: %u (%s)", \ + exit_reason, exit_reason_str(exit_reason)); \ +} while (0) + #define TEST_FAIL(fmt, ...) do { \ TEST_ASSERT(false, fmt, ##__VA_ARGS__); \ __builtin_unreachable(); \ diff --git a/tools/testing/selftests/kvm/lib/s390x/diag318_test_handler.c b/tools/testing/selftests/kvm/lib/s390x/diag318_test_handler.c index cdb7daeed5fd9..2c432fa164f19 100644 --- a/tools/testing/selftests/kvm/lib/s390x/diag318_test_handler.c +++ b/tools/testing/selftests/kvm/lib/s390x/diag318_test_handler.c @@ -35,8 +35,7 @@ static uint64_t diag318_handler(void) vcpu_run(vcpu); run = vcpu->run; - TEST_ASSERT(run->exit_reason == KVM_EXIT_S390_SIEIC, - "DIAGNOSE 0x0318 instruction was not intercepted"); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_S390_SIEIC); TEST_ASSERT(run->s390_sieic.icptcode == ICPT_INSTRUCTION, "Unexpected intercept code: 0x%x", run->s390_sieic.icptcode); TEST_ASSERT((run->s390_sieic.ipa & 0xff00) == IPA0_DIAG, diff --git a/tools/testing/selftests/kvm/s390x/sync_regs_test.c b/tools/testing/selftests/kvm/s390x/sync_regs_test.c index 2ddde41c44ba9..636a70ddac1ea 100644 --- a/tools/testing/selftests/kvm/s390x/sync_regs_test.c +++ b/tools/testing/selftests/kvm/s390x/sync_regs_test.c @@ -126,10 +126,7 @@ void test_req_and_verify_all_valid_regs(struct kvm_vcpu *vcpu) run->kvm_valid_regs = TEST_SYNC_FIELDS; rv = _vcpu_run(vcpu); TEST_ASSERT(rv == 0, "vcpu_run failed: %d\n", rv); - TEST_ASSERT(run->exit_reason == KVM_EXIT_S390_SIEIC, - "Unexpected exit reason: %u (%s)\n", - run->exit_reason, - exit_reason_str(run->exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_S390_SIEIC); TEST_ASSERT(run->s390_sieic.icptcode == 4 && (run->s390_sieic.ipa >> 8) == 0x83 && (run->s390_sieic.ipb >> 16) == 0x501, @@ -165,10 +162,7 @@ void test_set_and_verify_various_reg_values(struct kvm_vcpu *vcpu) rv = _vcpu_run(vcpu); TEST_ASSERT(rv == 0, "vcpu_run failed: %d\n", rv); - TEST_ASSERT(run->exit_reason == KVM_EXIT_S390_SIEIC, - "Unexpected exit reason: %u (%s)\n", - run->exit_reason, - exit_reason_str(run->exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_S390_SIEIC); TEST_ASSERT(run->s.regs.gprs[11] == 0xBAD1DEA + 1, "r11 sync regs value incorrect 0x%llx.", run->s.regs.gprs[11]); @@ -200,10 +194,7 @@ void test_clear_kvm_dirty_regs_bits(struct kvm_vcpu *vcpu) run->s.regs.diag318 = 0x4B1D; rv = _vcpu_run(vcpu); TEST_ASSERT(rv == 0, "vcpu_run failed: %d\n", rv); - TEST_ASSERT(run->exit_reason == KVM_EXIT_S390_SIEIC, - "Unexpected exit reason: %u (%s)\n", - run->exit_reason, - exit_reason_str(run->exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_S390_SIEIC); TEST_ASSERT(run->s.regs.gprs[11] != 0xDEADBEEF, "r11 sync regs value incorrect 0x%llx.", run->s.regs.gprs[11]); diff --git a/tools/testing/selftests/kvm/set_memory_region_test.c b/tools/testing/selftests/kvm/set_memory_region_test.c index 2ef1d1b72ce43..a849ce23ca975 100644 --- a/tools/testing/selftests/kvm/set_memory_region_test.c +++ b/tools/testing/selftests/kvm/set_memory_region_test.c @@ -308,7 +308,6 @@ static void test_delete_memory_region(void) static void test_zero_memory_regions(void) { struct kvm_vcpu *vcpu; - struct kvm_run *run; struct kvm_vm *vm; pr_info("Testing KVM_RUN with zero added memory regions\n"); @@ -318,10 +317,7 @@ static void test_zero_memory_regions(void) vm_ioctl(vm, KVM_SET_NR_MMU_PAGES, (void *)64ul); vcpu_run(vcpu); - - run = vcpu->run; - TEST_ASSERT(run->exit_reason == KVM_EXIT_INTERNAL_ERROR, - "Unexpected exit_reason = %u\n", run->exit_reason); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_INTERNAL_ERROR); kvm_vm_free(vm); } diff --git a/tools/testing/selftests/kvm/x86_64/amx_test.c b/tools/testing/selftests/kvm/x86_64/amx_test.c index bd72c6eb3b670..b646cdb5055ad 100644 --- a/tools/testing/selftests/kvm/x86_64/amx_test.c +++ b/tools/testing/selftests/kvm/x86_64/amx_test.c @@ -241,7 +241,6 @@ int main(int argc, char *argv[]) struct kvm_regs regs1, regs2; struct kvm_vcpu *vcpu; struct kvm_vm *vm; - struct kvm_run *run; struct kvm_x86_state *state; int xsave_restore_size; vm_vaddr_t amx_cfg, tiledata, xsavedata; @@ -268,7 +267,6 @@ int main(int argc, char *argv[]) "KVM should enumerate max XSAVE size when XSAVE is supported"); xsave_restore_size = kvm_cpu_property(X86_PROPERTY_XSTATE_MAX_SIZE); - run = vcpu->run; vcpu_regs_get(vcpu, ®s1); /* Register #NM handler */ @@ -291,10 +289,7 @@ int main(int argc, char *argv[]) for (stage = 1; ; stage++) { vcpu_run(vcpu); - TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, - "Stage %d: unexpected exit reason: %u (%s),\n", - stage, run->exit_reason, - exit_reason_str(run->exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); switch (get_ucall(vcpu, &uc)) { case UCALL_ABORT: @@ -350,7 +345,6 @@ int main(int argc, char *argv[]) /* Restore state in a new VM. */ vcpu = vm_recreate_with_one_vcpu(vm); vcpu_load_state(vcpu, state); - run = vcpu->run; kvm_x86_state_cleanup(state); memset(®s2, 0, sizeof(regs2)); diff --git a/tools/testing/selftests/kvm/x86_64/cr4_cpuid_sync_test.c b/tools/testing/selftests/kvm/x86_64/cr4_cpuid_sync_test.c index 1027a671c7d3a..624dc725e14dc 100644 --- a/tools/testing/selftests/kvm/x86_64/cr4_cpuid_sync_test.c +++ b/tools/testing/selftests/kvm/x86_64/cr4_cpuid_sync_test.c @@ -50,7 +50,6 @@ static void guest_code(void) int main(int argc, char *argv[]) { struct kvm_vcpu *vcpu; - struct kvm_run *run; struct kvm_vm *vm; struct kvm_sregs sregs; struct ucall uc; @@ -58,15 +57,10 @@ int main(int argc, char *argv[]) TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_XSAVE)); vm = vm_create_with_one_vcpu(&vcpu, guest_code); - run = vcpu->run; while (1) { vcpu_run(vcpu); - - TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, - "Unexpected exit reason: %u (%s),\n", - run->exit_reason, - exit_reason_str(run->exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); switch (get_ucall(vcpu, &uc)) { case UCALL_SYNC: diff --git a/tools/testing/selftests/kvm/x86_64/debug_regs.c b/tools/testing/selftests/kvm/x86_64/debug_regs.c index 7ef99c3359a0d..f6b295e0b2d2b 100644 --- a/tools/testing/selftests/kvm/x86_64/debug_regs.c +++ b/tools/testing/selftests/kvm/x86_64/debug_regs.c @@ -204,7 +204,7 @@ int main(void) vcpu_guest_debug_set(vcpu, &debug); vcpu_run(vcpu); - TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, "KVM_EXIT_IO"); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); cmd = get_ucall(vcpu, &uc); TEST_ASSERT(cmd == UCALL_DONE, "UCALL_DONE"); diff --git a/tools/testing/selftests/kvm/x86_64/flds_emulation.h b/tools/testing/selftests/kvm/x86_64/flds_emulation.h index e43a7df25f2c5..0a1573d52882b 100644 --- a/tools/testing/selftests/kvm/x86_64/flds_emulation.h +++ b/tools/testing/selftests/kvm/x86_64/flds_emulation.h @@ -24,10 +24,7 @@ static inline void handle_flds_emulation_failure_exit(struct kvm_vcpu *vcpu) uint8_t *insn_bytes; uint64_t flags; - TEST_ASSERT(run->exit_reason == KVM_EXIT_INTERNAL_ERROR, - "Unexpected exit reason: %u (%s)", - run->exit_reason, - exit_reason_str(run->exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_INTERNAL_ERROR); TEST_ASSERT(run->emulation_failure.suberror == KVM_INTERNAL_ERROR_EMULATION, "Unexpected suberror: %u", diff --git a/tools/testing/selftests/kvm/x86_64/hyperv_clock.c b/tools/testing/selftests/kvm/x86_64/hyperv_clock.c index 2ee0af0d449ef..f25749eaa6a84 100644 --- a/tools/testing/selftests/kvm/x86_64/hyperv_clock.c +++ b/tools/testing/selftests/kvm/x86_64/hyperv_clock.c @@ -207,13 +207,11 @@ int main(void) { struct kvm_vcpu *vcpu; struct kvm_vm *vm; - struct kvm_run *run; struct ucall uc; vm_vaddr_t tsc_page_gva; int stage; vm = vm_create_with_one_vcpu(&vcpu, guest_main); - run = vcpu->run; vcpu_set_hv_cpuid(vcpu); @@ -227,10 +225,7 @@ int main(void) for (stage = 1;; stage++) { vcpu_run(vcpu); - TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, - "Stage %d: unexpected exit reason: %u (%s),\n", - stage, run->exit_reason, - exit_reason_str(run->exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); switch (get_ucall(vcpu, &uc)) { case UCALL_ABORT: diff --git a/tools/testing/selftests/kvm/x86_64/hyperv_evmcs.c b/tools/testing/selftests/kvm/x86_64/hyperv_evmcs.c index af29e5776d403..7bde0c4dfdbd1 100644 --- a/tools/testing/selftests/kvm/x86_64/hyperv_evmcs.c +++ b/tools/testing/selftests/kvm/x86_64/hyperv_evmcs.c @@ -237,7 +237,6 @@ int main(int argc, char *argv[]) struct kvm_vcpu *vcpu; struct kvm_vm *vm; - struct kvm_run *run; struct ucall uc; int stage; @@ -266,13 +265,8 @@ int main(int argc, char *argv[]) pr_info("Running L1 which uses EVMCS to run L2\n"); for (stage = 1;; stage++) { - run = vcpu->run; - vcpu_run(vcpu); - TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, - "Stage %d: unexpected exit reason: %u (%s),\n", - stage, run->exit_reason, - exit_reason_str(run->exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); switch (get_ucall(vcpu, &uc)) { case UCALL_ABORT: diff --git a/tools/testing/selftests/kvm/x86_64/hyperv_features.c b/tools/testing/selftests/kvm/x86_64/hyperv_features.c index c5e3b39edd079..78606de9385da 100644 --- a/tools/testing/selftests/kvm/x86_64/hyperv_features.c +++ b/tools/testing/selftests/kvm/x86_64/hyperv_features.c @@ -122,7 +122,6 @@ static void guest_test_msrs_access(void) { struct kvm_cpuid2 *prev_cpuid = NULL; struct kvm_vcpu *vcpu; - struct kvm_run *run; struct kvm_vm *vm; struct ucall uc; int stage = 0; @@ -151,8 +150,6 @@ static void guest_test_msrs_access(void) vm_init_descriptor_tables(vm); vcpu_init_descriptor_tables(vcpu); - run = vcpu->run; - /* TODO: Make this entire test easier to maintain. */ if (stage >= 21) vcpu_enable_cap(vcpu, KVM_CAP_HYPERV_SYNIC2, 0); @@ -494,9 +491,7 @@ static void guest_test_msrs_access(void) msr->idx, msr->write ? "write" : "read"); vcpu_run(vcpu); - TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, - "unexpected exit reason: %u (%s)", - run->exit_reason, exit_reason_str(run->exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); switch (get_ucall(vcpu, &uc)) { case UCALL_ABORT: @@ -518,7 +513,6 @@ static void guest_test_hcalls_access(void) { struct kvm_cpuid2 *prev_cpuid = NULL; struct kvm_vcpu *vcpu; - struct kvm_run *run; struct kvm_vm *vm; struct ucall uc; int stage = 0; @@ -550,8 +544,6 @@ static void guest_test_hcalls_access(void) vcpu_init_cpuid(vcpu, prev_cpuid); } - run = vcpu->run; - switch (stage) { case 0: vcpu_set_cpuid_feature(vcpu, HV_MSR_HYPERCALL_AVAILABLE); @@ -669,9 +661,7 @@ static void guest_test_hcalls_access(void) pr_debug("Stage %d: testing hcall: 0x%lx\n", stage, hcall->control); vcpu_run(vcpu); - TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, - "unexpected exit reason: %u (%s)", - run->exit_reason, exit_reason_str(run->exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); switch (get_ucall(vcpu, &uc)) { case UCALL_ABORT: diff --git a/tools/testing/selftests/kvm/x86_64/hyperv_ipi.c b/tools/testing/selftests/kvm/x86_64/hyperv_ipi.c index 0cbb0e646ef8d..6feb5ddb031da 100644 --- a/tools/testing/selftests/kvm/x86_64/hyperv_ipi.c +++ b/tools/testing/selftests/kvm/x86_64/hyperv_ipi.c @@ -243,7 +243,6 @@ int main(int argc, char *argv[]) { struct kvm_vm *vm; struct kvm_vcpu *vcpu[3]; - unsigned int exit_reason; vm_vaddr_t hcall_page; pthread_t threads[2]; int stage = 1, r; @@ -283,10 +282,7 @@ int main(int argc, char *argv[]) while (true) { vcpu_run(vcpu[0]); - exit_reason = vcpu[0]->run->exit_reason; - TEST_ASSERT(exit_reason == KVM_EXIT_IO, - "unexpected exit reason: %u (%s)", - exit_reason, exit_reason_str(exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu[0], KVM_EXIT_IO); switch (get_ucall(vcpu[0], &uc)) { case UCALL_SYNC: diff --git a/tools/testing/selftests/kvm/x86_64/hyperv_svm_test.c b/tools/testing/selftests/kvm/x86_64/hyperv_svm_test.c index 68a7d354ea070..e446d76d1c0c3 100644 --- a/tools/testing/selftests/kvm/x86_64/hyperv_svm_test.c +++ b/tools/testing/selftests/kvm/x86_64/hyperv_svm_test.c @@ -156,7 +156,6 @@ int main(int argc, char *argv[]) vm_vaddr_t hcall_page; struct kvm_vcpu *vcpu; struct kvm_vm *vm; - struct kvm_run *run; struct ucall uc; int stage; @@ -165,7 +164,6 @@ int main(int argc, char *argv[]) /* Create VM */ vm = vm_create_with_one_vcpu(&vcpu, guest_code); vcpu_set_hv_cpuid(vcpu); - run = vcpu->run; vcpu_alloc_svm(vm, &nested_gva); vcpu_alloc_hyperv_test_pages(vm, &hv_pages_gva); @@ -177,10 +175,7 @@ int main(int argc, char *argv[]) for (stage = 1;; stage++) { vcpu_run(vcpu); - TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, - "Stage %d: unexpected exit reason: %u (%s),\n", - stage, run->exit_reason, - exit_reason_str(run->exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); switch (get_ucall(vcpu, &uc)) { case UCALL_ABORT: diff --git a/tools/testing/selftests/kvm/x86_64/hyperv_tlb_flush.c b/tools/testing/selftests/kvm/x86_64/hyperv_tlb_flush.c index 68f97ff720a74..4758b6ef5618e 100644 --- a/tools/testing/selftests/kvm/x86_64/hyperv_tlb_flush.c +++ b/tools/testing/selftests/kvm/x86_64/hyperv_tlb_flush.c @@ -542,18 +542,13 @@ static void *vcpu_thread(void *arg) struct ucall uc; int old; int r; - unsigned int exit_reason; r = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &old); TEST_ASSERT(!r, "pthread_setcanceltype failed on vcpu_id=%u with errno=%d", vcpu->id, r); vcpu_run(vcpu); - exit_reason = vcpu->run->exit_reason; - - TEST_ASSERT(exit_reason == KVM_EXIT_IO, - "vCPU %u exited with unexpected exit reason %u-%s, expected KVM_EXIT_IO", - vcpu->id, exit_reason, exit_reason_str(exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); switch (get_ucall(vcpu, &uc)) { case UCALL_ABORT: @@ -587,7 +582,6 @@ int main(int argc, char *argv[]) { struct kvm_vm *vm; struct kvm_vcpu *vcpu[3]; - unsigned int exit_reason; pthread_t threads[2]; vm_vaddr_t test_data_page, gva; vm_paddr_t gpa; @@ -657,11 +651,7 @@ int main(int argc, char *argv[]) while (true) { vcpu_run(vcpu[0]); - exit_reason = vcpu[0]->run->exit_reason; - - TEST_ASSERT(exit_reason == KVM_EXIT_IO, - "unexpected exit reason: %u (%s)", - exit_reason, exit_reason_str(exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu[0], KVM_EXIT_IO); switch (get_ucall(vcpu[0], &uc)) { case UCALL_SYNC: diff --git a/tools/testing/selftests/kvm/x86_64/kvm_clock_test.c b/tools/testing/selftests/kvm/x86_64/kvm_clock_test.c index 813ce282cf561..1778704360a66 100644 --- a/tools/testing/selftests/kvm/x86_64/kvm_clock_test.c +++ b/tools/testing/selftests/kvm/x86_64/kvm_clock_test.c @@ -105,7 +105,6 @@ static void setup_clock(struct kvm_vm *vm, struct test_case *test_case) static void enter_guest(struct kvm_vcpu *vcpu) { struct kvm_clock_data start, end; - struct kvm_run *run = vcpu->run; struct kvm_vm *vm = vcpu->vm; struct ucall uc; int i; @@ -118,9 +117,7 @@ static void enter_guest(struct kvm_vcpu *vcpu) vcpu_run(vcpu); vm_ioctl(vm, KVM_GET_CLOCK, &end); - TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, - "unexpected exit reason: %u (%s)", - run->exit_reason, exit_reason_str(run->exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); switch (get_ucall(vcpu, &uc)) { case UCALL_SYNC: diff --git a/tools/testing/selftests/kvm/x86_64/kvm_pv_test.c b/tools/testing/selftests/kvm/x86_64/kvm_pv_test.c index 619655c1a1f39..f774a9e62858f 100644 --- a/tools/testing/selftests/kvm/x86_64/kvm_pv_test.c +++ b/tools/testing/selftests/kvm/x86_64/kvm_pv_test.c @@ -111,14 +111,11 @@ static void pr_hcall(struct ucall *uc) static void enter_guest(struct kvm_vcpu *vcpu) { - struct kvm_run *run = vcpu->run; struct ucall uc; while (true) { vcpu_run(vcpu); - TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, - "unexpected exit reason: %u (%s)", - run->exit_reason, exit_reason_str(run->exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); switch (get_ucall(vcpu, &uc)) { case UCALL_PR_MSR: diff --git a/tools/testing/selftests/kvm/x86_64/monitor_mwait_test.c b/tools/testing/selftests/kvm/x86_64/monitor_mwait_test.c index 016070cad36ed..72812644d7f5e 100644 --- a/tools/testing/selftests/kvm/x86_64/monitor_mwait_test.c +++ b/tools/testing/selftests/kvm/x86_64/monitor_mwait_test.c @@ -64,7 +64,6 @@ int main(int argc, char *argv[]) { uint64_t disabled_quirks; struct kvm_vcpu *vcpu; - struct kvm_run *run; struct kvm_vm *vm; struct ucall uc; int testcase; @@ -74,18 +73,12 @@ int main(int argc, char *argv[]) vm = vm_create_with_one_vcpu(&vcpu, guest_code); vcpu_clear_cpuid_feature(vcpu, X86_FEATURE_MWAIT); - run = vcpu->run; - vm_init_descriptor_tables(vm); vcpu_init_descriptor_tables(vcpu); while (1) { vcpu_run(vcpu); - - TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, - "Unexpected exit reason: %u (%s),\n", - run->exit_reason, - exit_reason_str(run->exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); switch (get_ucall(vcpu, &uc)) { case UCALL_SYNC: diff --git a/tools/testing/selftests/kvm/x86_64/nested_exceptions_test.c b/tools/testing/selftests/kvm/x86_64/nested_exceptions_test.c index ac33835f78f45..6502aa23c2f84 100644 --- a/tools/testing/selftests/kvm/x86_64/nested_exceptions_test.c +++ b/tools/testing/selftests/kvm/x86_64/nested_exceptions_test.c @@ -166,12 +166,9 @@ static void __attribute__((__flatten__)) l1_guest_code(void *test_data) static void assert_ucall_vector(struct kvm_vcpu *vcpu, int vector) { - struct kvm_run *run = vcpu->run; struct ucall uc; - TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, - "Unexpected exit reason: %u (%s),\n", - run->exit_reason, exit_reason_str(run->exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); switch (get_ucall(vcpu, &uc)) { case UCALL_SYNC: diff --git a/tools/testing/selftests/kvm/x86_64/platform_info_test.c b/tools/testing/selftests/kvm/x86_64/platform_info_test.c index 310a104d94f06..c9a07963d68aa 100644 --- a/tools/testing/selftests/kvm/x86_64/platform_info_test.c +++ b/tools/testing/selftests/kvm/x86_64/platform_info_test.c @@ -36,15 +36,12 @@ static void guest_code(void) static void test_msr_platform_info_enabled(struct kvm_vcpu *vcpu) { - struct kvm_run *run = vcpu->run; struct ucall uc; vm_enable_cap(vcpu->vm, KVM_CAP_MSR_PLATFORM_INFO, true); vcpu_run(vcpu); - TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, - "Exit_reason other than KVM_EXIT_IO: %u (%s),\n", - run->exit_reason, - exit_reason_str(run->exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); + get_ucall(vcpu, &uc); TEST_ASSERT(uc.cmd == UCALL_SYNC, "Received ucall other than UCALL_SYNC: %lu\n", uc.cmd); @@ -56,14 +53,9 @@ static void test_msr_platform_info_enabled(struct kvm_vcpu *vcpu) static void test_msr_platform_info_disabled(struct kvm_vcpu *vcpu) { - struct kvm_run *run = vcpu->run; - vm_enable_cap(vcpu->vm, KVM_CAP_MSR_PLATFORM_INFO, false); vcpu_run(vcpu); - TEST_ASSERT(run->exit_reason == KVM_EXIT_SHUTDOWN, - "Exit_reason other than KVM_EXIT_SHUTDOWN: %u (%s)\n", - run->exit_reason, - exit_reason_str(run->exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_SHUTDOWN); } int main(int argc, char *argv[]) diff --git a/tools/testing/selftests/kvm/x86_64/pmu_event_filter_test.c b/tools/testing/selftests/kvm/x86_64/pmu_event_filter_test.c index bad7ef8c5b92e..2feef25ba6913 100644 --- a/tools/testing/selftests/kvm/x86_64/pmu_event_filter_test.c +++ b/tools/testing/selftests/kvm/x86_64/pmu_event_filter_test.c @@ -151,14 +151,10 @@ static void amd_guest_code(void) */ static uint64_t run_vcpu_to_sync(struct kvm_vcpu *vcpu) { - struct kvm_run *run = vcpu->run; struct ucall uc; vcpu_run(vcpu); - TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, - "Exit_reason other than KVM_EXIT_IO: %u (%s)\n", - run->exit_reason, - exit_reason_str(run->exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); get_ucall(vcpu, &uc); TEST_ASSERT(uc.cmd == UCALL_SYNC, "Received ucall other than UCALL_SYNC: %lu", uc.cmd); diff --git a/tools/testing/selftests/kvm/x86_64/smm_test.c b/tools/testing/selftests/kvm/x86_64/smm_test.c index cb38a478e1f62..e18b86666e1fc 100644 --- a/tools/testing/selftests/kvm/x86_64/smm_test.c +++ b/tools/testing/selftests/kvm/x86_64/smm_test.c @@ -133,7 +133,6 @@ int main(int argc, char *argv[]) struct kvm_vcpu *vcpu; struct kvm_regs regs; struct kvm_vm *vm; - struct kvm_run *run; struct kvm_x86_state *state; int stage, stage_reported; @@ -142,8 +141,6 @@ int main(int argc, char *argv[]) /* Create VM */ vm = vm_create_with_one_vcpu(&vcpu, guest_code); - run = vcpu->run; - vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS, SMRAM_GPA, SMRAM_MEMSLOT, SMRAM_PAGES, 0); TEST_ASSERT(vm_phy_pages_alloc(vm, SMRAM_PAGES, SMRAM_GPA, SMRAM_MEMSLOT) @@ -169,10 +166,7 @@ int main(int argc, char *argv[]) for (stage = 1;; stage++) { vcpu_run(vcpu); - TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, - "Stage %d: unexpected exit reason: %u (%s),\n", - stage, run->exit_reason, - exit_reason_str(run->exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); memset(®s, 0, sizeof(regs)); vcpu_regs_get(vcpu, ®s); @@ -208,7 +202,6 @@ int main(int argc, char *argv[]) vcpu = vm_recreate_with_one_vcpu(vm); vcpu_load_state(vcpu, state); - run = vcpu->run; kvm_x86_state_cleanup(state); } diff --git a/tools/testing/selftests/kvm/x86_64/state_test.c b/tools/testing/selftests/kvm/x86_64/state_test.c index ea578971fb9f9..4c4925a8ab452 100644 --- a/tools/testing/selftests/kvm/x86_64/state_test.c +++ b/tools/testing/selftests/kvm/x86_64/state_test.c @@ -158,14 +158,12 @@ int main(int argc, char *argv[]) struct kvm_regs regs1, regs2; struct kvm_vcpu *vcpu; struct kvm_vm *vm; - struct kvm_run *run; struct kvm_x86_state *state; struct ucall uc; int stage; /* Create VM */ vm = vm_create_with_one_vcpu(&vcpu, guest_code); - run = vcpu->run; vcpu_regs_get(vcpu, ®s1); @@ -183,10 +181,7 @@ int main(int argc, char *argv[]) for (stage = 1;; stage++) { vcpu_run(vcpu); - TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, - "Stage %d: unexpected exit reason: %u (%s),\n", - stage, run->exit_reason, - exit_reason_str(run->exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); switch (get_ucall(vcpu, &uc)) { case UCALL_ABORT: @@ -214,7 +209,6 @@ int main(int argc, char *argv[]) /* Restore state in a new VM. */ vcpu = vm_recreate_with_one_vcpu(vm); vcpu_load_state(vcpu, state); - run = vcpu->run; kvm_x86_state_cleanup(state); memset(®s2, 0, sizeof(regs2)); diff --git a/tools/testing/selftests/kvm/x86_64/svm_int_ctl_test.c b/tools/testing/selftests/kvm/x86_64/svm_int_ctl_test.c index 4a07ba227b995..32bef39bec217 100644 --- a/tools/testing/selftests/kvm/x86_64/svm_int_ctl_test.c +++ b/tools/testing/selftests/kvm/x86_64/svm_int_ctl_test.c @@ -85,7 +85,6 @@ static void l1_guest_code(struct svm_test_data *svm) int main(int argc, char *argv[]) { struct kvm_vcpu *vcpu; - struct kvm_run *run; vm_vaddr_t svm_gva; struct kvm_vm *vm; struct ucall uc; @@ -103,13 +102,8 @@ int main(int argc, char *argv[]) vcpu_alloc_svm(vm, &svm_gva); vcpu_args_set(vcpu, 1, svm_gva); - run = vcpu->run; - vcpu_run(vcpu); - TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, - "Got exit_reason other than KVM_EXIT_IO: %u (%s)\n", - run->exit_reason, - exit_reason_str(run->exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); switch (get_ucall(vcpu, &uc)) { case UCALL_ABORT: diff --git a/tools/testing/selftests/kvm/x86_64/svm_nested_shutdown_test.c b/tools/testing/selftests/kvm/x86_64/svm_nested_shutdown_test.c index e73fcdef47bbe..d6fcdcc3af314 100644 --- a/tools/testing/selftests/kvm/x86_64/svm_nested_shutdown_test.c +++ b/tools/testing/selftests/kvm/x86_64/svm_nested_shutdown_test.c @@ -42,7 +42,6 @@ static void l1_guest_code(struct svm_test_data *svm, struct idt_entry *idt) int main(int argc, char *argv[]) { struct kvm_vcpu *vcpu; - struct kvm_run *run; vm_vaddr_t svm_gva; struct kvm_vm *vm; @@ -55,13 +54,9 @@ int main(int argc, char *argv[]) vcpu_alloc_svm(vm, &svm_gva); vcpu_args_set(vcpu, 2, svm_gva, vm->idt); - run = vcpu->run; vcpu_run(vcpu); - TEST_ASSERT(run->exit_reason == KVM_EXIT_SHUTDOWN, - "Got exit_reason other than KVM_EXIT_SHUTDOWN: %u (%s)\n", - run->exit_reason, - exit_reason_str(run->exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_SHUTDOWN); kvm_vm_free(vm); } diff --git a/tools/testing/selftests/kvm/x86_64/svm_nested_soft_inject_test.c b/tools/testing/selftests/kvm/x86_64/svm_nested_soft_inject_test.c index b34980d45648a..4e2479716da6e 100644 --- a/tools/testing/selftests/kvm/x86_64/svm_nested_soft_inject_test.c +++ b/tools/testing/selftests/kvm/x86_64/svm_nested_soft_inject_test.c @@ -176,16 +176,12 @@ static void run_test(bool is_nmi) memset(&debug, 0, sizeof(debug)); vcpu_guest_debug_set(vcpu, &debug); - struct kvm_run *run = vcpu->run; struct ucall uc; alarm(2); vcpu_run(vcpu); alarm(0); - TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, - "Got exit_reason other than KVM_EXIT_IO: %u (%s)\n", - run->exit_reason, - exit_reason_str(run->exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); switch (get_ucall(vcpu, &uc)) { case UCALL_ABORT: diff --git a/tools/testing/selftests/kvm/x86_64/svm_vmcall_test.c b/tools/testing/selftests/kvm/x86_64/svm_vmcall_test.c index c3ac45df74832..8a62cca28cfbb 100644 --- a/tools/testing/selftests/kvm/x86_64/svm_vmcall_test.c +++ b/tools/testing/selftests/kvm/x86_64/svm_vmcall_test.c @@ -47,14 +47,10 @@ int main(int argc, char *argv[]) vcpu_args_set(vcpu, 1, svm_gva); for (;;) { - volatile struct kvm_run *run = vcpu->run; struct ucall uc; vcpu_run(vcpu); - TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, - "Got exit_reason other than KVM_EXIT_IO: %u (%s)\n", - run->exit_reason, - exit_reason_str(run->exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); switch (get_ucall(vcpu, &uc)) { case UCALL_ABORT: diff --git a/tools/testing/selftests/kvm/x86_64/sync_regs_test.c b/tools/testing/selftests/kvm/x86_64/sync_regs_test.c index d2f9b5bdfab20..2da89fdc2471a 100644 --- a/tools/testing/selftests/kvm/x86_64/sync_regs_test.c +++ b/tools/testing/selftests/kvm/x86_64/sync_regs_test.c @@ -132,10 +132,7 @@ int main(int argc, char *argv[]) /* TODO: BUILD TIME CHECK: TEST_ASSERT(KVM_SYNC_X86_NUM_FIELDS != 3); */ run->kvm_valid_regs = TEST_SYNC_FIELDS; rv = _vcpu_run(vcpu); - TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, - "Unexpected exit reason: %u (%s),\n", - run->exit_reason, - exit_reason_str(run->exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); vcpu_regs_get(vcpu, ®s); compare_regs(®s, &run->s.regs.regs); @@ -154,10 +151,7 @@ int main(int argc, char *argv[]) run->kvm_valid_regs = TEST_SYNC_FIELDS; run->kvm_dirty_regs = KVM_SYNC_X86_REGS | KVM_SYNC_X86_SREGS; rv = _vcpu_run(vcpu); - TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, - "Unexpected exit reason: %u (%s),\n", - run->exit_reason, - exit_reason_str(run->exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); TEST_ASSERT(run->s.regs.regs.rbx == 0xBAD1DEA + 1, "rbx sync regs value incorrect 0x%llx.", run->s.regs.regs.rbx); @@ -181,10 +175,7 @@ int main(int argc, char *argv[]) run->kvm_dirty_regs = 0; run->s.regs.regs.rbx = 0xDEADBEEF; rv = _vcpu_run(vcpu); - TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, - "Unexpected exit reason: %u (%s),\n", - run->exit_reason, - exit_reason_str(run->exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); TEST_ASSERT(run->s.regs.regs.rbx != 0xDEADBEEF, "rbx sync regs value incorrect 0x%llx.", run->s.regs.regs.rbx); @@ -199,10 +190,7 @@ int main(int argc, char *argv[]) regs.rbx = 0xBAC0; vcpu_regs_set(vcpu, ®s); rv = _vcpu_run(vcpu); - TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, - "Unexpected exit reason: %u (%s),\n", - run->exit_reason, - exit_reason_str(run->exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); TEST_ASSERT(run->s.regs.regs.rbx == 0xAAAA, "rbx sync regs value incorrect 0x%llx.", run->s.regs.regs.rbx); @@ -219,10 +207,7 @@ int main(int argc, char *argv[]) run->kvm_dirty_regs = TEST_SYNC_FIELDS; run->s.regs.regs.rbx = 0xBBBB; rv = _vcpu_run(vcpu); - TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, - "Unexpected exit reason: %u (%s),\n", - run->exit_reason, - exit_reason_str(run->exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); TEST_ASSERT(run->s.regs.regs.rbx == 0xBBBB, "rbx sync regs value incorrect 0x%llx.", run->s.regs.regs.rbx); diff --git a/tools/testing/selftests/kvm/x86_64/triple_fault_event_test.c b/tools/testing/selftests/kvm/x86_64/triple_fault_event_test.c index ead5d878a71c4..56306a19144a7 100644 --- a/tools/testing/selftests/kvm/x86_64/triple_fault_event_test.c +++ b/tools/testing/selftests/kvm/x86_64/triple_fault_event_test.c @@ -89,9 +89,7 @@ int main(void) run = vcpu->run; vcpu_run(vcpu); - TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, - "Expected KVM_EXIT_IO, got: %u (%s)\n", - run->exit_reason, exit_reason_str(run->exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); TEST_ASSERT(run->io.port == ARBITRARY_IO_PORT, "Expected IN from port %d from L2, got port %d", ARBITRARY_IO_PORT, run->io.port); @@ -111,10 +109,7 @@ int main(void) if (has_svm) { - TEST_ASSERT(run->exit_reason == KVM_EXIT_SHUTDOWN, - "Got exit_reason other than KVM_EXIT_SHUTDOWN: %u (%s)\n", - run->exit_reason, - exit_reason_str(run->exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_SHUTDOWN); } else { switch (get_ucall(vcpu, &uc)) { case UCALL_DONE: diff --git a/tools/testing/selftests/kvm/x86_64/tsc_scaling_sync.c b/tools/testing/selftests/kvm/x86_64/tsc_scaling_sync.c index 47139aab74084..5b669818e39aa 100644 --- a/tools/testing/selftests/kvm/x86_64/tsc_scaling_sync.c +++ b/tools/testing/selftests/kvm/x86_64/tsc_scaling_sync.c @@ -64,14 +64,10 @@ static void *run_vcpu(void *_cpu_nr) pthread_spin_unlock(&create_lock); for (;;) { - volatile struct kvm_run *run = vcpu->run; struct ucall uc; vcpu_run(vcpu); - TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, - "Got exit_reason other than KVM_EXIT_IO: %u (%s)\n", - run->exit_reason, - exit_reason_str(run->exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); switch (get_ucall(vcpu, &uc)) { case UCALL_DONE: diff --git a/tools/testing/selftests/kvm/x86_64/ucna_injection_test.c b/tools/testing/selftests/kvm/x86_64/ucna_injection_test.c index a897c7fd8abe4..85f34ca7e49e5 100644 --- a/tools/testing/selftests/kvm/x86_64/ucna_injection_test.c +++ b/tools/testing/selftests/kvm/x86_64/ucna_injection_test.c @@ -137,15 +137,11 @@ static void guest_gp_handler(struct ex_regs *regs) static void run_vcpu_expect_gp(struct kvm_vcpu *vcpu) { - unsigned int exit_reason; struct ucall uc; vcpu_run(vcpu); - exit_reason = vcpu->run->exit_reason; - TEST_ASSERT(exit_reason == KVM_EXIT_IO, - "exited with unexpected exit reason %u-%s, expected KVM_EXIT_IO", - exit_reason, exit_reason_str(exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); TEST_ASSERT(get_ucall(vcpu, &uc) == UCALL_SYNC, "Expect UCALL_SYNC\n"); TEST_ASSERT(uc.args[1] == SYNC_GP, "#GP is expected."); @@ -182,7 +178,6 @@ static void *run_ucna_injection(void *arg) struct ucall uc; int old; int r; - unsigned int exit_reason; r = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &old); TEST_ASSERT(r == 0, @@ -191,10 +186,7 @@ static void *run_ucna_injection(void *arg) vcpu_run(params->vcpu); - exit_reason = params->vcpu->run->exit_reason; - TEST_ASSERT(exit_reason == KVM_EXIT_IO, - "unexpected exit reason %u-%s, expected KVM_EXIT_IO", - exit_reason, exit_reason_str(exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(params->vcpu, KVM_EXIT_IO); TEST_ASSERT(get_ucall(params->vcpu, &uc) == UCALL_SYNC, "Expect UCALL_SYNC\n"); TEST_ASSERT(uc.args[1] == SYNC_FIRST_UCNA, "Injecting first UCNA."); @@ -204,10 +196,7 @@ static void *run_ucna_injection(void *arg) inject_ucna(params->vcpu, FIRST_UCNA_ADDR); vcpu_run(params->vcpu); - exit_reason = params->vcpu->run->exit_reason; - TEST_ASSERT(exit_reason == KVM_EXIT_IO, - "unexpected exit reason %u-%s, expected KVM_EXIT_IO", - exit_reason, exit_reason_str(exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(params->vcpu, KVM_EXIT_IO); TEST_ASSERT(get_ucall(params->vcpu, &uc) == UCALL_SYNC, "Expect UCALL_SYNC\n"); TEST_ASSERT(uc.args[1] == SYNC_SECOND_UCNA, "Injecting second UCNA."); @@ -217,10 +206,7 @@ static void *run_ucna_injection(void *arg) inject_ucna(params->vcpu, SECOND_UCNA_ADDR); vcpu_run(params->vcpu); - exit_reason = params->vcpu->run->exit_reason; - TEST_ASSERT(exit_reason == KVM_EXIT_IO, - "unexpected exit reason %u-%s, expected KVM_EXIT_IO", - exit_reason, exit_reason_str(exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(params->vcpu, KVM_EXIT_IO); if (get_ucall(params->vcpu, &uc) == UCALL_ABORT) { TEST_ASSERT(false, "vCPU assertion failure: %s.\n", (const char *)uc.args[0]); diff --git a/tools/testing/selftests/kvm/x86_64/userspace_io_test.c b/tools/testing/selftests/kvm/x86_64/userspace_io_test.c index 91076c9787b41..0cb51fa42773b 100644 --- a/tools/testing/selftests/kvm/x86_64/userspace_io_test.c +++ b/tools/testing/selftests/kvm/x86_64/userspace_io_test.c @@ -63,11 +63,7 @@ int main(int argc, char *argv[]) while (1) { vcpu_run(vcpu); - - TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, - "Unexpected exit reason: %u (%s),\n", - run->exit_reason, - exit_reason_str(run->exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); if (get_ucall(vcpu, &uc)) break; diff --git a/tools/testing/selftests/kvm/x86_64/userspace_msr_exit_test.c b/tools/testing/selftests/kvm/x86_64/userspace_msr_exit_test.c index 25fa55344a10e..3533dc2fbfeeb 100644 --- a/tools/testing/selftests/kvm/x86_64/userspace_msr_exit_test.c +++ b/tools/testing/selftests/kvm/x86_64/userspace_msr_exit_test.c @@ -410,10 +410,7 @@ static void process_rdmsr(struct kvm_vcpu *vcpu, uint32_t msr_index) check_for_guest_assert(vcpu); - TEST_ASSERT(run->exit_reason == KVM_EXIT_X86_RDMSR, - "Unexpected exit reason: %u (%s),\n", - run->exit_reason, - exit_reason_str(run->exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_X86_RDMSR); TEST_ASSERT(run->msr.index == msr_index, "Unexpected msr (0x%04x), expected 0x%04x", run->msr.index, msr_index); @@ -445,10 +442,7 @@ static void process_wrmsr(struct kvm_vcpu *vcpu, uint32_t msr_index) check_for_guest_assert(vcpu); - TEST_ASSERT(run->exit_reason == KVM_EXIT_X86_WRMSR, - "Unexpected exit reason: %u (%s),\n", - run->exit_reason, - exit_reason_str(run->exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_X86_WRMSR); TEST_ASSERT(run->msr.index == msr_index, "Unexpected msr (0x%04x), expected 0x%04x", run->msr.index, msr_index); @@ -472,15 +466,11 @@ static void process_wrmsr(struct kvm_vcpu *vcpu, uint32_t msr_index) static void process_ucall_done(struct kvm_vcpu *vcpu) { - struct kvm_run *run = vcpu->run; struct ucall uc; check_for_guest_assert(vcpu); - TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, - "Unexpected exit reason: %u (%s)", - run->exit_reason, - exit_reason_str(run->exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); TEST_ASSERT(get_ucall(vcpu, &uc) == UCALL_DONE, "Unexpected ucall command: %lu, expected UCALL_DONE (%d)", @@ -489,15 +479,11 @@ static void process_ucall_done(struct kvm_vcpu *vcpu) static uint64_t process_ucall(struct kvm_vcpu *vcpu) { - struct kvm_run *run = vcpu->run; struct ucall uc = {}; check_for_guest_assert(vcpu); - TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, - "Unexpected exit reason: %u (%s)", - run->exit_reason, - exit_reason_str(run->exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); switch (get_ucall(vcpu, &uc)) { case UCALL_SYNC: diff --git a/tools/testing/selftests/kvm/x86_64/vmx_apic_access_test.c b/tools/testing/selftests/kvm/x86_64/vmx_apic_access_test.c index 5abecf06329ea..2bed5fb3a0d6e 100644 --- a/tools/testing/selftests/kvm/x86_64/vmx_apic_access_test.c +++ b/tools/testing/selftests/kvm/x86_64/vmx_apic_access_test.c @@ -96,21 +96,14 @@ int main(int argc, char *argv[]) vcpu_run(vcpu); if (apic_access_addr == high_gpa) { - TEST_ASSERT(run->exit_reason == - KVM_EXIT_INTERNAL_ERROR, - "Got exit reason other than KVM_EXIT_INTERNAL_ERROR: %u (%s)\n", - run->exit_reason, - exit_reason_str(run->exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_INTERNAL_ERROR); TEST_ASSERT(run->internal.suberror == KVM_INTERNAL_ERROR_EMULATION, "Got internal suberror other than KVM_INTERNAL_ERROR_EMULATION: %u\n", run->internal.suberror); break; } - TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, - "Got exit_reason other than KVM_EXIT_IO: %u (%s)\n", - run->exit_reason, - exit_reason_str(run->exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); switch (get_ucall(vcpu, &uc)) { case UCALL_ABORT: diff --git a/tools/testing/selftests/kvm/x86_64/vmx_close_while_nested_test.c b/tools/testing/selftests/kvm/x86_64/vmx_close_while_nested_test.c index d79651b027402..dad988351493e 100644 --- a/tools/testing/selftests/kvm/x86_64/vmx_close_while_nested_test.c +++ b/tools/testing/selftests/kvm/x86_64/vmx_close_while_nested_test.c @@ -64,10 +64,7 @@ int main(int argc, char *argv[]) struct ucall uc; vcpu_run(vcpu); - TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, - "Got exit_reason other than KVM_EXIT_IO: %u (%s)\n", - run->exit_reason, - exit_reason_str(run->exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); if (run->io.port == PORT_L0_EXIT) break; diff --git a/tools/testing/selftests/kvm/x86_64/vmx_dirty_log_test.c b/tools/testing/selftests/kvm/x86_64/vmx_dirty_log_test.c index f0456fb031b1e..e4ad5fef52ffc 100644 --- a/tools/testing/selftests/kvm/x86_64/vmx_dirty_log_test.c +++ b/tools/testing/selftests/kvm/x86_64/vmx_dirty_log_test.c @@ -73,7 +73,6 @@ int main(int argc, char *argv[]) struct kvm_vcpu *vcpu; struct kvm_vm *vm; - struct kvm_run *run; struct ucall uc; bool done = false; @@ -84,7 +83,6 @@ int main(int argc, char *argv[]) vm = vm_create_with_one_vcpu(&vcpu, l1_guest_code); vmx = vcpu_alloc_vmx(vm, &vmx_pages_gva); vcpu_args_set(vcpu, 1, vmx_pages_gva); - run = vcpu->run; /* Add an extra memory slot for testing dirty logging */ vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS, @@ -117,10 +115,7 @@ int main(int argc, char *argv[]) while (!done) { memset(host_test_mem, 0xaa, TEST_MEM_PAGES * 4096); vcpu_run(vcpu); - TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, - "Unexpected exit reason: %u (%s),\n", - run->exit_reason, - exit_reason_str(run->exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); switch (get_ucall(vcpu, &uc)) { case UCALL_ABORT: diff --git a/tools/testing/selftests/kvm/x86_64/vmx_exception_with_invalid_guest_state.c b/tools/testing/selftests/kvm/x86_64/vmx_exception_with_invalid_guest_state.c index ccdfa5dc1a4dc..be0bdb8c6f78c 100644 --- a/tools/testing/selftests/kvm/x86_64/vmx_exception_with_invalid_guest_state.c +++ b/tools/testing/selftests/kvm/x86_64/vmx_exception_with_invalid_guest_state.c @@ -26,9 +26,7 @@ static void __run_vcpu_with_invalid_state(struct kvm_vcpu *vcpu) vcpu_run(vcpu); - TEST_ASSERT(run->exit_reason == KVM_EXIT_INTERNAL_ERROR, - "Expected KVM_EXIT_INTERNAL_ERROR, got %d (%s)\n", - run->exit_reason, exit_reason_str(run->exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_INTERNAL_ERROR); TEST_ASSERT(run->emulation_failure.suberror == KVM_INTERNAL_ERROR_EMULATION, "Expected emulation failure, got %d\n", run->emulation_failure.suberror); diff --git a/tools/testing/selftests/kvm/x86_64/vmx_invalid_nested_guest_state.c b/tools/testing/selftests/kvm/x86_64/vmx_invalid_nested_guest_state.c index 6bfb4bb471ca2..a100ee5f00093 100644 --- a/tools/testing/selftests/kvm/x86_64/vmx_invalid_nested_guest_state.c +++ b/tools/testing/selftests/kvm/x86_64/vmx_invalid_nested_guest_state.c @@ -74,9 +74,7 @@ int main(int argc, char *argv[]) * The first exit to L0 userspace should be an I/O access from L2. * Running L1 should launch L2 without triggering an exit to userspace. */ - TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, - "Expected KVM_EXIT_IO, got: %u (%s)\n", - run->exit_reason, exit_reason_str(run->exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); TEST_ASSERT(run->io.port == ARBITRARY_IO_PORT, "Expected IN from port %d from L2, got port %d", diff --git a/tools/testing/selftests/kvm/x86_64/vmx_nested_tsc_scaling_test.c b/tools/testing/selftests/kvm/x86_64/vmx_nested_tsc_scaling_test.c index 465a9434d61c2..d427eb146bc58 100644 --- a/tools/testing/selftests/kvm/x86_64/vmx_nested_tsc_scaling_test.c +++ b/tools/testing/selftests/kvm/x86_64/vmx_nested_tsc_scaling_test.c @@ -183,14 +183,10 @@ int main(int argc, char *argv[]) vcpu_ioctl(vcpu, KVM_SET_TSC_KHZ, (void *) (tsc_khz / l1_scale_factor)); for (;;) { - volatile struct kvm_run *run = vcpu->run; struct ucall uc; vcpu_run(vcpu); - TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, - "Got exit_reason other than KVM_EXIT_IO: %u (%s)\n", - run->exit_reason, - exit_reason_str(run->exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); switch (get_ucall(vcpu, &uc)) { case UCALL_ABORT: diff --git a/tools/testing/selftests/kvm/x86_64/vmx_preemption_timer_test.c b/tools/testing/selftests/kvm/x86_64/vmx_preemption_timer_test.c index 0efdc05969a56..affc328001584 100644 --- a/tools/testing/selftests/kvm/x86_64/vmx_preemption_timer_test.c +++ b/tools/testing/selftests/kvm/x86_64/vmx_preemption_timer_test.c @@ -157,7 +157,6 @@ int main(int argc, char *argv[]) struct kvm_regs regs1, regs2; struct kvm_vm *vm; - struct kvm_run *run; struct kvm_vcpu *vcpu; struct kvm_x86_state *state; struct ucall uc; @@ -173,7 +172,6 @@ int main(int argc, char *argv[]) /* Create VM */ vm = vm_create_with_one_vcpu(&vcpu, guest_code); - run = vcpu->run; vcpu_regs_get(vcpu, ®s1); @@ -182,10 +180,7 @@ int main(int argc, char *argv[]) for (stage = 1;; stage++) { vcpu_run(vcpu); - TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, - "Stage %d: unexpected exit reason: %u (%s),\n", - stage, run->exit_reason, - exit_reason_str(run->exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); switch (get_ucall(vcpu, &uc)) { case UCALL_ABORT: @@ -237,7 +232,6 @@ int main(int argc, char *argv[]) /* Restore state in a new VM. */ vcpu = vm_recreate_with_one_vcpu(vm); vcpu_load_state(vcpu, state); - run = vcpu->run; kvm_x86_state_cleanup(state); memset(®s2, 0, sizeof(regs2)); diff --git a/tools/testing/selftests/kvm/x86_64/vmx_tsc_adjust_test.c b/tools/testing/selftests/kvm/x86_64/vmx_tsc_adjust_test.c index ff8ecdf32ae07..2ceb5c78c4427 100644 --- a/tools/testing/selftests/kvm/x86_64/vmx_tsc_adjust_test.c +++ b/tools/testing/selftests/kvm/x86_64/vmx_tsc_adjust_test.c @@ -131,14 +131,10 @@ int main(int argc, char *argv[]) vcpu_args_set(vcpu, 1, vmx_pages_gva); for (;;) { - volatile struct kvm_run *run = vcpu->run; struct ucall uc; vcpu_run(vcpu); - TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, - "Got exit_reason other than KVM_EXIT_IO: %u (%s)\n", - run->exit_reason, - exit_reason_str(run->exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); switch (get_ucall(vcpu, &uc)) { case UCALL_ABORT: diff --git a/tools/testing/selftests/kvm/x86_64/xapic_ipi_test.c b/tools/testing/selftests/kvm/x86_64/xapic_ipi_test.c index 3d272d7f961ef..67ac2a3292efd 100644 --- a/tools/testing/selftests/kvm/x86_64/xapic_ipi_test.c +++ b/tools/testing/selftests/kvm/x86_64/xapic_ipi_test.c @@ -198,7 +198,6 @@ static void *vcpu_thread(void *arg) struct ucall uc; int old; int r; - unsigned int exit_reason; r = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &old); TEST_ASSERT(r == 0, @@ -207,11 +206,8 @@ static void *vcpu_thread(void *arg) fprintf(stderr, "vCPU thread running vCPU %u\n", vcpu->id); vcpu_run(vcpu); - exit_reason = vcpu->run->exit_reason; - TEST_ASSERT(exit_reason == KVM_EXIT_IO, - "vCPU %u exited with unexpected exit reason %u-%s, expected KVM_EXIT_IO", - vcpu->id, exit_reason, exit_reason_str(exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); if (get_ucall(vcpu, &uc) == UCALL_ABORT) { TEST_ASSERT(false, diff --git a/tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c b/tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c index d42701dfbd83a..05898ad9f4d99 100644 --- a/tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c +++ b/tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c @@ -622,15 +622,10 @@ int main(int argc, char *argv[]) bool evtchn_irq_expected = false; for (;;) { - volatile struct kvm_run *run = vcpu->run; struct ucall uc; vcpu_run(vcpu); - - TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, - "Got exit_reason other than KVM_EXIT_IO: %u (%s)\n", - run->exit_reason, - exit_reason_str(run->exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); switch (get_ucall(vcpu, &uc)) { case UCALL_ABORT: diff --git a/tools/testing/selftests/kvm/x86_64/xen_vmcall_test.c b/tools/testing/selftests/kvm/x86_64/xen_vmcall_test.c index 88914d48c65ed..c94cde3b523f2 100644 --- a/tools/testing/selftests/kvm/x86_64/xen_vmcall_test.c +++ b/tools/testing/selftests/kvm/x86_64/xen_vmcall_test.c @@ -122,10 +122,7 @@ int main(int argc, char *argv[]) continue; } - TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, - "Got exit_reason other than KVM_EXIT_IO: %u (%s)\n", - run->exit_reason, - exit_reason_str(run->exit_reason)); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); switch (get_ucall(vcpu, &uc)) { case UCALL_ABORT: From 6f974494b8077bb1a2a10fe33f62c143f246f102 Mon Sep 17 00:00:00 2001 From: Vipin Sharma Date: Fri, 3 Feb 2023 17:45:45 -0800 Subject: [PATCH 322/460] KVM: selftests: Print expected and actual exit reason in KVM exit reason assert Print what KVM exit reason a test was expecting and what it actually got int TEST_ASSERT_KVM_EXIT_REASON(). Signed-off-by: Vipin Sharma Message-Id: <20230204014547.583711-3-vipinsh@google.com> Signed-off-by: Paolo Bonzini --- tools/testing/selftests/kvm/include/test_util.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/kvm/include/test_util.h b/tools/testing/selftests/kvm/include/test_util.h index a13663557e2b0..a6e9f215ce700 100644 --- a/tools/testing/selftests/kvm/include/test_util.h +++ b/tools/testing/selftests/kvm/include/test_util.h @@ -67,7 +67,8 @@ void test_assert(bool exp, const char *exp_str, __u32 exit_reason = (vcpu)->run->exit_reason; \ \ TEST_ASSERT(exit_reason == (expected), \ - "Unexpected exit reason: %u (%s)", \ + "Wanted KVM exit reason: %u (%s), got: %u (%s)", \ + (expected), exit_reason_str((expected)), \ exit_reason, exit_reason_str(exit_reason)); \ } while (0) From 1b3d660e5d7b8b408a2b0988de65672199ebfaf2 Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Fri, 3 Feb 2023 17:45:46 -0800 Subject: [PATCH 323/460] KVM: selftests: Add macro to generate KVM exit reason strings Add and use a macro to generate the KVM exit reason strings array instead of relying on developers to correctly copy+paste+edit each string. Signed-off-by: Sean Christopherson Message-Id: <20230204014547.583711-4-vipinsh@google.com> Signed-off-by: Paolo Bonzini --- tools/testing/selftests/kvm/lib/kvm_util.c | 54 +++++++++++----------- 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c index 3ea24a5f4c43e..942f092a8e7d3 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -1815,38 +1815,40 @@ void vm_dump(FILE *stream, struct kvm_vm *vm, uint8_t indent) vcpu_dump(stream, vcpu, indent + 2); } +#define KVM_EXIT_STRING(x) {KVM_EXIT_##x, #x} + /* Known KVM exit reasons */ static struct exit_reason { unsigned int reason; const char *name; } exit_reasons_known[] = { - {KVM_EXIT_UNKNOWN, "UNKNOWN"}, - {KVM_EXIT_EXCEPTION, "EXCEPTION"}, - {KVM_EXIT_IO, "IO"}, - {KVM_EXIT_HYPERCALL, "HYPERCALL"}, - {KVM_EXIT_DEBUG, "DEBUG"}, - {KVM_EXIT_HLT, "HLT"}, - {KVM_EXIT_MMIO, "MMIO"}, - {KVM_EXIT_IRQ_WINDOW_OPEN, "IRQ_WINDOW_OPEN"}, - {KVM_EXIT_SHUTDOWN, "SHUTDOWN"}, - {KVM_EXIT_FAIL_ENTRY, "FAIL_ENTRY"}, - {KVM_EXIT_INTR, "INTR"}, - {KVM_EXIT_SET_TPR, "SET_TPR"}, - {KVM_EXIT_TPR_ACCESS, "TPR_ACCESS"}, - {KVM_EXIT_S390_SIEIC, "S390_SIEIC"}, - {KVM_EXIT_S390_RESET, "S390_RESET"}, - {KVM_EXIT_DCR, "DCR"}, - {KVM_EXIT_NMI, "NMI"}, - {KVM_EXIT_INTERNAL_ERROR, "INTERNAL_ERROR"}, - {KVM_EXIT_OSI, "OSI"}, - {KVM_EXIT_PAPR_HCALL, "PAPR_HCALL"}, - {KVM_EXIT_DIRTY_RING_FULL, "DIRTY_RING_FULL"}, - {KVM_EXIT_X86_RDMSR, "RDMSR"}, - {KVM_EXIT_X86_WRMSR, "WRMSR"}, - {KVM_EXIT_XEN, "XEN"}, - {KVM_EXIT_HYPERV, "HYPERV"}, + KVM_EXIT_STRING(UNKNOWN), + KVM_EXIT_STRING(EXCEPTION), + KVM_EXIT_STRING(IO), + KVM_EXIT_STRING(HYPERCALL), + KVM_EXIT_STRING(DEBUG), + KVM_EXIT_STRING(HLT), + KVM_EXIT_STRING(MMIO), + KVM_EXIT_STRING(IRQ_WINDOW_OPEN), + KVM_EXIT_STRING(SHUTDOWN), + KVM_EXIT_STRING(FAIL_ENTRY), + KVM_EXIT_STRING(INTR), + KVM_EXIT_STRING(SET_TPR), + KVM_EXIT_STRING(TPR_ACCESS), + KVM_EXIT_STRING(S390_SIEIC), + KVM_EXIT_STRING(S390_RESET), + KVM_EXIT_STRING(DCR), + KVM_EXIT_STRING(NMI), + KVM_EXIT_STRING(INTERNAL_ERROR), + KVM_EXIT_STRING(OSI), + KVM_EXIT_STRING(PAPR_HCALL), + KVM_EXIT_STRING(DIRTY_RING_FULL), + KVM_EXIT_STRING(X86_RDMSR), + KVM_EXIT_STRING(X86_WRMSR), + KVM_EXIT_STRING(XEN), + KVM_EXIT_STRING(HYPERV), #ifdef KVM_EXIT_MEMORY_NOT_PRESENT - {KVM_EXIT_MEMORY_NOT_PRESENT, "MEMORY_NOT_PRESENT"}, + KVM_EXIT_STRING(MEMORY_NOT_PRESENT), #endif }; From f3e707413dbe3920a972d0c2b51175180e7de36b Mon Sep 17 00:00:00 2001 From: Vipin Sharma Date: Fri, 3 Feb 2023 17:45:47 -0800 Subject: [PATCH 324/460] KVM: selftests: Sync KVM exit reasons in selftests Add missing KVM_EXIT_* reasons in KVM selftests from include/uapi/linux/kvm.h Signed-off-by: Vipin Sharma Message-Id: <20230204014547.583711-5-vipinsh@google.com> Signed-off-by: Paolo Bonzini --- tools/testing/selftests/kvm/lib/kvm_util.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c index 942f092a8e7d3..8ec20ac33de02 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -1842,11 +1842,24 @@ static struct exit_reason { KVM_EXIT_STRING(INTERNAL_ERROR), KVM_EXIT_STRING(OSI), KVM_EXIT_STRING(PAPR_HCALL), - KVM_EXIT_STRING(DIRTY_RING_FULL), + KVM_EXIT_STRING(S390_UCONTROL), + KVM_EXIT_STRING(WATCHDOG), + KVM_EXIT_STRING(S390_TSCH), + KVM_EXIT_STRING(EPR), + KVM_EXIT_STRING(SYSTEM_EVENT), + KVM_EXIT_STRING(S390_STSI), + KVM_EXIT_STRING(IOAPIC_EOI), + KVM_EXIT_STRING(HYPERV), + KVM_EXIT_STRING(ARM_NISV), KVM_EXIT_STRING(X86_RDMSR), KVM_EXIT_STRING(X86_WRMSR), + KVM_EXIT_STRING(DIRTY_RING_FULL), + KVM_EXIT_STRING(AP_RESET_HOLD), + KVM_EXIT_STRING(X86_BUS_LOCK), KVM_EXIT_STRING(XEN), - KVM_EXIT_STRING(HYPERV), + KVM_EXIT_STRING(RISCV_SBI), + KVM_EXIT_STRING(RISCV_CSR), + KVM_EXIT_STRING(NOTIFY), #ifdef KVM_EXIT_MEMORY_NOT_PRESENT KVM_EXIT_STRING(MEMORY_NOT_PRESENT), #endif From 934ef33ee75c3846f605f18b65048acd147e3918 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Mon, 13 Mar 2023 15:45:48 +0100 Subject: [PATCH 325/460] x86/PVH: obtain VGA console info in Dom0 A new platform-op was added to Xen to allow obtaining the same VGA console information PV Dom0 is handed. Invoke the new function and have the output data processed by xen_init_vga(). Signed-off-by: Jan Beulich Reviewed-by: Juergen Gross Link: https://lore.kernel.org/r/8f315e92-7bda-c124-71cc-478ab9c5e610@suse.com Signed-off-by: Juergen Gross --- arch/x86/xen/Makefile | 2 +- arch/x86/xen/enlighten_pv.c | 3 ++- arch/x86/xen/enlighten_pvh.c | 13 +++++++++++++ arch/x86/xen/vga.c | 5 ++--- arch/x86/xen/xen-ops.h | 7 ++++--- include/xen/interface/platform.h | 3 +++ 6 files changed, 25 insertions(+), 8 deletions(-) diff --git a/arch/x86/xen/Makefile b/arch/x86/xen/Makefile index 3c5b52fbe4a7f..a9ec8c9f5c5dd 100644 --- a/arch/x86/xen/Makefile +++ b/arch/x86/xen/Makefile @@ -45,6 +45,6 @@ obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= spinlock.o obj-$(CONFIG_XEN_DEBUG_FS) += debugfs.o -obj-$(CONFIG_XEN_PV_DOM0) += vga.o +obj-$(CONFIG_XEN_DOM0) += vga.o obj-$(CONFIG_XEN_EFI) += efi.o diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c index 5b13796628770..68f5f5d209dfa 100644 --- a/arch/x86/xen/enlighten_pv.c +++ b/arch/x86/xen/enlighten_pv.c @@ -1389,7 +1389,8 @@ asmlinkage __visible void __init xen_start_kernel(struct start_info *si) x86_platform.set_legacy_features = xen_dom0_set_legacy_features; - xen_init_vga(info, xen_start_info->console.dom0.info_size); + xen_init_vga(info, xen_start_info->console.dom0.info_size, + &boot_params.screen_info); xen_start_info->console.domU.mfn = 0; xen_start_info->console.domU.evtchn = 0; diff --git a/arch/x86/xen/enlighten_pvh.c b/arch/x86/xen/enlighten_pvh.c index bcae606bbc5cf..1da44aca896c6 100644 --- a/arch/x86/xen/enlighten_pvh.c +++ b/arch/x86/xen/enlighten_pvh.c @@ -43,6 +43,19 @@ void __init xen_pvh_init(struct boot_params *boot_params) x86_init.oem.banner = xen_banner; xen_efi_init(boot_params); + + if (xen_initial_domain()) { + struct xen_platform_op op = { + .cmd = XENPF_get_dom0_console, + }; + long ret = HYPERVISOR_platform_op(&op); + + if (ret > 0) + xen_init_vga(&op.u.dom0_console, + min(ret * sizeof(char), + sizeof(op.u.dom0_console)), + &boot_params->screen_info); + } } void __init mem_map_via_hcall(struct boot_params *boot_params_p) diff --git a/arch/x86/xen/vga.c b/arch/x86/xen/vga.c index 14ea32e734d59..d97adab8420f4 100644 --- a/arch/x86/xen/vga.c +++ b/arch/x86/xen/vga.c @@ -9,10 +9,9 @@ #include "xen-ops.h" -void __init xen_init_vga(const struct dom0_vga_console_info *info, size_t size) +void __init xen_init_vga(const struct dom0_vga_console_info *info, size_t size, + struct screen_info *screen_info) { - struct screen_info *screen_info = &boot_params.screen_info; - /* This is drawn from a dump from vgacon:startup in * standard Linux. */ screen_info->orig_video_mode = 3; diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h index 9a8bb972193d8..a10903785a338 100644 --- a/arch/x86/xen/xen-ops.h +++ b/arch/x86/xen/xen-ops.h @@ -108,11 +108,12 @@ static inline void xen_uninit_lock_cpu(int cpu) struct dom0_vga_console_info; -#ifdef CONFIG_XEN_PV_DOM0 -void __init xen_init_vga(const struct dom0_vga_console_info *, size_t size); +#ifdef CONFIG_XEN_DOM0 +void __init xen_init_vga(const struct dom0_vga_console_info *, size_t size, + struct screen_info *); #else static inline void __init xen_init_vga(const struct dom0_vga_console_info *info, - size_t size) + size_t size, struct screen_info *si) { } #endif diff --git a/include/xen/interface/platform.h b/include/xen/interface/platform.h index 655d92e803e14..79a443c65ea93 100644 --- a/include/xen/interface/platform.h +++ b/include/xen/interface/platform.h @@ -483,6 +483,8 @@ struct xenpf_symdata { }; DEFINE_GUEST_HANDLE_STRUCT(xenpf_symdata); +#define XENPF_get_dom0_console 64 + struct xen_platform_op { uint32_t cmd; uint32_t interface_version; /* XENPF_INTERFACE_VERSION */ @@ -506,6 +508,7 @@ struct xen_platform_op { struct xenpf_mem_hotadd mem_add; struct xenpf_core_parking core_parking; struct xenpf_symdata symdata; + struct dom0_vga_console_info dom0_console; uint8_t pad[128]; } u; }; From b4ee9606378bb9520c94d8b96f0305c3696f5c29 Mon Sep 17 00:00:00 2001 From: Xiaogang Chen Date: Wed, 1 Mar 2023 10:21:06 -0600 Subject: [PATCH 326/460] drm/amdkfd: Fix BO offset for multi-VMA page migration svm_migrate_ram_to_vram migrates a prange from sys ram to vram. The prange may cross multiple vma. Need remember current dst vram offset in the TTM resource for each migration. v2: squash in warning fix (Alex) Signed-off-by: Xiaogang Chen Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_migrate.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c index de8ce72344fc5..391da6acb3e5a 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c @@ -289,7 +289,7 @@ static unsigned long svm_migrate_unsuccessful_pages(struct migrate_vma *migrate) static int svm_migrate_copy_to_vram(struct amdgpu_device *adev, struct svm_range *prange, struct migrate_vma *migrate, struct dma_fence **mfence, - dma_addr_t *scratch) + dma_addr_t *scratch, uint64_t ttm_res_offset) { uint64_t npages = migrate->npages; struct device *dev = adev->dev; @@ -299,8 +299,8 @@ svm_migrate_copy_to_vram(struct amdgpu_device *adev, struct svm_range *prange, uint64_t i, j; int r; - pr_debug("svms 0x%p [0x%lx 0x%lx]\n", prange->svms, prange->start, - prange->last); + pr_debug("svms 0x%p [0x%lx 0x%lx 0x%llx]\n", prange->svms, prange->start, + prange->last, ttm_res_offset); src = scratch; dst = (uint64_t *)(scratch + npages); @@ -311,7 +311,7 @@ svm_migrate_copy_to_vram(struct amdgpu_device *adev, struct svm_range *prange, goto out; } - amdgpu_res_first(prange->ttm_res, prange->offset << PAGE_SHIFT, + amdgpu_res_first(prange->ttm_res, ttm_res_offset, npages << PAGE_SHIFT, &cursor); for (i = j = 0; i < npages; i++) { struct page *spage; @@ -398,7 +398,7 @@ svm_migrate_copy_to_vram(struct amdgpu_device *adev, struct svm_range *prange, static long svm_migrate_vma_to_vram(struct amdgpu_device *adev, struct svm_range *prange, struct vm_area_struct *vma, uint64_t start, - uint64_t end, uint32_t trigger) + uint64_t end, uint32_t trigger, uint64_t ttm_res_offset) { struct kfd_process *p = container_of(prange->svms, struct kfd_process, svms); uint64_t npages = (end - start) >> PAGE_SHIFT; @@ -451,7 +451,7 @@ svm_migrate_vma_to_vram(struct amdgpu_device *adev, struct svm_range *prange, else pr_debug("0x%lx pages migrated\n", cpages); - r = svm_migrate_copy_to_vram(adev, prange, &migrate, &mfence, scratch); + r = svm_migrate_copy_to_vram(adev, prange, &migrate, &mfence, scratch, ttm_res_offset); migrate_vma_pages(&migrate); pr_debug("successful/cpages/npages 0x%lx/0x%lx/0x%lx\n", @@ -499,6 +499,7 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t best_loc, unsigned long addr, start, end; struct vm_area_struct *vma; struct amdgpu_device *adev; + uint64_t ttm_res_offset; unsigned long cpages = 0; long r = 0; @@ -519,6 +520,7 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t best_loc, start = prange->start << PAGE_SHIFT; end = (prange->last + 1) << PAGE_SHIFT; + ttm_res_offset = prange->offset << PAGE_SHIFT; for (addr = start; addr < end;) { unsigned long next; @@ -528,13 +530,14 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t best_loc, break; next = min(vma->vm_end, end); - r = svm_migrate_vma_to_vram(adev, prange, vma, addr, next, trigger); + r = svm_migrate_vma_to_vram(adev, prange, vma, addr, next, trigger, ttm_res_offset); if (r < 0) { pr_debug("failed %ld to migrate\n", r); break; } else { cpages += r; } + ttm_res_offset += next - addr; addr = next; } From 8eeddc0d4200762063e1c66b9cc63afa7b24ebf0 Mon Sep 17 00:00:00 2001 From: Xiaogang Chen Date: Thu, 9 Mar 2023 17:44:55 -0600 Subject: [PATCH 327/460] drm/amdkfd: Get prange->offset after svm_range_vram_node_new During miration to vram prange->offset is valid after vram buffer is located, either use old one or allocate a new one. Move svm_range_vram_node_new before migrate for each vma to get valid prange->offset. v2: squash in warning fix Fixes: b4ee9606378b ("drm/amdkfd: Fix BO offset for multi-VMA page migration") Signed-off-by: Xiaogang Chen Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_migrate.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c index 391da6acb3e5a..54933903bcb8a 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c @@ -305,12 +305,6 @@ svm_migrate_copy_to_vram(struct amdgpu_device *adev, struct svm_range *prange, src = scratch; dst = (uint64_t *)(scratch + npages); - r = svm_range_vram_node_new(adev, prange, true); - if (r) { - dev_dbg(adev->dev, "fail %d to alloc vram\n", r); - goto out; - } - amdgpu_res_first(prange->ttm_res, ttm_res_offset, npages << PAGE_SHIFT, &cursor); for (i = j = 0; i < npages; i++) { @@ -391,7 +385,7 @@ svm_migrate_copy_to_vram(struct amdgpu_device *adev, struct svm_range *prange, migrate->dst[i + 3] = 0; } #endif -out: + return r; } @@ -520,6 +514,12 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t best_loc, start = prange->start << PAGE_SHIFT; end = (prange->last + 1) << PAGE_SHIFT; + + r = svm_range_vram_node_new(adev, prange, true); + if (r) { + dev_dbg(adev->dev, "fail %ld to alloc vram\n", r); + return r; + } ttm_res_offset = prange->offset << PAGE_SHIFT; for (addr = start; addr < end;) { @@ -543,6 +543,8 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t best_loc, if (cpages) prange->actual_loc = best_loc; + else + svm_range_vram_node_free(prange); return r < 0 ? r : 0; } From b2ca5c5d416b4e72d1e9d0293fc720e2d525fd42 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Tue, 7 Mar 2023 16:19:02 -0800 Subject: [PATCH 328/460] drm/amdkfd: fix a potential double free in pqm_create_queue Set *q to NULL on errors, otherwise pqm_create_queue would free it again. Signed-off-by: Chia-I Wu Signed-off-by: Felix Kuehling Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c index 5137476ec18e6..4236539d9f932 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c @@ -218,8 +218,8 @@ static int init_user_queue(struct process_queue_manager *pqm, return 0; cleanup: - if (dev->shared_resources.enable_mes) - uninit_queue(*q); + uninit_queue(*q); + *q = NULL; return retval; } From ab9bdb1213b4b40942af6a383f555d0c14874c1b Mon Sep 17 00:00:00 2001 From: Tim Huang Date: Wed, 1 Mar 2023 10:53:03 +0800 Subject: [PATCH 329/460] drm/amd/pm: bump SMU 13.0.4 driver_if header version Align the SMU driver interface version with PMFW to suppress the version mismatch message on driver loading. Signed-off-by: Tim Huang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org # 6.1.x --- .../drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_4.h | 4 ++-- drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_4.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_4.h index f77401709d83c..2162ecd1057d1 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_4.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_4.h @@ -27,7 +27,7 @@ // *** IMPORTANT *** // SMU TEAM: Always increment the interface version if // any structure is changed in this file -#define PMFW_DRIVER_IF_VERSION 7 +#define PMFW_DRIVER_IF_VERSION 8 typedef struct { int32_t value; @@ -198,7 +198,7 @@ typedef struct { uint16_t SkinTemp; uint16_t DeviceState; uint16_t CurTemp; //[centi-Celsius] - uint16_t spare2; + uint16_t FilterAlphaValue; uint16_t AverageGfxclkFrequency; uint16_t AverageFclkFrequency; diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h index 1c0ae2cb757b8..f085cb97a6206 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h @@ -29,7 +29,7 @@ #define SMU13_DRIVER_IF_VERSION_YELLOW_CARP 0x04 #define SMU13_DRIVER_IF_VERSION_ALDE 0x08 #define SMU13_DRIVER_IF_VERSION_SMU_V13_0_0_0 0x37 -#define SMU13_DRIVER_IF_VERSION_SMU_V13_0_4 0x07 +#define SMU13_DRIVER_IF_VERSION_SMU_V13_0_4 0x08 #define SMU13_DRIVER_IF_VERSION_SMU_V13_0_5 0x04 #define SMU13_DRIVER_IF_VERSION_SMU_V13_0_0_10 0x32 #define SMU13_DRIVER_IF_VERSION_SMU_V13_0_7 0x37 From a9386ee9681585794dbab95d4ce6826f73d19af6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C5=82a=C5=BCej=20Szczygie=C5=82?= Date: Sun, 5 Mar 2023 00:44:31 +0100 Subject: [PATCH 330/460] drm/amd/pm: Fix sienna cichlid incorrect OD volage after resume MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Always setup overdrive tables after resume. Preserve only some user-defined settings in user_overdrive_table if they're set. Copy restored user_overdrive_table into od_table to get correct values. On cold boot, BTC was triggered and GfxVfCurve was calibrated. We got VfCurve settings (a). On resuming back, BTC will be triggered again and GfxVfCurve will be recalibrated. VfCurve settings (b) got may be different from those of cold boot. So if we reuse those VfCurve settings (a) got on cold boot on suspend, we can run into discrepencies. Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/1897 Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/2276 Reviewed-by: Evan Quan Signed-off-by: Błażej Szczygieł Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- .../amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 43 ++++++++++++++----- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index 697e98a0a20ab..75f18681e984c 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -2143,16 +2143,9 @@ static int sienna_cichlid_set_default_od_settings(struct smu_context *smu) (OverDriveTable_t *)smu->smu_table.boot_overdrive_table; OverDriveTable_t *user_od_table = (OverDriveTable_t *)smu->smu_table.user_overdrive_table; + OverDriveTable_t user_od_table_bak; int ret = 0; - /* - * For S3/S4/Runpm resume, no need to setup those overdrive tables again as - * - either they already have the default OD settings got during cold bootup - * - or they have some user customized OD settings which cannot be overwritten - */ - if (smu->adev->in_suspend) - return 0; - ret = smu_cmn_update_table(smu, SMU_TABLE_OVERDRIVE, 0, (void *)boot_od_table, false); if (ret) { @@ -2163,7 +2156,23 @@ static int sienna_cichlid_set_default_od_settings(struct smu_context *smu) sienna_cichlid_dump_od_table(smu, boot_od_table); memcpy(od_table, boot_od_table, sizeof(OverDriveTable_t)); - memcpy(user_od_table, boot_od_table, sizeof(OverDriveTable_t)); + + /* + * For S3/S4/Runpm resume, we need to setup those overdrive tables again, + * but we have to preserve user defined values in "user_od_table". + */ + if (!smu->adev->in_suspend) { + memcpy(user_od_table, boot_od_table, sizeof(OverDriveTable_t)); + smu->user_dpm_profile.user_od = false; + } else if (smu->user_dpm_profile.user_od) { + memcpy(&user_od_table_bak, user_od_table, sizeof(OverDriveTable_t)); + memcpy(user_od_table, boot_od_table, sizeof(OverDriveTable_t)); + user_od_table->GfxclkFmin = user_od_table_bak.GfxclkFmin; + user_od_table->GfxclkFmax = user_od_table_bak.GfxclkFmax; + user_od_table->UclkFmin = user_od_table_bak.UclkFmin; + user_od_table->UclkFmax = user_od_table_bak.UclkFmax; + user_od_table->VddGfxOffset = user_od_table_bak.VddGfxOffset; + } return 0; } @@ -2373,6 +2382,20 @@ static int sienna_cichlid_od_edit_dpm_table(struct smu_context *smu, return ret; } +static int sienna_cichlid_restore_user_od_settings(struct smu_context *smu) +{ + struct smu_table_context *table_context = &smu->smu_table; + OverDriveTable_t *od_table = table_context->overdrive_table; + OverDriveTable_t *user_od_table = table_context->user_overdrive_table; + int res; + + res = smu_v11_0_restore_user_od_settings(smu); + if (res == 0) + memcpy(od_table, user_od_table, sizeof(OverDriveTable_t)); + + return res; +} + static int sienna_cichlid_run_btc(struct smu_context *smu) { int res; @@ -4400,7 +4423,7 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = { .set_soft_freq_limited_range = smu_v11_0_set_soft_freq_limited_range, .set_default_od_settings = sienna_cichlid_set_default_od_settings, .od_edit_dpm_table = sienna_cichlid_od_edit_dpm_table, - .restore_user_od_settings = smu_v11_0_restore_user_od_settings, + .restore_user_od_settings = sienna_cichlid_restore_user_od_settings, .run_btc = sienna_cichlid_run_btc, .set_power_source = smu_v11_0_set_power_source, .get_pp_feature_mask = smu_cmn_get_pp_feature_mask, From d71e38df3b730a17ab6b25cabb2ccfe8a7f04385 Mon Sep 17 00:00:00 2001 From: Jane Jian Date: Tue, 28 Feb 2023 18:48:41 +0800 Subject: [PATCH 331/460] drm/amdgpu/vcn: custom video info caps for sriov for sriov, we added a new flag to indicate av1 support, this will override the original caps info. Signed-off-by: Jane Jian Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h | 4 + drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h | 3 +- drivers/gpu/drm/amd/amdgpu/soc21.c | 103 ++++++++++++++++++-- 3 files changed, 99 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h index b9e9480448afe..4f7bab52282ac 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h @@ -124,6 +124,8 @@ enum AMDGIM_FEATURE_FLAG { AMDGIM_FEATURE_PP_ONE_VF = (1 << 4), /* Indirect Reg Access enabled */ AMDGIM_FEATURE_INDIRECT_REG_ACCESS = (1 << 5), + /* AV1 Support MODE*/ + AMDGIM_FEATURE_AV1_SUPPORT = (1 << 6), }; enum AMDGIM_REG_ACCESS_FLAG { @@ -322,6 +324,8 @@ static inline bool is_virtual_machine(void) ((!amdgpu_in_reset(adev)) && adev->virt.tdr_debug) #define amdgpu_sriov_is_normal(adev) \ ((!amdgpu_in_reset(adev)) && (!adev->virt.tdr_debug)) +#define amdgpu_sriov_is_av1_support(adev) \ + ((adev)->virt.gim_feature & AMDGIM_FEATURE_AV1_SUPPORT) bool amdgpu_virt_mmio_blocked(struct amdgpu_device *adev); void amdgpu_virt_init_setting(struct amdgpu_device *adev); void amdgpu_virt_kiq_reg_write_reg_wait(struct amdgpu_device *adev, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h b/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h index 6c97148ca0ed3..24d42d24e6a01 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h @@ -93,7 +93,8 @@ union amd_sriov_msg_feature_flags { uint32_t mm_bw_management : 1; uint32_t pp_one_vf_mode : 1; uint32_t reg_indirect_acc : 1; - uint32_t reserved : 26; + uint32_t av1_support : 1; + uint32_t reserved : 25; } flags; uint32_t all; }; diff --git a/drivers/gpu/drm/amd/amdgpu/soc21.c b/drivers/gpu/drm/amd/amdgpu/soc21.c index 061793d390ccc..c82b3a7ea5f08 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc21.c +++ b/drivers/gpu/drm/amd/amdgpu/soc21.c @@ -102,6 +102,59 @@ static const struct amdgpu_video_codecs vcn_4_0_0_video_codecs_decode_vcn1 = .codec_array = vcn_4_0_0_video_codecs_decode_array_vcn1, }; +/* SRIOV SOC21, not const since data is controlled by host */ +static struct amdgpu_video_codec_info sriov_vcn_4_0_0_video_codecs_encode_array_vcn0[] = { + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 2304, 0)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 4096, 2304, 0)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_AV1, 8192, 4352, 0)}, +}; + +static struct amdgpu_video_codec_info sriov_vcn_4_0_0_video_codecs_encode_array_vcn1[] = { + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 2304, 0)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 4096, 2304, 0)}, +}; + +static struct amdgpu_video_codecs sriov_vcn_4_0_0_video_codecs_encode_vcn0 = { + .codec_count = ARRAY_SIZE(sriov_vcn_4_0_0_video_codecs_encode_array_vcn0), + .codec_array = sriov_vcn_4_0_0_video_codecs_encode_array_vcn0, +}; + +static struct amdgpu_video_codecs sriov_vcn_4_0_0_video_codecs_encode_vcn1 = { + .codec_count = ARRAY_SIZE(sriov_vcn_4_0_0_video_codecs_encode_array_vcn1), + .codec_array = sriov_vcn_4_0_0_video_codecs_encode_array_vcn1, +}; + +static struct amdgpu_video_codec_info sriov_vcn_4_0_0_video_codecs_decode_array_vcn0[] = { + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 4096, 4096, 3)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4, 4096, 4096, 5)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 52)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 4096, 4096, 4)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 8192, 4352, 186)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 4096, 4096, 0)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VP9, 8192, 4352, 0)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_AV1, 8192, 4352, 0)}, +}; + +static struct amdgpu_video_codec_info sriov_vcn_4_0_0_video_codecs_decode_array_vcn1[] = { + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 4096, 4096, 3)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4, 4096, 4096, 5)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 52)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 4096, 4096, 4)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 8192, 4352, 186)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 4096, 4096, 0)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VP9, 8192, 4352, 0)}, +}; + +static struct amdgpu_video_codecs sriov_vcn_4_0_0_video_codecs_decode_vcn0 = { + .codec_count = ARRAY_SIZE(sriov_vcn_4_0_0_video_codecs_decode_array_vcn0), + .codec_array = sriov_vcn_4_0_0_video_codecs_decode_array_vcn0, +}; + +static struct amdgpu_video_codecs sriov_vcn_4_0_0_video_codecs_decode_vcn1 = { + .codec_count = ARRAY_SIZE(sriov_vcn_4_0_0_video_codecs_decode_array_vcn1), + .codec_array = sriov_vcn_4_0_0_video_codecs_decode_array_vcn1, +}; + static int soc21_query_video_codecs(struct amdgpu_device *adev, bool encode, const struct amdgpu_video_codecs **codecs) { @@ -112,16 +165,31 @@ static int soc21_query_video_codecs(struct amdgpu_device *adev, bool encode, 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; - else - *codecs = &vcn_4_0_0_video_codecs_decode_vcn1; + if (amdgpu_sriov_vf(adev)) { + if ((adev->vcn.harvest_config & AMDGPU_VCN_HARVEST_VCN0) || + !amdgpu_sriov_is_av1_support(adev)) { + if (encode) + *codecs = &sriov_vcn_4_0_0_video_codecs_encode_vcn1; + else + *codecs = &sriov_vcn_4_0_0_video_codecs_decode_vcn1; + } else { + if (encode) + *codecs = &sriov_vcn_4_0_0_video_codecs_encode_vcn0; + else + *codecs = &sriov_vcn_4_0_0_video_codecs_decode_vcn0; + } } else { - if (encode) - *codecs = &vcn_4_0_0_video_codecs_encode_vcn0; - else - *codecs = &vcn_4_0_0_video_codecs_decode_vcn0; + if ((adev->vcn.harvest_config & AMDGPU_VCN_HARVEST_VCN0)) { + if (encode) + *codecs = &vcn_4_0_0_video_codecs_encode_vcn1; + else + *codecs = &vcn_4_0_0_video_codecs_decode_vcn1; + } else { + if (encode) + *codecs = &vcn_4_0_0_video_codecs_encode_vcn0; + else + *codecs = &vcn_4_0_0_video_codecs_decode_vcn0; + } } return 0; default: @@ -730,8 +798,23 @@ static int soc21_common_late_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; - if (amdgpu_sriov_vf(adev)) + if (amdgpu_sriov_vf(adev)) { xgpu_nv_mailbox_get_irq(adev); + if ((adev->vcn.harvest_config & AMDGPU_VCN_HARVEST_VCN0) || + !amdgpu_sriov_is_av1_support(adev)) { + amdgpu_virt_update_sriov_video_codec(adev, + sriov_vcn_4_0_0_video_codecs_encode_array_vcn1, + ARRAY_SIZE(sriov_vcn_4_0_0_video_codecs_encode_array_vcn1), + sriov_vcn_4_0_0_video_codecs_decode_array_vcn1, + ARRAY_SIZE(sriov_vcn_4_0_0_video_codecs_decode_array_vcn1)); + } else { + amdgpu_virt_update_sriov_video_codec(adev, + sriov_vcn_4_0_0_video_codecs_encode_array_vcn0, + ARRAY_SIZE(sriov_vcn_4_0_0_video_codecs_encode_array_vcn0), + sriov_vcn_4_0_0_video_codecs_decode_array_vcn0, + ARRAY_SIZE(sriov_vcn_4_0_0_video_codecs_decode_array_vcn0)); + } + } return 0; } From 9da050b0d9e04439d225a2ec3044af70cdfb3933 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Wed, 8 Mar 2023 13:37:24 -0800 Subject: [PATCH 332/460] drm/amdkfd: fix potential kgd_mem UAFs kgd_mem pointers returned by kfd_process_device_translate_handle are only guaranteed to be valid while p->mutex is held. As soon as the mutex is unlocked, another thread can free the BO. Signed-off-by: Chia-I Wu Signed-off-by: Felix Kuehling Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index a0e30f21e12e7..de310ed367ca1 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -1312,14 +1312,14 @@ static int kfd_ioctl_map_memory_to_gpu(struct file *filep, args->n_success = i+1; } - mutex_unlock(&p->mutex); - err = amdgpu_amdkfd_gpuvm_sync_memory(dev->adev, (struct kgd_mem *) mem, true); if (err) { pr_debug("Sync memory failed, wait interrupted by user signal\n"); goto sync_memory_failed; } + mutex_unlock(&p->mutex); + /* Flush TLBs after waiting for the page table updates to complete */ for (i = 0; i < args->n_devices; i++) { peer_pdd = kfd_process_device_data_by_id(p, devices_arr[i]); @@ -1335,9 +1335,9 @@ static int kfd_ioctl_map_memory_to_gpu(struct file *filep, bind_process_to_device_failed: get_mem_obj_from_handle_failed: map_memory_to_gpu_failed: +sync_memory_failed: mutex_unlock(&p->mutex); copy_from_user_failed: -sync_memory_failed: kfree(devices_arr); return err; @@ -1351,6 +1351,7 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file *filep, void *mem; long err = 0; uint32_t *devices_arr = NULL, i; + bool flush_tlb; if (!args->n_devices) { pr_debug("Device IDs array empty\n"); @@ -1403,16 +1404,19 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file *filep, } args->n_success = i+1; } - mutex_unlock(&p->mutex); - if (kfd_flush_tlb_after_unmap(pdd->dev)) { + flush_tlb = kfd_flush_tlb_after_unmap(pdd->dev); + if (flush_tlb) { err = amdgpu_amdkfd_gpuvm_sync_memory(pdd->dev->adev, (struct kgd_mem *) mem, true); if (err) { pr_debug("Sync memory failed, wait interrupted by user signal\n"); goto sync_memory_failed; } + } + mutex_unlock(&p->mutex); + if (flush_tlb) { /* Flush TLBs after waiting for the page table updates to complete */ for (i = 0; i < args->n_devices; i++) { peer_pdd = kfd_process_device_data_by_id(p, devices_arr[i]); @@ -1428,9 +1432,9 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file *filep, bind_process_to_device_failed: get_mem_obj_from_handle_failed: unmap_memory_from_gpu_failed: +sync_memory_failed: mutex_unlock(&p->mutex); copy_from_user_failed: -sync_memory_failed: kfree(devices_arr); return err; } From 728cefa53a36ba378ed4a7f31a0c08289687d824 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Fri, 17 Feb 2023 16:08:21 -0500 Subject: [PATCH 333/460] drm/amd/display: Fix HDCP failing to enable after suspend [Why] On resume some displays are not ready for HDCP, so they will fail if we start the hdcp authentintication too soon. Add a delay so that the displays can be ready before we start. NOTE: Previoulsy this delay was set to 3 seconds but it was causing issues with compliance, 2 seconds should enough for compliance and the s3 resume case. [How] Change the Delay to 2 seconds. Reviewed-by: Aurabindo Pillai Acked-by: Qingqing Zhuo Signed-off-by: Bhawanpreet Lakha Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c index 8e572f07ec476..4abfd2c9679f4 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c @@ -561,7 +561,7 @@ static void update_config(void *handle, struct cp_psp_stream_config *config) link->dp.mst_enabled = config->mst_enabled; link->dp.usb4_enabled = config->usb4_enabled; display->adjust.disable = MOD_HDCP_DISPLAY_DISABLE_AUTHENTICATION; - link->adjust.auth_delay = 0; + link->adjust.auth_delay = 2; link->adjust.hdcp1.disable = 0; conn_state = aconnector->base.state; From 3fadda5de8073e2cb65744803a6941736411d55b Mon Sep 17 00:00:00 2001 From: Guchun Chen Date: Thu, 9 Mar 2023 10:02:45 +0800 Subject: [PATCH 334/460] drm/amdgpu: move poll enabled/disable into non DC path Some amd asics having reliable hotplug support don't call drm_kms_helper_poll_init in driver init sequence. However, due to the unified suspend/resume path for all asics, because the output_poll_work->func is not set for these asics, a warning arrives when suspending. [ 90.656049] [ 90.656050] ? console_unlock+0x4d/0x100 [ 90.656053] ? __irq_work_queue_local+0x27/0x60 [ 90.656056] ? irq_work_queue+0x2b/0x50 [ 90.656057] ? __wake_up_klogd+0x40/0x60 [ 90.656059] __cancel_work_timer+0xed/0x180 [ 90.656061] drm_kms_helper_poll_disable.cold+0x1f/0x2c [drm_kms_helper] [ 90.656072] amdgpu_device_suspend+0x81/0x170 [amdgpu] [ 90.656180] amdgpu_pmops_runtime_suspend+0xb5/0x1b0 [amdgpu] [ 90.656269] pci_pm_runtime_suspend+0x61/0x1b0 drm_kms_helper_poll_enable/disable is valid when poll_init is called in amdgpu code, which is only used in non DC path. So move such codes into non-DC path code to get rid of such warnings. v1: introduce use_kms_poll flag in amdgpu as the poll stuff check v2: use dc_enabled as the flag to simply code v3: move code into non DC path instead of relying on any flag Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/2411 Fixes: a4e771729a51 ("drm/probe_helper: sort out poll_running vs poll_enabled") Reported-by: Bert Karwatzki Suggested-by: Dmitry Baryshkov Suggested-by: Alex Deucher Signed-off-by: Guchun Chen Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 4 ---- drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 4 ++++ 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index c4a4e2fe66814..da5b0258a237b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -4145,8 +4145,6 @@ int amdgpu_device_suspend(struct drm_device *dev, bool fbcon) if (amdgpu_acpi_smart_shift_update(dev, AMDGPU_SS_DEV_D3)) DRM_WARN("smart shift update failed\n"); - drm_kms_helper_poll_disable(dev); - if (fbcon) drm_fb_helper_set_suspend_unlocked(adev_to_drm(adev)->fb_helper, true); @@ -4243,8 +4241,6 @@ int amdgpu_device_resume(struct drm_device *dev, bool fbcon) if (fbcon) drm_fb_helper_set_suspend_unlocked(adev_to_drm(adev)->fb_helper, false); - drm_kms_helper_poll_enable(dev); - amdgpu_ras_resume(adev); if (adev->mode_info.num_crtc) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index 503f89a766c37..d60fe7eb5579a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -1618,6 +1618,8 @@ int amdgpu_display_suspend_helper(struct amdgpu_device *adev) struct drm_connector_list_iter iter; int r; + drm_kms_helper_poll_disable(dev); + /* turn off display hw */ drm_modeset_lock_all(dev); drm_connector_list_iter_begin(dev, &iter); @@ -1694,6 +1696,8 @@ int amdgpu_display_resume_helper(struct amdgpu_device *adev) drm_modeset_unlock_all(dev); + drm_kms_helper_poll_enable(dev); + return 0; } From 751281c55579f0cb0e56c9797d4663f689909681 Mon Sep 17 00:00:00 2001 From: Benjamin Cheng Date: Sun, 12 Mar 2023 20:47:39 -0400 Subject: [PATCH 335/460] drm/amd/display: Write to correct dirty_rect When FB_DAMAGE_CLIPS are provided in a non-MPO scenario, the loop does not use the counter i. This causes the fill_dc_dity_rect() to always fill dirty_rects[0], causing graphical artifacts when a damage clip aware DRM client sends more than 1 damage clip. Instead, use the flip_addrs->dirty_rect_count which is incremented by fill_dc_dirty_rect() on a successful fill. Fixes: 30ebe41582d1 ("drm/amd/display: add FB_DAMAGE_CLIPS support") Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/2453 Signed-off-by: Benjamin Cheng Signed-off-by: Hamza Mahfooz Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org # 6.1.x --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 009ef917dad47..32abbafd43fa4 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -5105,9 +5105,9 @@ static void fill_dc_dirty_rects(struct drm_plane *plane, for (; flip_addrs->dirty_rect_count < num_clips; clips++) fill_dc_dirty_rect(new_plane_state->plane, - &dirty_rects[i], clips->x1, - clips->y1, clips->x2 - clips->x1, - clips->y2 - clips->y1, + &dirty_rects[flip_addrs->dirty_rect_count], + clips->x1, clips->y1, + clips->x2 - clips->x1, clips->y2 - clips->y1, &flip_addrs->dirty_rect_count, false); return; From 45aa07fa832412f1de99194f37fd847915d7e0f6 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 8 Mar 2023 22:45:59 -0500 Subject: [PATCH 336/460] drm/amdgpu/nv: fix codec array for SR_IOV Copy paste error. Fixes: 384334120b66 ("drm/amdgpu/nv: don't expose AV1 if VCN0 is harvested") Reported-by: Abaci Robot Link: https://bugzilla.openanolis.cn/show_bug.cgi?id=4454 Cc: Jiapeng Chong Acked-by: Guchun Chen Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/nv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/nv.c b/drivers/gpu/drm/amd/amdgpu/nv.c index 855d390c41de1..22e25ca285f80 100644 --- a/drivers/gpu/drm/amd/amdgpu/nv.c +++ b/drivers/gpu/drm/amd/amdgpu/nv.c @@ -1055,8 +1055,8 @@ static int nv_common_late_init(void *handle) amdgpu_virt_update_sriov_video_codec(adev, sriov_sc_video_codecs_encode_array, ARRAY_SIZE(sriov_sc_video_codecs_encode_array), - sriov_sc_video_codecs_decode_array_vcn1, - ARRAY_SIZE(sriov_sc_video_codecs_decode_array_vcn1)); + sriov_sc_video_codecs_decode_array_vcn0, + ARRAY_SIZE(sriov_sc_video_codecs_decode_array_vcn0)); } } From 542a56e8eb4467ae654eefab31ff194569db39cd Mon Sep 17 00:00:00 2001 From: "Guilherme G. Piccoli" Date: Sun, 12 Mar 2023 13:51:00 -0300 Subject: [PATCH 337/460] drm/amdgpu/vcn: Disable indirect SRAM on Vangogh broken BIOSes The VCN firmware loading path enables the indirect SRAM mode if it's advertised as supported. We might have some cases of FW issues that prevents this mode to working properly though, ending-up in a failed probe. An example below, observed in the Steam Deck: [...] [drm] failed to load ucode VCN0_RAM(0x3A) [drm] psp gfx command LOAD_IP_FW(0x6) failed and response status is (0xFFFF0000) amdgpu 0000:04:00.0: [drm:amdgpu_ring_test_helper [amdgpu]] *ERROR* ring vcn_dec_0 test failed (-110) [drm:amdgpu_device_init.cold [amdgpu]] *ERROR* hw_init of IP block failed -110 amdgpu 0000:04:00.0: amdgpu: amdgpu_device_ip_init failed amdgpu 0000:04:00.0: amdgpu: Fatal error during GPU init [...] Disabling the VCN block circumvents this, but it's a very invasive workaround that turns off the entire feature. So, let's add a quirk on VCN loading that checks for known problematic BIOSes on Vangogh, so we can proactively disable the indirect SRAM mode and allow the HW proper probe and VCN IP block to work fine. Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/2385 Fixes: 82132ecc5432 ("drm/amdgpu: enable Vangogh VCN indirect sram mode") Cc: stable@vger.kernel.org Cc: James Zhu Cc: Leo Liu Signed-off-by: Guilherme G. Piccoli Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c index 25217b05c0ea8..e7974de8b035d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -114,6 +115,24 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev) (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)) adev->vcn.indirect_sram = true; + /* + * Some Steam Deck's BIOS versions are incompatible with the + * indirect SRAM mode, leading to amdgpu being unable to get + * properly probed (and even potentially crashing the kernel). + * Hence, check for these versions here - notice this is + * restricted to Vangogh (Deck's APU). + */ + if (adev->ip_versions[UVD_HWIP][0] == IP_VERSION(3, 0, 2)) { + const char *bios_ver = dmi_get_system_info(DMI_BIOS_VERSION); + + if (bios_ver && (!strncmp("F7A0113", bios_ver, 7) || + !strncmp("F7A0114", bios_ver, 7))) { + adev->vcn.indirect_sram = false; + dev_info(adev->dev, + "Steam Deck quirk: indirect SRAM disabled on BIOS %s\n", bios_ver); + } + } + hdr = (const struct common_firmware_header *)adev->vcn.fw->data; adev->vcn.fw_version = le32_to_cpu(hdr->ucode_version); From 34e0a279a993debaff03158fc2fbf6a00c093643 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 13 Mar 2023 10:30:02 +0100 Subject: [PATCH 338/460] block: do not reverse request order when flushing plug list Commit 26fed4ac4eab ("block: flush plug based on hardware and software queue order") changed flushing of plug list to submit requests one device at a time. However while doing that it also started using list_add_tail() instead of list_add() used previously thus effectively submitting requests in reverse order. Also when forming a rq_list with remaining requests (in case two or more devices are used), we effectively reverse the ordering of the plug list for each device we process. Submitting requests in reverse order has negative impact on performance for rotational disks (when BFQ is not in use). We observe 10-25% regression in random 4k write throughput, as well as ~20% regression in MariaDB OLTP benchmark on rotational storage on btrfs filesystem. Fix the problem by preserving ordering of the plug list when inserting requests into the queuelist as well as by appending to requeue_list instead of prepending to it. Fixes: 26fed4ac4eab ("block: flush plug based on hardware and software queue order") Signed-off-by: Jan Kara Reviewed-by: Christoph Hellwig Link: https://lore.kernel.org/r/20230313093002.11756-1-jack@suse.cz Signed-off-by: Jens Axboe --- block/blk-mq.c | 5 +++-- include/linux/blk-mq.h | 6 ++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/block/blk-mq.c b/block/blk-mq.c index d0cb2ef18fe21..cf1a39adf9a5b 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -2725,6 +2725,7 @@ static void blk_mq_dispatch_plug_list(struct blk_plug *plug, bool from_sched) struct blk_mq_hw_ctx *this_hctx = NULL; struct blk_mq_ctx *this_ctx = NULL; struct request *requeue_list = NULL; + struct request **requeue_lastp = &requeue_list; unsigned int depth = 0; LIST_HEAD(list); @@ -2735,10 +2736,10 @@ static void blk_mq_dispatch_plug_list(struct blk_plug *plug, bool from_sched) this_hctx = rq->mq_hctx; this_ctx = rq->mq_ctx; } else if (this_hctx != rq->mq_hctx || this_ctx != rq->mq_ctx) { - rq_list_add(&requeue_list, rq); + rq_list_add_tail(&requeue_lastp, rq); continue; } - list_add_tail(&rq->queuelist, &list); + list_add(&rq->queuelist, &list); depth++; } while (!rq_list_empty(plug->mq_list)); diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h index dd5ce1137f04a..de0b0c3e7395a 100644 --- a/include/linux/blk-mq.h +++ b/include/linux/blk-mq.h @@ -228,6 +228,12 @@ static inline unsigned short req_get_ioprio(struct request *req) *(listptr) = rq; \ } while (0) +#define rq_list_add_tail(lastpptr, rq) do { \ + (rq)->rq_next = NULL; \ + **(lastpptr) = rq; \ + *(lastpptr) = &rq->rq_next; \ +} while (0) + #define rq_list_pop(listptr) \ ({ \ struct request *__req = NULL; \ From 28e8cabe80f3e6e3c98121576eda898eeb20f1b1 Mon Sep 17 00:00:00 2001 From: Kristian Overskeid Date: Tue, 7 Mar 2023 14:32:29 +0100 Subject: [PATCH 339/460] net: hsr: Don't log netdev_err message on unknown prp dst node If no frames has been exchanged with a node for HSR_NODE_FORGET_TIME, the node will be deleted from the node_db list. If a frame is sent to the node after it is deleted, a netdev_err message for each slave interface is produced. This should not happen with dan nodes because of supervision frames, but can happen often with san nodes, which clutters the kernel log. Since the hsr protocol does not support sans, this is only relevant for the prp protocol. Signed-off-by: Kristian Overskeid Signed-off-by: David S. Miller --- net/hsr/hsr_framereg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/hsr/hsr_framereg.c b/net/hsr/hsr_framereg.c index 00db74d96583d..865eda39d6014 100644 --- a/net/hsr/hsr_framereg.c +++ b/net/hsr/hsr_framereg.c @@ -415,7 +415,7 @@ void hsr_addr_subst_dest(struct hsr_node *node_src, struct sk_buff *skb, node_dst = find_node_by_addr_A(&port->hsr->node_db, eth_hdr(skb)->h_dest); if (!node_dst) { - if (net_ratelimit()) + if (net_ratelimit() && port->hsr->prot_version != PRP_V1) netdev_err(skb->dev, "%s: Unknown node\n", __func__); return; } From 9026c0bf233db53b86f74f4c620715e94eb32a09 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 13 Mar 2023 00:49:24 +0000 Subject: [PATCH 340/460] ALSA: asihpi: check pao in control_message() control_message() might be called with pao = NULL. Here indicates control_message() as sample. (B) static void control_message(struct hpi_adapter_obj *pao, ...) { ^^^ struct hpi_hw_obj *phw = pao->priv; ... ^^^ } (A) void _HPI_6205(struct hpi_adapter_obj *pao, ...) { ^^^ ... case HPI_OBJ_CONTROL: (B) control_message(pao, phm, phr); break; ^^^ ... } void HPI_6205(...) { ... (A) _HPI_6205(NULL, phm, phr); ... ^^^^ } Therefore, We will get too many warning via cppcheck, like below sound/pci/asihpi/hpi6205.c:238:27: warning: Possible null pointer dereference: pao [nullPointer] struct hpi_hw_obj *phw = pao->priv; ^ sound/pci/asihpi/hpi6205.c:433:13: note: Calling function '_HPI_6205', 1st argument 'NULL' value is 0 _HPI_6205(NULL, phm, phr); ^ sound/pci/asihpi/hpi6205.c:401:20: note: Calling function 'control_message', 1st argument 'pao' value is 0 control_message(pao, phm, phr); ^ Set phr->error like many functions doing, and don't call _HPI_6205() with NULL. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87ttypeaqz.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Takashi Iwai --- sound/pci/asihpi/hpi6205.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/asihpi/hpi6205.c b/sound/pci/asihpi/hpi6205.c index 27e11b5f70b97..c7d7eff86727f 100644 --- a/sound/pci/asihpi/hpi6205.c +++ b/sound/pci/asihpi/hpi6205.c @@ -430,7 +430,7 @@ void HPI_6205(struct hpi_message *phm, struct hpi_response *phr) pao = hpi_find_adapter(phm->adapter_index); } else { /* subsys messages don't address an adapter */ - _HPI_6205(NULL, phm, phr); + phr->error = HPI_ERROR_INVALID_OBJ_INDEX; return; } From 98e5eb110095ec77cb6d775051d181edbf9cd3cf Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 13 Mar 2023 00:50:28 +0000 Subject: [PATCH 341/460] ALSA: hda/ca0132: fixup buffer overrun at tuning_ctl_set() tuning_ctl_set() might have buffer overrun at (X) if it didn't break from loop by matching (A). static int tuning_ctl_set(...) { for (i = 0; i < TUNING_CTLS_COUNT; i++) (A) if (nid == ca0132_tuning_ctls[i].nid) break; snd_hda_power_up(...); (X) dspio_set_param(..., ca0132_tuning_ctls[i].mid, ...); snd_hda_power_down(...); ^ return 1; } We will get below error by cppcheck sound/pci/hda/patch_ca0132.c:4229:2: note: After for loop, i has value 12 for (i = 0; i < TUNING_CTLS_COUNT; i++) ^ sound/pci/hda/patch_ca0132.c:4234:43: note: Array index out of bounds dspio_set_param(codec, ca0132_tuning_ctls[i].mid, 0x20, ^ This patch cares non match case. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87sfe9eap7.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_ca0132.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index acde4cd58785e..099722ebaed83 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -4228,8 +4228,10 @@ static int tuning_ctl_set(struct hda_codec *codec, hda_nid_t nid, for (i = 0; i < TUNING_CTLS_COUNT; i++) if (nid == ca0132_tuning_ctls[i].nid) - break; + goto found; + return -EINVAL; +found: snd_hda_power_up(codec); dspio_set_param(codec, ca0132_tuning_ctls[i].mid, 0x20, ca0132_tuning_ctls[i].req, From 42da2c00b91486980a724c05c29818a7e60a067e Mon Sep 17 00:00:00 2001 From: Xujun Leng Date: Sun, 12 Mar 2023 15:14:23 +0800 Subject: [PATCH 342/460] docs: process: typo fix In the second paragraph of section "Respond to review comments", there is a spelling mistake: "aganst" should be "against". Signed-off-by: Xujun Leng Link: https://lore.kernel.org/r/20230312071423.3042-1-lengxujun2007@126.com Signed-off-by: Jonathan Corbet --- Documentation/process/submitting-patches.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/process/submitting-patches.rst b/Documentation/process/submitting-patches.rst index eac7167dce83d..69ce64e03c70f 100644 --- a/Documentation/process/submitting-patches.rst +++ b/Documentation/process/submitting-patches.rst @@ -320,7 +320,7 @@ for their time. Code review is a tiring and time-consuming process, and reviewers sometimes get grumpy. Even in that case, though, respond politely and address the problems they have pointed out. When sending a next version, add a ``patch changelog`` to the cover letter or to individual patches -explaining difference aganst previous submission (see +explaining difference against previous submission (see :ref:`the_canonical_patch_format`). See Documentation/process/email-clients.rst for recommendations on email From d7ba3657d5162bd551e5c653f67f941c94a7dc0a Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 10 Mar 2023 10:58:57 +0100 Subject: [PATCH 343/460] docs: vfio: fix header path The text points to a different header file, fix by changing the path to "uapi". Signed-off-by: Jiri Pirko Reviewed-by: Yi Liu Link: https://lore.kernel.org/r/20230310095857.985814-1-jiri@resnulli.us Signed-off-by: Jonathan Corbet --- Documentation/driver-api/vfio.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/driver-api/vfio.rst b/Documentation/driver-api/vfio.rst index 50b690f7f6639..68abc089d6ddd 100644 --- a/Documentation/driver-api/vfio.rst +++ b/Documentation/driver-api/vfio.rst @@ -242,7 +242,7 @@ group and can access them as follows:: VFIO User API ------------------------------------------------------------------------------- -Please see include/linux/vfio.h for complete API documentation. +Please see include/uapi/linux/vfio.h for complete API documentation. VFIO bus driver API ------------------------------------------------------------------------------- From 6fa7f537351c8fad0e43e9279efe76dbc942bea0 Mon Sep 17 00:00:00 2001 From: Todd Brandt Date: Mon, 13 Mar 2023 15:26:52 -0700 Subject: [PATCH 344/460] pm-graph: sleepgraph: Avoid crashing on binary data in device names A regression has occurred in the hid-sensor code where a device name string has not been initialized to 0, and ends up without a NULL char and is printed with %s. This includes random binary data in the device name, which makes its way into the ftrace output and ends up crashing sleepgraph because it expects the ftrace output to be ASCII only. For example: "HID-SENSOR-INT-020b?.39.auto" ends up in ftrace instead of "HID-SENSOR-INT-020b.39.auto". It causes this crash in sleepgraph: File "/usr/bin/sleepgraph", line 5579, in executeSuspend for line in fp: File "/usr/lib/python3.10/codecs.py", line 322, in decode (result, consumed) = self._buffer_decode(data, self.errors, final) UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 1568: invalid start byte The issue is present in 6.3-rc1 and is described in full here: https://bugzilla.kernel.org/show_bug.cgi?id=217169 A separate fix has been submitted to have this issue repaired, but it has also exposed a larger bug in sleepgraph, since nothing should make sleepgraph crash. Sleepgraph needs to be able to handle binary data showing up in ftrace gracefully. Modify the ftrace processing code to treat it as potentially binary and to filter out binary data and leave just the ASCII. Link: https://bugzilla.kernel.org/show_bug.cgi?id=217169 Fixes: 98c062e82451 ("HID: hid-sensor-custom: Allow more custom iio sensors") Signed-off-by: Todd Brandt [ rjw: Subject and changelog edits ] Signed-off-by: Rafael J. Wysocki --- tools/power/pm-graph/sleepgraph.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tools/power/pm-graph/sleepgraph.py b/tools/power/pm-graph/sleepgraph.py index 82c09cd25cc21..bf4ac24a1c7aa 100755 --- a/tools/power/pm-graph/sleepgraph.py +++ b/tools/power/pm-graph/sleepgraph.py @@ -5556,9 +5556,8 @@ def executeSuspend(quiet=False): if not quiet: pprint('CAPTURING TRACE') op = sv.writeDatafileHeader(sv.ftracefile, testdata) - fp = open(tp+'trace', 'r') - for line in fp: - op.write(line) + fp = open(tp+'trace', 'rb') + op.write(ascii(fp.read())) op.close() sv.fsetVal('', 'trace') sv.platforminfo(cmdafter) From 91d7b60a65d9f71230ea09b86d2058a884a3c2af Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Wed, 8 Mar 2023 11:26:32 +0000 Subject: [PATCH 345/460] ACPI: PPTT: Fix to avoid sleep in the atomic context when PPTT is absent Commit 0c80f9e165f8 ("ACPI: PPTT: Leave the table mapped for the runtime usage") enabled to map PPTT once on the first invocation of acpi_get_pptt() and never unmapped the same allowing it to be used at runtime with out the hassle of mapping and unmapping the table. This was needed to fetch LLC information from the PPTT in the cpuhotplug path which is executed in the atomic context as the acpi_get_table() might sleep waiting for a mutex. However it missed to handle the case when there is no PPTT on the system which results in acpi_get_pptt() being called from all the secondary CPUs attempting to fetch the LLC information in the atomic context without knowing the absence of PPTT resulting in the splat like below: | BUG: sleeping function called from invalid context at kernel/locking/semaphore.c:164 | in_atomic(): 1, irqs_disabled(): 1, non_block: 0, pid: 0, name: swapper/1 | preempt_count: 1, expected: 0 | RCU nest depth: 0, expected: 0 | no locks held by swapper/1/0. | irq event stamp: 0 | hardirqs last enabled at (0): 0x0 | hardirqs last disabled at (0): copy_process+0x61c/0x1b40 | softirqs last enabled at (0): copy_process+0x61c/0x1b40 | softirqs last disabled at (0): 0x0 | CPU: 1 PID: 0 Comm: swapper/1 Not tainted 6.3.0-rc1 #1 | Call trace: | dump_backtrace+0xac/0x138 | show_stack+0x30/0x48 | dump_stack_lvl+0x60/0xb0 | dump_stack+0x18/0x28 | __might_resched+0x160/0x270 | __might_sleep+0x58/0xb0 | down_timeout+0x34/0x98 | acpi_os_wait_semaphore+0x7c/0xc0 | acpi_ut_acquire_mutex+0x58/0x108 | acpi_get_table+0x40/0xe8 | acpi_get_pptt+0x48/0xa0 | acpi_get_cache_info+0x38/0x140 | init_cache_level+0xf4/0x118 | detect_cache_attributes+0x2e4/0x640 | update_siblings_masks+0x3c/0x330 | store_cpu_topology+0x88/0xf0 | secondary_start_kernel+0xd0/0x168 | __secondary_switched+0xb8/0xc0 Update acpi_get_pptt() to consider the fact that PPTT is once checked and is not available on the system and return NULL avoiding any attempts to fetch PPTT and thereby avoiding any possible sleep waiting for a mutex in the atomic context. Fixes: 0c80f9e165f8 ("ACPI: PPTT: Leave the table mapped for the runtime usage") Reported-by: Aishwarya TCV Signed-off-by: Sudeep Holla Tested-by: Pierre Gondois Cc: 6.0+ # 6.0+ Signed-off-by: Rafael J. Wysocki --- drivers/acpi/pptt.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/pptt.c b/drivers/acpi/pptt.c index 10975bb603fb1..a35dd0e41c270 100644 --- a/drivers/acpi/pptt.c +++ b/drivers/acpi/pptt.c @@ -536,16 +536,19 @@ static int topology_get_acpi_cpu_tag(struct acpi_table_header *table, static struct acpi_table_header *acpi_get_pptt(void) { static struct acpi_table_header *pptt; + static bool is_pptt_checked; acpi_status status; /* * PPTT will be used at runtime on every CPU hotplug in path, so we * don't need to call acpi_put_table() to release the table mapping. */ - if (!pptt) { + if (!pptt && !is_pptt_checked) { status = acpi_get_table(ACPI_SIG_PPTT, 0, &pptt); if (ACPI_FAILURE(status)) acpi_pptt_warn_missing(); + + is_pptt_checked = true; } return pptt; From 0bc23d8b2237a104d7f8379d687aa4cb82e2968b Mon Sep 17 00:00:00 2001 From: Chen Yu Date: Wed, 8 Mar 2023 21:23:09 +0800 Subject: [PATCH 346/460] ACPI: tools: pfrut: Check if the input of level and type is in the right numeric range MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The user provides arbitrary non-numeic value to level and type, which could bring unexpected behavior. In this case the expected behavior would be to throw an error. pfrut -h usage: pfrut [OPTIONS] code injection: -l, --load -s, --stage -a, --activate -u, --update [stage and activate] -q, --query -d, --revid update telemetry: -G, --getloginfo -T, --type(0:execution, 1:history) -L, --level(0, 1, 2, 4) -R, --read -D, --revid log pfrut -T A pfrut -G log_level:0 log_type:0 log_revid:2 max_data_size:65536 chunk1_size:0 chunk2_size:1530 rollover_cnt:0 reset_cnt:17 Fix this by restricting the input to be in the expected range. Reported-by: Hariganesh Govindarajulu Suggested-by: "Rafael J. Wysocki" Signed-off-by: Chen Yu Signed-off-by: Rafael J. Wysocki --- tools/power/acpi/tools/pfrut/pfrut.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/tools/power/acpi/tools/pfrut/pfrut.c b/tools/power/acpi/tools/pfrut/pfrut.c index 52aa0351533c3..388c9e3ad0407 100644 --- a/tools/power/acpi/tools/pfrut/pfrut.c +++ b/tools/power/acpi/tools/pfrut/pfrut.c @@ -97,7 +97,7 @@ static struct option long_options[] = { static void parse_options(int argc, char **argv) { int option_index = 0; - char *pathname; + char *pathname, *endptr; int opt; pathname = strdup(argv[0]); @@ -125,11 +125,23 @@ static void parse_options(int argc, char **argv) log_getinfo = 1; break; case 'T': - log_type = atoi(optarg); + log_type = strtol(optarg, &endptr, 0); + if (*endptr || (log_type != 0 && log_type != 1)) { + printf("Number expected: type(0:execution, 1:history) - Quit.\n"); + exit(1); + } + set_log_type = 1; break; case 'L': - log_level = atoi(optarg); + log_level = strtol(optarg, &endptr, 0); + if (*endptr || + (log_level != 0 && log_level != 1 && + log_level != 2 && log_level != 4)) { + printf("Number expected: level(0, 1, 2, 4) - Quit.\n"); + exit(1); + } + set_log_level = 1; break; case 'R': From c2679254b9c9980d9045f0f722cf093a2b1f7590 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Google)" Date: Fri, 10 Mar 2023 17:28:56 -0500 Subject: [PATCH 347/460] tracing: Make tracepoint lockdep check actually test something A while ago where the trace events had the following: rcu_read_lock_sched_notrace(); rcu_dereference_sched(...); rcu_read_unlock_sched_notrace(); If the tracepoint is enabled, it could trigger RCU issues if called in the wrong place. And this warning was only triggered if lockdep was enabled. If the tracepoint was never enabled with lockdep, the bug would not be caught. To handle this, the above sequence was done when lockdep was enabled regardless if the tracepoint was enabled or not (although the always enabled code really didn't do anything, it would still trigger a warning). But a lot has changed since that lockdep code was added. One is, that sequence no longer triggers any warning. Another is, the tracepoint when enabled doesn't even do that sequence anymore. The main check we care about today is whether RCU is "watching" or not. So if lockdep is enabled, always check if rcu_is_watching() which will trigger a warning if it is not (tracepoints require RCU to be watching). Note, that old sequence did add a bit of overhead when lockdep was enabled, and with the latest kernel updates, would cause the system to slow down enough to trigger kernel "stalled" warnings. Link: http://lore.kernel.org/lkml/20140806181801.GA4605@redhat.com Link: http://lore.kernel.org/lkml/20140807175204.C257CAC5@viggo.jf.intel.com Link: https://lore.kernel.org/lkml/20230307184645.521db5c9@gandalf.local.home/ Link: https://lore.kernel.org/linux-trace-kernel/20230310172856.77406446@gandalf.local.home Cc: stable@vger.kernel.org Cc: Masami Hiramatsu Cc: Dave Hansen Cc: "Paul E. McKenney" Cc: Mathieu Desnoyers Cc: Joel Fernandes Acked-by: Peter Zijlstra (Intel) Acked-by: Paul E. McKenney Fixes: e6753f23d961 ("tracepoint: Make rcuidle tracepoint callers use SRCU") Signed-off-by: Steven Rostedt (Google) --- include/linux/tracepoint.h | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h index fa1004fcf8109..2083f2d2f05bc 100644 --- a/include/linux/tracepoint.h +++ b/include/linux/tracepoint.h @@ -231,12 +231,11 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p) * not add unwanted padding between the beginning of the section and the * structure. Force alignment to the same alignment as the section start. * - * When lockdep is enabled, we make sure to always do the RCU portions of - * the tracepoint code, regardless of whether tracing is on. However, - * don't check if the condition is false, due to interaction with idle - * instrumentation. This lets us find RCU issues triggered with tracepoints - * even when this tracepoint is off. This code has no purpose other than - * poking RCU a bit. + * When lockdep is enabled, we make sure to always test if RCU is + * "watching" regardless if the tracepoint is enabled or not. Tracepoints + * require RCU to be active, and it should always warn at the tracepoint + * site if it is not watching, as it will need to be active when the + * tracepoint is enabled. */ #define __DECLARE_TRACE(name, proto, args, cond, data_proto) \ extern int __traceiter_##name(data_proto); \ @@ -249,9 +248,7 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p) TP_ARGS(args), \ TP_CONDITION(cond), 0); \ if (IS_ENABLED(CONFIG_LOCKDEP) && (cond)) { \ - rcu_read_lock_sched_notrace(); \ - rcu_dereference_sched(__tracepoint_##name.funcs);\ - rcu_read_unlock_sched_notrace(); \ + WARN_ON_ONCE(!rcu_is_watching()); \ } \ } \ __DECLARE_TRACE_RCU(name, PARAMS(proto), PARAMS(args), \ From 211baef0eabf4169ce4f73ebd917749d1a7edd74 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 13 Mar 2023 16:09:54 +0100 Subject: [PATCH 348/460] cifs: Fix smb2_set_path_size() If cifs_get_writable_path() finds a writable file, smb2_compound_op() must use that file's FID and not the COMPOUND_FID. Cc: stable@vger.kernel.org Signed-off-by: Volker Lendecke Reviewed-by: Paulo Alcantara (SUSE) Signed-off-by: Steve French --- fs/cifs/smb2inode.c | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/fs/cifs/smb2inode.c b/fs/cifs/smb2inode.c index 9b956294e8643..8dd3791b5c538 100644 --- a/fs/cifs/smb2inode.c +++ b/fs/cifs/smb2inode.c @@ -234,15 +234,32 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, size[0] = 8; /* sizeof __le64 */ data[0] = ptr; - rc = SMB2_set_info_init(tcon, server, - &rqst[num_rqst], COMPOUND_FID, - COMPOUND_FID, current->tgid, - FILE_END_OF_FILE_INFORMATION, - SMB2_O_INFO_FILE, 0, data, size); + if (cfile) { + rc = SMB2_set_info_init(tcon, server, + &rqst[num_rqst], + cfile->fid.persistent_fid, + cfile->fid.volatile_fid, + current->tgid, + FILE_END_OF_FILE_INFORMATION, + SMB2_O_INFO_FILE, 0, + data, size); + } else { + rc = SMB2_set_info_init(tcon, server, + &rqst[num_rqst], + COMPOUND_FID, + COMPOUND_FID, + current->tgid, + FILE_END_OF_FILE_INFORMATION, + SMB2_O_INFO_FILE, 0, + data, size); + if (!rc) { + smb2_set_next_command(tcon, &rqst[num_rqst]); + smb2_set_related(&rqst[num_rqst]); + } + } if (rc) goto finished; - smb2_set_next_command(tcon, &rqst[num_rqst]); - smb2_set_related(&rqst[num_rqst++]); + num_rqst++; trace_smb3_set_eof_enter(xid, ses->Suid, tcon->tid, full_path); break; case SMB2_OP_SET_INFO: From 05ce0448c3f36febd8db0ee0e9e16557f3ab5ee8 Mon Sep 17 00:00:00 2001 From: Shyam Prasad N Date: Fri, 10 Mar 2023 15:32:01 +0000 Subject: [PATCH 349/460] cifs: generate signkey for the channel that's reconnecting Before my changes to how multichannel reconnects work, the primary channel was always used to do a non-binding session setup. With my changes, that is not the case anymore. Missed this place where channel at index 0 was forcibly updated with the signing key. Signed-off-by: Shyam Prasad N Reviewed-by: Paulo Alcantara (SUSE) Cc: stable@vger.kernel.org Signed-off-by: Steve French --- fs/cifs/smb2transport.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c index 381babc1212c9..d827b7547ffad 100644 --- a/fs/cifs/smb2transport.c +++ b/fs/cifs/smb2transport.c @@ -425,7 +425,7 @@ generate_smb3signingkey(struct cifs_ses *ses, /* safe to access primary channel, since it will never go away */ spin_lock(&ses->chan_lock); - memcpy(ses->chans[0].signkey, ses->smb3signingkey, + memcpy(ses->chans[chan_index].signkey, ses->smb3signingkey, SMB3_SIGN_KEY_SIZE); spin_unlock(&ses->chan_lock); From 9b0cb770f5d7b1ff40bea7ca385438ee94570eec Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Tue, 14 Mar 2023 11:21:54 -0700 Subject: [PATCH 350/460] loop: Fix use-after-free issues do_req_filebacked() calls blk_mq_complete_request() synchronously or asynchronously when using asynchronous I/O unless memory allocation fails. Hence, modify loop_handle_cmd() such that it does not dereference 'cmd' nor 'rq' after do_req_filebacked() finished unless we are sure that the request has not yet been completed. This patch fixes the following kernel crash: Unable to handle kernel NULL pointer dereference at virtual address 0000000000000054 Call trace: css_put.42938+0x1c/0x1ac loop_process_work+0xc8c/0xfd4 loop_rootcg_workfn+0x24/0x34 process_one_work+0x244/0x558 worker_thread+0x400/0x8fc kthread+0x16c/0x1e0 ret_from_fork+0x10/0x20 Cc: Christoph Hellwig Cc: Ming Lei Cc: Jan Kara Cc: Johannes Weiner Cc: Dan Schatzberg Fixes: c74d40e8b5e2 ("loop: charge i/o to mem and blk cg") Fixes: bc07c10a3603 ("block: loop: support DIO & AIO") Signed-off-by: Bart Van Assche Reviewed-by: Ming Lei Link: https://lore.kernel.org/r/20230314182155.80625-1-bvanassche@acm.org Signed-off-by: Jens Axboe --- drivers/block/loop.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 839373451c2b7..28eb59fd71ca2 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -1859,35 +1859,44 @@ static blk_status_t loop_queue_rq(struct blk_mq_hw_ctx *hctx, static void loop_handle_cmd(struct loop_cmd *cmd) { + struct cgroup_subsys_state *cmd_blkcg_css = cmd->blkcg_css; + struct cgroup_subsys_state *cmd_memcg_css = cmd->memcg_css; struct request *rq = blk_mq_rq_from_pdu(cmd); const bool write = op_is_write(req_op(rq)); struct loop_device *lo = rq->q->queuedata; int ret = 0; struct mem_cgroup *old_memcg = NULL; + const bool use_aio = cmd->use_aio; if (write && (lo->lo_flags & LO_FLAGS_READ_ONLY)) { ret = -EIO; goto failed; } - if (cmd->blkcg_css) - kthread_associate_blkcg(cmd->blkcg_css); - if (cmd->memcg_css) + if (cmd_blkcg_css) + kthread_associate_blkcg(cmd_blkcg_css); + if (cmd_memcg_css) old_memcg = set_active_memcg( - mem_cgroup_from_css(cmd->memcg_css)); + mem_cgroup_from_css(cmd_memcg_css)); + /* + * do_req_filebacked() may call blk_mq_complete_request() synchronously + * or asynchronously if using aio. Hence, do not touch 'cmd' after + * do_req_filebacked() has returned unless we are sure that 'cmd' has + * not yet been completed. + */ ret = do_req_filebacked(lo, rq); - if (cmd->blkcg_css) + if (cmd_blkcg_css) kthread_associate_blkcg(NULL); - if (cmd->memcg_css) { + if (cmd_memcg_css) { set_active_memcg(old_memcg); - css_put(cmd->memcg_css); + css_put(cmd_memcg_css); } failed: /* complete non-aio request */ - if (!cmd->use_aio || ret) { + if (!use_aio || ret) { if (ret == -EOPNOTSUPP) cmd->ret = ret; else From 00e885efcfbb8712d3e1bfc1ae30639c15ca1d3b Mon Sep 17 00:00:00 2001 From: Chris Leech Date: Fri, 10 Mar 2023 09:09:13 +0800 Subject: [PATCH 351/460] blk-mq: fix "bad unlock balance detected" on q->srcu in __blk_mq_run_dispatch_ops The 'q' parameter of the macro __blk_mq_run_dispatch_ops may not be one local variable, such as, it is rq->q, then request queue pointed by this variable could be changed to another queue in case of BLK_MQ_F_TAG_QUEUE_SHARED after 'dispatch_ops' returns, then 'bad unlock balance' is triggered. Fixes the issue by adding one local variable for doing srcu lock/unlock. Fixes: 2a904d00855f ("blk-mq: remove hctx_lock and hctx_unlock") Cc: Marco Patalano Signed-off-by: Chris Leech Signed-off-by: Ming Lei Link: https://lore.kernel.org/r/20230310010913.1014789-1-ming.lei@redhat.com Signed-off-by: Jens Axboe --- block/blk-mq.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/block/blk-mq.h b/block/blk-mq.h index ef59fee62780d..a7482d2cc82e7 100644 --- a/block/blk-mq.h +++ b/block/blk-mq.h @@ -378,12 +378,13 @@ static inline bool hctx_may_queue(struct blk_mq_hw_ctx *hctx, #define __blk_mq_run_dispatch_ops(q, check_sleep, dispatch_ops) \ do { \ if ((q)->tag_set->flags & BLK_MQ_F_BLOCKING) { \ + struct blk_mq_tag_set *__tag_set = (q)->tag_set; \ int srcu_idx; \ \ might_sleep_if(check_sleep); \ - srcu_idx = srcu_read_lock((q)->tag_set->srcu); \ + srcu_idx = srcu_read_lock(__tag_set->srcu); \ (dispatch_ops); \ - srcu_read_unlock((q)->tag_set->srcu, srcu_idx); \ + srcu_read_unlock(__tag_set->srcu, srcu_idx); \ } else { \ rcu_read_lock(); \ (dispatch_ops); \ From b56bce502f55505a97e381d546ee881928183126 Mon Sep 17 00:00:00 2001 From: Paulo Alcantara Date: Tue, 14 Mar 2023 20:32:53 -0300 Subject: [PATCH 352/460] cifs: set DFS root session in cifs_get_smb_ses() Set the DFS root session pointer earlier when creating a new SMB session to prevent racing with smb2_reconnect(), cifs_reconnect_tcon() and DFS cache refresher. Signed-off-by: Paulo Alcantara (SUSE) Cc: stable@vger.kernel.org # 6.2 Signed-off-by: Steve French --- fs/cifs/cifs_dfs_ref.c | 1 + fs/cifs/cifsglob.h | 1 - fs/cifs/connect.c | 1 + fs/cifs/dfs.c | 19 ++++++++----------- fs/cifs/dfs.h | 3 ++- fs/cifs/fs_context.h | 1 + 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c index 2b1a8d55b4ec4..cb40074feb3e9 100644 --- a/fs/cifs/cifs_dfs_ref.c +++ b/fs/cifs/cifs_dfs_ref.c @@ -179,6 +179,7 @@ static struct vfsmount *cifs_dfs_do_automount(struct path *path) tmp.source = full_path; tmp.leaf_fullpath = NULL; tmp.UNC = tmp.prepath = NULL; + tmp.dfs_root_ses = NULL; rc = smb3_fs_context_dup(ctx, &tmp); if (rc) { diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index a99883f16d946..1a8190f71c244 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -1749,7 +1749,6 @@ struct cifs_mount_ctx { struct TCP_Server_Info *server; struct cifs_ses *ses; struct cifs_tcon *tcon; - struct cifs_ses *root_ses; uuid_t mount_id; char *origin_fullpath, *leaf_fullpath; }; diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 5233f14f0636a..b96375f137fa8 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -2229,6 +2229,7 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx) * need to lock before changing something in the session. */ spin_lock(&cifs_tcp_ses_lock); + ses->dfs_root_ses = ctx->dfs_root_ses; list_add(&ses->smb_ses_list, &server->smb_ses_list); spin_unlock(&cifs_tcp_ses_lock); diff --git a/fs/cifs/dfs.c b/fs/cifs/dfs.c index b64d20374b9c8..6505f1b20147e 100644 --- a/fs/cifs/dfs.c +++ b/fs/cifs/dfs.c @@ -95,25 +95,22 @@ static int get_session(struct cifs_mount_ctx *mnt_ctx, const char *full_path) ctx->leaf_fullpath = (char *)full_path; rc = cifs_mount_get_session(mnt_ctx); ctx->leaf_fullpath = NULL; - if (!rc) { - struct cifs_ses *ses = mnt_ctx->ses; - mutex_lock(&ses->session_mutex); - ses->dfs_root_ses = mnt_ctx->root_ses; - mutex_unlock(&ses->session_mutex); - } return rc; } static void set_root_ses(struct cifs_mount_ctx *mnt_ctx) { - if (mnt_ctx->ses) { + struct smb3_fs_context *ctx = mnt_ctx->fs_ctx; + struct cifs_ses *ses = mnt_ctx->ses; + + if (ses) { spin_lock(&cifs_tcp_ses_lock); - mnt_ctx->ses->ses_count++; + ses->ses_count++; spin_unlock(&cifs_tcp_ses_lock); - dfs_cache_add_refsrv_session(&mnt_ctx->mount_id, mnt_ctx->ses); + dfs_cache_add_refsrv_session(&mnt_ctx->mount_id, ses); } - mnt_ctx->root_ses = mnt_ctx->ses; + ctx->dfs_root_ses = mnt_ctx->ses; } static int get_dfs_conn(struct cifs_mount_ctx *mnt_ctx, const char *ref_path, const char *full_path, @@ -260,7 +257,7 @@ int dfs_mount_share(struct cifs_mount_ctx *mnt_ctx, bool *isdfs) rc = get_session(mnt_ctx, NULL); if (rc) return rc; - mnt_ctx->root_ses = mnt_ctx->ses; + ctx->dfs_root_ses = mnt_ctx->ses; /* * If called with 'nodfs' mount option, then skip DFS resolving. Otherwise unconditionally * try to get an DFS referral (even cached) to determine whether it is an DFS mount. diff --git a/fs/cifs/dfs.h b/fs/cifs/dfs.h index 344bea6d8bab1..baf16df55d7e7 100644 --- a/fs/cifs/dfs.h +++ b/fs/cifs/dfs.h @@ -22,9 +22,10 @@ static inline char *dfs_get_path(struct cifs_sb_info *cifs_sb, const char *path) static inline int dfs_get_referral(struct cifs_mount_ctx *mnt_ctx, const char *path, struct dfs_info3_param *ref, struct dfs_cache_tgt_list *tl) { + struct smb3_fs_context *ctx = mnt_ctx->fs_ctx; struct cifs_sb_info *cifs_sb = mnt_ctx->cifs_sb; - return dfs_cache_find(mnt_ctx->xid, mnt_ctx->root_ses, cifs_sb->local_nls, + return dfs_cache_find(mnt_ctx->xid, ctx->dfs_root_ses, cifs_sb->local_nls, cifs_remap(cifs_sb), path, ref, tl); } diff --git a/fs/cifs/fs_context.h b/fs/cifs/fs_context.h index 44cb5639ed3ba..1b8d4e27f831c 100644 --- a/fs/cifs/fs_context.h +++ b/fs/cifs/fs_context.h @@ -265,6 +265,7 @@ struct smb3_fs_context { bool rootfs:1; /* if it's a SMB root file system */ bool witness:1; /* use witness protocol */ char *leaf_fullpath; + struct cifs_ses *dfs_root_ses; }; extern const struct fs_parameter_spec smb3_fs_parameters[]; From 396935de145589c8bfe552fa03a5e38604071829 Mon Sep 17 00:00:00 2001 From: Paulo Alcantara Date: Tue, 14 Mar 2023 20:32:54 -0300 Subject: [PATCH 353/460] cifs: fix use-after-free bug in refresh_cache_worker() The UAF bug occurred because we were putting DFS root sessions in cifs_umount() while DFS cache refresher was being executed. Make DFS root sessions have same lifetime as DFS tcons so we can avoid the use-after-free bug is DFS cache refresher and other places that require IPCs to get new DFS referrals on. Also, get rid of mount group handling in DFS cache as we no longer need it. This fixes below use-after-free bug catched by KASAN [ 379.946955] BUG: KASAN: use-after-free in __refresh_tcon.isra.0+0x10b/0xc10 [cifs] [ 379.947642] Read of size 8 at addr ffff888018f57030 by task kworker/u4:3/56 [ 379.948096] [ 379.948208] CPU: 0 PID: 56 Comm: kworker/u4:3 Not tainted 6.2.0-rc7-lku #23 [ 379.948661] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.16.0-0-gd239552-rebuilt.opensuse.org 04/01/2014 [ 379.949368] Workqueue: cifs-dfscache refresh_cache_worker [cifs] [ 379.949942] Call Trace: [ 379.950113] [ 379.950260] dump_stack_lvl+0x50/0x67 [ 379.950510] print_report+0x16a/0x48e [ 379.950759] ? __virt_addr_valid+0xd8/0x160 [ 379.951040] ? __phys_addr+0x41/0x80 [ 379.951285] kasan_report+0xdb/0x110 [ 379.951533] ? __refresh_tcon.isra.0+0x10b/0xc10 [cifs] [ 379.952056] ? __refresh_tcon.isra.0+0x10b/0xc10 [cifs] [ 379.952585] __refresh_tcon.isra.0+0x10b/0xc10 [cifs] [ 379.953096] ? __pfx___refresh_tcon.isra.0+0x10/0x10 [cifs] [ 379.953637] ? __pfx___mutex_lock+0x10/0x10 [ 379.953915] ? lock_release+0xb6/0x720 [ 379.954167] ? __pfx_lock_acquire+0x10/0x10 [ 379.954443] ? refresh_cache_worker+0x34e/0x6d0 [cifs] [ 379.954960] ? __pfx_wb_workfn+0x10/0x10 [ 379.955239] refresh_cache_worker+0x4ad/0x6d0 [cifs] [ 379.955755] ? __pfx_refresh_cache_worker+0x10/0x10 [cifs] [ 379.956323] ? __pfx_lock_acquired+0x10/0x10 [ 379.956615] ? read_word_at_a_time+0xe/0x20 [ 379.956898] ? lockdep_hardirqs_on_prepare+0x12/0x220 [ 379.957235] process_one_work+0x535/0x990 [ 379.957509] ? __pfx_process_one_work+0x10/0x10 [ 379.957812] ? lock_acquired+0xb7/0x5f0 [ 379.958069] ? __list_add_valid+0x37/0xd0 [ 379.958341] ? __list_add_valid+0x37/0xd0 [ 379.958611] worker_thread+0x8e/0x630 [ 379.958861] ? __pfx_worker_thread+0x10/0x10 [ 379.959148] kthread+0x17d/0x1b0 [ 379.959369] ? __pfx_kthread+0x10/0x10 [ 379.959630] ret_from_fork+0x2c/0x50 [ 379.959879] Signed-off-by: Paulo Alcantara (SUSE) Cc: stable@vger.kernel.org # 6.2 Signed-off-by: Steve French --- fs/cifs/cifs_fs_sb.h | 2 - fs/cifs/cifsglob.h | 3 +- fs/cifs/connect.c | 9 +-- fs/cifs/dfs.c | 52 ++++++++++++---- fs/cifs/dfs.h | 16 +++++ fs/cifs/dfs_cache.c | 140 ------------------------------------------- fs/cifs/dfs_cache.h | 2 - fs/cifs/misc.c | 7 +++ 8 files changed, 67 insertions(+), 164 deletions(-) diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h index 013a4bd65280c..6517591922801 100644 --- a/fs/cifs/cifs_fs_sb.h +++ b/fs/cifs/cifs_fs_sb.h @@ -61,8 +61,6 @@ struct cifs_sb_info { /* only used when CIFS_MOUNT_USE_PREFIX_PATH is set */ char *prepath; - /* randomly generated 128-bit number for indexing dfs mount groups in referral cache */ - uuid_t dfs_mount_id; /* * Indicate whether serverino option was turned off later * (cifs_autodisable_serverino) in order to match new mounts. diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 1a8190f71c244..08a73dcb77864 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -1233,6 +1233,7 @@ struct cifs_tcon { /* BB add field for back pointer to sb struct(s)? */ #ifdef CONFIG_CIFS_DFS_UPCALL struct list_head ulist; /* cache update list */ + struct list_head dfs_ses_list; #endif struct delayed_work query_interfaces; /* query interfaces workqueue job */ }; @@ -1749,8 +1750,8 @@ struct cifs_mount_ctx { struct TCP_Server_Info *server; struct cifs_ses *ses; struct cifs_tcon *tcon; - uuid_t mount_id; char *origin_fullpath, *leaf_fullpath; + struct list_head dfs_ses_list; }; static inline void free_dfs_info_param(struct dfs_info3_param *param) diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index b96375f137fa8..0eceddde7140a 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -3408,7 +3408,8 @@ int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx) bool isdfs; int rc; - uuid_gen(&mnt_ctx.mount_id); + INIT_LIST_HEAD(&mnt_ctx.dfs_ses_list); + rc = dfs_mount_share(&mnt_ctx, &isdfs); if (rc) goto error; @@ -3428,7 +3429,6 @@ int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx) kfree(cifs_sb->prepath); cifs_sb->prepath = ctx->prepath; ctx->prepath = NULL; - uuid_copy(&cifs_sb->dfs_mount_id, &mnt_ctx.mount_id); out: cifs_try_adding_channels(cifs_sb, mnt_ctx.ses); @@ -3440,7 +3440,7 @@ int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx) return rc; error: - dfs_cache_put_refsrv_sessions(&mnt_ctx.mount_id); + dfs_put_root_smb_sessions(&mnt_ctx.dfs_ses_list); kfree(mnt_ctx.origin_fullpath); kfree(mnt_ctx.leaf_fullpath); cifs_mount_put_conns(&mnt_ctx); @@ -3638,9 +3638,6 @@ cifs_umount(struct cifs_sb_info *cifs_sb) spin_unlock(&cifs_sb->tlink_tree_lock); kfree(cifs_sb->prepath); -#ifdef CONFIG_CIFS_DFS_UPCALL - dfs_cache_put_refsrv_sessions(&cifs_sb->dfs_mount_id); -#endif call_rcu(&cifs_sb->rcu, delayed_free); } diff --git a/fs/cifs/dfs.c b/fs/cifs/dfs.c index 6505f1b20147e..c8bda52fa096c 100644 --- a/fs/cifs/dfs.c +++ b/fs/cifs/dfs.c @@ -99,18 +99,27 @@ static int get_session(struct cifs_mount_ctx *mnt_ctx, const char *full_path) return rc; } -static void set_root_ses(struct cifs_mount_ctx *mnt_ctx) +static int get_root_smb_session(struct cifs_mount_ctx *mnt_ctx) { struct smb3_fs_context *ctx = mnt_ctx->fs_ctx; + struct dfs_root_ses *root_ses; struct cifs_ses *ses = mnt_ctx->ses; if (ses) { + root_ses = kmalloc(sizeof(*root_ses), GFP_KERNEL); + if (!root_ses) + return -ENOMEM; + + INIT_LIST_HEAD(&root_ses->list); + spin_lock(&cifs_tcp_ses_lock); ses->ses_count++; spin_unlock(&cifs_tcp_ses_lock); - dfs_cache_add_refsrv_session(&mnt_ctx->mount_id, ses); + root_ses->ses = ses; + list_add_tail(&root_ses->list, &mnt_ctx->dfs_ses_list); } - ctx->dfs_root_ses = mnt_ctx->ses; + ctx->dfs_root_ses = ses; + return 0; } static int get_dfs_conn(struct cifs_mount_ctx *mnt_ctx, const char *ref_path, const char *full_path, @@ -118,7 +127,8 @@ static int get_dfs_conn(struct cifs_mount_ctx *mnt_ctx, const char *ref_path, co { struct smb3_fs_context *ctx = mnt_ctx->fs_ctx; struct dfs_info3_param ref = {}; - int rc; + bool is_refsrv = false; + int rc, rc2; rc = dfs_cache_get_tgt_referral(ref_path + 1, tit, &ref); if (rc) @@ -133,8 +143,7 @@ static int get_dfs_conn(struct cifs_mount_ctx *mnt_ctx, const char *ref_path, co if (rc) goto out; - if (ref.flags & DFSREF_REFERRAL_SERVER) - set_root_ses(mnt_ctx); + is_refsrv = !!(ref.flags & DFSREF_REFERRAL_SERVER); rc = -EREMOTE; if (ref.flags & DFSREF_STORAGE_SERVER) { @@ -143,13 +152,17 @@ static int get_dfs_conn(struct cifs_mount_ctx *mnt_ctx, const char *ref_path, co goto out; /* some servers may not advertise referral capability under ref.flags */ - if (!(ref.flags & DFSREF_REFERRAL_SERVER) && - is_tcon_dfs(mnt_ctx->tcon)) - set_root_ses(mnt_ctx); + is_refsrv |= is_tcon_dfs(mnt_ctx->tcon); rc = cifs_is_path_remote(mnt_ctx); } + if (rc == -EREMOTE && is_refsrv) { + rc2 = get_root_smb_session(mnt_ctx); + if (rc2) + rc = rc2; + } + out: free_dfs_info_param(&ref); return rc; @@ -162,6 +175,7 @@ static int __dfs_mount_share(struct cifs_mount_ctx *mnt_ctx) char *ref_path = NULL, *full_path = NULL; struct dfs_cache_tgt_iterator *tit; struct TCP_Server_Info *server; + struct cifs_tcon *tcon; char *origin_fullpath = NULL; int num_links = 0; int rc; @@ -231,12 +245,22 @@ static int __dfs_mount_share(struct cifs_mount_ctx *mnt_ctx) if (!rc) { server = mnt_ctx->server; + tcon = mnt_ctx->tcon; mutex_lock(&server->refpath_lock); - server->origin_fullpath = origin_fullpath; - server->current_fullpath = server->leaf_fullpath; + if (!server->origin_fullpath) { + server->origin_fullpath = origin_fullpath; + server->current_fullpath = server->leaf_fullpath; + origin_fullpath = NULL; + } mutex_unlock(&server->refpath_lock); - origin_fullpath = NULL; + + if (list_empty(&tcon->dfs_ses_list)) { + list_replace_init(&mnt_ctx->dfs_ses_list, + &tcon->dfs_ses_list); + } else { + dfs_put_root_smb_sessions(&mnt_ctx->dfs_ses_list); + } } out: @@ -277,7 +301,9 @@ int dfs_mount_share(struct cifs_mount_ctx *mnt_ctx, bool *isdfs) } *isdfs = true; - set_root_ses(mnt_ctx); + rc = get_root_smb_session(mnt_ctx); + if (rc) + return rc; return __dfs_mount_share(mnt_ctx); } diff --git a/fs/cifs/dfs.h b/fs/cifs/dfs.h index baf16df55d7e7..13f26e01f7b97 100644 --- a/fs/cifs/dfs.h +++ b/fs/cifs/dfs.h @@ -10,6 +10,11 @@ #include "fs_context.h" #include "cifs_unicode.h" +struct dfs_root_ses { + struct list_head list; + struct cifs_ses *ses; +}; + int dfs_parse_target_referral(const char *full_path, const struct dfs_info3_param *ref, struct smb3_fs_context *ctx); int dfs_mount_share(struct cifs_mount_ctx *mnt_ctx, bool *isdfs); @@ -44,4 +49,15 @@ static inline char *dfs_get_automount_devname(struct dentry *dentry, void *page) true); } +static inline void dfs_put_root_smb_sessions(struct list_head *head) +{ + struct dfs_root_ses *root, *tmp; + + list_for_each_entry_safe(root, tmp, head, list) { + list_del_init(&root->list); + cifs_put_smb_ses(root->ses); + kfree(root); + } +} + #endif /* _CIFS_DFS_H */ diff --git a/fs/cifs/dfs_cache.c b/fs/cifs/dfs_cache.c index ac86bd0ebd637..1c59811bfa73a 100644 --- a/fs/cifs/dfs_cache.c +++ b/fs/cifs/dfs_cache.c @@ -49,17 +49,6 @@ struct cache_entry { struct cache_dfs_tgt *tgthint; }; -/* List of referral server sessions per dfs mount */ -struct mount_group { - struct list_head list; - uuid_t id; - struct cifs_ses *sessions[CACHE_MAX_ENTRIES]; - int num_sessions; - spinlock_t lock; - struct list_head refresh_list; - struct kref refcount; -}; - static struct kmem_cache *cache_slab __read_mostly; static struct workqueue_struct *dfscache_wq __read_mostly; @@ -76,85 +65,10 @@ static atomic_t cache_count; static struct hlist_head cache_htable[CACHE_HTABLE_SIZE]; static DECLARE_RWSEM(htable_rw_lock); -static LIST_HEAD(mount_group_list); -static DEFINE_MUTEX(mount_group_list_lock); - static void refresh_cache_worker(struct work_struct *work); static DECLARE_DELAYED_WORK(refresh_task, refresh_cache_worker); -static void __mount_group_release(struct mount_group *mg) -{ - int i; - - for (i = 0; i < mg->num_sessions; i++) - cifs_put_smb_ses(mg->sessions[i]); - kfree(mg); -} - -static void mount_group_release(struct kref *kref) -{ - struct mount_group *mg = container_of(kref, struct mount_group, refcount); - - mutex_lock(&mount_group_list_lock); - list_del(&mg->list); - mutex_unlock(&mount_group_list_lock); - __mount_group_release(mg); -} - -static struct mount_group *find_mount_group_locked(const uuid_t *id) -{ - struct mount_group *mg; - - list_for_each_entry(mg, &mount_group_list, list) { - if (uuid_equal(&mg->id, id)) - return mg; - } - return ERR_PTR(-ENOENT); -} - -static struct mount_group *__get_mount_group_locked(const uuid_t *id) -{ - struct mount_group *mg; - - mg = find_mount_group_locked(id); - if (!IS_ERR(mg)) - return mg; - - mg = kmalloc(sizeof(*mg), GFP_KERNEL); - if (!mg) - return ERR_PTR(-ENOMEM); - kref_init(&mg->refcount); - uuid_copy(&mg->id, id); - mg->num_sessions = 0; - spin_lock_init(&mg->lock); - list_add(&mg->list, &mount_group_list); - return mg; -} - -static struct mount_group *get_mount_group(const uuid_t *id) -{ - struct mount_group *mg; - - mutex_lock(&mount_group_list_lock); - mg = __get_mount_group_locked(id); - if (!IS_ERR(mg)) - kref_get(&mg->refcount); - mutex_unlock(&mount_group_list_lock); - - return mg; -} - -static void free_mount_group_list(void) -{ - struct mount_group *mg, *tmp_mg; - - list_for_each_entry_safe(mg, tmp_mg, &mount_group_list, list) { - list_del_init(&mg->list); - __mount_group_release(mg); - } -} - /** * dfs_cache_canonical_path - get a canonical DFS path * @@ -704,7 +618,6 @@ void dfs_cache_destroy(void) { cancel_delayed_work_sync(&refresh_task); unload_nls(cache_cp); - free_mount_group_list(); flush_cache_ents(); kmem_cache_destroy(cache_slab); destroy_workqueue(dfscache_wq); @@ -1111,54 +1024,6 @@ int dfs_cache_get_tgt_referral(const char *path, const struct dfs_cache_tgt_iter return rc; } -/** - * dfs_cache_add_refsrv_session - add SMB session of referral server - * - * @mount_id: mount group uuid to lookup. - * @ses: reference counted SMB session of referral server. - */ -void dfs_cache_add_refsrv_session(const uuid_t *mount_id, struct cifs_ses *ses) -{ - struct mount_group *mg; - - if (WARN_ON_ONCE(!mount_id || uuid_is_null(mount_id) || !ses)) - return; - - mg = get_mount_group(mount_id); - if (WARN_ON_ONCE(IS_ERR(mg))) - return; - - spin_lock(&mg->lock); - if (mg->num_sessions < ARRAY_SIZE(mg->sessions)) - mg->sessions[mg->num_sessions++] = ses; - spin_unlock(&mg->lock); - kref_put(&mg->refcount, mount_group_release); -} - -/** - * dfs_cache_put_refsrv_sessions - put all referral server sessions - * - * Put all SMB sessions from the given mount group id. - * - * @mount_id: mount group uuid to lookup. - */ -void dfs_cache_put_refsrv_sessions(const uuid_t *mount_id) -{ - struct mount_group *mg; - - if (!mount_id || uuid_is_null(mount_id)) - return; - - mutex_lock(&mount_group_list_lock); - mg = find_mount_group_locked(mount_id); - if (IS_ERR(mg)) { - mutex_unlock(&mount_group_list_lock); - return; - } - mutex_unlock(&mount_group_list_lock); - kref_put(&mg->refcount, mount_group_release); -} - /* Extract share from DFS target and return a pointer to prefix path or NULL */ static const char *parse_target_share(const char *target, char **share) { @@ -1384,11 +1249,6 @@ int dfs_cache_remount_fs(struct cifs_sb_info *cifs_sb) cifs_dbg(FYI, "%s: not a dfs mount\n", __func__); return 0; } - - if (uuid_is_null(&cifs_sb->dfs_mount_id)) { - cifs_dbg(FYI, "%s: no dfs mount group id\n", __func__); - return -EINVAL; - } /* * After reconnecting to a different server, unique ids won't match anymore, so we disable * serverino. This prevents dentry revalidation to think the dentry are stale (ESTALE). diff --git a/fs/cifs/dfs_cache.h b/fs/cifs/dfs_cache.h index be3b5a44cf827..e0d39393035a9 100644 --- a/fs/cifs/dfs_cache.h +++ b/fs/cifs/dfs_cache.h @@ -40,8 +40,6 @@ int dfs_cache_get_tgt_referral(const char *path, const struct dfs_cache_tgt_iter struct dfs_info3_param *ref); int dfs_cache_get_tgt_share(char *path, const struct dfs_cache_tgt_iterator *it, char **share, char **prefix); -void dfs_cache_put_refsrv_sessions(const uuid_t *mount_id); -void dfs_cache_add_refsrv_session(const uuid_t *mount_id, struct cifs_ses *ses); char *dfs_cache_canonical_path(const char *path, const struct nls_table *cp, int remap); int dfs_cache_remount_fs(struct cifs_sb_info *cifs_sb); diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index a0d286ee723dd..6f9c78650528a 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -22,6 +22,7 @@ #ifdef CONFIG_CIFS_DFS_UPCALL #include "dns_resolve.h" #include "dfs_cache.h" +#include "dfs.h" #endif #include "fs_context.h" #include "cached_dir.h" @@ -134,6 +135,9 @@ tconInfoAlloc(void) spin_lock_init(&ret_buf->stat_lock); atomic_set(&ret_buf->num_local_opens, 0); atomic_set(&ret_buf->num_remote_opens, 0); +#ifdef CONFIG_CIFS_DFS_UPCALL + INIT_LIST_HEAD(&ret_buf->dfs_ses_list); +#endif return ret_buf; } @@ -149,6 +153,9 @@ tconInfoFree(struct cifs_tcon *tcon) atomic_dec(&tconInfoAllocCount); kfree(tcon->nativeFileSystem); kfree_sensitive(tcon->password); +#ifdef CONFIG_CIFS_DFS_UPCALL + dfs_put_root_smb_sessions(&tcon->dfs_ses_list); +#endif kfree(tcon); } From 47dd902aaee9b9341808a3a994793199e7eddb88 Mon Sep 17 00:00:00 2001 From: Dylan Jhong Date: Fri, 10 Mar 2023 15:50:21 +0800 Subject: [PATCH 354/460] RISC-V: mm: Support huge page in vmalloc_fault() Since RISC-V supports ioremap() with huge page (pud/pmd) mapping, However, vmalloc_fault() assumes that the vmalloc range is limited to pte mappings. To complete the vmalloc_fault() function by adding huge page support. Fixes: 310f541a027b ("riscv: Enable HAVE_ARCH_HUGE_VMAP for 64BIT") Cc: stable@vger.kernel.org Signed-off-by: Dylan Jhong Reviewed-by: Alexandre Ghiti Link: https://lore.kernel.org/r/20230310075021.3919290-1-dylan@andestech.com Signed-off-by: Palmer Dabbelt --- arch/riscv/mm/fault.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/riscv/mm/fault.c b/arch/riscv/mm/fault.c index 460f785f6e09c..d5f3e501dffb3 100644 --- a/arch/riscv/mm/fault.c +++ b/arch/riscv/mm/fault.c @@ -143,6 +143,8 @@ static inline void vmalloc_fault(struct pt_regs *regs, int code, unsigned long a no_context(regs, addr); return; } + if (pud_leaf(*pud_k)) + goto flush_tlb; /* * Since the vmalloc area is global, it is unnecessary @@ -153,6 +155,8 @@ static inline void vmalloc_fault(struct pt_regs *regs, int code, unsigned long a no_context(regs, addr); return; } + if (pmd_leaf(*pmd_k)) + goto flush_tlb; /* * Make sure the actual PTE exists as well to @@ -172,6 +176,7 @@ static inline void vmalloc_fault(struct pt_regs *regs, int code, unsigned long a * ordering constraint, not a cache flush; it is * necessary even after writing invalid entries. */ +flush_tlb: local_flush_tlb_page(addr); } From 6015b1aca1a233379625385feb01dd014aca60b5 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 14 Mar 2023 19:32:38 -0700 Subject: [PATCH 355/460] sched_getaffinity: don't assume 'cpumask_size()' is fully initialized The getaffinity() system call uses 'cpumask_size()' to decide how big the CPU mask is - so far so good. It is indeed the allocation size of a cpumask. But the code also assumes that the whole allocation is initialized without actually doing so itself. That's wrong, because we might have fixed-size allocations (making copying and clearing more efficient), but not all of it is then necessarily used if 'nr_cpu_ids' is smaller. Having checked other users of 'cpumask_size()', they all seem to be ok, either using it purely for the allocation size, or explicitly zeroing the cpumask before using the size in bytes to copy it. See for example the ublk_ctrl_get_queue_affinity() function that uses the proper 'zalloc_cpumask_var()' to make sure that the whole mask is cleared, whether the storage is on the stack or if it was an external allocation. Fix this by just zeroing the allocation before using it. Do the same for the compat version of sched_getaffinity(), which had the same logic. Also, for consistency, make sched_getaffinity() use 'cpumask_bits()' to access the bits. For a cpumask_var_t, it ends up being a pointer to the same data either way, but it's just a good idea to treat it like you would a 'cpumask_t'. The compat case already did that. Reported-by: Ryan Roberts Link: https://lore.kernel.org/lkml/7d026744-6bd6-6827-0471-b5e8eae0be3f@arm.com/ Cc: Yury Norov Signed-off-by: Linus Torvalds --- kernel/compat.c | 2 +- kernel/sched/core.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel/compat.c b/kernel/compat.c index 55551989d9da5..fb50f29d9b361 100644 --- a/kernel/compat.c +++ b/kernel/compat.c @@ -152,7 +152,7 @@ COMPAT_SYSCALL_DEFINE3(sched_getaffinity, compat_pid_t, pid, unsigned int, len, if (len & (sizeof(compat_ulong_t)-1)) return -EINVAL; - if (!alloc_cpumask_var(&mask, GFP_KERNEL)) + if (!zalloc_cpumask_var(&mask, GFP_KERNEL)) return -ENOMEM; ret = sched_getaffinity(pid, mask); diff --git a/kernel/sched/core.c b/kernel/sched/core.c index af017e038b482..488655f2319f5 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -8414,14 +8414,14 @@ SYSCALL_DEFINE3(sched_getaffinity, pid_t, pid, unsigned int, len, if (len & (sizeof(unsigned long)-1)) return -EINVAL; - if (!alloc_cpumask_var(&mask, GFP_KERNEL)) + if (!zalloc_cpumask_var(&mask, GFP_KERNEL)) return -ENOMEM; ret = sched_getaffinity(pid, mask); if (ret == 0) { unsigned int retlen = min(len, cpumask_size()); - if (copy_to_user(user_mask_ptr, mask, retlen)) + if (copy_to_user(user_mask_ptr, cpumask_bits(mask), retlen)) ret = -EFAULT; else ret = retlen; From f446a630802f154ef0087771683bd4f8e9d08384 Mon Sep 17 00:00:00 2001 From: Paulo Alcantara Date: Tue, 14 Mar 2023 20:32:55 -0300 Subject: [PATCH 356/460] cifs: return DFS root session id in DebugData Return the DFS root session id in /proc/fs/cifs/DebugData to make it easier to track which IPC tcon was used to get new DFS referrals for a specific connection, and aids in debugging. A simple output of it would be Sessions: 1) Address: 192.168.1.13 Uses: 1 Capability: 0x300067 Session Status: 1 Security type: RawNTLMSSP SessionId: 0xd80000000009 User: 0 Cred User: 0 DFS root session id: 0x128006c000035 Signed-off-by: Paulo Alcantara (SUSE) Cc: stable@vger.kernel.org # 6.2 Signed-off-by: Steve French --- fs/cifs/cifs_debug.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c index 1911f7016fa1d..19a70a69c7603 100644 --- a/fs/cifs/cifs_debug.c +++ b/fs/cifs/cifs_debug.c @@ -420,6 +420,11 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v) from_kuid(&init_user_ns, ses->linux_uid), from_kuid(&init_user_ns, ses->cred_uid)); + if (ses->dfs_root_ses) { + seq_printf(m, "\n\tDFS root session id: 0x%llx", + ses->dfs_root_ses->Suid); + } + spin_lock(&ses->chan_lock); if (CIFS_CHAN_NEEDS_RECONNECT(ses, 0)) seq_puts(m, "\tPrimary channel: DISCONNECTED "); From 6284e46bdd47743a064fe6ac834a7ac05b1fd206 Mon Sep 17 00:00:00 2001 From: Paulo Alcantara Date: Tue, 14 Mar 2023 20:32:56 -0300 Subject: [PATCH 357/460] cifs: use DFS root session instead of tcon ses Use DFS root session whenever possible to get new DFS referrals otherwise we might end up with an IPC tcon (tcon->ses->tcon_ipc) that doesn't respond to them. It should be safe accessing @ses->dfs_root_ses directly in cifs_inval_name_dfs_link_error() as it has same lifetime as of @tcon. Signed-off-by: Paulo Alcantara (SUSE) Cc: stable@vger.kernel.org # 6.2 Signed-off-by: Steve French --- fs/cifs/misc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 6f9c78650528a..b44fb51968bfb 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -1262,6 +1262,7 @@ int cifs_inval_name_dfs_link_error(const unsigned int xid, * removing cached DFS targets that the client would eventually * need during failover. */ + ses = CIFS_DFS_ROOT_SES(ses); if (ses->server->ops->get_dfs_refer && !ses->server->ops->get_dfs_refer(xid, ses, ref_path, &refs, &num_refs, cifs_sb->local_nls, From 248401cb2c4612d83eb0c352ee8103b78b8eb365 Mon Sep 17 00:00:00 2001 From: Dave Ertman Date: Fri, 10 Mar 2023 11:48:33 -0800 Subject: [PATCH 358/460] ice: avoid bonding causing auxiliary plug/unplug under RTNL lock RDMA is not supported in ice on a PF that has been added to a bonded interface. To enforce this, when an interface enters a bond, we unplug the auxiliary device that supports RDMA functionality. This unplug currently happens in the context of handling the netdev bonding event. This event is sent to the ice driver under RTNL context. This is causing a deadlock where the RDMA driver is waiting for the RTNL lock to complete the removal. Defer the unplugging/re-plugging of the auxiliary device to the service task so that it is not performed under the RTNL lock context. Cc: stable@vger.kernel.org # 6.1.x Reported-by: Jaroslav Pulchart Link: https://lore.kernel.org/netdev/CAK8fFZ6A_Gphw_3-QMGKEFQk=sfCw1Qmq0TVZK3rtAi7vb621A@mail.gmail.com/ Fixes: 5cb1ebdbc434 ("ice: Fix race condition during interface enslave") Fixes: 4eace75e0853 ("RDMA/irdma: Report the correct link speed") Signed-off-by: Dave Ertman Tested-by: Arpana Arland (A Contingent worker at Intel) Signed-off-by: Tony Nguyen Reviewed-by: Leon Romanovsky Link: https://lore.kernel.org/r/20230310194833.3074601-1-anthony.l.nguyen@intel.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/intel/ice/ice.h | 14 +++++--------- drivers/net/ethernet/intel/ice/ice_main.c | 19 ++++++++----------- 2 files changed, 13 insertions(+), 20 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h index b0e29e3424018..e809249500e18 100644 --- a/drivers/net/ethernet/intel/ice/ice.h +++ b/drivers/net/ethernet/intel/ice/ice.h @@ -509,6 +509,7 @@ enum ice_pf_flags { ICE_FLAG_VF_VLAN_PRUNING, ICE_FLAG_LINK_LENIENT_MODE_ENA, ICE_FLAG_PLUG_AUX_DEV, + ICE_FLAG_UNPLUG_AUX_DEV, ICE_FLAG_MTU_CHANGED, ICE_FLAG_GNSS, /* GNSS successfully initialized */ ICE_PF_FLAGS_NBITS /* must be last */ @@ -955,16 +956,11 @@ static inline void ice_set_rdma_cap(struct ice_pf *pf) */ static inline void ice_clear_rdma_cap(struct ice_pf *pf) { - /* We can directly unplug aux device here only if the flag bit - * ICE_FLAG_PLUG_AUX_DEV is not set because ice_unplug_aux_dev() - * could race with ice_plug_aux_dev() called from - * ice_service_task(). In this case we only clear that bit now and - * aux device will be unplugged later once ice_plug_aux_device() - * called from ice_service_task() finishes (see ice_service_task()). + /* defer unplug to service task to avoid RTNL lock and + * clear PLUG bit so that pending plugs don't interfere */ - if (!test_and_clear_bit(ICE_FLAG_PLUG_AUX_DEV, pf->flags)) - ice_unplug_aux_dev(pf); - + clear_bit(ICE_FLAG_PLUG_AUX_DEV, pf->flags); + set_bit(ICE_FLAG_UNPLUG_AUX_DEV, pf->flags); clear_bit(ICE_FLAG_RDMA_ENA, pf->flags); } #endif /* _ICE_H_ */ diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index 567694bf098ba..c233464b8f6bf 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -2316,18 +2316,15 @@ static void ice_service_task(struct work_struct *work) } } - if (test_bit(ICE_FLAG_PLUG_AUX_DEV, pf->flags)) { - /* Plug aux device per request */ - ice_plug_aux_dev(pf); + /* unplug aux dev per request, if an unplug request came in + * while processing a plug request, this will handle it + */ + if (test_and_clear_bit(ICE_FLAG_UNPLUG_AUX_DEV, pf->flags)) + ice_unplug_aux_dev(pf); - /* Mark plugging as done but check whether unplug was - * requested during ice_plug_aux_dev() call - * (e.g. from ice_clear_rdma_cap()) and if so then - * plug aux device. - */ - if (!test_and_clear_bit(ICE_FLAG_PLUG_AUX_DEV, pf->flags)) - ice_unplug_aux_dev(pf); - } + /* Plug aux device per request */ + if (test_and_clear_bit(ICE_FLAG_PLUG_AUX_DEV, pf->flags)) + ice_plug_aux_dev(pf); if (test_and_clear_bit(ICE_FLAG_MTU_CHANGED, pf->flags)) { struct iidc_event *event; From 4b397c06cb987935b1b097336532aa6b4210e091 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 10 Mar 2023 19:11:09 +0000 Subject: [PATCH 359/460] net: tunnels: annotate lockless accesses to dev->needed_headroom IP tunnels can apparently update dev->needed_headroom in their xmit path. This patch takes care of three tunnels xmit, and also the core LL_RESERVED_SPACE() and LL_RESERVED_SPACE_EXTRA() helpers. More changes might be needed for completeness. BUG: KCSAN: data-race in ip_tunnel_xmit / ip_tunnel_xmit read to 0xffff88815b9da0ec of 2 bytes by task 888 on cpu 1: ip_tunnel_xmit+0x1270/0x1730 net/ipv4/ip_tunnel.c:803 __gre_xmit net/ipv4/ip_gre.c:469 [inline] ipgre_xmit+0x516/0x570 net/ipv4/ip_gre.c:661 __netdev_start_xmit include/linux/netdevice.h:4881 [inline] netdev_start_xmit include/linux/netdevice.h:4895 [inline] xmit_one net/core/dev.c:3580 [inline] dev_hard_start_xmit+0x127/0x400 net/core/dev.c:3596 __dev_queue_xmit+0x1007/0x1eb0 net/core/dev.c:4246 dev_queue_xmit include/linux/netdevice.h:3051 [inline] neigh_direct_output+0x17/0x20 net/core/neighbour.c:1623 neigh_output include/net/neighbour.h:546 [inline] ip_finish_output2+0x740/0x840 net/ipv4/ip_output.c:228 ip_finish_output+0xf4/0x240 net/ipv4/ip_output.c:316 NF_HOOK_COND include/linux/netfilter.h:291 [inline] ip_output+0xe5/0x1b0 net/ipv4/ip_output.c:430 dst_output include/net/dst.h:444 [inline] ip_local_out+0x64/0x80 net/ipv4/ip_output.c:126 iptunnel_xmit+0x34a/0x4b0 net/ipv4/ip_tunnel_core.c:82 ip_tunnel_xmit+0x1451/0x1730 net/ipv4/ip_tunnel.c:813 __gre_xmit net/ipv4/ip_gre.c:469 [inline] ipgre_xmit+0x516/0x570 net/ipv4/ip_gre.c:661 __netdev_start_xmit include/linux/netdevice.h:4881 [inline] netdev_start_xmit include/linux/netdevice.h:4895 [inline] xmit_one net/core/dev.c:3580 [inline] dev_hard_start_xmit+0x127/0x400 net/core/dev.c:3596 __dev_queue_xmit+0x1007/0x1eb0 net/core/dev.c:4246 dev_queue_xmit include/linux/netdevice.h:3051 [inline] neigh_direct_output+0x17/0x20 net/core/neighbour.c:1623 neigh_output include/net/neighbour.h:546 [inline] ip_finish_output2+0x740/0x840 net/ipv4/ip_output.c:228 ip_finish_output+0xf4/0x240 net/ipv4/ip_output.c:316 NF_HOOK_COND include/linux/netfilter.h:291 [inline] ip_output+0xe5/0x1b0 net/ipv4/ip_output.c:430 dst_output include/net/dst.h:444 [inline] ip_local_out+0x64/0x80 net/ipv4/ip_output.c:126 iptunnel_xmit+0x34a/0x4b0 net/ipv4/ip_tunnel_core.c:82 ip_tunnel_xmit+0x1451/0x1730 net/ipv4/ip_tunnel.c:813 __gre_xmit net/ipv4/ip_gre.c:469 [inline] ipgre_xmit+0x516/0x570 net/ipv4/ip_gre.c:661 __netdev_start_xmit include/linux/netdevice.h:4881 [inline] netdev_start_xmit include/linux/netdevice.h:4895 [inline] xmit_one net/core/dev.c:3580 [inline] dev_hard_start_xmit+0x127/0x400 net/core/dev.c:3596 __dev_queue_xmit+0x1007/0x1eb0 net/core/dev.c:4246 dev_queue_xmit include/linux/netdevice.h:3051 [inline] neigh_direct_output+0x17/0x20 net/core/neighbour.c:1623 neigh_output include/net/neighbour.h:546 [inline] ip_finish_output2+0x740/0x840 net/ipv4/ip_output.c:228 ip_finish_output+0xf4/0x240 net/ipv4/ip_output.c:316 NF_HOOK_COND include/linux/netfilter.h:291 [inline] ip_output+0xe5/0x1b0 net/ipv4/ip_output.c:430 dst_output include/net/dst.h:444 [inline] ip_local_out+0x64/0x80 net/ipv4/ip_output.c:126 iptunnel_xmit+0x34a/0x4b0 net/ipv4/ip_tunnel_core.c:82 ip_tunnel_xmit+0x1451/0x1730 net/ipv4/ip_tunnel.c:813 __gre_xmit net/ipv4/ip_gre.c:469 [inline] ipgre_xmit+0x516/0x570 net/ipv4/ip_gre.c:661 __netdev_start_xmit include/linux/netdevice.h:4881 [inline] netdev_start_xmit include/linux/netdevice.h:4895 [inline] xmit_one net/core/dev.c:3580 [inline] dev_hard_start_xmit+0x127/0x400 net/core/dev.c:3596 __dev_queue_xmit+0x1007/0x1eb0 net/core/dev.c:4246 dev_queue_xmit include/linux/netdevice.h:3051 [inline] neigh_direct_output+0x17/0x20 net/core/neighbour.c:1623 neigh_output include/net/neighbour.h:546 [inline] ip_finish_output2+0x740/0x840 net/ipv4/ip_output.c:228 ip_finish_output+0xf4/0x240 net/ipv4/ip_output.c:316 NF_HOOK_COND include/linux/netfilter.h:291 [inline] ip_output+0xe5/0x1b0 net/ipv4/ip_output.c:430 dst_output include/net/dst.h:444 [inline] ip_local_out+0x64/0x80 net/ipv4/ip_output.c:126 iptunnel_xmit+0x34a/0x4b0 net/ipv4/ip_tunnel_core.c:82 ip_tunnel_xmit+0x1451/0x1730 net/ipv4/ip_tunnel.c:813 __gre_xmit net/ipv4/ip_gre.c:469 [inline] ipgre_xmit+0x516/0x570 net/ipv4/ip_gre.c:661 __netdev_start_xmit include/linux/netdevice.h:4881 [inline] netdev_start_xmit include/linux/netdevice.h:4895 [inline] xmit_one net/core/dev.c:3580 [inline] dev_hard_start_xmit+0x127/0x400 net/core/dev.c:3596 __dev_queue_xmit+0x1007/0x1eb0 net/core/dev.c:4246 dev_queue_xmit include/linux/netdevice.h:3051 [inline] neigh_direct_output+0x17/0x20 net/core/neighbour.c:1623 neigh_output include/net/neighbour.h:546 [inline] ip_finish_output2+0x740/0x840 net/ipv4/ip_output.c:228 ip_finish_output+0xf4/0x240 net/ipv4/ip_output.c:316 NF_HOOK_COND include/linux/netfilter.h:291 [inline] ip_output+0xe5/0x1b0 net/ipv4/ip_output.c:430 dst_output include/net/dst.h:444 [inline] ip_local_out+0x64/0x80 net/ipv4/ip_output.c:126 iptunnel_xmit+0x34a/0x4b0 net/ipv4/ip_tunnel_core.c:82 ip_tunnel_xmit+0x1451/0x1730 net/ipv4/ip_tunnel.c:813 __gre_xmit net/ipv4/ip_gre.c:469 [inline] ipgre_xmit+0x516/0x570 net/ipv4/ip_gre.c:661 __netdev_start_xmit include/linux/netdevice.h:4881 [inline] netdev_start_xmit include/linux/netdevice.h:4895 [inline] xmit_one net/core/dev.c:3580 [inline] dev_hard_start_xmit+0x127/0x400 net/core/dev.c:3596 __dev_queue_xmit+0x1007/0x1eb0 net/core/dev.c:4246 dev_queue_xmit include/linux/netdevice.h:3051 [inline] neigh_direct_output+0x17/0x20 net/core/neighbour.c:1623 neigh_output include/net/neighbour.h:546 [inline] ip_finish_output2+0x740/0x840 net/ipv4/ip_output.c:228 ip_finish_output+0xf4/0x240 net/ipv4/ip_output.c:316 NF_HOOK_COND include/linux/netfilter.h:291 [inline] ip_output+0xe5/0x1b0 net/ipv4/ip_output.c:430 dst_output include/net/dst.h:444 [inline] ip_local_out+0x64/0x80 net/ipv4/ip_output.c:126 iptunnel_xmit+0x34a/0x4b0 net/ipv4/ip_tunnel_core.c:82 ip_tunnel_xmit+0x1451/0x1730 net/ipv4/ip_tunnel.c:813 __gre_xmit net/ipv4/ip_gre.c:469 [inline] ipgre_xmit+0x516/0x570 net/ipv4/ip_gre.c:661 __netdev_start_xmit include/linux/netdevice.h:4881 [inline] netdev_start_xmit include/linux/netdevice.h:4895 [inline] xmit_one net/core/dev.c:3580 [inline] dev_hard_start_xmit+0x127/0x400 net/core/dev.c:3596 __dev_queue_xmit+0x1007/0x1eb0 net/core/dev.c:4246 write to 0xffff88815b9da0ec of 2 bytes by task 2379 on cpu 0: ip_tunnel_xmit+0x1294/0x1730 net/ipv4/ip_tunnel.c:804 __gre_xmit net/ipv4/ip_gre.c:469 [inline] ipgre_xmit+0x516/0x570 net/ipv4/ip_gre.c:661 __netdev_start_xmit include/linux/netdevice.h:4881 [inline] netdev_start_xmit include/linux/netdevice.h:4895 [inline] xmit_one net/core/dev.c:3580 [inline] dev_hard_start_xmit+0x127/0x400 net/core/dev.c:3596 __dev_queue_xmit+0x1007/0x1eb0 net/core/dev.c:4246 dev_queue_xmit include/linux/netdevice.h:3051 [inline] neigh_direct_output+0x17/0x20 net/core/neighbour.c:1623 neigh_output include/net/neighbour.h:546 [inline] ip6_finish_output2+0x9bc/0xc50 net/ipv6/ip6_output.c:134 __ip6_finish_output net/ipv6/ip6_output.c:195 [inline] ip6_finish_output+0x39a/0x4e0 net/ipv6/ip6_output.c:206 NF_HOOK_COND include/linux/netfilter.h:291 [inline] ip6_output+0xeb/0x220 net/ipv6/ip6_output.c:227 dst_output include/net/dst.h:444 [inline] NF_HOOK include/linux/netfilter.h:302 [inline] mld_sendpack+0x438/0x6a0 net/ipv6/mcast.c:1820 mld_send_cr net/ipv6/mcast.c:2121 [inline] mld_ifc_work+0x519/0x7b0 net/ipv6/mcast.c:2653 process_one_work+0x3e6/0x750 kernel/workqueue.c:2390 worker_thread+0x5f2/0xa10 kernel/workqueue.c:2537 kthread+0x1ac/0x1e0 kernel/kthread.c:376 ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:308 value changed: 0x0dd4 -> 0x0e14 Reported by Kernel Concurrency Sanitizer on: CPU: 0 PID: 2379 Comm: kworker/0:0 Not tainted 6.3.0-rc1-syzkaller-00002-g8ca09d5fa354-dirty #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 03/02/2023 Workqueue: mld mld_ifc_work Fixes: 8eb30be0352d ("ipv6: Create ip6_tnl_xmit") Reported-by: syzbot Signed-off-by: Eric Dumazet Link: https://lore.kernel.org/r/20230310191109.2384387-1-edumazet@google.com Signed-off-by: Jakub Kicinski --- include/linux/netdevice.h | 6 ++++-- net/ipv4/ip_tunnel.c | 12 ++++++------ net/ipv6/ip6_tunnel.c | 4 ++-- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 6a14b7b117668..470085b121d3c 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -297,9 +297,11 @@ struct hh_cache { * relationship HH alignment <= LL alignment. */ #define LL_RESERVED_SPACE(dev) \ - ((((dev)->hard_header_len+(dev)->needed_headroom)&~(HH_DATA_MOD - 1)) + HH_DATA_MOD) + ((((dev)->hard_header_len + READ_ONCE((dev)->needed_headroom)) \ + & ~(HH_DATA_MOD - 1)) + HH_DATA_MOD) #define LL_RESERVED_SPACE_EXTRA(dev,extra) \ - ((((dev)->hard_header_len+(dev)->needed_headroom+(extra))&~(HH_DATA_MOD - 1)) + HH_DATA_MOD) + ((((dev)->hard_header_len + READ_ONCE((dev)->needed_headroom) + (extra)) \ + & ~(HH_DATA_MOD - 1)) + HH_DATA_MOD) struct header_ops { int (*create) (struct sk_buff *skb, struct net_device *dev, diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index de90b09dfe78f..2541083d49ad6 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c @@ -614,10 +614,10 @@ void ip_md_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, } headroom += LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len; - if (headroom > dev->needed_headroom) - dev->needed_headroom = headroom; + if (headroom > READ_ONCE(dev->needed_headroom)) + WRITE_ONCE(dev->needed_headroom, headroom); - if (skb_cow_head(skb, dev->needed_headroom)) { + if (skb_cow_head(skb, READ_ONCE(dev->needed_headroom))) { ip_rt_put(rt); goto tx_dropped; } @@ -800,10 +800,10 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, max_headroom = LL_RESERVED_SPACE(rt->dst.dev) + sizeof(struct iphdr) + rt->dst.header_len + ip_encap_hlen(&tunnel->encap); - if (max_headroom > dev->needed_headroom) - dev->needed_headroom = max_headroom; + if (max_headroom > READ_ONCE(dev->needed_headroom)) + WRITE_ONCE(dev->needed_headroom, max_headroom); - if (skb_cow_head(skb, dev->needed_headroom)) { + if (skb_cow_head(skb, READ_ONCE(dev->needed_headroom))) { ip_rt_put(rt); DEV_STATS_INC(dev, tx_dropped); kfree_skb(skb); diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 47b6607a13706..5e80e517f0710 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -1240,8 +1240,8 @@ int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield, */ max_headroom = LL_RESERVED_SPACE(dst->dev) + sizeof(struct ipv6hdr) + dst->header_len + t->hlen; - if (max_headroom > dev->needed_headroom) - dev->needed_headroom = max_headroom; + if (max_headroom > READ_ONCE(dev->needed_headroom)) + WRITE_ONCE(dev->needed_headroom, max_headroom); err = ip6_tnl_encap(skb, t, &proto, fl6); if (err) From c22c3bbf351e4ce905f082649cffa1ff893ea8c1 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sat, 11 Mar 2023 19:34:45 +0100 Subject: [PATCH 360/460] net: phy: smsc: bail out in lan87xx_read_status if genphy_read_status fails If genphy_read_status fails then further access to the PHY may result in unpredictable behavior. To prevent this bail out immediately if genphy_read_status fails. Fixes: 4223dbffed9f ("net: phy: smsc: Re-enable EDPD mode for LAN87xx") Signed-off-by: Heiner Kallweit Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/026aa4f2-36f5-1c10-ab9f-cdb17dda6ac4@gmail.com Signed-off-by: Jakub Kicinski --- drivers/net/phy/smsc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c index 00d9eff91dcfa..df2c5435c5c49 100644 --- a/drivers/net/phy/smsc.c +++ b/drivers/net/phy/smsc.c @@ -199,8 +199,11 @@ static int lan95xx_config_aneg_ext(struct phy_device *phydev) static int lan87xx_read_status(struct phy_device *phydev) { struct smsc_phy_priv *priv = phydev->priv; + int err; - int err = genphy_read_status(phydev); + err = genphy_read_status(phydev); + if (err) + return err; if (!phydev->link && priv->energy_enable && phydev->irq == PHY_POLL) { /* Disable EDPD to wake up PHY */ From d9ba9934285514f1f95d96326a82398a22dc77f2 Mon Sep 17 00:00:00 2001 From: Kuniyuki Iwashima Date: Sat, 11 Mar 2023 19:19:03 -0800 Subject: [PATCH 361/460] tcp: Fix bind() conflict check for dual-stack wildcard address. Paul Holzinger reported [0] that commit 5456262d2baa ("net: Fix incorrect address comparison when searching for a bind2 bucket") introduced a bind() regression. Paul also gave a nice repro that calls two types of bind() on the same port, both of which now succeed, but the second call should fail: bind(fd1, ::, port) + bind(fd2, 127.0.0.1, port) The cited commit added address family tests in three functions to fix the uninit-value KMSAN report. [1] However, the test added to inet_bind2_bucket_match_addr_any() removed a necessary conflict check; the dual-stack wildcard address no longer conflicts with an IPv4 non-wildcard address. If tb->family is AF_INET6 and sk->sk_family is AF_INET in inet_bind2_bucket_match_addr_any(), we still need to check if tb has the dual-stack wildcard address. Note that the IPv4 wildcard address does not conflict with IPv6 non-wildcard addresses. [0]: https://lore.kernel.org/netdev/e21bf153-80b0-9ec0-15ba-e04a4ad42c34@redhat.com/ [1]: https://lore.kernel.org/netdev/CAG_fn=Ud3zSW7AZWXc+asfMhZVL5ETnvuY44Pmyv4NPv-ijN-A@mail.gmail.com/ Fixes: 5456262d2baa ("net: Fix incorrect address comparison when searching for a bind2 bucket") Signed-off-by: Kuniyuki Iwashima Reported-by: Paul Holzinger Link: https://lore.kernel.org/netdev/CAG_fn=Ud3zSW7AZWXc+asfMhZVL5ETnvuY44Pmyv4NPv-ijN-A@mail.gmail.com/ Reviewed-by: Eric Dumazet Tested-by: Paul Holzinger Reviewed-by: Martin KaFai Lau Signed-off-by: Jakub Kicinski --- net/ipv4/inet_hashtables.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c index e41fdc38ce196..6edae38868855 100644 --- a/net/ipv4/inet_hashtables.c +++ b/net/ipv4/inet_hashtables.c @@ -828,8 +828,14 @@ bool inet_bind2_bucket_match_addr_any(const struct inet_bind2_bucket *tb, const #if IS_ENABLED(CONFIG_IPV6) struct in6_addr addr_any = {}; - if (sk->sk_family != tb->family) + if (sk->sk_family != tb->family) { + if (sk->sk_family == AF_INET) + return net_eq(ib2_net(tb), net) && tb->port == port && + tb->l3mdev == l3mdev && + ipv6_addr_equal(&tb->v6_rcv_saddr, &addr_any); + return false; + } if (sk->sk_family == AF_INET6) return net_eq(ib2_net(tb), net) && tb->port == port && From 13715acf8ab5b32a6d7e42686fceeb66df114185 Mon Sep 17 00:00:00 2001 From: Kuniyuki Iwashima Date: Sat, 11 Mar 2023 19:19:04 -0800 Subject: [PATCH 362/460] selftest: Add test for bind() conflicts. The test checks if (IPv4, IPv6) address pair properly conflict or not. * IPv4 * 0.0.0.0 * 127.0.0.1 * IPv6 * :: * ::1 If the IPv6 address is [::], the second bind() always fails. Signed-off-by: Kuniyuki Iwashima Signed-off-by: Jakub Kicinski --- tools/testing/selftests/net/.gitignore | 1 + tools/testing/selftests/net/Makefile | 1 + tools/testing/selftests/net/bind_wildcard.c | 114 ++++++++++++++++++++ 3 files changed, 116 insertions(+) create mode 100644 tools/testing/selftests/net/bind_wildcard.c diff --git a/tools/testing/selftests/net/.gitignore b/tools/testing/selftests/net/.gitignore index a6911cae368c7..80f06aa620345 100644 --- a/tools/testing/selftests/net/.gitignore +++ b/tools/testing/selftests/net/.gitignore @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only bind_bhash bind_timewait +bind_wildcard csum cmsg_sender diag_uid diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile index 6cd8993454d7e..80fbfe0330f6e 100644 --- a/tools/testing/selftests/net/Makefile +++ b/tools/testing/selftests/net/Makefile @@ -80,6 +80,7 @@ TEST_GEN_FILES += sctp_hello TEST_GEN_FILES += csum TEST_GEN_FILES += nat6to4.o TEST_GEN_FILES += ip_local_port_range +TEST_GEN_FILES += bind_wildcard TEST_FILES := settings diff --git a/tools/testing/selftests/net/bind_wildcard.c b/tools/testing/selftests/net/bind_wildcard.c new file mode 100644 index 0000000000000..58edfc15d28bd --- /dev/null +++ b/tools/testing/selftests/net/bind_wildcard.c @@ -0,0 +1,114 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright Amazon.com Inc. or its affiliates. */ + +#include +#include + +#include "../kselftest_harness.h" + +FIXTURE(bind_wildcard) +{ + struct sockaddr_in addr4; + struct sockaddr_in6 addr6; + int expected_errno; +}; + +FIXTURE_VARIANT(bind_wildcard) +{ + const __u32 addr4_const; + const struct in6_addr *addr6_const; +}; + +FIXTURE_VARIANT_ADD(bind_wildcard, v4_any_v6_any) +{ + .addr4_const = INADDR_ANY, + .addr6_const = &in6addr_any, +}; + +FIXTURE_VARIANT_ADD(bind_wildcard, v4_any_v6_local) +{ + .addr4_const = INADDR_ANY, + .addr6_const = &in6addr_loopback, +}; + +FIXTURE_VARIANT_ADD(bind_wildcard, v4_local_v6_any) +{ + .addr4_const = INADDR_LOOPBACK, + .addr6_const = &in6addr_any, +}; + +FIXTURE_VARIANT_ADD(bind_wildcard, v4_local_v6_local) +{ + .addr4_const = INADDR_LOOPBACK, + .addr6_const = &in6addr_loopback, +}; + +FIXTURE_SETUP(bind_wildcard) +{ + self->addr4.sin_family = AF_INET; + self->addr4.sin_port = htons(0); + self->addr4.sin_addr.s_addr = htonl(variant->addr4_const); + + self->addr6.sin6_family = AF_INET6; + self->addr6.sin6_port = htons(0); + self->addr6.sin6_addr = *variant->addr6_const; + + if (variant->addr6_const == &in6addr_any) + self->expected_errno = EADDRINUSE; + else + self->expected_errno = 0; +} + +FIXTURE_TEARDOWN(bind_wildcard) +{ +} + +void bind_sockets(struct __test_metadata *_metadata, + FIXTURE_DATA(bind_wildcard) *self, + struct sockaddr *addr1, socklen_t addrlen1, + struct sockaddr *addr2, socklen_t addrlen2) +{ + int fd[2]; + int ret; + + fd[0] = socket(addr1->sa_family, SOCK_STREAM, 0); + ASSERT_GT(fd[0], 0); + + ret = bind(fd[0], addr1, addrlen1); + ASSERT_EQ(ret, 0); + + ret = getsockname(fd[0], addr1, &addrlen1); + ASSERT_EQ(ret, 0); + + ((struct sockaddr_in *)addr2)->sin_port = ((struct sockaddr_in *)addr1)->sin_port; + + fd[1] = socket(addr2->sa_family, SOCK_STREAM, 0); + ASSERT_GT(fd[1], 0); + + ret = bind(fd[1], addr2, addrlen2); + if (self->expected_errno) { + ASSERT_EQ(ret, -1); + ASSERT_EQ(errno, self->expected_errno); + } else { + ASSERT_EQ(ret, 0); + } + + close(fd[1]); + close(fd[0]); +} + +TEST_F(bind_wildcard, v4_v6) +{ + bind_sockets(_metadata, self, + (struct sockaddr *)&self->addr4, sizeof(self->addr6), + (struct sockaddr *)&self->addr6, sizeof(self->addr6)); +} + +TEST_F(bind_wildcard, v6_v4) +{ + bind_sockets(_metadata, self, + (struct sockaddr *)&self->addr6, sizeof(self->addr6), + (struct sockaddr *)&self->addr4, sizeof(self->addr4)); +} + +TEST_HARNESS_MAIN From 5000fe6c27827a61d8250a7e4a1d26c3298ef4f6 Mon Sep 17 00:00:00 2001 From: Zheng Wang Date: Mon, 13 Mar 2023 00:08:37 +0800 Subject: [PATCH 363/460] nfc: st-nci: Fix use after free bug in ndlc_remove due to race condition This bug influences both st_nci_i2c_remove and st_nci_spi_remove. Take st_nci_i2c_remove as an example. In st_nci_i2c_probe, it called ndlc_probe and bound &ndlc->sm_work with llt_ndlc_sm_work. When it calls ndlc_recv or timeout handler, it will finally call schedule_work to start the work. When we call st_nci_i2c_remove to remove the driver, there may be a sequence as follows: Fix it by finishing the work before cleanup in ndlc_remove CPU0 CPU1 |llt_ndlc_sm_work st_nci_i2c_remove | ndlc_remove | st_nci_remove | nci_free_device| kfree(ndev) | //free ndlc->ndev | |llt_ndlc_rcv_queue |nci_recv_frame |//use ndlc->ndev Fixes: 35630df68d60 ("NFC: st21nfcb: Add driver for STMicroelectronics ST21NFCB NFC chip") Signed-off-by: Zheng Wang Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230312160837.2040857-1-zyytlz.wz@163.com Signed-off-by: Jakub Kicinski --- drivers/nfc/st-nci/ndlc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/nfc/st-nci/ndlc.c b/drivers/nfc/st-nci/ndlc.c index 755460a73c0dc..d2aa9f766738e 100644 --- a/drivers/nfc/st-nci/ndlc.c +++ b/drivers/nfc/st-nci/ndlc.c @@ -282,13 +282,15 @@ EXPORT_SYMBOL(ndlc_probe); void ndlc_remove(struct llt_ndlc *ndlc) { - st_nci_remove(ndlc->ndev); - /* cancel timers */ del_timer_sync(&ndlc->t1_timer); del_timer_sync(&ndlc->t2_timer); ndlc->t2_active = false; ndlc->t1_active = false; + /* cancel work */ + cancel_work_sync(&ndlc->sm_work); + + st_nci_remove(ndlc->ndev); skb_queue_purge(&ndlc->rcv_q); skb_queue_purge(&ndlc->send_q); From 5ce76fe1eead179c058d9151ee1f4088cfdc1c6b Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Tue, 14 Mar 2023 00:08:40 +0100 Subject: [PATCH 364/460] veth: rely on rtnl_dereference() instead of on rcu_dereference() in veth_set_xdp_features() Fix the following kernel warning in veth_set_xdp_features routine relying on rtnl_dereference() instead of on rcu_dereference(): ============================= WARNING: suspicious RCU usage 6.3.0-rc1-00144-g064d70527aaa #149 Not tainted ----------------------------- drivers/net/veth.c:1265 suspicious rcu_dereference_check() usage! other info that might help us debug this: rcu_scheduler_active = 2, debug_locks = 1 1 lock held by ip/135: (net/core/rtnetlink.c:6172) stack backtrace: CPU: 1 PID: 135 Comm: ip Not tainted 6.3.0-rc1-00144-g064d70527aaa #149 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014 Call Trace: dump_stack_lvl (lib/dump_stack.c:107) lockdep_rcu_suspicious (include/linux/context_tracking.h:152) veth_set_xdp_features (drivers/net/veth.c:1265 (discriminator 9)) veth_newlink (drivers/net/veth.c:1892) ? veth_set_features (drivers/net/veth.c:1774) ? kasan_save_stack (mm/kasan/common.c:47) ? kasan_save_stack (mm/kasan/common.c:46) ? kasan_set_track (mm/kasan/common.c:52) ? alloc_netdev_mqs (include/linux/slab.h:737) ? rcu_read_lock_sched_held (kernel/rcu/update.c:125) ? trace_kmalloc (include/trace/events/kmem.h:54) ? __xdp_rxq_info_reg (net/core/xdp.c:188) ? alloc_netdev_mqs (net/core/dev.c:10657) ? rtnl_create_link (net/core/rtnetlink.c:3312) rtnl_newlink_create (net/core/rtnetlink.c:3440) ? rtnl_link_get_net_capable.constprop.0 (net/core/rtnetlink.c:3391) __rtnl_newlink (net/core/rtnetlink.c:3657) ? lock_downgrade (kernel/locking/lockdep.c:5321) ? rtnl_link_unregister (net/core/rtnetlink.c:3487) rtnl_newlink (net/core/rtnetlink.c:3671) rtnetlink_rcv_msg (net/core/rtnetlink.c:6174) ? rtnl_link_fill (net/core/rtnetlink.c:6070) ? mark_usage (kernel/locking/lockdep.c:4914) ? mark_usage (kernel/locking/lockdep.c:4914) netlink_rcv_skb (net/netlink/af_netlink.c:2574) ? rtnl_link_fill (net/core/rtnetlink.c:6070) ? netlink_ack (net/netlink/af_netlink.c:2551) ? lock_acquire (kernel/locking/lockdep.c:467) ? net_generic (include/linux/rcupdate.h:805) ? netlink_deliver_tap (include/linux/rcupdate.h:805) netlink_unicast (net/netlink/af_netlink.c:1340) ? netlink_attachskb (net/netlink/af_netlink.c:1350) netlink_sendmsg (net/netlink/af_netlink.c:1942) ? netlink_unicast (net/netlink/af_netlink.c:1861) ? netlink_unicast (net/netlink/af_netlink.c:1861) sock_sendmsg (net/socket.c:727) ____sys_sendmsg (net/socket.c:2501) ? kernel_sendmsg (net/socket.c:2448) ? __copy_msghdr (net/socket.c:2428) ___sys_sendmsg (net/socket.c:2557) ? mark_usage (kernel/locking/lockdep.c:4914) ? do_recvmmsg (net/socket.c:2544) ? lock_acquire (kernel/locking/lockdep.c:467) ? find_held_lock (kernel/locking/lockdep.c:5159) ? __lock_release (kernel/locking/lockdep.c:5345) ? __might_fault (mm/memory.c:5625) ? lock_downgrade (kernel/locking/lockdep.c:5321) ? __fget_light (include/linux/atomic/atomic-arch-fallback.h:227) __sys_sendmsg (include/linux/file.h:31) ? __sys_sendmsg_sock (net/socket.c:2572) ? rseq_get_rseq_cs (kernel/rseq.c:275) ? lockdep_hardirqs_on_prepare.part.0 (kernel/locking/lockdep.c:4263) do_syscall_64 (arch/x86/entry/common.c:50) entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:120) RIP: 0033:0x7f0d1aadeb17 Code: 0f 00 f7 d8 64 89 02 48 c7 c0 ff ff ff ff eb b9 0f 1f 00 f3 0f 1e fa 64 8b 04 25 18 00 00 00 85 c0 75 10 b8 2e 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 51 c3 48 83 ec 28 89 54 24 1c 48 89 74 24 10 Fixes: fccca038f300 ("veth: take into account device reconfiguration for xdp_features flag") Suggested-by: Eric Dumazet Reported-by: Matthieu Baerts Link: https://lore.kernel.org/netdev/cover.1678364612.git.lorenzo@kernel.org/T/#me4c9d8e985ec7ebee981cfdb5bc5ec651ef4035d Signed-off-by: Lorenzo Bianconi Reported-by: syzbot+c3d0d9c42d59ff644ea6@syzkaller.appspotmail.com Reviewed-by: Eric Dumazet Tested-by: Matthieu Baerts Link: https://lore.kernel.org/r/dfd6a9a7d85e9113063165e1f47b466b90ad7b8a.1678748579.git.lorenzo@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/veth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/veth.c b/drivers/net/veth.c index 293dc3b2c84a6..4da74ac27f9a2 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c @@ -1262,7 +1262,7 @@ static void veth_set_xdp_features(struct net_device *dev) struct veth_priv *priv = netdev_priv(dev); struct net_device *peer; - peer = rcu_dereference(priv->peer); + peer = rtnl_dereference(priv->peer); if (peer && peer->real_num_tx_queues <= dev->real_num_rx_queues) { xdp_features_t val = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT | From 35c356924fe3669dfbb1185607ce3b37f70bfa80 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Mon, 13 Mar 2023 18:21:24 +0100 Subject: [PATCH 365/460] mlxsw: spectrum: Fix incorrect parsing depth after reload Spectrum ASICs have a configurable limit on how deep into the packet they parse. By default, the limit is 96 bytes. There are several cases where this parsing depth is not enough and there is a need to increase it. For example, timestamping of PTP packets and a FIB multipath hash policy that requires hashing on inner fields. The driver therefore maintains a reference count that reflects the number of consumers that require an increased parsing depth. During reload_down() the parsing depth reference count does not necessarily drop to zero, but the parsing depth itself is restored to the default during reload_up() when the firmware is reset. It is therefore possible to end up in situations where the driver thinks that the parsing depth was increased (reference count is non-zero), when it is not. Fix by making sure that all the consumers that increase the parsing depth reference count also decrease it during reload_down(). Specifically, make sure that when the routing code is de-initialized it drops the reference count if it was increased because of a FIB multipath hash policy that requires hashing on inner fields. Add a warning if the reference count is not zero after the driver was de-initialized and explicitly reset it to zero during initialization for good measures. Fixes: 2d91f0803b84 ("mlxsw: spectrum: Add infrastructure for parsing configuration") Reported-by: Maksym Yaremchuk Signed-off-by: Ido Schimmel Signed-off-by: Petr Machata Link: https://lore.kernel.org/r/9c35e1b3e6c1d8f319a2449d14e2b86373f3b3ba.1678727526.git.petrm@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 2 ++ .../net/ethernet/mellanox/mlxsw/spectrum_router.c | 14 ++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index a8f94b7544eea..02a327744a61b 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -2937,6 +2937,7 @@ static int mlxsw_sp_netdevice_event(struct notifier_block *unused, static void mlxsw_sp_parsing_init(struct mlxsw_sp *mlxsw_sp) { + refcount_set(&mlxsw_sp->parsing.parsing_depth_ref, 0); mlxsw_sp->parsing.parsing_depth = MLXSW_SP_DEFAULT_PARSING_DEPTH; mlxsw_sp->parsing.vxlan_udp_dport = MLXSW_SP_DEFAULT_VXLAN_UDP_DPORT; mutex_init(&mlxsw_sp->parsing.lock); @@ -2945,6 +2946,7 @@ static void mlxsw_sp_parsing_init(struct mlxsw_sp *mlxsw_sp) static void mlxsw_sp_parsing_fini(struct mlxsw_sp *mlxsw_sp) { mutex_destroy(&mlxsw_sp->parsing.lock); + WARN_ON_ONCE(refcount_read(&mlxsw_sp->parsing.parsing_depth_ref)); } struct mlxsw_sp_ipv6_addr_node { diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index 09e32778b012d..4a73e2fe95ef9 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -10381,11 +10381,23 @@ static int mlxsw_sp_mp_hash_init(struct mlxsw_sp *mlxsw_sp) old_inc_parsing_depth); return err; } + +static void mlxsw_sp_mp_hash_fini(struct mlxsw_sp *mlxsw_sp) +{ + bool old_inc_parsing_depth = mlxsw_sp->router->inc_parsing_depth; + + mlxsw_sp_mp_hash_parsing_depth_adjust(mlxsw_sp, old_inc_parsing_depth, + false); +} #else static int mlxsw_sp_mp_hash_init(struct mlxsw_sp *mlxsw_sp) { return 0; } + +static void mlxsw_sp_mp_hash_fini(struct mlxsw_sp *mlxsw_sp) +{ +} #endif static int mlxsw_sp_dscp_init(struct mlxsw_sp *mlxsw_sp) @@ -10615,6 +10627,7 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp, err_register_inetaddr_notifier: mlxsw_core_flush_owq(); err_dscp_init: + mlxsw_sp_mp_hash_fini(mlxsw_sp); err_mp_hash_init: mlxsw_sp_neigh_fini(mlxsw_sp); err_neigh_init: @@ -10655,6 +10668,7 @@ void mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp) unregister_inet6addr_notifier(&mlxsw_sp->router->inet6addr_nb); unregister_inetaddr_notifier(&mlxsw_sp->router->inetaddr_nb); mlxsw_core_flush_owq(); + mlxsw_sp_mp_hash_fini(mlxsw_sp); mlxsw_sp_neigh_fini(mlxsw_sp); mlxsw_sp_lb_rif_fini(mlxsw_sp); mlxsw_sp_vrs_fini(mlxsw_sp); From 13085e1b5cab8ad802904d72e6a6dae85ae0cd20 Mon Sep 17 00:00:00 2001 From: Wenjia Zhang Date: Mon, 13 Mar 2023 11:08:28 +0100 Subject: [PATCH 366/460] net/smc: fix deadlock triggered by cancel_delayed_work_syn() The following LOCKDEP was detected: Workqueue: events smc_lgr_free_work [smc] WARNING: possible circular locking dependency detected 6.1.0-20221027.rc2.git8.56bc5b569087.300.fc36.s390x+debug #1 Not tainted ------------------------------------------------------ kworker/3:0/176251 is trying to acquire lock: 00000000f1467148 ((wq_completion)smc_tx_wq-00000000#2){+.+.}-{0:0}, at: __flush_workqueue+0x7a/0x4f0 but task is already holding lock: 0000037fffe97dc8 ((work_completion)(&(&lgr->free_work)->work)){+.+.}-{0:0}, at: process_one_work+0x232/0x730 which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #4 ((work_completion)(&(&lgr->free_work)->work)){+.+.}-{0:0}: __lock_acquire+0x58e/0xbd8 lock_acquire.part.0+0xe2/0x248 lock_acquire+0xac/0x1c8 __flush_work+0x76/0xf0 __cancel_work_timer+0x170/0x220 __smc_lgr_terminate.part.0+0x34/0x1c0 [smc] smc_connect_rdma+0x15e/0x418 [smc] __smc_connect+0x234/0x480 [smc] smc_connect+0x1d6/0x230 [smc] __sys_connect+0x90/0xc0 __do_sys_socketcall+0x186/0x370 __do_syscall+0x1da/0x208 system_call+0x82/0xb0 -> #3 (smc_client_lgr_pending){+.+.}-{3:3}: __lock_acquire+0x58e/0xbd8 lock_acquire.part.0+0xe2/0x248 lock_acquire+0xac/0x1c8 __mutex_lock+0x96/0x8e8 mutex_lock_nested+0x32/0x40 smc_connect_rdma+0xa4/0x418 [smc] __smc_connect+0x234/0x480 [smc] smc_connect+0x1d6/0x230 [smc] __sys_connect+0x90/0xc0 __do_sys_socketcall+0x186/0x370 __do_syscall+0x1da/0x208 system_call+0x82/0xb0 -> #2 (sk_lock-AF_SMC){+.+.}-{0:0}: __lock_acquire+0x58e/0xbd8 lock_acquire.part.0+0xe2/0x248 lock_acquire+0xac/0x1c8 lock_sock_nested+0x46/0xa8 smc_tx_work+0x34/0x50 [smc] process_one_work+0x30c/0x730 worker_thread+0x62/0x420 kthread+0x138/0x150 __ret_from_fork+0x3c/0x58 ret_from_fork+0xa/0x40 -> #1 ((work_completion)(&(&smc->conn.tx_work)->work)){+.+.}-{0:0}: __lock_acquire+0x58e/0xbd8 lock_acquire.part.0+0xe2/0x248 lock_acquire+0xac/0x1c8 process_one_work+0x2bc/0x730 worker_thread+0x62/0x420 kthread+0x138/0x150 __ret_from_fork+0x3c/0x58 ret_from_fork+0xa/0x40 -> #0 ((wq_completion)smc_tx_wq-00000000#2){+.+.}-{0:0}: check_prev_add+0xd8/0xe88 validate_chain+0x70c/0xb20 __lock_acquire+0x58e/0xbd8 lock_acquire.part.0+0xe2/0x248 lock_acquire+0xac/0x1c8 __flush_workqueue+0xaa/0x4f0 drain_workqueue+0xaa/0x158 destroy_workqueue+0x44/0x2d8 smc_lgr_free+0x9e/0xf8 [smc] process_one_work+0x30c/0x730 worker_thread+0x62/0x420 kthread+0x138/0x150 __ret_from_fork+0x3c/0x58 ret_from_fork+0xa/0x40 other info that might help us debug this: Chain exists of: (wq_completion)smc_tx_wq-00000000#2 --> smc_client_lgr_pending --> (work_completion)(&(&lgr->free_work)->work) Possible unsafe locking scenario: CPU0 CPU1 ---- ---- lock((work_completion)(&(&lgr->free_work)->work)); lock(smc_client_lgr_pending); lock((work_completion) (&(&lgr->free_work)->work)); lock((wq_completion)smc_tx_wq-00000000#2); *** DEADLOCK *** 2 locks held by kworker/3:0/176251: #0: 0000000080183548 ((wq_completion)events){+.+.}-{0:0}, at: process_one_work+0x232/0x730 #1: 0000037fffe97dc8 ((work_completion) (&(&lgr->free_work)->work)){+.+.}-{0:0}, at: process_one_work+0x232/0x730 stack backtrace: CPU: 3 PID: 176251 Comm: kworker/3:0 Not tainted Hardware name: IBM 8561 T01 701 (z/VM 7.2.0) Call Trace: [<000000002983c3e4>] dump_stack_lvl+0xac/0x100 [<0000000028b477ae>] check_noncircular+0x13e/0x160 [<0000000028b48808>] check_prev_add+0xd8/0xe88 [<0000000028b49cc4>] validate_chain+0x70c/0xb20 [<0000000028b4bd26>] __lock_acquire+0x58e/0xbd8 [<0000000028b4cf6a>] lock_acquire.part.0+0xe2/0x248 [<0000000028b4d17c>] lock_acquire+0xac/0x1c8 [<0000000028addaaa>] __flush_workqueue+0xaa/0x4f0 [<0000000028addf9a>] drain_workqueue+0xaa/0x158 [<0000000028ae303c>] destroy_workqueue+0x44/0x2d8 [<000003ff8029af26>] smc_lgr_free+0x9e/0xf8 [smc] [<0000000028adf3d4>] process_one_work+0x30c/0x730 [<0000000028adf85a>] worker_thread+0x62/0x420 [<0000000028aeac50>] kthread+0x138/0x150 [<0000000028a63914>] __ret_from_fork+0x3c/0x58 [<00000000298503da>] ret_from_fork+0xa/0x40 INFO: lockdep is turned off. =================================================================== This deadlock occurs because cancel_delayed_work_sync() waits for the work(&lgr->free_work) to finish, while the &lgr->free_work waits for the work(lgr->tx_wq), which needs the sk_lock-AF_SMC, that is already used under the mutex_lock. The solution is to use cancel_delayed_work() instead, which kills off a pending work. Fixes: a52bcc919b14 ("net/smc: improve termination processing") Signed-off-by: Wenjia Zhang Reviewed-by: Jan Karcher Reviewed-by: Karsten Graul Reviewed-by: Tony Lu Signed-off-by: David S. Miller --- net/smc/smc_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/smc/smc_core.c b/net/smc/smc_core.c index d52060b2680cf..454356771cda5 100644 --- a/net/smc/smc_core.c +++ b/net/smc/smc_core.c @@ -1464,7 +1464,7 @@ static void __smc_lgr_terminate(struct smc_link_group *lgr, bool soft) if (lgr->terminating) return; /* lgr already terminating */ /* cancel free_work sync, will terminate when lgr->freeing is set */ - cancel_delayed_work_sync(&lgr->free_work); + cancel_delayed_work(&lgr->free_work); lgr->terminating = 1; /* kill remaining link group connections */ From 9d876d3ef27fa84355597ad269939772192356d8 Mon Sep 17 00:00:00 2001 From: Stefan Raspl Date: Mon, 13 Mar 2023 11:08:29 +0100 Subject: [PATCH 367/460] net/smc: Fix device de-init sequence CLC message initialization was not properly reversed in error handling path. Reported-and-suggested-by: Alexander Gordeev Signed-off-by: Stefan Raspl Signed-off-by: Wenjia Zhang Reviewed-by: Tony Lu Signed-off-by: David S. Miller --- net/smc/af_smc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c index ff6dd86bdc9f3..c6b4a62276f6d 100644 --- a/net/smc/af_smc.c +++ b/net/smc/af_smc.c @@ -3501,6 +3501,7 @@ static int __init smc_init(void) out_nl: smc_nl_exit(); out_ism: + smc_clc_exit(); smc_ism_exit(); out_pernet_subsys_stat: unregister_pernet_subsys(&smc_net_stat_ops); From d8b228318935044dafe3a5bc07ee71a1f1424b8d Mon Sep 17 00:00:00 2001 From: Szymon Heidrich Date: Mon, 13 Mar 2023 23:00:45 +0100 Subject: [PATCH 368/460] net: usb: smsc75xx: Limit packet length to skb->len Packet length retrieved from skb data may be larger than the actual socket buffer length (up to 9026 bytes). In such case the cloned skb passed up the network stack will leak kernel memory contents. Fixes: d0cad871703b ("smsc75xx: SMSC LAN75xx USB gigabit ethernet adapter driver") Signed-off-by: Szymon Heidrich Signed-off-by: David S. Miller --- drivers/net/usb/smsc75xx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c index 95de452ff4dad..db34f8d1d6051 100644 --- a/drivers/net/usb/smsc75xx.c +++ b/drivers/net/usb/smsc75xx.c @@ -2212,7 +2212,8 @@ static int smsc75xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) dev->net->stats.rx_frame_errors++; } else { /* MAX_SINGLE_PACKET_SIZE + 4(CRC) + 2(COE) + 4(Vlan) */ - if (unlikely(size > (MAX_SINGLE_PACKET_SIZE + ETH_HLEN + 12))) { + if (unlikely(size > (MAX_SINGLE_PACKET_SIZE + ETH_HLEN + 12) || + size > skb->len)) { netif_dbg(dev, rx_err, dev->net, "size err rx_cmd_a=0x%08x\n", rx_cmd_a); From 611e2dabb4b3243d176739fd6a5a34d007fa3f86 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Tue, 14 Mar 2023 00:34:26 +0000 Subject: [PATCH 369/460] net: ethernet: mtk_eth_soc: reset PCS state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reset the internal PCS state machine when changing interface mode. This prevents confusing the state machine when changing interface modes, e.g. from SGMII to 2500Base-X or vice-versa. Fixes: 7e538372694b ("net: ethernet: mediatek: Re-add support SGMII") Reviewed-by: Russell King (Oracle) Tested-by: Bjørn Mork Signed-off-by: Daniel Golle Signed-off-by: David S. Miller --- drivers/net/ethernet/mediatek/mtk_eth_soc.h | 4 ++++ drivers/net/ethernet/mediatek/mtk_sgmii.c | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h index b65de174c3d9b..084a6badef6d9 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h @@ -542,6 +542,10 @@ #define SGMII_SEND_AN_ERROR_EN BIT(11) #define SGMII_IF_MODE_MASK GENMASK(5, 1) +/* Register to reset SGMII design */ +#define SGMII_RESERVED_0 0x34 +#define SGMII_SW_RESET BIT(0) + /* Register to set SGMII speed, ANA RG_ Control Signals III*/ #define SGMSYS_ANA_RG_CS3 0x2028 #define RG_PHY_SPEED_MASK (BIT(2) | BIT(3)) diff --git a/drivers/net/ethernet/mediatek/mtk_sgmii.c b/drivers/net/ethernet/mediatek/mtk_sgmii.c index bb00de1003ac4..612f65bb03454 100644 --- a/drivers/net/ethernet/mediatek/mtk_sgmii.c +++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c @@ -88,6 +88,10 @@ static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode, regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, SGMII_PHYA_PWD, SGMII_PHYA_PWD); + /* Reset SGMII PCS state */ + regmap_update_bits(mpcs->regmap, SGMII_RESERVED_0, + SGMII_SW_RESET, SGMII_SW_RESET); + if (interface == PHY_INTERFACE_MODE_2500BASEX) rgc3 = RG_PHY_SPEED_3_125G; else From 6e933a804c7db8be64f367f33e63cd7dcc302ebb Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Tue, 14 Mar 2023 00:34:45 +0000 Subject: [PATCH 370/460] net: ethernet: mtk_eth_soc: only write values if needed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only restart auto-negotiation and write link timer if actually necessary. This prevents losing the link in case of minor changes. Fixes: 7e538372694b ("net: ethernet: mediatek: Re-add support SGMII") Reviewed-by: Russell King (Oracle) Tested-by: Bjørn Mork Signed-off-by: Daniel Golle Signed-off-by: David S. Miller --- drivers/net/ethernet/mediatek/mtk_sgmii.c | 24 +++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/mediatek/mtk_sgmii.c b/drivers/net/ethernet/mediatek/mtk_sgmii.c index 612f65bb03454..83976dc868875 100644 --- a/drivers/net/ethernet/mediatek/mtk_sgmii.c +++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c @@ -38,20 +38,16 @@ static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode, const unsigned long *advertising, bool permit_pause_to_mac) { + bool mode_changed = false, changed, use_an; struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs); unsigned int rgc3, sgm_mode, bmcr; int advertise, link_timer; - bool changed, use_an; advertise = phylink_mii_c22_pcs_encode_advertisement(interface, advertising); if (advertise < 0) return advertise; - link_timer = phylink_get_link_timer_ns(interface); - if (link_timer < 0) - return link_timer; - /* Clearing IF_MODE_BIT0 switches the PCS to BASE-X mode, and * we assume that fixes it's speed at bitrate = line rate (in * other words, 1000Mbps or 2500Mbps). @@ -77,13 +73,16 @@ static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode, } if (use_an) { - /* FIXME: Do we need to set AN_RESTART here? */ - bmcr = SGMII_AN_RESTART | SGMII_AN_ENABLE; + bmcr = SGMII_AN_ENABLE; } else { bmcr = 0; } if (mpcs->interface != interface) { + link_timer = phylink_get_link_timer_ns(interface); + if (link_timer < 0) + return link_timer; + /* PHYA power down */ regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, SGMII_PHYA_PWD, SGMII_PHYA_PWD); @@ -101,16 +100,17 @@ static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode, regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3, RG_PHY_SPEED_3_125G, rgc3); + /* Setup the link timer */ + regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER, link_timer / 2 / 8); + mpcs->interface = interface; + mode_changed = true; } /* Update the advertisement, noting whether it has changed */ regmap_update_bits_check(mpcs->regmap, SGMSYS_PCS_ADVERTISE, SGMII_ADVERTISE, advertise, &changed); - /* Setup the link timer and QPHY power up inside SGMIISYS */ - regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER, link_timer / 2 / 8); - /* Update the sgmsys mode register */ regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE, SGMII_REMOTE_FAULT_DIS | SGMII_SPEED_DUPLEX_AN | @@ -118,7 +118,7 @@ static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode, /* Update the BMCR */ regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1, - SGMII_AN_RESTART | SGMII_AN_ENABLE, bmcr); + SGMII_AN_ENABLE, bmcr); /* Release PHYA power down state * Only removing bit SGMII_PHYA_PWD isn't enough. @@ -132,7 +132,7 @@ static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode, usleep_range(50, 100); regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, 0); - return changed; + return changed || mode_changed; } static void mtk_pcs_restart_an(struct phylink_pcs *pcs) From 0d3c9333d976af41d7dbc6bf4d9d2e95fbdf9c89 Mon Sep 17 00:00:00 2001 From: Liu Ying Date: Tue, 14 Mar 2023 13:50:35 +0800 Subject: [PATCH 371/460] drm/bridge: Fix returned array size name for atomic_get_input_bus_fmts kdoc The returned array size for input formats is set through atomic_get_input_bus_fmts()'s 'num_input_fmts' argument, so use 'num_input_fmts' to represent the array size in the function's kdoc, not 'num_output_fmts'. Fixes: 91ea83306bfa ("drm/bridge: Fix the bridge kernel doc") Fixes: f32df58acc68 ("drm/bridge: Add the necessary bits to support bus format negotiation") Signed-off-by: Liu Ying Reviewed-by: Robert Foss Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/20230314055035.3731179-1-victor.liu@nxp.com --- include/drm/drm_bridge.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h index 42f86327b40a7..bf964cdfb3300 100644 --- a/include/drm/drm_bridge.h +++ b/include/drm/drm_bridge.h @@ -423,11 +423,11 @@ struct drm_bridge_funcs { * * The returned array must be allocated with kmalloc() and will be * freed by the caller. If the allocation fails, NULL should be - * returned. num_output_fmts must be set to the returned array size. + * returned. num_input_fmts must be set to the returned array size. * Formats listed in the returned array should be listed in decreasing * preference order (the core will try all formats until it finds one * that works). When the format is not supported NULL should be - * returned and num_output_fmts should be set to 0. + * returned and num_input_fmts should be set to 0. * * This method is called on all elements of the bridge chain as part of * the bus format negotiation process that happens in From 4028cbf867f70a3c599c9b0c9509334c56ed97d7 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Thu, 9 Mar 2023 16:24:46 +0100 Subject: [PATCH 372/460] drm/meson: dw-hdmi: Fix devm_regulator_*get_enable*() conversion again MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit devm_regulator_get_enable_optional() returns -ENODEV if requested optional regulator is not present. Adjust code for that, because in the 67d0a30128c9 I've incorrectly assumed that it also returns 0 when regulator is not present. Reported-by: Ricardo Cañuelo Fixes: 67d0a30128c9 ("drm/meson: dw-hdmi: Fix devm_regulator_*get_enable*() conversion") Signed-off-by: Marek Szyprowski Acked-by: Martin Blumenstingl Acked-by: Neil Armstrong Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/20230309152446.104913-1-m.szyprowski@samsung.com --- drivers/gpu/drm/meson/meson_dw_hdmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/meson/meson_dw_hdmi.c b/drivers/gpu/drm/meson/meson_dw_hdmi.c index 534621a13a34d..3d046878ce6cb 100644 --- a/drivers/gpu/drm/meson/meson_dw_hdmi.c +++ b/drivers/gpu/drm/meson/meson_dw_hdmi.c @@ -718,7 +718,7 @@ static int meson_dw_hdmi_bind(struct device *dev, struct device *master, dw_plat_data = &meson_dw_hdmi->dw_plat_data; ret = devm_regulator_get_enable_optional(dev, "hdmi"); - if (ret < 0) + if (ret < 0 && ret != -ENODEV) return ret; meson_dw_hdmi->hdmitx_apb = devm_reset_control_get_exclusive(dev, From f2c7e3562b4c4f1699acc1538ebf3e75f5cced35 Mon Sep 17 00:00:00 2001 From: Russell Currey Date: Fri, 10 Mar 2023 16:08:34 +1100 Subject: [PATCH 373/460] powerpc/mm: Fix false detection of read faults MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To support detection of read faults with Radix execute-only memory, the vma_is_accessible() check in access_error() (which checks for PROT_NONE) was replaced with a check to see if VM_READ was missing, and if so, returns true to assert the fault was caused by a bad read. This is incorrect, as it ignores that both VM_WRITE and VM_EXEC imply read on powerpc, as defined in protection_map[]. This causes mappings containing VM_WRITE or VM_EXEC without VM_READ to misreport the cause of page faults, since the MMU is still allowing reads. Correct this by restoring the original vma_is_accessible() check for PROT_NONE mappings, and adding a separate check for Radix PROT_EXEC-only mappings. Fixes: 395cac7752b9 ("powerpc/mm: Support execute-only memory on the Radix MMU") Reported-by: Michal Suchánek Link: https://lore.kernel.org/r/20230308152702.GR19419@kitsune.suse.cz Tested-by: Benjamin Gray Signed-off-by: Russell Currey Signed-off-by: Michael Ellerman Link: https://msgid.link/20230310050834.63105-1-ruscur@russell.cc --- arch/powerpc/mm/fault.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c index 2bef19cc1b98c..af46aa88422bf 100644 --- a/arch/powerpc/mm/fault.c +++ b/arch/powerpc/mm/fault.c @@ -271,11 +271,16 @@ static bool access_error(bool is_write, bool is_exec, struct vm_area_struct *vma } /* - * Check for a read fault. This could be caused by a read on an - * inaccessible page (i.e. PROT_NONE), or a Radix MMU execute-only page. + * VM_READ, VM_WRITE and VM_EXEC all imply read permissions, as + * defined in protection_map[]. Read faults can only be caused by + * a PROT_NONE mapping, or with a PROT_EXEC-only mapping on Radix. */ - if (unlikely(!(vma->vm_flags & VM_READ))) + if (unlikely(!vma_is_accessible(vma))) return true; + + if (unlikely(radix_enabled() && ((vma->vm_flags & VM_ACCESS_FLAGS) == VM_EXEC))) + return true; + /* * We should ideally do the vma pkey access check here. But in the * fault path, handle_mm_fault() also does the same check. To avoid From 63f886597085f346276e3b3c8974de0100d65f32 Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Tue, 14 Mar 2023 13:11:05 +0900 Subject: [PATCH 374/460] block: null_blk: Fix handling of fake timeout request When injecting a fake timeout into the null_blk driver using fail_io_timeout, the request timeout handler does not execute blk_mq_complete_request(), so the complete callback is never executed for a timedout request. The null_blk driver also has a driver-specific fake timeout mechanism which does not have this problem. Fix the problem with fail_io_timeout by using the same meachanism as null_blk internal timeout feature, using the fake_timeout field of null_blk commands. Reported-by: Akinobu Mita Fixes: de3510e52b0a ("null_blk: fix command timeout completion handling") Signed-off-by: Damien Le Moal Reviewed-by: Johannes Thumshirn Link: https://lore.kernel.org/r/20230314041106.19173-2-damien.lemoal@opensource.wdc.com Signed-off-by: Jens Axboe --- drivers/block/null_blk/main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/block/null_blk/main.c b/drivers/block/null_blk/main.c index 4c601ca9552a0..7d95ad203c977 100644 --- a/drivers/block/null_blk/main.c +++ b/drivers/block/null_blk/main.c @@ -1413,8 +1413,7 @@ static inline void nullb_complete_cmd(struct nullb_cmd *cmd) case NULL_IRQ_SOFTIRQ: switch (cmd->nq->dev->queue_mode) { case NULL_Q_MQ: - if (likely(!blk_should_fake_timeout(cmd->rq->q))) - blk_mq_complete_request(cmd->rq); + blk_mq_complete_request(cmd->rq); break; case NULL_Q_BIO: /* @@ -1675,7 +1674,8 @@ static blk_status_t null_queue_rq(struct blk_mq_hw_ctx *hctx, cmd->rq = bd->rq; cmd->error = BLK_STS_OK; cmd->nq = nq; - cmd->fake_timeout = should_timeout_request(bd->rq); + cmd->fake_timeout = should_timeout_request(bd->rq) || + blk_should_fake_timeout(bd->rq->q); blk_mq_start_request(bd->rq); From b6402014cab0481bdfd1ffff3e1dad714e8e1205 Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Tue, 14 Mar 2023 13:11:06 +0900 Subject: [PATCH 375/460] block: null_blk: cleanup null_queue_rq() Use a local struct request pointer variable to avoid having to dereference struct blk_mq_queue_data multiple times. While at it, also fix the function argument indentation and remove a useless "else" after a return. Signed-off-by: Damien Le Moal Reviewed-by: Johannes Thumshirn Reviewed-by: Pankaj Raghav Link: https://lore.kernel.org/r/20230314041106.19173-2-damien.lemoal@opensource.wdc.com Signed-off-by: Jens Axboe --- drivers/block/null_blk/main.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/drivers/block/null_blk/main.c b/drivers/block/null_blk/main.c index 7d95ad203c977..9e6b032c8ecc2 100644 --- a/drivers/block/null_blk/main.c +++ b/drivers/block/null_blk/main.c @@ -1657,12 +1657,13 @@ static enum blk_eh_timer_return null_timeout_rq(struct request *rq) } static blk_status_t null_queue_rq(struct blk_mq_hw_ctx *hctx, - const struct blk_mq_queue_data *bd) + const struct blk_mq_queue_data *bd) { - struct nullb_cmd *cmd = blk_mq_rq_to_pdu(bd->rq); + struct request *rq = bd->rq; + struct nullb_cmd *cmd = blk_mq_rq_to_pdu(rq); struct nullb_queue *nq = hctx->driver_data; - sector_t nr_sectors = blk_rq_sectors(bd->rq); - sector_t sector = blk_rq_pos(bd->rq); + sector_t nr_sectors = blk_rq_sectors(rq); + sector_t sector = blk_rq_pos(rq); const bool is_poll = hctx->type == HCTX_TYPE_POLL; might_sleep_if(hctx->flags & BLK_MQ_F_BLOCKING); @@ -1671,15 +1672,15 @@ static blk_status_t null_queue_rq(struct blk_mq_hw_ctx *hctx, hrtimer_init(&cmd->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); cmd->timer.function = null_cmd_timer_expired; } - cmd->rq = bd->rq; + cmd->rq = rq; cmd->error = BLK_STS_OK; cmd->nq = nq; - cmd->fake_timeout = should_timeout_request(bd->rq) || - blk_should_fake_timeout(bd->rq->q); + cmd->fake_timeout = should_timeout_request(rq) || + blk_should_fake_timeout(rq->q); - blk_mq_start_request(bd->rq); + blk_mq_start_request(rq); - if (should_requeue_request(bd->rq)) { + if (should_requeue_request(rq)) { /* * Alternate between hitting the core BUSY path, and the * driver driven requeue path @@ -1687,22 +1688,20 @@ static blk_status_t null_queue_rq(struct blk_mq_hw_ctx *hctx, nq->requeue_selection++; if (nq->requeue_selection & 1) return BLK_STS_RESOURCE; - else { - blk_mq_requeue_request(bd->rq, true); - return BLK_STS_OK; - } + blk_mq_requeue_request(rq, true); + return BLK_STS_OK; } if (is_poll) { spin_lock(&nq->poll_lock); - list_add_tail(&bd->rq->queuelist, &nq->poll_list); + list_add_tail(&rq->queuelist, &nq->poll_list); spin_unlock(&nq->poll_lock); return BLK_STS_OK; } if (cmd->fake_timeout) return BLK_STS_OK; - return null_handle_cmd(cmd, sector, nr_sectors, req_op(bd->rq)); + return null_handle_cmd(cmd, sector, nr_sectors, req_op(rq)); } static void cleanup_queue(struct nullb_queue *nq) From a5fc1441af7719e93dc7a638a960befb694ade89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Koutn=C3=BD?= Date: Tue, 14 Mar 2023 19:33:32 +0100 Subject: [PATCH 376/460] io_uring/sqpoll: Do not set PF_NO_SETAFFINITY on sqpoll threads MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Users may specify a CPU where the sqpoll thread would run. This may conflict with cpuset operations because of strict PF_NO_SETAFFINITY requirement. That flag is unnecessary for polling "kernel" threads, see the reasoning in commit 01e68ce08a30 ("io_uring/io-wq: stop setting PF_NO_SETAFFINITY on io-wq workers"). Drop the flag on poll threads too. Fixes: 01e68ce08a30 ("io_uring/io-wq: stop setting PF_NO_SETAFFINITY on io-wq workers") Link: https://lore.kernel.org/all/20230314162559.pnyxdllzgw7jozgx@blackpad/ Signed-off-by: Michal Koutný Link: https://lore.kernel.org/r/20230314183332.25834-1-mkoutny@suse.com Signed-off-by: Jens Axboe --- io_uring/sqpoll.c | 1 - 1 file changed, 1 deletion(-) diff --git a/io_uring/sqpoll.c b/io_uring/sqpoll.c index 0119d3f1a5569..9db4bc1f521a3 100644 --- a/io_uring/sqpoll.c +++ b/io_uring/sqpoll.c @@ -233,7 +233,6 @@ static int io_sq_thread(void *data) set_cpus_allowed_ptr(current, cpumask_of(sqd->sq_cpu)); else set_cpus_allowed_ptr(current, cpu_online_mask); - current->flags |= PF_NO_SETAFFINITY; mutex_lock(&sqd->lock); while (1) { From 54686b611eb054a5c84976e6f6e03788fa8e6a38 Mon Sep 17 00:00:00 2001 From: Lukas Bulwahn Date: Wed, 8 Mar 2023 15:41:32 +0100 Subject: [PATCH 377/460] MAINTAINERS: repair malformed T: entries in NVM EXPRESS DRIVERS 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: b508fc354f6d ("nvme: update maintainers information") Signed-off-by: Lukas Bulwahn Reviewed-by: Sagi Grimberg Signed-off-by: Christoph Hellwig --- MAINTAINERS | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 8d5bc223f3053..1296426b38791 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14872,12 +14872,12 @@ M: Sagi Grimberg L: linux-nvme@lists.infradead.org S: Supported W: http://git.infradead.org/nvme.git -T: git://git.infradead.org/nvme.git +T: git git://git.infradead.org/nvme.git F: Documentation/nvme/ -F: drivers/nvme/host/ F: drivers/nvme/common/ -F: include/linux/nvme.h +F: drivers/nvme/host/ F: include/linux/nvme-*.h +F: include/linux/nvme.h F: include/uapi/linux/nvme_ioctl.h NVM EXPRESS FABRICS AUTHENTICATION @@ -14912,7 +14912,7 @@ M: Chaitanya Kulkarni L: linux-nvme@lists.infradead.org S: Supported W: http://git.infradead.org/nvme.git -T: git://git.infradead.org/nvme.git +T: git git://git.infradead.org/nvme.git F: drivers/nvme/target/ NVMEM FRAMEWORK From 37f0dc2ec78af0c3f35dd05578763de059f6fe77 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Sat, 4 Mar 2023 07:13:45 +0800 Subject: [PATCH 378/460] nvme: fix handling single range discard request When investigating one customer report on warning in nvme_setup_discard, we observed the controller(nvme/tcp) actually exposes queue_max_discard_segments(req->q) == 1. Obviously the current code can't handle this situation, since contiguity merge like normal RW request is taken. Fix the issue by building range from request sector/nr_sectors directly. Fixes: b35ba01ea697 ("nvme: support ranged discard requests") Signed-off-by: Ming Lei Reviewed-by: Chaitanya Kulkarni Signed-off-by: Christoph Hellwig --- drivers/nvme/host/core.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index c2730b116dc68..d4be525f8100a 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -781,16 +781,26 @@ static blk_status_t nvme_setup_discard(struct nvme_ns *ns, struct request *req, range = page_address(ns->ctrl->discard_page); } - __rq_for_each_bio(bio, req) { - u64 slba = nvme_sect_to_lba(ns, bio->bi_iter.bi_sector); - u32 nlb = bio->bi_iter.bi_size >> ns->lba_shift; - - if (n < segments) { - range[n].cattr = cpu_to_le32(0); - range[n].nlb = cpu_to_le32(nlb); - range[n].slba = cpu_to_le64(slba); + if (queue_max_discard_segments(req->q) == 1) { + u64 slba = nvme_sect_to_lba(ns, blk_rq_pos(req)); + u32 nlb = blk_rq_sectors(req) >> (ns->lba_shift - 9); + + range[0].cattr = cpu_to_le32(0); + range[0].nlb = cpu_to_le32(nlb); + range[0].slba = cpu_to_le64(slba); + n = 1; + } else { + __rq_for_each_bio(bio, req) { + u64 slba = nvme_sect_to_lba(ns, bio->bi_iter.bi_sector); + u32 nlb = bio->bi_iter.bi_size >> ns->lba_shift; + + if (n < segments) { + range[n].cattr = cpu_to_le32(0); + range[n].nlb = cpu_to_le32(nlb); + range[n].slba = cpu_to_le64(slba); + } + n++; } - n++; } if (WARN_ON_ONCE(n != segments)) { From a61d265533b7fe0026a02a49916aa564ffe38e4c Mon Sep 17 00:00:00 2001 From: Irvin Cote Date: Wed, 8 Mar 2023 18:05:08 -0300 Subject: [PATCH 379/460] nvme-pci: fixing memory leak in probe teardown path In case the nvme_probe teardown path is triggered the ctrl ref count does not reach 0 thus creating a memory leak upon failure of nvme_probe. Signed-off-by: Irvin Cote Signed-off-by: Christoph Hellwig --- drivers/nvme/host/pci.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index 5b95c94ee40f2..e77a8a873b1ae 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -3073,6 +3073,7 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id) nvme_dev_unmap(dev); out_uninit_ctrl: nvme_uninit_ctrl(&dev->ctrl); + nvme_put_ctrl(&dev->ctrl); return result; } From 9630d80655bfe7e62e4aff2889dc4eae7ceeb887 Mon Sep 17 00:00:00 2001 From: Elmer Miroslav Mosher Golovin Date: Wed, 8 Mar 2023 19:19:29 +0300 Subject: [PATCH 380/460] nvme-pci: add NVME_QUIRK_BOGUS_NID for Netac NV3000 Added a quirk to fix the Netac NV3000 SSD reporting duplicate NGUIDs. Cc: Signed-off-by: Elmer Miroslav Mosher Golovin Reviewed-by: Chaitanya Kulkarni Signed-off-by: Christoph Hellwig --- drivers/nvme/host/pci.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index e77a8a873b1ae..8a536d5300a42 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -3416,6 +3416,8 @@ static const struct pci_device_id nvme_id_table[] = { .driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, }, { PCI_DEVICE(0x2646, 0x501E), /* KINGSTON OM3PGP4xxxxQ OS21011 NVMe SSD */ .driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, }, + { PCI_DEVICE(0x1f40, 0x1202), /* Netac Technologies Co. NV3000 NVMe SSD */ + .driver_data = NVME_QUIRK_BOGUS_NID, }, { PCI_DEVICE(0x1f40, 0x5236), /* Netac Technologies Co. NV7000 NVMe SSD */ .driver_data = NVME_QUIRK_BOGUS_NID, }, { PCI_DEVICE(0x1e4B, 0x1001), /* MAXIO MAP1001 */ From b65d44fa0fe072c91bf41cd8756baa2b4c77eff2 Mon Sep 17 00:00:00 2001 From: Philipp Geulen Date: Mon, 13 Mar 2023 11:11:50 +0100 Subject: [PATCH 381/460] nvme-pci: add NVME_QUIRK_BOGUS_NID for Lexar NM620 Added a quirk to fix Lexar NM620 1TB SSD reporting duplicate NGUIDs. Signed-off-by: Philipp Geulen Reviewed-by: Chaitanya Kulkarni Signed-off-by: Christoph Hellwig --- drivers/nvme/host/pci.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index 8a536d5300a42..b615906263f37 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -3438,6 +3438,8 @@ static const struct pci_device_id nvme_id_table[] = { .driver_data = NVME_QUIRK_BOGUS_NID, }, { PCI_DEVICE(0x1d97, 0x2263), /* Lexar NM610 */ .driver_data = NVME_QUIRK_BOGUS_NID, }, + { PCI_DEVICE(0x1d97, 0x1d97), /* Lexar NM620 */ + .driver_data = NVME_QUIRK_BOGUS_NID, }, { PCI_DEVICE(0x1d97, 0x2269), /* Lexar NM760 */ .driver_data = NVME_QUIRK_BOGUS_NID, }, { PCI_DEVICE(PCI_VENDOR_ID_AMAZON, 0x0061), From a3406352c54fbc476f4f6b98159c3ea1c7dbb6fc Mon Sep 17 00:00:00 2001 From: Sagi Grimberg Date: Mon, 13 Mar 2023 10:56:22 +0200 Subject: [PATCH 382/460] nvme-tcp: fix opcode reporting in the timeout handler For non in-capsule writes we reuse the request pdu space for a h2cdata pdu in order to avoid over allocating space (either preallocate or dynamically upon receving an r2t pdu). However if the request times out the core expects to find the opcode in the start of the request, which we override. In order to prevent that, without sacrificing additional 24 bytes per request, we just use the tail of the command pdu space instead (last 24 bytes from the 72 bytes command pdu). That should make the command opcode always available, and we get away from allocating more space. If in the future we would need the last 24 bytes of the nvme command available we would need to allocate a dedicated space for it in the request, but until then we can avoid doing so. Reported-by: Akinobu Mita Signed-off-by: Sagi Grimberg Reviewed-by: Chaitanya Kulkarni Tested-by: Akinobu Mita Signed-off-by: Christoph Hellwig --- drivers/nvme/host/tcp.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c index 7723a49895244..2e174fad57d77 100644 --- a/drivers/nvme/host/tcp.c +++ b/drivers/nvme/host/tcp.c @@ -208,6 +208,18 @@ static inline u8 nvme_tcp_ddgst_len(struct nvme_tcp_queue *queue) return queue->data_digest ? NVME_TCP_DIGEST_LENGTH : 0; } +static inline void *nvme_tcp_req_cmd_pdu(struct nvme_tcp_request *req) +{ + return req->pdu; +} + +static inline void *nvme_tcp_req_data_pdu(struct nvme_tcp_request *req) +{ + /* use the pdu space in the back for the data pdu */ + return req->pdu + sizeof(struct nvme_tcp_cmd_pdu) - + sizeof(struct nvme_tcp_data_pdu); +} + static inline size_t nvme_tcp_inline_data_size(struct nvme_tcp_request *req) { if (nvme_is_fabrics(req->req.cmd)) @@ -614,7 +626,7 @@ static int nvme_tcp_handle_comp(struct nvme_tcp_queue *queue, static void nvme_tcp_setup_h2c_data_pdu(struct nvme_tcp_request *req) { - struct nvme_tcp_data_pdu *data = req->pdu; + struct nvme_tcp_data_pdu *data = nvme_tcp_req_data_pdu(req); struct nvme_tcp_queue *queue = req->queue; struct request *rq = blk_mq_rq_from_pdu(req); u32 h2cdata_sent = req->pdu_len; @@ -1038,7 +1050,7 @@ static int nvme_tcp_try_send_data(struct nvme_tcp_request *req) static int nvme_tcp_try_send_cmd_pdu(struct nvme_tcp_request *req) { struct nvme_tcp_queue *queue = req->queue; - struct nvme_tcp_cmd_pdu *pdu = req->pdu; + struct nvme_tcp_cmd_pdu *pdu = nvme_tcp_req_cmd_pdu(req); bool inline_data = nvme_tcp_has_inline_data(req); u8 hdgst = nvme_tcp_hdgst_len(queue); int len = sizeof(*pdu) + hdgst - req->offset; @@ -1077,7 +1089,7 @@ static int nvme_tcp_try_send_cmd_pdu(struct nvme_tcp_request *req) static int nvme_tcp_try_send_data_pdu(struct nvme_tcp_request *req) { struct nvme_tcp_queue *queue = req->queue; - struct nvme_tcp_data_pdu *pdu = req->pdu; + struct nvme_tcp_data_pdu *pdu = nvme_tcp_req_data_pdu(req); u8 hdgst = nvme_tcp_hdgst_len(queue); int len = sizeof(*pdu) - req->offset + hdgst; int ret; @@ -2284,7 +2296,7 @@ static enum blk_eh_timer_return nvme_tcp_timeout(struct request *rq) { struct nvme_tcp_request *req = blk_mq_rq_to_pdu(rq); struct nvme_ctrl *ctrl = &req->queue->ctrl->ctrl; - struct nvme_tcp_cmd_pdu *pdu = req->pdu; + struct nvme_tcp_cmd_pdu *pdu = nvme_tcp_req_cmd_pdu(req); u8 opc = pdu->cmd.common.opcode, fctype = pdu->cmd.fabrics.fctype; int qid = nvme_tcp_queue_id(req->queue); @@ -2323,7 +2335,7 @@ static blk_status_t nvme_tcp_map_data(struct nvme_tcp_queue *queue, struct request *rq) { struct nvme_tcp_request *req = blk_mq_rq_to_pdu(rq); - struct nvme_tcp_cmd_pdu *pdu = req->pdu; + struct nvme_tcp_cmd_pdu *pdu = nvme_tcp_req_cmd_pdu(req); struct nvme_command *c = &pdu->cmd; c->common.flags |= NVME_CMD_SGL_METABUF; @@ -2343,7 +2355,7 @@ static blk_status_t nvme_tcp_setup_cmd_pdu(struct nvme_ns *ns, struct request *rq) { struct nvme_tcp_request *req = blk_mq_rq_to_pdu(rq); - struct nvme_tcp_cmd_pdu *pdu = req->pdu; + struct nvme_tcp_cmd_pdu *pdu = nvme_tcp_req_cmd_pdu(req); struct nvme_tcp_queue *queue = req->queue; u8 hdgst = nvme_tcp_hdgst_len(queue), ddgst = 0; blk_status_t ret; From 7e87965d3807ab1f518ef2365f91d5ba6b0c5abe Mon Sep 17 00:00:00 2001 From: Sagi Grimberg Date: Mon, 13 Mar 2023 10:56:23 +0200 Subject: [PATCH 383/460] nvme-tcp: add nvme-tcp pdu size build protection Make sure that we don't somehow mess up the wire structures in the spec. Signed-off-by: Sagi Grimberg Reviewed-by: Chaitanya Kulkarni Signed-off-by: Christoph Hellwig --- drivers/nvme/host/tcp.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c index 2e174fad57d77..42c0598c31f2b 100644 --- a/drivers/nvme/host/tcp.c +++ b/drivers/nvme/host/tcp.c @@ -2694,6 +2694,15 @@ static struct nvmf_transport_ops nvme_tcp_transport = { static int __init nvme_tcp_init_module(void) { + BUILD_BUG_ON(sizeof(struct nvme_tcp_hdr) != 8); + BUILD_BUG_ON(sizeof(struct nvme_tcp_cmd_pdu) != 72); + BUILD_BUG_ON(sizeof(struct nvme_tcp_data_pdu) != 24); + BUILD_BUG_ON(sizeof(struct nvme_tcp_rsp_pdu) != 24); + BUILD_BUG_ON(sizeof(struct nvme_tcp_r2t_pdu) != 24); + BUILD_BUG_ON(sizeof(struct nvme_tcp_icreq_pdu) != 128); + BUILD_BUG_ON(sizeof(struct nvme_tcp_icresp_pdu) != 128); + BUILD_BUG_ON(sizeof(struct nvme_tcp_term_pdu) != 24); + nvme_tcp_wq = alloc_workqueue("nvme_tcp_wq", WQ_MEM_RECLAIM | WQ_HIGHPRI, 0); if (!nvme_tcp_wq) From 8e19b87cfce2de2125f11363d7dea3d08f16ccae Mon Sep 17 00:00:00 2001 From: Minwoo Im Date: Thu, 9 Mar 2023 23:31:18 +0900 Subject: [PATCH 384/460] nvme-trace: show more opcode names We have more commands to show in the trace. Sync up. Signed-off-by: Minwoo Im Reviewed-by: Chaitanya Kulkarni Signed-off-by: Christoph Hellwig --- include/linux/nvme.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/linux/nvme.h b/include/linux/nvme.h index 4fad4aa245fb0..779507ac750b8 100644 --- a/include/linux/nvme.h +++ b/include/linux/nvme.h @@ -812,6 +812,7 @@ enum nvme_opcode { nvme_opcode_name(nvme_cmd_compare), \ nvme_opcode_name(nvme_cmd_write_zeroes), \ nvme_opcode_name(nvme_cmd_dsm), \ + nvme_opcode_name(nvme_cmd_verify), \ nvme_opcode_name(nvme_cmd_resv_register), \ nvme_opcode_name(nvme_cmd_resv_report), \ nvme_opcode_name(nvme_cmd_resv_acquire), \ @@ -1144,10 +1145,14 @@ enum nvme_admin_opcode { nvme_admin_opcode_name(nvme_admin_ns_mgmt), \ nvme_admin_opcode_name(nvme_admin_activate_fw), \ nvme_admin_opcode_name(nvme_admin_download_fw), \ + nvme_admin_opcode_name(nvme_admin_dev_self_test), \ nvme_admin_opcode_name(nvme_admin_ns_attach), \ nvme_admin_opcode_name(nvme_admin_keep_alive), \ nvme_admin_opcode_name(nvme_admin_directive_send), \ nvme_admin_opcode_name(nvme_admin_directive_recv), \ + nvme_admin_opcode_name(nvme_admin_virtual_mgmt), \ + nvme_admin_opcode_name(nvme_admin_nvme_mi_send), \ + nvme_admin_opcode_name(nvme_admin_nvme_mi_recv), \ nvme_admin_opcode_name(nvme_admin_dbbuf), \ nvme_admin_opcode_name(nvme_admin_format_nvm), \ nvme_admin_opcode_name(nvme_admin_security_send), \ From 6173a77b7e9d3e202bdb9897b23f2a8afe7bf286 Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Mon, 6 Mar 2023 10:13:13 +0900 Subject: [PATCH 385/460] nvmet: avoid potential UAF in nvmet_req_complete() An nvme target ->queue_response() operation implementation may free the request passed as argument. Such implementation potentially could result in a use after free of the request pointer when percpu_ref_put() is called in nvmet_req_complete(). Avoid such problem by using a local variable to save the sq pointer before calling __nvmet_req_complete(), thus avoiding dereferencing the req pointer after that function call. Fixes: a07b4970f464 ("nvmet: add a generic NVMe target") Signed-off-by: Damien Le Moal Reviewed-by: Chaitanya Kulkarni Signed-off-by: Christoph Hellwig --- drivers/nvme/target/core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c index f66ed13d7c11d..3935165048e74 100644 --- a/drivers/nvme/target/core.c +++ b/drivers/nvme/target/core.c @@ -756,8 +756,10 @@ static void __nvmet_req_complete(struct nvmet_req *req, u16 status) void nvmet_req_complete(struct nvmet_req *req, u16 status) { + struct nvmet_sq *sq = req->sq; + __nvmet_req_complete(req, status); - percpu_ref_put(&req->sq->ref); + percpu_ref_put(&sq->ref); } EXPORT_SYMBOL_GPL(nvmet_req_complete); From 6030363199e3a6341afb467ddddbed56640cbf6a Mon Sep 17 00:00:00 2001 From: Liang He Date: Wed, 15 Mar 2023 14:20:32 +0800 Subject: [PATCH 386/460] block: sunvdc: add check for mdesc_grab() returning NULL In vdc_port_probe(), we should check the return value of mdesc_grab() as it may return NULL, which can cause potential NPD bug. Fixes: 43fdf27470b2 ("[SPARC64]: Abstract out mdesc accesses for better MD update handling.") Signed-off-by: Liang He Link: https://lore.kernel.org/r/20230315062032.1741692-1-windhl@126.com [axboe: style cleanup] Signed-off-by: Jens Axboe --- drivers/block/sunvdc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/block/sunvdc.c b/drivers/block/sunvdc.c index fb855da971ee7..9fa821fa76b07 100644 --- a/drivers/block/sunvdc.c +++ b/drivers/block/sunvdc.c @@ -972,6 +972,8 @@ static int vdc_port_probe(struct vio_dev *vdev, const struct vio_device_id *id) print_version(); hp = mdesc_grab(); + if (!hp) + return -ENODEV; err = -ENODEV; if ((vdev->dev_no << PARTITION_SHIFT) & ~(u64)MINORMASK) { From 5f27571382ca42daa3e3d40d1b252bf18c2b61d2 Mon Sep 17 00:00:00 2001 From: Yu Kuai Date: Thu, 23 Feb 2023 17:12:26 +0800 Subject: [PATCH 387/460] block: count 'ios' and 'sectors' when io is done for bio-based device While using iostat for raid, I observed very strange 'await' occasionally, and turns out it's due to that 'ios' and 'sectors' is counted in bdev_start_io_acct(), while 'nsecs' is counted in bdev_end_io_acct(). I'm not sure why they are ccounted like that but I think this behaviour is obviously wrong because user will get wrong disk stats. Fix the problem by counting 'ios' and 'sectors' when io is done, like what rq-based device does. Fixes: 394ffa503bc4 ("blk: introduce generic io stat accounting help function") Signed-off-by: Yu Kuai Reviewed-by: Christoph Hellwig Link: https://lore.kernel.org/r/20230223091226.1135678-1-yukuai1@huaweicloud.com Signed-off-by: Jens Axboe --- block/blk-core.c | 16 ++++++---------- drivers/md/dm.c | 6 +++--- drivers/nvme/host/multipath.c | 8 ++++---- include/linux/blkdev.h | 5 ++--- 4 files changed, 15 insertions(+), 20 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index 9e5e0277a4d95..42926e6cb83c8 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -959,16 +959,11 @@ void update_io_ticks(struct block_device *part, unsigned long now, bool end) } } -unsigned long bdev_start_io_acct(struct block_device *bdev, - unsigned int sectors, enum req_op op, +unsigned long bdev_start_io_acct(struct block_device *bdev, enum req_op op, unsigned long start_time) { - const int sgrp = op_stat_group(op); - part_stat_lock(); update_io_ticks(bdev, start_time, false); - part_stat_inc(bdev, ios[sgrp]); - part_stat_add(bdev, sectors[sgrp], sectors); part_stat_local_inc(bdev, in_flight[op_is_write(op)]); part_stat_unlock(); @@ -984,13 +979,12 @@ EXPORT_SYMBOL(bdev_start_io_acct); */ unsigned long bio_start_io_acct(struct bio *bio) { - return bdev_start_io_acct(bio->bi_bdev, bio_sectors(bio), - bio_op(bio), jiffies); + return bdev_start_io_acct(bio->bi_bdev, bio_op(bio), jiffies); } EXPORT_SYMBOL_GPL(bio_start_io_acct); void bdev_end_io_acct(struct block_device *bdev, enum req_op op, - unsigned long start_time) + unsigned int sectors, unsigned long start_time) { const int sgrp = op_stat_group(op); unsigned long now = READ_ONCE(jiffies); @@ -998,6 +992,8 @@ void bdev_end_io_acct(struct block_device *bdev, enum req_op op, part_stat_lock(); update_io_ticks(bdev, now, true); + part_stat_inc(bdev, ios[sgrp]); + part_stat_add(bdev, sectors[sgrp], sectors); part_stat_add(bdev, nsecs[sgrp], jiffies_to_nsecs(duration)); part_stat_local_dec(bdev, in_flight[op_is_write(op)]); part_stat_unlock(); @@ -1007,7 +1003,7 @@ EXPORT_SYMBOL(bdev_end_io_acct); void bio_end_io_acct_remapped(struct bio *bio, unsigned long start_time, struct block_device *orig_bdev) { - bdev_end_io_acct(orig_bdev, bio_op(bio), start_time); + bdev_end_io_acct(orig_bdev, bio_op(bio), bio_sectors(bio), start_time); } EXPORT_SYMBOL_GPL(bio_end_io_acct_remapped); diff --git a/drivers/md/dm.c b/drivers/md/dm.c index eace45a18d456..f5cc330bb549e 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -512,10 +512,10 @@ static void dm_io_acct(struct dm_io *io, bool end) sectors = io->sectors; if (!end) - bdev_start_io_acct(bio->bi_bdev, sectors, bio_op(bio), - start_time); + bdev_start_io_acct(bio->bi_bdev, bio_op(bio), start_time); else - bdev_end_io_acct(bio->bi_bdev, bio_op(bio), start_time); + bdev_end_io_acct(bio->bi_bdev, bio_op(bio), sectors, + start_time); if (static_branch_unlikely(&stats_enabled) && unlikely(dm_stats_used(&md->stats))) { diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c index fc39d01e7b63b..9171452e2f6d4 100644 --- a/drivers/nvme/host/multipath.c +++ b/drivers/nvme/host/multipath.c @@ -123,9 +123,8 @@ void nvme_mpath_start_request(struct request *rq) return; nvme_req(rq)->flags |= NVME_MPATH_IO_STATS; - nvme_req(rq)->start_time = bdev_start_io_acct(disk->part0, - blk_rq_bytes(rq) >> SECTOR_SHIFT, - req_op(rq), jiffies); + nvme_req(rq)->start_time = bdev_start_io_acct(disk->part0, req_op(rq), + jiffies); } EXPORT_SYMBOL_GPL(nvme_mpath_start_request); @@ -136,7 +135,8 @@ void nvme_mpath_end_request(struct request *rq) if (!(nvme_req(rq)->flags & NVME_MPATH_IO_STATS)) return; bdev_end_io_acct(ns->head->disk->part0, req_op(rq), - nvme_req(rq)->start_time); + blk_rq_bytes(rq) >> SECTOR_SHIFT, + nvme_req(rq)->start_time); } void nvme_kick_requeue_lists(struct nvme_ctrl *ctrl) diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index d1aee08f8c181..941304f17492f 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -1446,11 +1446,10 @@ static inline void blk_wake_io_task(struct task_struct *waiter) wake_up_process(waiter); } -unsigned long bdev_start_io_acct(struct block_device *bdev, - unsigned int sectors, enum req_op op, +unsigned long bdev_start_io_acct(struct block_device *bdev, enum req_op op, unsigned long start_time); void bdev_end_io_acct(struct block_device *bdev, enum req_op op, - unsigned long start_time); + unsigned int sectors, unsigned long start_time); unsigned long bio_start_io_acct(struct bio *bio); void bio_end_io_acct_remapped(struct bio *bio, unsigned long start_time, From 6c0f5898836c05c6d850a750ed7940ba29e4e6c5 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 13 Mar 2023 13:29:17 -0700 Subject: [PATCH 388/460] md: select BLOCK_LEGACY_AUTOLOAD When BLOCK_LEGACY_AUTOLOAD is not enable, mdadm is not able to activate new arrays unless "CREATE names=yes" appears in mdadm.conf As this is a regression we need to always enable BLOCK_LEGACY_AUTOLOAD for when MD is selected - at least until mdadm is updated and the updates widely available. Cc: stable@vger.kernel.org # v5.18+ Fixes: fbdee71bb5d8 ("block: deprecate autoloading based on dev_t") Signed-off-by: NeilBrown Signed-off-by: Song Liu --- drivers/md/Kconfig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig index 998a5cfdbc4e9..662d219c39bf4 100644 --- a/drivers/md/Kconfig +++ b/drivers/md/Kconfig @@ -16,6 +16,10 @@ if MD config BLK_DEV_MD tristate "RAID support" select BLOCK_HOLDER_DEPRECATED if SYSFS + # BLOCK_LEGACY_AUTOLOAD requirement should be removed + # after relevant mdadm enhancements - to make "names=yes" + # the default - are widely available. + select BLOCK_LEGACY_AUTOLOAD help This driver lets you combine several hard disk partitions into one logical block device. This can be used to simply append one From 709671ffb15dcd1b4f6afe2a9d8c67c7c4ead4a1 Mon Sep 17 00:00:00 2001 From: Saaem Rizvi Date: Mon, 27 Feb 2023 18:55:07 -0500 Subject: [PATCH 389/460] drm/amd/display: Remove OTG DIV register write for Virtual signals. [WHY] Hot plugging and then hot unplugging leads to k1 and k2 values to change, as signal is detected as a virtual signal on hot unplug. Writing these values to OTG_PIXEL_RATE_DIV register might cause primary display to blank (known hw bug). [HOW] No longer write k1 and k2 values to register if signal is virtual, we have safe guards in place in the case that k1 and k2 is unassigned so that an unknown value is not written to the register either. Cc: stable@vger.kernel.org Cc: Mario Limonciello Reviewed-by: Samson Tam Reviewed-by: Alvin Lee Acked-by: Qingqing Zhuo Signed-off-by: Saaem Rizvi Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c index 16f892125b6fa..9d14045cccd63 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c @@ -1104,7 +1104,7 @@ unsigned int dcn32_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsign *k2_div = PIXEL_RATE_DIV_BY_2; else *k2_div = PIXEL_RATE_DIV_BY_4; - } else if (dc_is_dp_signal(stream->signal) || dc_is_virtual_signal(stream->signal)) { + } else if (dc_is_dp_signal(stream->signal)) { if (two_pix_per_container) { *k1_div = PIXEL_RATE_DIV_BY_1; *k2_div = PIXEL_RATE_DIV_BY_2; From 56574f89dbd84004c3fd6485bcaafb5aa9b8be14 Mon Sep 17 00:00:00 2001 From: Wesley Chalmers Date: Thu, 3 Nov 2022 22:29:31 -0400 Subject: [PATCH 390/460] drm/amd/display: Do not set DRR on pipe Commit [WHY] Writing to DRR registers such as OTG_V_TOTAL_MIN on the same frame as a pipe commit can cause underflow. Cc: stable@vger.kernel.org Cc: Mario Limonciello Reviewed-by: Jun Lei Acked-by: Qingqing Zhuo Signed-off-by: Wesley Chalmers Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c index 3b4d4d68359bb..df787fcf8e86e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c @@ -998,8 +998,5 @@ void dcn30_prepare_bandwidth(struct dc *dc, dc->clk_mgr->funcs->set_max_memclk(dc->clk_mgr, dc->clk_mgr->bw_params->clk_table.entries[dc->clk_mgr->bw_params->clk_table.num_entries - 1].memclk_mhz); dcn20_prepare_bandwidth(dc, context); - - dc_dmub_srv_p_state_delegate(dc, - context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching, context); } From cbd6c1b17d3b42b7935526a86ad5f66838767d03 Mon Sep 17 00:00:00 2001 From: Cruise Hung Date: Thu, 2 Mar 2023 10:33:51 +0800 Subject: [PATCH 391/460] drm/amd/display: Fix DP MST sinks removal issue [Why] In USB4 DP tunneling, it's possible to have this scenario that the path becomes unavailable and CM tears down the path a little bit late. So, in this case, the HPD is high but fails to read any DPCD register. That causes the link connection type to be set to sst. And not all sinks are removed behind the MST branch. [How] Restore the link connection type if it fails to read DPCD register. Cc: stable@vger.kernel.org Cc: Mario Limonciello Reviewed-by: Wenjing Liu Acked-by: Qingqing Zhuo Signed-off-by: Cruise Hung Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/link/link_detection.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/link/link_detection.c b/drivers/gpu/drm/amd/display/dc/link/link_detection.c index 38216c789d777..f70025ef7b69e 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_detection.c +++ b/drivers/gpu/drm/amd/display/dc/link/link_detection.c @@ -855,6 +855,7 @@ static bool detect_link_and_local_sink(struct dc_link *link, struct dc_sink *prev_sink = NULL; struct dpcd_caps prev_dpcd_caps; enum dc_connection_type new_connection_type = dc_connection_none; + enum dc_connection_type pre_connection_type = link->type; const uint32_t post_oui_delay = 30; // 30ms DC_LOGGER_INIT(link->ctx->logger); @@ -957,6 +958,8 @@ static bool detect_link_and_local_sink(struct dc_link *link, } if (!detect_dp(link, &sink_caps, reason)) { + link->type = pre_connection_type; + if (prev_sink) dc_sink_release(prev_sink); return false; @@ -1244,11 +1247,16 @@ bool link_detect(struct dc_link *link, enum dc_detect_reason reason) bool is_delegated_to_mst_top_mgr = false; enum dc_connection_type pre_link_type = link->type; + DC_LOGGER_INIT(link->ctx->logger); + is_local_sink_detect_success = detect_link_and_local_sink(link, reason); if (is_local_sink_detect_success && link->local_sink) verify_link_capability(link, link->local_sink, reason); + DC_LOG_DC("%s: link_index=%d is_local_sink_detect_success=%d pre_link_type=%d link_type=%d\n", __func__, + link->link_index, is_local_sink_detect_success, pre_link_type, link->type); + if (is_local_sink_detect_success && link->local_sink && dc_is_dp_signal(link->local_sink->sink_signal) && link->dpcd_caps.is_mst_capable) From 7304ee979b6b6422f41a1312391a5e505fc29ccd Mon Sep 17 00:00:00 2001 From: Ayush Gupta Date: Thu, 2 Mar 2023 09:58:05 -0500 Subject: [PATCH 392/460] drm/amd/display: disconnect MPCC only on OTG change [Why] Framedrops are observed while playing Vp9 and Av1 10 bit video on 8k resolution using VSR while playback controls are disappeared/appeared [How] Now ODM 2 to 1 is disabled for 5k or greater resolutions on VSR. Cc: stable@vger.kernel.org Cc: Mario Limonciello Reviewed-by: Alvin Lee Acked-by: Qingqing Zhuo Signed-off-by: Ayush Gupta Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c index 74e50c09bb62f..d024007f0f650 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c @@ -1915,6 +1915,7 @@ int dcn32_populate_dml_pipes_from_context( bool subvp_in_use = false; uint8_t is_pipe_split_expected[MAX_PIPES] = {0}; struct dc_crtc_timing *timing; + bool vsr_odm_support = false; dcn20_populate_dml_pipes_from_context(dc, context, pipes, fast_validate); @@ -1932,12 +1933,15 @@ int dcn32_populate_dml_pipes_from_context( timing = &pipe->stream->timing; pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_dal; + vsr_odm_support = (res_ctx->pipe_ctx[i].stream->src.width >= 5120 && + res_ctx->pipe_ctx[i].stream->src.width > res_ctx->pipe_ctx[i].stream->dst.width); if (context->stream_count == 1 && context->stream_status[0].plane_count == 1 && !dc_is_hdmi_signal(res_ctx->pipe_ctx[i].stream->signal) && is_h_timing_divisible_by_2(res_ctx->pipe_ctx[i].stream) && pipe->stream->timing.pix_clk_100hz * 100 > DCN3_2_VMIN_DISPCLK_HZ && - dc->debug.enable_single_display_2to1_odm_policy) { + dc->debug.enable_single_display_2to1_odm_policy && + !vsr_odm_support) { //excluding 2to1 ODM combine on >= 5k vsr pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_2to1; } pipe_cnt++; From 20bc9f76b6a2455c6b54b91ae7634f147f64987f Mon Sep 17 00:00:00 2001 From: David Belanger Date: Tue, 28 Feb 2023 14:11:24 -0500 Subject: [PATCH 393/460] drm/amdkfd: Fixed kfd_process cleanup on module exit. Handle case when module is unloaded (kfd_exit) before a process space (mm_struct) is released. v2: Fixed potential race conditions by removing all kfd_process from the process table first, then working on releasing the resources. v3: Fixed loop element access / synchronization. Fixed extra empty lines. Signed-off-by: David Belanger Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_module.c | 1 + drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 1 + drivers/gpu/drm/amd/amdkfd/kfd_process.c | 67 +++++++++++++++++++++--- 3 files changed, 62 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_module.c b/drivers/gpu/drm/amd/amdkfd/kfd_module.c index 09b966dc37681..aee2212e52f69 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_module.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_module.c @@ -77,6 +77,7 @@ static int kfd_init(void) static void kfd_exit(void) { + kfd_cleanup_processes(); kfd_debugfs_fini(); kfd_process_destroy_wq(); kfd_procfs_shutdown(); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index bfa30d12406b3..7e4d992e48b3c 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -928,6 +928,7 @@ bool kfd_dev_is_large_bar(struct kfd_dev *dev); int kfd_process_create_wq(void); void kfd_process_destroy_wq(void); +void kfd_cleanup_processes(void); struct kfd_process *kfd_create_process(struct file *filep); struct kfd_process *kfd_get_process(const struct task_struct *task); struct kfd_process *kfd_lookup_process_by_pasid(u32 pasid); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index 7acd55a814b2f..4208e0f01064d 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -1167,6 +1167,17 @@ static void kfd_process_free_notifier(struct mmu_notifier *mn) kfd_unref_process(container_of(mn, struct kfd_process, mmu_notifier)); } +static void kfd_process_notifier_release_internal(struct kfd_process *p) +{ + cancel_delayed_work_sync(&p->eviction_work); + cancel_delayed_work_sync(&p->restore_work); + + /* Indicate to other users that MM is no longer valid */ + p->mm = NULL; + + mmu_notifier_put(&p->mmu_notifier); +} + static void kfd_process_notifier_release(struct mmu_notifier *mn, struct mm_struct *mm) { @@ -1181,17 +1192,22 @@ static void kfd_process_notifier_release(struct mmu_notifier *mn, return; mutex_lock(&kfd_processes_mutex); + /* + * Do early return if table is empty. + * + * This could potentially happen if this function is called concurrently + * by mmu_notifier and by kfd_cleanup_pocesses. + * + */ + if (hash_empty(kfd_processes_table)) { + mutex_unlock(&kfd_processes_mutex); + return; + } hash_del_rcu(&p->kfd_processes); mutex_unlock(&kfd_processes_mutex); synchronize_srcu(&kfd_processes_srcu); - cancel_delayed_work_sync(&p->eviction_work); - cancel_delayed_work_sync(&p->restore_work); - - /* Indicate to other users that MM is no longer valid */ - p->mm = NULL; - - mmu_notifier_put(&p->mmu_notifier); + kfd_process_notifier_release_internal(p); } static const struct mmu_notifier_ops kfd_process_mmu_notifier_ops = { @@ -1200,6 +1216,43 @@ static const struct mmu_notifier_ops kfd_process_mmu_notifier_ops = { .free_notifier = kfd_process_free_notifier, }; +/* + * This code handles the case when driver is being unloaded before all + * mm_struct are released. We need to safely free the kfd_process and + * avoid race conditions with mmu_notifier that might try to free them. + * + */ +void kfd_cleanup_processes(void) +{ + struct kfd_process *p; + struct hlist_node *p_temp; + unsigned int temp; + HLIST_HEAD(cleanup_list); + + /* + * Move all remaining kfd_process from the process table to a + * temp list for processing. Once done, callback from mmu_notifier + * release will not see the kfd_process in the table and do early return, + * avoiding double free issues. + */ + mutex_lock(&kfd_processes_mutex); + hash_for_each_safe(kfd_processes_table, temp, p_temp, p, kfd_processes) { + hash_del_rcu(&p->kfd_processes); + synchronize_srcu(&kfd_processes_srcu); + hlist_add_head(&p->kfd_processes, &cleanup_list); + } + mutex_unlock(&kfd_processes_mutex); + + hlist_for_each_entry_safe(p, p_temp, &cleanup_list, kfd_processes) + kfd_process_notifier_release_internal(p); + + /* + * Ensures that all outstanding free_notifier get called, triggering + * the release of the kfd_process struct. + */ + mmu_notifier_synchronize(); +} + static int kfd_process_init_cwsr_apu(struct kfd_process *p, struct file *filep) { unsigned long offset; From f3921a9a641483784448fb982b2eb738b383d9b9 Mon Sep 17 00:00:00 2001 From: Felix Kuehling Date: Mon, 13 Mar 2023 20:03:08 -0400 Subject: [PATCH 394/460] drm/amdgpu: Don't resume IOMMU after incomplete init Check kfd->init_complete in kgd2kfd_iommu_resume, consistent with other kgd2kfd calls. This should fix IOMMU errors on resume from suspend when KFD IOMMU initialization failed. Reported-by: Matt Fagnani Link: https://lore.kernel.org/r/4a3b225c-2ffd-e758-4de1-447375e34cad@bell.net/ Link: https://bugzilla.kernel.org/show_bug.cgi?id=217170 Link: https://gitlab.freedesktop.org/drm/amd/-/issues/2454 Cc: Vasant Hegde Cc: Linux regression tracking (Thorsten Leemhuis) Cc: stable@vger.kernel.org Signed-off-by: Felix Kuehling Acked-by: Alex Deucher Tested-by: Matt Fagnani Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_device.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c index 3de7f616a001c..ec70a1658dc38 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c @@ -59,6 +59,7 @@ static int kfd_gtt_sa_init(struct kfd_dev *kfd, unsigned int buf_size, unsigned int chunk_size); static void kfd_gtt_sa_fini(struct kfd_dev *kfd); +static int kfd_resume_iommu(struct kfd_dev *kfd); static int kfd_resume(struct kfd_dev *kfd); static void kfd_device_info_set_sdma_info(struct kfd_dev *kfd) @@ -624,7 +625,7 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd, svm_migrate_init(kfd->adev); - if (kgd2kfd_resume_iommu(kfd)) + if (kfd_resume_iommu(kfd)) goto device_iommu_error; if (kfd_resume(kfd)) @@ -772,6 +773,14 @@ int kgd2kfd_resume(struct kfd_dev *kfd, bool run_pm) } int kgd2kfd_resume_iommu(struct kfd_dev *kfd) +{ + if (!kfd->init_complete) + return 0; + + return kfd_resume_iommu(kfd); +} + +static int kfd_resume_iommu(struct kfd_dev *kfd) { int err = 0; From 37beabe9a891b92174cd1aafbfa881fe9e05aa87 Mon Sep 17 00:00:00 2001 From: Emeel Hakim Date: Wed, 8 Feb 2023 14:25:54 +0200 Subject: [PATCH 395/460] net/mlx5e: Fix macsec ASO context alignment Currently mlx5e_macsec_umr struct does not satisfy hardware memory alignment requirement. Hence the result of querying advanced steering operation (ASO) is not copied to the memory region as expected. Fix by satisfying hardware memory alignment requirement and move context to be first field in struct for better readability. Fixes: 1f53da676439 ("net/mlx5e: Create advanced steering operation (ASO) object for MACsec") Signed-off-by: Emeel Hakim Reviewed-by: Leon Romanovsky Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c index 08d0929e82603..8af53178e40d4 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c @@ -89,8 +89,8 @@ struct mlx5e_macsec_rx_sc { }; struct mlx5e_macsec_umr { + u8 __aligned(64) ctx[MLX5_ST_SZ_BYTES(macsec_aso)]; dma_addr_t dma_addr; - u8 ctx[MLX5_ST_SZ_BYTES(macsec_aso)]; u32 mkey; }; From 9a92fe1db9e57ea94388a1d768e8ee42af858377 Mon Sep 17 00:00:00 2001 From: Parav Pandit Date: Fri, 12 Mar 2021 07:21:29 -0600 Subject: [PATCH 396/460] net/mlx5e: Don't cache tunnel offloads capability When mlx5e attaches again after device health recovery, the device capabilities might have changed by the eswitch manager. For example in one flow when ECPF changes the eswitch mode between legacy and switchdev, it updates the flow table tunnel capability. The cached value is only used in one place, so just check the capability there instead. Fixes: 5bef709d76a2 ("net/mlx5: Enable host PF HCA after eswitch is initialized") Signed-off-by: Parav Pandit Signed-off-by: Daniel Jurgens Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en.h | 1 - drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 4 +--- drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 1 - drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c | 1 - 4 files changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index 4276c6eb68201..4a19ef4a98110 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -313,7 +313,6 @@ struct mlx5e_params { } channel; } mqprio; bool rx_cqe_compress_def; - bool tunneled_offload_en; struct dim_cq_moder rx_cq_moderation; struct dim_cq_moder tx_cq_moderation; struct mlx5e_packet_merge_param packet_merge; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 51b5f3cca5047..56fc2aebb9eee 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -4979,8 +4979,6 @@ void mlx5e_build_nic_params(struct mlx5e_priv *priv, struct mlx5e_xsk *xsk, u16 /* TX inline */ mlx5_query_min_inline(mdev, ¶ms->tx_min_inline_mode); - params->tunneled_offload_en = mlx5_tunnel_inner_ft_supported(mdev); - /* AF_XDP */ params->xsk = xsk; @@ -5285,7 +5283,7 @@ static int mlx5e_init_nic_rx(struct mlx5e_priv *priv) } features = MLX5E_RX_RES_FEATURE_PTP; - if (priv->channels.params.tunneled_offload_en) + if (mlx5_tunnel_inner_ft_supported(mdev)) features |= MLX5E_RX_RES_FEATURE_INNER_FT; err = mlx5e_rx_res_init(priv->rx_res, priv->mdev, features, priv->max_nch, priv->drop_rq.rqn, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index 43fd12fb87b87..8ff654b4e9e14 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -755,7 +755,6 @@ static void mlx5e_build_rep_params(struct net_device *netdev) mlx5e_set_rx_cq_mode_params(params, cq_period_mode); params->mqprio.num_tc = 1; - params->tunneled_offload_en = false; if (rep->vport != MLX5_VPORT_UPLINK) params->vlan_strip_disable = true; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c index c2a4f86bc8909..baa7ef8123139 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c @@ -70,7 +70,6 @@ static void mlx5i_build_nic_params(struct mlx5_core_dev *mdev, params->packet_merge.type = MLX5E_PACKET_MERGE_NONE; params->hard_mtu = MLX5_IB_GRH_BYTES + MLX5_IPOIB_HARD_LEN; - params->tunneled_offload_en = false; /* CQE compression is not supported for IPoIB */ params->rx_cqe_compress_def = false; From ba5d8f72b82cc197355c9340ef89dab813815865 Mon Sep 17 00:00:00 2001 From: Parav Pandit Date: Thu, 24 Jun 2021 18:22:57 +0300 Subject: [PATCH 397/460] net/mlx5: Fix setting ec_function bit in MANAGE_PAGES When ECPF is a page supplier, reclaim pages missed to honor the ec_function bit provided by the firmware. It always used the ec_function to true during driver unload flow for ECPF. This is incorrect. Honor the ec_function bit provided by device during page allocation request event. Fixes: d6945242f45d ("net/mlx5: Hold pages RB tree per VF") Signed-off-by: Parav Pandit Signed-off-by: Daniel Jurgens Signed-off-by: Saeed Mahameed --- .../ethernet/mellanox/mlx5/core/pagealloc.c | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c b/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c index 64d4e7125e9bb..95dc67fb30015 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c @@ -82,6 +82,16 @@ static u16 func_id_to_type(struct mlx5_core_dev *dev, u16 func_id, bool ec_funct return func_id <= mlx5_core_max_vfs(dev) ? MLX5_VF : MLX5_SF; } +static u32 mlx5_get_ec_function(u32 function) +{ + return function >> 16; +} + +static u32 mlx5_get_func_id(u32 function) +{ + return function & 0xffff; +} + static struct rb_root *page_root_per_function(struct mlx5_core_dev *dev, u32 function) { struct rb_root *root; @@ -665,20 +675,22 @@ static int optimal_reclaimed_pages(void) } static int mlx5_reclaim_root_pages(struct mlx5_core_dev *dev, - struct rb_root *root, u16 func_id) + struct rb_root *root, u32 function) { u64 recl_pages_to_jiffies = msecs_to_jiffies(mlx5_tout_ms(dev, RECLAIM_PAGES)); unsigned long end = jiffies + recl_pages_to_jiffies; while (!RB_EMPTY_ROOT(root)) { + u32 ec_function = mlx5_get_ec_function(function); + u32 function_id = mlx5_get_func_id(function); int nclaimed; int err; - err = reclaim_pages(dev, func_id, optimal_reclaimed_pages(), - &nclaimed, false, mlx5_core_is_ecpf(dev)); + err = reclaim_pages(dev, function_id, optimal_reclaimed_pages(), + &nclaimed, false, ec_function); if (err) { - mlx5_core_warn(dev, "failed reclaiming pages (%d) for func id 0x%x\n", - err, func_id); + mlx5_core_warn(dev, "reclaim_pages err (%d) func_id=0x%x ec_func=0x%x\n", + err, function_id, ec_function); return err; } From 7ba930fc25def6fd736abcdfa224272948a65cf7 Mon Sep 17 00:00:00 2001 From: Daniel Jurgens Date: Thu, 20 Oct 2022 00:13:50 +0300 Subject: [PATCH 398/460] net/mlx5: Disable eswitch before waiting for VF pages The offending commit changed the ordering of moving to legacy mode and waiting for the VF pages. Moving to legacy mode is important in bluefield, because it sends the host driver into error state, and frees its pages. Without this transition we end up waiting 2 minutes for pages that aren't coming before carrying on with the unload process. Fixes: f019679ea5f2 ("net/mlx5: E-switch, Remove dependency between sriov and eswitch mode") Signed-off-by: Daniel Jurgens Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index 540840e80493b..f36a3aa4b5c8f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c @@ -1364,8 +1364,8 @@ static void mlx5_unload(struct mlx5_core_dev *dev) { mlx5_devlink_traps_unregister(priv_to_devlink(dev)); mlx5_sf_dev_table_destroy(dev); - mlx5_sriov_detach(dev); mlx5_eswitch_disable(dev->priv.eswitch); + mlx5_sriov_detach(dev); mlx5_lag_remove_mdev(dev); mlx5_ec_cleanup(dev); mlx5_sf_hw_table_destroy(dev); From 1313d78ac0c1cfcff7bdece8da54b080e71487c4 Mon Sep 17 00:00:00 2001 From: Maor Dickman Date: Tue, 7 Feb 2023 15:07:00 +0200 Subject: [PATCH 399/460] net/mlx5: E-switch, Fix wrong usage of source port rewrite in split rules In few cases, rules with mirror use case are split to two FTEs, one which do the mirror action and forward to second FTE which do the rest of the rule actions and the second redirect action. In case of mirror rules which do split and forward to ovs internal port or VF stack devices, source port rewrite should be used in the second FTE but it is wrongly also set in the first FTE which break the offload. Fix this issue by removing the wrong check if source port rewrite is needed to be used on the first FTE of the split and instead return EOPNOTSUPP which will block offload of rules which mirror to ovs internal port or VF stack devices which isn't supported. Fixes: 10742efc20a4 ("net/mlx5e: VF tunnel TX traffic offloading") Fixes: a508728a4c8b ("net/mlx5e: VF tunnel RX traffic offloading") Signed-off-by: Maor Dickman Reviewed-by: Roi Dayan Signed-off-by: Saeed Mahameed --- .../net/ethernet/mellanox/mlx5/core/eswitch_offloads.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index d766a64b18234..22075943bb582 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -723,11 +723,11 @@ mlx5_eswitch_add_fwd_rule(struct mlx5_eswitch *esw, flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; for (i = 0; i < esw_attr->split_count; i++) { - if (esw_is_indir_table(esw, attr)) - err = esw_setup_indir_table(dest, &flow_act, esw, attr, false, &i); - else if (esw_is_chain_src_port_rewrite(esw, esw_attr)) - err = esw_setup_chain_src_port_rewrite(dest, &flow_act, esw, chains, attr, - &i); + if (esw_attr->dests[i].flags & MLX5_ESW_DEST_CHAIN_WITH_SRC_PORT_CHANGE) + /* Source port rewrite (forward to ovs internal port or statck device) isn't + * supported in the rule of split action. + */ + err = -EOPNOTSUPP; else esw_setup_vport_dest(dest, &flow_act, esw, esw_attr, i, i, false); From 28d3815a629cbdee660dd1c9de28d77cb3d77917 Mon Sep 17 00:00:00 2001 From: Maor Dickman Date: Wed, 8 Feb 2023 11:37:41 +0200 Subject: [PATCH 400/460] net/mlx5: E-switch, Fix missing set of split_count when forward to ovs internal port Rules with mirror actions are split to two FTEs when the actions after the mirror action contains pedit, vlan push/pop or ct. Forward to ovs internal port adds implicit header rewrite (pedit) but missing trigger to do split. Fix by setting split_count when forwarding to ovs internal port which will trigger split in mirror rules. Fixes: 27484f7170ed ("net/mlx5e: Offload tc rules that redirect to ovs internal port") Signed-off-by: Maor Dickman Reviewed-by: Roi Dayan Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index 70b8d2dfa751f..90944bf271ce4 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -4304,6 +4304,7 @@ int mlx5e_set_fwd_to_int_port_actions(struct mlx5e_priv *priv, esw_attr->dest_int_port = dest_int_port; esw_attr->dests[out_index].flags |= MLX5_ESW_DEST_CHAIN_WITH_SRC_PORT_CHANGE; + esw_attr->split_count = out_index; /* Forward to root fdb for matching against the new source vport */ attr->dest_chain = 0; From c9668f0b1d28570327dbba189f2c61f6f9e43ae7 Mon Sep 17 00:00:00 2001 From: Paul Blakey Date: Sun, 12 Feb 2023 11:01:43 +0200 Subject: [PATCH 401/460] net/mlx5e: Fix cleanup null-ptr deref on encap lock During module is unloaded while a peer tc flow is still offloaded, first the peer uplink rep profile is changed to a nic profile, and so neigh encap lock is destroyed. Next during unload, the VF reps netdevs are unregistered which causes the original non-peer tc flow to be deleted, which deletes the peer flow. The peer flow deletion detaches the encap entry and try to take the already destroyed encap lock, causing the below trace. Fix this by clearing peer flows during tc eswitch cleanup (mlx5e_tc_esw_cleanup()). Relevant trace: [ 4316.837128] BUG: kernel NULL pointer dereference, address: 00000000000001d8 [ 4316.842239] RIP: 0010:__mutex_lock+0xb5/0xc40 [ 4316.851897] Call Trace: [ 4316.852481] [ 4316.857214] mlx5e_rep_neigh_entry_release+0x93/0x790 [mlx5_core] [ 4316.858258] mlx5e_rep_encap_entry_detach+0xa7/0xf0 [mlx5_core] [ 4316.859134] mlx5e_encap_dealloc+0xa3/0xf0 [mlx5_core] [ 4316.859867] clean_encap_dests.part.0+0x5c/0xe0 [mlx5_core] [ 4316.860605] mlx5e_tc_del_fdb_flow+0x32a/0x810 [mlx5_core] [ 4316.862609] __mlx5e_tc_del_fdb_peer_flow+0x1a2/0x250 [mlx5_core] [ 4316.863394] mlx5e_tc_del_flow+0x(/0x630 [mlx5_core] [ 4316.864090] mlx5e_flow_put+0x5f/0x100 [mlx5_core] [ 4316.864771] mlx5e_delete_flower+0x4de/0xa40 [mlx5_core] [ 4316.865486] tc_setup_cb_reoffload+0x20/0x80 [ 4316.865905] fl_reoffload+0x47c/0x510 [cls_flower] [ 4316.869181] tcf_block_playback_offloads+0x91/0x1d0 [ 4316.869649] tcf_block_unbind+0xe7/0x1b0 [ 4316.870049] tcf_block_offload_cmd.isra.0+0x1ee/0x270 [ 4316.879266] tcf_block_offload_unbind+0x61/0xa0 [ 4316.879711] __tcf_block_put+0xa4/0x310 Fixes: 04de7dda7394 ("net/mlx5e: Infrastructure for duplicated offloading of TC flows") Fixes: 1418ddd96afd ("net/mlx5e: Duplicate offloaded TC eswitch rules under uplink LAG") Signed-off-by: Paul Blakey Reviewed-by: Chris Mi Reviewed-by: Roi Dayan Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index 90944bf271ce4..cc35cbc9934d1 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -5464,6 +5464,16 @@ int mlx5e_tc_esw_init(struct mlx5_rep_uplink_priv *uplink_priv) void mlx5e_tc_esw_cleanup(struct mlx5_rep_uplink_priv *uplink_priv) { + struct mlx5e_rep_priv *rpriv; + struct mlx5_eswitch *esw; + struct mlx5e_priv *priv; + + rpriv = container_of(uplink_priv, struct mlx5e_rep_priv, uplink_priv); + priv = netdev_priv(rpriv->netdev); + esw = priv->mdev->priv.eswitch; + + mlx5e_tc_clean_fdb_peer_flows(esw); + mlx5e_tc_tun_cleanup(uplink_priv->encap); mapping_destroy(uplink_priv->tunnel_enc_opts_mapping); From dd64572490c3d7aab04083db8791fab157a941ed Mon Sep 17 00:00:00 2001 From: Gal Pressman Date: Tue, 24 Jan 2023 17:34:32 +0200 Subject: [PATCH 402/460] net/mlx5e: kTLS, Fix missing error unwind on unsupported cipher type Do proper error unwinding when adding an unsupported TX/RX cipher type. Move the switch case prior to key creation so there's less to unwind, and change the goto label name to describe the action performed instead of what failed. Fixes: 4960c414db35 ("net/mlx5e: Support 256 bit keys with kTLS device offload") Signed-off-by: Gal Pressman Reviewed-by: Tariq Toukan Signed-off-by: Saeed Mahameed --- .../mellanox/mlx5/core/en_accel/ktls_rx.c | 24 ++++++++++--------- .../mellanox/mlx5/core/en_accel/ktls_tx.c | 22 +++++++++-------- 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c index 4be770443b0cd..9b597cb245985 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c @@ -621,15 +621,6 @@ int mlx5e_ktls_add_rx(struct net_device *netdev, struct sock *sk, if (unlikely(!priv_rx)) return -ENOMEM; - dek = mlx5_ktls_create_key(priv->tls->dek_pool, crypto_info); - if (IS_ERR(dek)) { - err = PTR_ERR(dek); - goto err_create_key; - } - priv_rx->dek = dek; - - INIT_LIST_HEAD(&priv_rx->list); - spin_lock_init(&priv_rx->lock); switch (crypto_info->cipher_type) { case TLS_CIPHER_AES_GCM_128: priv_rx->crypto_info.crypto_info_128 = @@ -642,9 +633,20 @@ int mlx5e_ktls_add_rx(struct net_device *netdev, struct sock *sk, default: WARN_ONCE(1, "Unsupported cipher type %u\n", crypto_info->cipher_type); - return -EOPNOTSUPP; + err = -EOPNOTSUPP; + goto err_cipher_type; } + dek = mlx5_ktls_create_key(priv->tls->dek_pool, crypto_info); + if (IS_ERR(dek)) { + err = PTR_ERR(dek); + goto err_cipher_type; + } + priv_rx->dek = dek; + + INIT_LIST_HEAD(&priv_rx->list); + spin_lock_init(&priv_rx->lock); + rxq = mlx5e_ktls_sk_get_rxq(sk); priv_rx->rxq = rxq; priv_rx->sk = sk; @@ -677,7 +679,7 @@ int mlx5e_ktls_add_rx(struct net_device *netdev, struct sock *sk, mlx5e_tir_destroy(&priv_rx->tir); err_create_tir: mlx5_ktls_destroy_key(priv->tls->dek_pool, priv_rx->dek); -err_create_key: +err_cipher_type: kfree(priv_rx); return err; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c index 60b3e08a10286..0e4c0a093293a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c @@ -469,14 +469,6 @@ int mlx5e_ktls_add_tx(struct net_device *netdev, struct sock *sk, if (IS_ERR(priv_tx)) return PTR_ERR(priv_tx); - dek = mlx5_ktls_create_key(priv->tls->dek_pool, crypto_info); - if (IS_ERR(dek)) { - err = PTR_ERR(dek); - goto err_create_key; - } - priv_tx->dek = dek; - - priv_tx->expected_seq = start_offload_tcp_sn; switch (crypto_info->cipher_type) { case TLS_CIPHER_AES_GCM_128: priv_tx->crypto_info.crypto_info_128 = @@ -489,8 +481,18 @@ int mlx5e_ktls_add_tx(struct net_device *netdev, struct sock *sk, default: WARN_ONCE(1, "Unsupported cipher type %u\n", crypto_info->cipher_type); - return -EOPNOTSUPP; + err = -EOPNOTSUPP; + goto err_pool_push; } + + dek = mlx5_ktls_create_key(priv->tls->dek_pool, crypto_info); + if (IS_ERR(dek)) { + err = PTR_ERR(dek); + goto err_pool_push; + } + + priv_tx->dek = dek; + priv_tx->expected_seq = start_offload_tcp_sn; priv_tx->tx_ctx = tls_offload_ctx_tx(tls_ctx); mlx5e_set_ktls_tx_priv_ctx(tls_ctx, priv_tx); @@ -500,7 +502,7 @@ int mlx5e_ktls_add_tx(struct net_device *netdev, struct sock *sk, return 0; -err_create_key: +err_pool_push: pool_push(pool, priv_tx); return err; } From 031a163f2c476adcb2c01e27a7d323e66174ac11 Mon Sep 17 00:00:00 2001 From: Shay Drory Date: Tue, 28 Feb 2023 10:36:19 +0200 Subject: [PATCH 403/460] net/mlx5: Set BREAK_FW_WAIT flag first when removing driver Currently, BREAK_FW_WAIT flag is set after syncing with fw_reset. However, fw_reset can call mlx5_load_one() which is waiting for fw init bit and BREAK_FW_WAIT flag is intended to stop. e.g.: the driver might wait on a loop it should exit. Fix it by setting the flag before syncing with fw_reset. Fixes: 8324a02c342a ("net/mlx5: Add exit route when waiting for FW") Signed-off-by: Shay Drory Reviewed-by: Moshe Shemesh Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index f36a3aa4b5c8f..f1de152a61135 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c @@ -1789,11 +1789,11 @@ static void remove_one(struct pci_dev *pdev) struct mlx5_core_dev *dev = pci_get_drvdata(pdev); struct devlink *devlink = priv_to_devlink(dev); + set_bit(MLX5_BREAK_FW_WAIT, &dev->intf_state); /* mlx5_drain_fw_reset() is using devlink APIs. Hence, we must drain * fw_reset before unregistering the devlink. */ mlx5_drain_fw_reset(dev); - set_bit(MLX5_BREAK_FW_WAIT, &dev->intf_state); devlink_unregister(devlink); mlx5_sriov_disable(pdev); mlx5_crdump_disable(dev); From 78dee7befd56987283c13877b834c0aa97ad51b9 Mon Sep 17 00:00:00 2001 From: Adham Faris Date: Mon, 23 Jan 2023 10:09:01 +0200 Subject: [PATCH 404/460] net/mlx5e: Lower maximum allowed MTU in XSK to match XDP prerequisites XSK redirecting XDP programs require linearity, hence applies restrictions on the MTU. For PAGE_SIZE=4K, MTU shouldn't exceed 3498. Features that contradict with XDP such HW-LRO and HW-GRO are enforced by the driver in advance, during XSK params validation, except for MTU, which was not enforced before this patch. This has been spotted during test scenario described below: Attaching xdpsock program (PAGE_SIZE=4K), with MTU < 3498, detaching XDP program, changing the MTU to arbitrary value in the range [3499, 3754], attaching XDP program again, which ended up with failure since MTU is > 3498. This commit lowers the XSK MTU limitation to be aligned with XDP MTU limitation, since XSK socket is meaningless without XDP program. Signed-off-by: Adham Faris Reviewed-by: Tariq Toukan Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 56fc2aebb9eee..a7f2ab22cc40c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -4169,13 +4169,17 @@ static bool mlx5e_xsk_validate_mtu(struct net_device *netdev, struct xsk_buff_pool *xsk_pool = mlx5e_xsk_get_pool(&chs->params, chs->params.xsk, ix); struct mlx5e_xsk_param xsk; + int max_xdp_mtu; if (!xsk_pool) continue; mlx5e_build_xsk_param(xsk_pool, &xsk); + max_xdp_mtu = mlx5e_xdp_max_mtu(new_params, &xsk); - if (!mlx5e_validate_xsk_param(new_params, &xsk, mdev)) { + /* Validate XSK params and XDP MTU in advance */ + if (!mlx5e_validate_xsk_param(new_params, &xsk, mdev) || + new_params->sw_mtu > max_xdp_mtu) { u32 hr = mlx5e_get_linear_rq_headroom(new_params, &xsk); int max_mtu_frame, max_mtu_page, max_mtu; @@ -4185,9 +4189,9 @@ static bool mlx5e_xsk_validate_mtu(struct net_device *netdev, */ max_mtu_frame = MLX5E_HW2SW_MTU(new_params, xsk.chunk_size - hr); max_mtu_page = MLX5E_HW2SW_MTU(new_params, SKB_MAX_HEAD(0)); - max_mtu = min(max_mtu_frame, max_mtu_page); + max_mtu = min3(max_mtu_frame, max_mtu_page, max_xdp_mtu); - netdev_err(netdev, "MTU %d is too big for an XSK running on channel %u. Try MTU <= %d\n", + netdev_err(netdev, "MTU %d is too big for an XSK running on channel %u or its redirection XDP program. Try MTU <= %d\n", new_params->sw_mtu, ix, max_mtu); return false; } From d1a0075ad6b693c2bd41e7aedb8a4f3b74b6999c Mon Sep 17 00:00:00 2001 From: Oz Shlomo Date: Thu, 16 Feb 2023 12:34:21 +0000 Subject: [PATCH 405/460] net/sched: TC, fix raw counter initialization Freed counters may be reused by fs core. As such, raw counters may not be initialized to zero. Cache the counter values when the action stats object is initialized to have a proper base value for calculating the difference from the previous query. Fixes: 2b68d659a704 ("net/mlx5e: TC, support per action stats") Signed-off-by: Oz Shlomo Reviewed-by: Paul Blakey Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en/tc/act_stats.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act_stats.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act_stats.c index 626cb7470fa57..07c1895a2b234 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act_stats.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act_stats.c @@ -64,6 +64,7 @@ mlx5e_tc_act_stats_add(struct mlx5e_tc_act_stats_handle *handle, { struct mlx5e_tc_act_stats *act_stats, *old_act_stats; struct rhashtable *ht = &handle->ht; + u64 lastused; int err = 0; act_stats = kvzalloc(sizeof(*act_stats), GFP_KERNEL); @@ -73,6 +74,10 @@ mlx5e_tc_act_stats_add(struct mlx5e_tc_act_stats_handle *handle, act_stats->tc_act_cookie = act_cookie; act_stats->counter = counter; + mlx5_fc_query_cached_raw(counter, + &act_stats->lastbytes, + &act_stats->lastpackets, &lastused); + rcu_read_lock(); old_act_stats = rhashtable_lookup_get_insert_fast(ht, &act_stats->hash, From 1166add424dae14ccdb64a6eefbf26766c9d0ef2 Mon Sep 17 00:00:00 2001 From: Oz Shlomo Date: Tue, 21 Feb 2023 14:46:56 +0000 Subject: [PATCH 406/460] net/mlx5e: TC, fix missing error code Missing error code when mlx5e_tc_act_stats_create fails Fixes: d13674b1d14c ("net/mlx5e: TC, map tc action cookie to a hw counter") Reported-by: Dan Carpenter Signed-off-by: Oz Shlomo Reviewed-by: Paul Blakey Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index cc35cbc9934d1..d2e191ee07047 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -5305,8 +5305,10 @@ int mlx5e_tc_nic_init(struct mlx5e_priv *priv) mlx5e_tc_debugfs_init(tc, mlx5e_fs_get_debugfs_root(priv->fs)); tc->action_stats_handle = mlx5e_tc_act_stats_create(); - if (IS_ERR(tc->action_stats_handle)) + if (IS_ERR(tc->action_stats_handle)) { + err = PTR_ERR(tc->action_stats_handle); goto err_act_stats; + } return 0; @@ -5441,8 +5443,10 @@ int mlx5e_tc_esw_init(struct mlx5_rep_uplink_priv *uplink_priv) } uplink_priv->action_stats_handle = mlx5e_tc_act_stats_create(); - if (IS_ERR(uplink_priv->action_stats_handle)) + if (IS_ERR(uplink_priv->action_stats_handle)) { + err = PTR_ERR(uplink_priv->action_stats_handle); goto err_action_counter; + } return 0; From b23bf10cca59b2955fa5c2b5e4f753962b4f88ca Mon Sep 17 00:00:00 2001 From: Oz Shlomo Date: Tue, 21 Feb 2023 15:24:39 +0000 Subject: [PATCH 407/460] net/mlx5e: TC, fix cloned flow attribute Currently the cloned flow attr resets the original tc action cookies count. Fix that by resetting the cloned flow attribute. Fixes: cca7eac13856 ("net/mlx5e: TC, store tc action cookies per attr") Signed-off-by: Oz Shlomo Reviewed-by: Paul Blakey Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index d2e191ee07047..6bfed633343ab 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -3752,7 +3752,7 @@ mlx5e_clone_flow_attr_for_post_act(struct mlx5_flow_attr *attr, parse_attr->filter_dev = attr->parse_attr->filter_dev; attr2->action = 0; attr2->counter = NULL; - attr->tc_act_cookies_count = 0; + attr2->tc_act_cookies_count = 0; attr2->flags = 0; attr2->parse_attr = parse_attr; attr2->dest_chain = 0; From c7b7c64ab5821352db0b3fbaa92773e5a60bfaa7 Mon Sep 17 00:00:00 2001 From: Oz Shlomo Date: Wed, 22 Feb 2023 10:03:36 +0000 Subject: [PATCH 408/460] net/mlx5e: TC, Remove error message log print The cited commit attempts to update the hw stats when dumping tc actions. However, the driver may be called to update the stats of a police action that may not be in hardware. In such cases the driver will fail to lookup the police action object and will output an error message both to extack and dmesg. The dmesg error is confusing as it may not indicate an actual error. Remove the dmesg error. Fixes: 2b68d659a704 ("net/mlx5e: TC, support per action stats") Signed-off-by: Oz Shlomo Reviewed-by: Paul Blakey Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/police.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/police.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/police.c index c4378afdec09e..1bd1c94fb9776 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/police.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/police.c @@ -178,7 +178,6 @@ tc_act_police_stats(struct mlx5e_priv *priv, meter = mlx5e_tc_meter_get(priv->mdev, ¶ms); if (IS_ERR(meter)) { NL_SET_ERR_MSG_MOD(fl_act->extack, "Failed to get flow meter"); - mlx5_core_err(priv->mdev, "Failed to get flow meter %d\n", params.index); return PTR_ERR(meter); } From 6acd352dfee558194643adbed7e849fe80fd1b93 Mon Sep 17 00:00:00 2001 From: Li zeming Date: Sat, 18 Mar 2023 02:25:38 +0800 Subject: [PATCH 409/460] io_uring: rsrc: Optimize return value variable 'ret' The initialization assignment of the variable ret is changed to 0, only in 'goto fail;' Use the ret variable as the function return value. Signed-off-by: Li zeming Link: https://lore.kernel.org/r/20230317182538.3027-1-zeming@nfschina.com Signed-off-by: Jens Axboe --- io_uring/rsrc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/io_uring/rsrc.c b/io_uring/rsrc.c index 056f40946ff68..09a16d709cb55 100644 --- a/io_uring/rsrc.c +++ b/io_uring/rsrc.c @@ -410,7 +410,7 @@ __cold static int io_rsrc_data_alloc(struct io_ring_ctx *ctx, unsigned nr, struct io_rsrc_data **pdata) { struct io_rsrc_data *data; - int ret = -ENOMEM; + int ret = 0; unsigned i; data = kzalloc(sizeof(*data), GFP_KERNEL); From 7c10131803e45269ddc6c817f19ed649110f3cae Mon Sep 17 00:00:00 2001 From: Shawn Bohrer Date: Tue, 14 Mar 2023 10:33:51 -0500 Subject: [PATCH 410/460] veth: Fix use after free in XDP_REDIRECT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 718a18a0c8a6 ("veth: Rework veth_xdp_rcv_skb in order to accept non-linear skb") introduced a bug where it tried to use pskb_expand_head() if the headroom was less than XDP_PACKET_HEADROOM. This however uses kmalloc to expand the head, which will later allow consume_skb() to free the skb while is it still in use by AF_XDP. Previously if the headroom was less than XDP_PACKET_HEADROOM we continued on to allocate a new skb from pages so this restores that behavior. BUG: KASAN: use-after-free in __xsk_rcv+0x18d/0x2c0 Read of size 78 at addr ffff888976250154 by task napi/iconduit-g/148640 CPU: 5 PID: 148640 Comm: napi/iconduit-g Kdump: loaded Tainted: G O 6.1.4-cloudflare-kasan-2023.1.2 #1 Hardware name: Quanta Computer Inc. QuantaPlex T41S-2U/S2S-MB, BIOS S2S_3B10.03 06/21/2018 Call Trace: dump_stack_lvl+0x34/0x48 print_report+0x170/0x473 ? __xsk_rcv+0x18d/0x2c0 kasan_report+0xad/0x130 ? __xsk_rcv+0x18d/0x2c0 kasan_check_range+0x149/0x1a0 memcpy+0x20/0x60 __xsk_rcv+0x18d/0x2c0 __xsk_map_redirect+0x1f3/0x490 ? veth_xdp_rcv_skb+0x89c/0x1ba0 [veth] xdp_do_redirect+0x5ca/0xd60 veth_xdp_rcv_skb+0x935/0x1ba0 [veth] ? __netif_receive_skb_list_core+0x671/0x920 ? veth_xdp+0x670/0x670 [veth] veth_xdp_rcv+0x304/0xa20 [veth] ? do_xdp_generic+0x150/0x150 ? veth_xdp_rcv_one+0xde0/0xde0 [veth] ? _raw_spin_lock_bh+0xe0/0xe0 ? newidle_balance+0x887/0xe30 ? __perf_event_task_sched_in+0xdb/0x800 veth_poll+0x139/0x571 [veth] ? veth_xdp_rcv+0xa20/0xa20 [veth] ? _raw_spin_unlock+0x39/0x70 ? finish_task_switch.isra.0+0x17e/0x7d0 ? __switch_to+0x5cf/0x1070 ? __schedule+0x95b/0x2640 ? io_schedule_timeout+0x160/0x160 __napi_poll+0xa1/0x440 napi_threaded_poll+0x3d1/0x460 ? __napi_poll+0x440/0x440 ? __kthread_parkme+0xc6/0x1f0 ? __napi_poll+0x440/0x440 kthread+0x2a2/0x340 ? kthread_complete_and_exit+0x20/0x20 ret_from_fork+0x22/0x30 Freed by task 148640: kasan_save_stack+0x23/0x50 kasan_set_track+0x21/0x30 kasan_save_free_info+0x2a/0x40 ____kasan_slab_free+0x169/0x1d0 slab_free_freelist_hook+0xd2/0x190 __kmem_cache_free+0x1a1/0x2f0 skb_release_data+0x449/0x600 consume_skb+0x9f/0x1c0 veth_xdp_rcv_skb+0x89c/0x1ba0 [veth] veth_xdp_rcv+0x304/0xa20 [veth] veth_poll+0x139/0x571 [veth] __napi_poll+0xa1/0x440 napi_threaded_poll+0x3d1/0x460 kthread+0x2a2/0x340 ret_from_fork+0x22/0x30 The buggy address belongs to the object at ffff888976250000 which belongs to the cache kmalloc-2k of size 2048 The buggy address is located 340 bytes inside of 2048-byte region [ffff888976250000, ffff888976250800) The buggy address belongs to the physical page: page:00000000ae18262a refcount:2 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x976250 head:00000000ae18262a order:3 compound_mapcount:0 compound_pincount:0 flags: 0x2ffff800010200(slab|head|node=0|zone=2|lastcpupid=0x1ffff) raw: 002ffff800010200 0000000000000000 dead000000000122 ffff88810004cf00 raw: 0000000000000000 0000000080080008 00000002ffffffff 0000000000000000 page dumped because: kasan: bad access detected Memory state around the buggy address: ffff888976250000: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb ffff888976250080: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb > ffff888976250100: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb ^ ffff888976250180: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb ffff888976250200: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb Fixes: 718a18a0c8a6 ("veth: Rework veth_xdp_rcv_skb in order to accept non-linear skb") Signed-off-by: Shawn Bohrer Acked-by: Lorenzo Bianconi Acked-by: Toshiaki Makita Acked-by: Toke Høiland-Jørgensen Link: https://lore.kernel.org/r/20230314153351.2201328-1-sbohrer@cloudflare.com Signed-off-by: Jakub Kicinski --- drivers/net/veth.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/net/veth.c b/drivers/net/veth.c index 4da74ac27f9a2..a30a66cace143 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c @@ -708,7 +708,8 @@ static int veth_convert_skb_to_xdp_buff(struct veth_rq *rq, u32 frame_sz; if (skb_shared(skb) || skb_head_is_locked(skb) || - skb_shinfo(skb)->nr_frags) { + skb_shinfo(skb)->nr_frags || + skb_headroom(skb) < XDP_PACKET_HEADROOM) { u32 size, len, max_head_size, off; struct sk_buff *nskb; struct page *page; @@ -773,9 +774,6 @@ static int veth_convert_skb_to_xdp_buff(struct veth_rq *rq, consume_skb(skb); skb = nskb; - } else if (skb_headroom(skb) < XDP_PACKET_HEADROOM && - pskb_expand_head(skb, VETH_XDP_HEADROOM, 0, GFP_ATOMIC)) { - goto drop; } /* SKB "head" area always have tailroom for skb_shared_info */ From cd356010ce4c69ac7e1a40586112df24d22c6a4b Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Tue, 14 Mar 2023 17:30:25 +0200 Subject: [PATCH 411/460] net: phy: mscc: fix deadlock in phy_ethtool_{get,set}_wol() Since the blamed commit, phy_ethtool_get_wol() and phy_ethtool_set_wol() acquire phydev->lock, but the mscc phy driver implementations, vsc85xx_wol_get() and vsc85xx_wol_set(), acquire the same lock as well, resulting in a deadlock. $ ip link set swp3 down ============================================ WARNING: possible recursive locking detected mscc_felix 0000:00:00.5 swp3: Link is Down -------------------------------------------- ip/375 is trying to acquire lock: ffff3d7e82e987a8 (&dev->lock){+.+.}-{4:4}, at: vsc85xx_wol_get+0x2c/0xf4 but task is already holding lock: ffff3d7e82e987a8 (&dev->lock){+.+.}-{4:4}, at: phy_ethtool_get_wol+0x3c/0x6c other info that might help us debug this: Possible unsafe locking scenario: CPU0 ---- lock(&dev->lock); lock(&dev->lock); *** DEADLOCK *** May be due to missing lock nesting notation 2 locks held by ip/375: #0: ffffd43b2a955788 (rtnl_mutex){+.+.}-{4:4}, at: rtnetlink_rcv_msg+0x144/0x58c #1: ffff3d7e82e987a8 (&dev->lock){+.+.}-{4:4}, at: phy_ethtool_get_wol+0x3c/0x6c Call trace: __mutex_lock+0x98/0x454 mutex_lock_nested+0x2c/0x38 vsc85xx_wol_get+0x2c/0xf4 phy_ethtool_get_wol+0x50/0x6c phy_suspend+0x84/0xcc phy_state_machine+0x1b8/0x27c phy_stop+0x70/0x154 phylink_stop+0x34/0xc0 dsa_port_disable_rt+0x2c/0xa4 dsa_slave_close+0x38/0xec __dev_close_many+0xc8/0x16c __dev_change_flags+0xdc/0x218 dev_change_flags+0x24/0x6c do_setlink+0x234/0xea4 __rtnl_newlink+0x46c/0x878 rtnl_newlink+0x50/0x7c rtnetlink_rcv_msg+0x16c/0x58c Removing the mutex_lock(&phydev->lock) calls from the driver restores the functionality. Fixes: 2f987d486610 ("net: phy: Add locks to ethtool functions") Signed-off-by: Vladimir Oltean Reviewed-by: Simon Horman Reviewed-by: Andrew Lunn Link: https://lore.kernel.org/r/20230314153025.2372970-1-vladimir.oltean@nxp.com Signed-off-by: Jakub Kicinski --- drivers/net/phy/mscc/mscc_main.c | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/drivers/net/phy/mscc/mscc_main.c b/drivers/net/phy/mscc/mscc_main.c index 8a13b1ad9a330..62bf99e45af16 100644 --- a/drivers/net/phy/mscc/mscc_main.c +++ b/drivers/net/phy/mscc/mscc_main.c @@ -280,12 +280,9 @@ static int vsc85xx_wol_set(struct phy_device *phydev, u16 pwd[3] = {0, 0, 0}; struct ethtool_wolinfo *wol_conf = wol; - mutex_lock(&phydev->lock); rc = phy_select_page(phydev, MSCC_PHY_PAGE_EXTENDED_2); - if (rc < 0) { - rc = phy_restore_page(phydev, rc, rc); - goto out_unlock; - } + if (rc < 0) + return phy_restore_page(phydev, rc, rc); if (wol->wolopts & WAKE_MAGIC) { /* Store the device address for the magic packet */ @@ -323,7 +320,7 @@ static int vsc85xx_wol_set(struct phy_device *phydev, rc = phy_restore_page(phydev, rc, rc > 0 ? 0 : rc); if (rc < 0) - goto out_unlock; + return rc; if (wol->wolopts & WAKE_MAGIC) { /* Enable the WOL interrupt */ @@ -331,22 +328,19 @@ static int vsc85xx_wol_set(struct phy_device *phydev, reg_val |= MII_VSC85XX_INT_MASK_WOL; rc = phy_write(phydev, MII_VSC85XX_INT_MASK, reg_val); if (rc) - goto out_unlock; + return rc; } else { /* Disable the WOL interrupt */ reg_val = phy_read(phydev, MII_VSC85XX_INT_MASK); reg_val &= (~MII_VSC85XX_INT_MASK_WOL); rc = phy_write(phydev, MII_VSC85XX_INT_MASK, reg_val); if (rc) - goto out_unlock; + return rc; } /* Clear WOL iterrupt status */ reg_val = phy_read(phydev, MII_VSC85XX_INT_STATUS); -out_unlock: - mutex_unlock(&phydev->lock); - - return rc; + return 0; } static void vsc85xx_wol_get(struct phy_device *phydev, @@ -358,10 +352,9 @@ static void vsc85xx_wol_get(struct phy_device *phydev, u16 pwd[3] = {0, 0, 0}; struct ethtool_wolinfo *wol_conf = wol; - mutex_lock(&phydev->lock); rc = phy_select_page(phydev, MSCC_PHY_PAGE_EXTENDED_2); if (rc < 0) - goto out_unlock; + goto out_restore_page; reg_val = __phy_read(phydev, MSCC_PHY_WOL_MAC_CONTROL); if (reg_val & SECURE_ON_ENABLE) @@ -377,9 +370,8 @@ static void vsc85xx_wol_get(struct phy_device *phydev, } } -out_unlock: +out_restore_page: phy_restore_page(phydev, rc, rc > 0 ? 0 : rc); - mutex_unlock(&phydev->lock); } #if IS_ENABLED(CONFIG_OF_MDIO) From 7ad2c39860dc0ca01d2152232224d2124e160fe3 Mon Sep 17 00:00:00 2001 From: Yu Zhe Date: Thu, 16 Mar 2023 16:39:54 +0800 Subject: [PATCH 412/460] xen: remove unnecessary (void*) conversions Pointer variables of void * type do not require type cast. Signed-off-by: Yu Zhe Reviewed-by: Juergen Gross Link: https://lore.kernel.org/r/20230316083954.4223-1-yuzhe@nfschina.com Signed-off-by: Juergen Gross --- drivers/xen/xenfs/xensyms.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/xen/xenfs/xensyms.c b/drivers/xen/xenfs/xensyms.c index c6c73a33c44d5..b799bc759c15f 100644 --- a/drivers/xen/xenfs/xensyms.c +++ b/drivers/xen/xenfs/xensyms.c @@ -64,7 +64,7 @@ static int xensyms_next_sym(struct xensyms *xs) static void *xensyms_start(struct seq_file *m, loff_t *pos) { - struct xensyms *xs = (struct xensyms *)m->private; + struct xensyms *xs = m->private; xs->op.u.symdata.symnum = *pos; @@ -76,7 +76,7 @@ static void *xensyms_start(struct seq_file *m, loff_t *pos) static void *xensyms_next(struct seq_file *m, void *p, loff_t *pos) { - struct xensyms *xs = (struct xensyms *)m->private; + struct xensyms *xs = m->private; xs->op.u.symdata.symnum = ++(*pos); @@ -88,7 +88,7 @@ static void *xensyms_next(struct seq_file *m, void *p, loff_t *pos) static int xensyms_show(struct seq_file *m, void *p) { - struct xensyms *xs = (struct xensyms *)m->private; + struct xensyms *xs = m->private; struct xenpf_symdata *symdata = &xs->op.u.symdata; seq_printf(m, "%016llx %c %s\n", symdata->address, @@ -120,7 +120,7 @@ static int xensyms_open(struct inode *inode, struct file *file) return ret; m = file->private_data; - xs = (struct xensyms *)m->private; + xs = m->private; xs->namelen = XEN_KSYM_NAME_LEN + 1; xs->name = kzalloc(xs->namelen, GFP_KERNEL); @@ -138,7 +138,7 @@ static int xensyms_open(struct inode *inode, struct file *file) static int xensyms_release(struct inode *inode, struct file *file) { struct seq_file *m = file->private_data; - struct xensyms *xs = (struct xensyms *)m->private; + struct xensyms *xs = m->private; kfree(xs->name); return seq_release_private(inode, file); From 5da28edd7bd5518f97175ecea77615bb729a7a28 Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Thu, 16 Mar 2023 12:11:42 +0000 Subject: [PATCH 413/460] io_uring/msg_ring: let target know allocated index msg_ring requests transferring files support auto index selection via IORING_FILE_INDEX_ALLOC, however they don't return the selected index to the target ring and there is no other good way for the userspace to know where is the receieved file. Return the index for allocated slots and 0 otherwise, which is consistent with other fixed file installing requests. Cc: stable@vger.kernel.org # v6.0+ Fixes: e6130eba8a848 ("io_uring: add support for passing fixed file descriptors") Signed-off-by: Pavel Begunkov Link: https://github.com/axboe/liburing/issues/809 Signed-off-by: Jens Axboe --- io_uring/msg_ring.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/io_uring/msg_ring.c b/io_uring/msg_ring.c index 8803c0979e2a9..85fd7ce5f05b8 100644 --- a/io_uring/msg_ring.c +++ b/io_uring/msg_ring.c @@ -202,7 +202,7 @@ static int io_msg_install_complete(struct io_kiocb *req, unsigned int issue_flag * completes with -EOVERFLOW, then the sender must ensure that a * later IORING_OP_MSG_RING delivers the message. */ - if (!io_post_aux_cqe(target_ctx, msg->user_data, msg->len, 0)) + if (!io_post_aux_cqe(target_ctx, msg->user_data, ret, 0)) ret = -EOVERFLOW; out_unlock: io_double_unlock_ctx(target_ctx); @@ -229,6 +229,8 @@ static int io_msg_send_fd(struct io_kiocb *req, unsigned int issue_flags) struct io_ring_ctx *ctx = req->ctx; struct file *src_file = msg->src_file; + if (msg->len) + return -EINVAL; if (target_ctx == ctx) return -EINVAL; if (target_ctx->flags & IORING_SETUP_R_DISABLED) From d2acf789088bb562cea342b6a24e646df4d47839 Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Thu, 16 Mar 2023 15:26:05 +0000 Subject: [PATCH 414/460] io_uring/rsrc: fix folio accounting | BUG: Bad page state in process kworker/u8:0 pfn:5c001 | page:00000000bfda61c8 refcount:0 mapcount:0 mapping:0000000000000000 index:0x20001 pfn:0x5c001 | head:0000000011409842 order:9 entire_mapcount:0 nr_pages_mapped:0 pincount:1 | anon flags: 0x3fffc00000b0004(uptodate|head|mappedtodisk|swapbacked|node=0|zone=0|lastcpupid=0xffff) | raw: 03fffc0000000000 fffffc0000700001 ffffffff00700903 0000000100000000 | raw: 0000000000000200 0000000000000000 00000000ffffffff 0000000000000000 | head: 03fffc00000b0004 dead000000000100 dead000000000122 ffff00000a809dc1 | head: 0000000000020000 0000000000000000 00000000ffffffff 0000000000000000 | page dumped because: nonzero pincount | CPU: 3 PID: 9 Comm: kworker/u8:0 Not tainted 6.3.0-rc2-00001-gc6811bf0cd87 #1 | Hardware name: linux,dummy-virt (DT) | Workqueue: events_unbound io_ring_exit_work | Call trace: | dump_backtrace+0x13c/0x208 | show_stack+0x34/0x58 | dump_stack_lvl+0x150/0x1a8 | dump_stack+0x20/0x30 | bad_page+0xec/0x238 | free_tail_pages_check+0x280/0x350 | free_pcp_prepare+0x60c/0x830 | free_unref_page+0x50/0x498 | free_compound_page+0xcc/0x100 | free_transhuge_page+0x1f0/0x2b8 | destroy_large_folio+0x80/0xc8 | __folio_put+0xc4/0xf8 | gup_put_folio+0xd0/0x250 | unpin_user_page+0xcc/0x128 | io_buffer_unmap+0xec/0x2c0 | __io_sqe_buffers_unregister+0xa4/0x1e0 | io_ring_exit_work+0x68c/0x1188 | process_one_work+0x91c/0x1a58 | worker_thread+0x48c/0xe30 | kthread+0x278/0x2f0 | ret_from_fork+0x10/0x20 Mark reports an issue with the recent patches coalescing compound pages while registering them in io_uring. The reason is that we try to drop excessive references with folio_put_refs(), but pages were acquired with pin_user_pages(), which has extra accounting and so should be put down with matching unpin_user_pages() or at least gup_put_folio(). As a fix unpin_user_pages() all but first page instead, and let's figure out a better API after. Fixes: 57bebf807e2abcf8 ("io_uring/rsrc: optimise registered huge pages") Reported-by: Mark Rutland Reviewed-by: Jens Axboe Tested-by: Jens Axboe Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/10efd5507d6d1f05ea0f3c601830e08767e189bd.1678980230.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- io_uring/rsrc.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/io_uring/rsrc.c b/io_uring/rsrc.c index 09a16d709cb55..e2bac9f899029 100644 --- a/io_uring/rsrc.c +++ b/io_uring/rsrc.c @@ -1235,7 +1235,13 @@ static int io_sqe_buffer_register(struct io_ring_ctx *ctx, struct iovec *iov, } } if (folio) { - folio_put_refs(folio, nr_pages - 1); + /* + * The pages are bound to the folio, it doesn't + * actually unpin them but drops all but one reference, + * which is usually put down by io_buffer_unmap(). + * Note, needs a better helper. + */ + unpin_user_pages(&pages[1], nr_pages - 1); nr_pages = 1; } } From 8f0d196e4dc137470bbd5de98278d941c8002fcb Mon Sep 17 00:00:00 2001 From: Lukas Bulwahn Date: Thu, 16 Mar 2023 12:16:30 +0100 Subject: [PATCH 415/460] block: remove obsolete config BLOCK_COMPAT Before commit bdc1ddad3e5f ("compat_ioctl: block: move blkdev_compat_ioctl() into ioctl.c"), the config BLOCK_COMPAT was used to include compat_ioctl.c into the kernel build. With this commit, the code is moved into ioctl.c and included with the config COMPAT. So, since then, the config BLOCK_COMPAT has no effect and any further purpose. Remove this obsolete config BLOCK_COMPAT. Signed-off-by: Lukas Bulwahn Reviewed-by: Christoph Hellwig Acked-by: Arnd Bergmann Link: https://lore.kernel.org/r/20230316111630.4897-1-lukas.bulwahn@gmail.com Signed-off-by: Jens Axboe --- block/Kconfig | 3 --- 1 file changed, 3 deletions(-) diff --git a/block/Kconfig b/block/Kconfig index 5d9d9c84d5165..941b2dca70db7 100644 --- a/block/Kconfig +++ b/block/Kconfig @@ -204,9 +204,6 @@ config BLK_INLINE_ENCRYPTION_FALLBACK source "block/partitions/Kconfig" -config BLOCK_COMPAT - def_bool COMPAT - config BLK_MQ_PCI def_bool PCI From 077706165717686a2a6a71405fef036cd5b37ae0 Mon Sep 17 00:00:00 2001 From: Arseniy Krasnov Date: Tue, 14 Mar 2023 14:05:48 +0300 Subject: [PATCH 416/460] virtio/vsock: don't use skbuff state to account credit 'skb->len' can vary when we partially read the data, this complicates the calculation of credit to be updated in 'virtio_transport_inc_rx_pkt()/ virtio_transport_dec_rx_pkt()'. Also in 'virtio_transport_dec_rx_pkt()' we were miscalculating the credit since 'skb->len' was redundant. For these reasons, let's replace the use of skbuff state to calculate new 'rx_bytes'/'fwd_cnt' values with explicit value as input argument. This makes code more simple, because it is not needed to change skbuff state before each call to update 'rx_bytes'/'fwd_cnt'. Fixes: 71dc9ec9ac7d ("virtio/vsock: replace virtio_vsock_pkt with sk_buff") Signed-off-by: Arseniy Krasnov Reviewed-by: Stefano Garzarella Acked-by: Bobby Eshleman Signed-off-by: David S. Miller --- net/vmw_vsock/virtio_transport_common.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c index a1581c77cf84a..618680fd9906f 100644 --- a/net/vmw_vsock/virtio_transport_common.c +++ b/net/vmw_vsock/virtio_transport_common.c @@ -241,21 +241,18 @@ static int virtio_transport_send_pkt_info(struct vsock_sock *vsk, } static bool virtio_transport_inc_rx_pkt(struct virtio_vsock_sock *vvs, - struct sk_buff *skb) + u32 len) { - if (vvs->rx_bytes + skb->len > vvs->buf_alloc) + if (vvs->rx_bytes + len > vvs->buf_alloc) return false; - vvs->rx_bytes += skb->len; + vvs->rx_bytes += len; return true; } static void virtio_transport_dec_rx_pkt(struct virtio_vsock_sock *vvs, - struct sk_buff *skb) + u32 len) { - int len; - - len = skb_headroom(skb) - sizeof(struct virtio_vsock_hdr) - skb->len; vvs->rx_bytes -= len; vvs->fwd_cnt += len; } @@ -388,7 +385,9 @@ virtio_transport_stream_do_dequeue(struct vsock_sock *vsk, skb_pull(skb, bytes); if (skb->len == 0) { - virtio_transport_dec_rx_pkt(vvs, skb); + u32 pkt_len = le32_to_cpu(virtio_vsock_hdr(skb)->len); + + virtio_transport_dec_rx_pkt(vvs, pkt_len); consume_skb(skb); } else { __skb_queue_head(&vvs->rx_queue, skb); @@ -437,17 +436,17 @@ static int virtio_transport_seqpacket_do_dequeue(struct vsock_sock *vsk, while (!msg_ready) { struct virtio_vsock_hdr *hdr; + size_t pkt_len; skb = __skb_dequeue(&vvs->rx_queue); if (!skb) break; hdr = virtio_vsock_hdr(skb); + pkt_len = (size_t)le32_to_cpu(hdr->len); if (dequeued_len >= 0) { - size_t pkt_len; size_t bytes_to_copy; - pkt_len = (size_t)le32_to_cpu(hdr->len); bytes_to_copy = min(user_buf_len, pkt_len); if (bytes_to_copy) { @@ -484,7 +483,7 @@ static int virtio_transport_seqpacket_do_dequeue(struct vsock_sock *vsk, msg->msg_flags |= MSG_EOR; } - virtio_transport_dec_rx_pkt(vvs, skb); + virtio_transport_dec_rx_pkt(vvs, pkt_len); kfree_skb(skb); } @@ -1040,7 +1039,7 @@ virtio_transport_recv_enqueue(struct vsock_sock *vsk, spin_lock_bh(&vvs->rx_lock); - can_enqueue = virtio_transport_inc_rx_pkt(vvs, skb); + can_enqueue = virtio_transport_inc_rx_pkt(vvs, len); if (!can_enqueue) { free_pkt = true; goto out; From 6825e6b4f8e53799d83bc39ca6ec5baed4e2adde Mon Sep 17 00:00:00 2001 From: Arseniy Krasnov Date: Tue, 14 Mar 2023 14:06:53 +0300 Subject: [PATCH 417/460] virtio/vsock: remove redundant 'skb_pull()' call Since we now no longer use 'skb->len' to update credit, there is no sense to update skbuff state, because it is used only once after dequeue to copy data and then will be released. Fixes: 71dc9ec9ac7d ("virtio/vsock: replace virtio_vsock_pkt with sk_buff") Signed-off-by: Arseniy Krasnov Reviewed-by: Stefano Garzarella Acked-by: Bobby Eshleman Signed-off-by: David S. Miller --- net/vmw_vsock/virtio_transport_common.c | 1 - 1 file changed, 1 deletion(-) diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c index 618680fd9906f..9a411475e2010 100644 --- a/net/vmw_vsock/virtio_transport_common.c +++ b/net/vmw_vsock/virtio_transport_common.c @@ -465,7 +465,6 @@ static int virtio_transport_seqpacket_do_dequeue(struct vsock_sock *vsk, dequeued_len = err; } else { user_buf_len -= bytes_to_copy; - skb_pull(skb, bytes_to_copy); } spin_lock_bh(&vvs->rx_lock); From 8daaf39f7f6ef53a11817f6a11ec104016c3545f Mon Sep 17 00:00:00 2001 From: Arseniy Krasnov Date: Tue, 14 Mar 2023 14:08:20 +0300 Subject: [PATCH 418/460] virtio/vsock: don't drop skbuff on copy failure This returns behaviour of SOCK_STREAM read as before skbuff usage. When copying to user fails current skbuff won't be dropped, but returned to sockets's queue. Technically instead of 'skb_dequeue()', 'skb_peek()' is called and when skbuff becomes empty, it is removed from queue by '__skb_unlink()'. Fixes: 71dc9ec9ac7d ("virtio/vsock: replace virtio_vsock_pkt with sk_buff") Signed-off-by: Arseniy Krasnov Reviewed-by: Stefano Garzarella Acked-by: Bobby Eshleman Signed-off-by: David S. Miller --- net/vmw_vsock/virtio_transport_common.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c index 9a411475e2010..6564192e7f201 100644 --- a/net/vmw_vsock/virtio_transport_common.c +++ b/net/vmw_vsock/virtio_transport_common.c @@ -364,7 +364,7 @@ virtio_transport_stream_do_dequeue(struct vsock_sock *vsk, spin_lock_bh(&vvs->rx_lock); while (total < len && !skb_queue_empty(&vvs->rx_queue)) { - skb = __skb_dequeue(&vvs->rx_queue); + skb = skb_peek(&vvs->rx_queue); bytes = len - total; if (bytes > skb->len) @@ -388,9 +388,8 @@ virtio_transport_stream_do_dequeue(struct vsock_sock *vsk, u32 pkt_len = le32_to_cpu(virtio_vsock_hdr(skb)->len); virtio_transport_dec_rx_pkt(vvs, pkt_len); + __skb_unlink(skb, &vvs->rx_queue); consume_skb(skb); - } else { - __skb_queue_head(&vvs->rx_queue, skb); } } From 7e699d2a4e8104d304e921ac5e0a0c73f0f7b623 Mon Sep 17 00:00:00 2001 From: Arseniy Krasnov Date: Tue, 14 Mar 2023 14:09:27 +0300 Subject: [PATCH 419/460] test/vsock: copy to user failure test This adds SOCK_STREAM and SOCK_SEQPACKET tests for invalid buffer case. It tries to read data to NULL buffer (data already presents in socket's queue), then uses valid buffer. For SOCK_STREAM second read must return data, because skbuff is not dropped, but for SOCK_SEQPACKET skbuff will be dropped by kernel, and 'recv()' will return EAGAIN. Signed-off-by: Arseniy Krasnov Reviewed-by: Stefano Garzarella Signed-off-by: David S. Miller --- tools/testing/vsock/vsock_test.c | 118 +++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) diff --git a/tools/testing/vsock/vsock_test.c b/tools/testing/vsock/vsock_test.c index 67e9f9df3a8c4..3de10dbb50f52 100644 --- a/tools/testing/vsock/vsock_test.c +++ b/tools/testing/vsock/vsock_test.c @@ -860,6 +860,114 @@ static void test_stream_poll_rcvlowat_client(const struct test_opts *opts) close(fd); } +#define INV_BUF_TEST_DATA_LEN 512 + +static void test_inv_buf_client(const struct test_opts *opts, bool stream) +{ + unsigned char data[INV_BUF_TEST_DATA_LEN] = {0}; + ssize_t ret; + int fd; + + if (stream) + fd = vsock_stream_connect(opts->peer_cid, 1234); + else + fd = vsock_seqpacket_connect(opts->peer_cid, 1234); + + if (fd < 0) { + perror("connect"); + exit(EXIT_FAILURE); + } + + control_expectln("SENDDONE"); + + /* Use invalid buffer here. */ + ret = recv(fd, NULL, sizeof(data), 0); + if (ret != -1) { + fprintf(stderr, "expected recv(2) failure, got %zi\n", ret); + exit(EXIT_FAILURE); + } + + if (errno != ENOMEM) { + fprintf(stderr, "unexpected recv(2) errno %d\n", errno); + exit(EXIT_FAILURE); + } + + ret = recv(fd, data, sizeof(data), MSG_DONTWAIT); + + if (stream) { + /* For SOCK_STREAM we must continue reading. */ + if (ret != sizeof(data)) { + fprintf(stderr, "expected recv(2) success, got %zi\n", ret); + exit(EXIT_FAILURE); + } + /* Don't check errno in case of success. */ + } else { + /* For SOCK_SEQPACKET socket's queue must be empty. */ + if (ret != -1) { + fprintf(stderr, "expected recv(2) failure, got %zi\n", ret); + exit(EXIT_FAILURE); + } + + if (errno != EAGAIN) { + fprintf(stderr, "unexpected recv(2) errno %d\n", errno); + exit(EXIT_FAILURE); + } + } + + control_writeln("DONE"); + + close(fd); +} + +static void test_inv_buf_server(const struct test_opts *opts, bool stream) +{ + unsigned char data[INV_BUF_TEST_DATA_LEN] = {0}; + ssize_t res; + int fd; + + if (stream) + fd = vsock_stream_accept(VMADDR_CID_ANY, 1234, NULL); + else + fd = vsock_seqpacket_accept(VMADDR_CID_ANY, 1234, NULL); + + if (fd < 0) { + perror("accept"); + exit(EXIT_FAILURE); + } + + res = send(fd, data, sizeof(data), 0); + if (res != sizeof(data)) { + fprintf(stderr, "unexpected send(2) result %zi\n", res); + exit(EXIT_FAILURE); + } + + control_writeln("SENDDONE"); + + control_expectln("DONE"); + + close(fd); +} + +static void test_stream_inv_buf_client(const struct test_opts *opts) +{ + test_inv_buf_client(opts, true); +} + +static void test_stream_inv_buf_server(const struct test_opts *opts) +{ + test_inv_buf_server(opts, true); +} + +static void test_seqpacket_inv_buf_client(const struct test_opts *opts) +{ + test_inv_buf_client(opts, false); +} + +static void test_seqpacket_inv_buf_server(const struct test_opts *opts) +{ + test_inv_buf_server(opts, false); +} + static struct test_case test_cases[] = { { .name = "SOCK_STREAM connection reset", @@ -920,6 +1028,16 @@ static struct test_case test_cases[] = { .run_client = test_seqpacket_bigmsg_client, .run_server = test_seqpacket_bigmsg_server, }, + { + .name = "SOCK_STREAM test invalid buffer", + .run_client = test_stream_inv_buf_client, + .run_server = test_stream_inv_buf_server, + }, + { + .name = "SOCK_SEQPACKET test invalid buffer", + .run_client = test_seqpacket_inv_buf_client, + .run_server = test_seqpacket_inv_buf_server, + }, {}, }; From b830c9642386867863ac64295185f896ff2928ac Mon Sep 17 00:00:00 2001 From: Maciej Fijalkowski Date: Tue, 14 Mar 2023 10:45:43 -0700 Subject: [PATCH 420/460] ice: xsk: disable txq irq before flushing hw ice_qp_dis() intends to stop a given queue pair that is a target of xsk pool attach/detach. One of the steps is to disable interrupts on these queues. It currently is broken in a way that txq irq is turned off *after* HW flush which in turn takes no effect. ice_qp_dis(): -> ice_qvec_dis_irq() --> disable rxq irq --> flush hw -> ice_vsi_stop_tx_ring() -->disable txq irq Below splat can be triggered by following steps: - start xdpsock WITHOUT loading xdp prog - run xdp_rxq_info with XDP_TX action on this interface - start traffic - terminate xdpsock [ 256.312485] BUG: kernel NULL pointer dereference, address: 0000000000000018 [ 256.319560] #PF: supervisor read access in kernel mode [ 256.324775] #PF: error_code(0x0000) - not-present page [ 256.329994] PGD 0 P4D 0 [ 256.332574] Oops: 0000 [#1] PREEMPT SMP NOPTI [ 256.337006] CPU: 3 PID: 32 Comm: ksoftirqd/3 Tainted: G OE 6.2.0-rc5+ #51 [ 256.345218] Hardware name: Intel Corporation S2600WFT/S2600WFT, BIOS SE5C620.86B.02.01.0008.031920191559 03/19/2019 [ 256.355807] RIP: 0010:ice_clean_rx_irq_zc+0x9c/0x7d0 [ice] [ 256.361423] Code: b7 8f 8a 00 00 00 66 39 ca 0f 84 f1 04 00 00 49 8b 47 40 4c 8b 24 d0 41 0f b7 45 04 66 25 ff 3f 66 89 04 24 0f 84 85 02 00 00 <49> 8b 44 24 18 0f b7 14 24 48 05 00 01 00 00 49 89 04 24 49 89 44 [ 256.380463] RSP: 0018:ffffc900088bfd20 EFLAGS: 00010206 [ 256.385765] RAX: 000000000000003c RBX: 0000000000000035 RCX: 000000000000067f [ 256.393012] RDX: 0000000000000775 RSI: 0000000000000000 RDI: ffff8881deb3ac80 [ 256.400256] RBP: 000000000000003c R08: ffff889847982710 R09: 0000000000010000 [ 256.407500] R10: ffffffff82c060c0 R11: 0000000000000004 R12: 0000000000000000 [ 256.414746] R13: ffff88811165eea0 R14: ffffc9000d255000 R15: ffff888119b37600 [ 256.421990] FS: 0000000000000000(0000) GS:ffff8897e0cc0000(0000) knlGS:0000000000000000 [ 256.430207] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 256.436036] CR2: 0000000000000018 CR3: 0000000005c0a006 CR4: 00000000007706e0 [ 256.443283] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 256.450527] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [ 256.457770] PKRU: 55555554 [ 256.460529] Call Trace: [ 256.463015] [ 256.465157] ? ice_xmit_zc+0x6e/0x150 [ice] [ 256.469437] ice_napi_poll+0x46d/0x680 [ice] [ 256.473815] ? _raw_spin_unlock_irqrestore+0x1b/0x40 [ 256.478863] __napi_poll+0x29/0x160 [ 256.482409] net_rx_action+0x136/0x260 [ 256.486222] __do_softirq+0xe8/0x2e5 [ 256.489853] ? smpboot_thread_fn+0x2c/0x270 [ 256.494108] run_ksoftirqd+0x2a/0x50 [ 256.497747] smpboot_thread_fn+0x1c1/0x270 [ 256.501907] ? __pfx_smpboot_thread_fn+0x10/0x10 [ 256.506594] kthread+0xea/0x120 [ 256.509785] ? __pfx_kthread+0x10/0x10 [ 256.513597] ret_from_fork+0x29/0x50 [ 256.517238] In fact, irqs were not disabled and napi managed to be scheduled and run while xsk_pool pointer was still valid, but SW ring of xdp_buff pointers was already freed. To fix this, call ice_qvec_dis_irq() after ice_vsi_stop_tx_ring(). Also while at it, remove redundant ice_clean_rx_ring() call - this is handled in ice_qp_clean_rings(). Fixes: 2d4238f55697 ("ice: Add support for AF_XDP") Signed-off-by: Maciej Fijalkowski Reviewed-by: Larysa Zaremba Tested-by: Chandan Kumar Rout (A Contingent Worker at Intel) Acked-by: John Fastabend Signed-off-by: Tony Nguyen Reviewed-by: Leon Romanovsky Signed-off-by: David S. Miller --- drivers/net/ethernet/intel/ice/ice_xsk.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_xsk.c b/drivers/net/ethernet/intel/ice/ice_xsk.c index 31565bbafa224..d1e489da7363f 100644 --- a/drivers/net/ethernet/intel/ice/ice_xsk.c +++ b/drivers/net/ethernet/intel/ice/ice_xsk.c @@ -184,8 +184,6 @@ static int ice_qp_dis(struct ice_vsi *vsi, u16 q_idx) } netif_tx_stop_queue(netdev_get_tx_queue(vsi->netdev, q_idx)); - ice_qvec_dis_irq(vsi, rx_ring, q_vector); - ice_fill_txq_meta(vsi, tx_ring, &txq_meta); err = ice_vsi_stop_tx_ring(vsi, ICE_NO_RESET, 0, tx_ring, &txq_meta); if (err) @@ -200,10 +198,11 @@ static int ice_qp_dis(struct ice_vsi *vsi, u16 q_idx) if (err) return err; } + ice_qvec_dis_irq(vsi, rx_ring, q_vector); + err = ice_vsi_ctrl_one_rx_ring(vsi, false, q_idx, true); if (err) return err; - ice_clean_rx_ring(rx_ring); ice_qvec_toggle_napi(vsi, q_vector, false); ice_qp_clean_rings(vsi, q_idx); From 636e8adf7878eab3614250234341bde45537f47a Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Tue, 14 Mar 2023 20:24:04 +0200 Subject: [PATCH 421/460] net: dsa: don't error out when drivers return ETH_DATA_LEN in .port_max_mtu() Currently, when dsa_slave_change_mtu() is called on a user port where dev->max_mtu is 1500 (as returned by ds->ops->port_max_mtu()), the code will stumble upon this check: if (new_master_mtu > mtu_limit) return -ERANGE; because new_master_mtu is adjusted for the tagger overhead but mtu_limit is not. But it would be good if the logic went through, for example if the DSA master really depends on an MTU adjustment to accept DSA-tagged frames. To make the code pass through the check, we need to adjust mtu_limit for the overhead as well, if the minimum restriction was caused by the DSA user port's MTU (dev->max_mtu). A DSA user port MTU and a DSA master MTU are always offset by the protocol overhead. Currently no drivers return 1500 .port_max_mtu(), but this is only temporary and a bug in itself - mv88e6xxx should have done that, but since commit b9c587fed61c ("dsa: mv88e6xxx: Include tagger overhead when setting MTU for DSA and CPU ports") it no longer does. This is a preparation for fixing that. Fixes: bfcb813203e6 ("net: dsa: configure the MTU for switch ports") Signed-off-by: Vladimir Oltean Reviewed-by: Simon Horman Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- net/dsa/slave.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 6957971c2db23..cac17183589fe 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -1933,6 +1933,7 @@ int dsa_slave_change_mtu(struct net_device *dev, int new_mtu) int new_master_mtu; int old_master_mtu; int mtu_limit; + int overhead; int cpu_mtu; int err; @@ -1961,9 +1962,10 @@ int dsa_slave_change_mtu(struct net_device *dev, int new_mtu) largest_mtu = slave_mtu; } - mtu_limit = min_t(int, master->max_mtu, dev->max_mtu); + overhead = dsa_tag_protocol_overhead(cpu_dp->tag_ops); + mtu_limit = min_t(int, master->max_mtu, dev->max_mtu + overhead); old_master_mtu = master->mtu; - new_master_mtu = largest_mtu + dsa_tag_protocol_overhead(cpu_dp->tag_ops); + new_master_mtu = largest_mtu + overhead; if (new_master_mtu > mtu_limit) return -ERANGE; @@ -1998,8 +2000,7 @@ int dsa_slave_change_mtu(struct net_device *dev, int new_mtu) out_port_failed: if (new_master_mtu != old_master_mtu) - dsa_port_mtu_change(cpu_dp, old_master_mtu - - dsa_tag_protocol_overhead(cpu_dp->tag_ops)); + dsa_port_mtu_change(cpu_dp, old_master_mtu - overhead); out_cpu_failed: if (new_master_mtu != old_master_mtu) dev_set_mtu(master, old_master_mtu); From 7e9517375a14f44ee830ca1c3278076dd65fcc8f Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Tue, 14 Mar 2023 20:24:05 +0200 Subject: [PATCH 422/460] net: dsa: mv88e6xxx: fix max_mtu of 1492 on 6165, 6191, 6220, 6250, 6290 There are 3 classes of switch families that the driver is aware of, as far as mv88e6xxx_change_mtu() is concerned: - MTU configuration is available per port. Here, the chip->info->ops->port_set_jumbo_size() method will be present. - MTU configuration is global to the switch. Here, the chip->info->ops->set_max_frame_size() method will be present. - We don't know how to change the MTU. Here, none of the above methods will be present. Switch families MV88E6165, MV88E6191, MV88E6220, MV88E6250 and MV88E6290 fall in category 3. The blamed commit has adjusted the MTU for all 3 categories by EDSA_HLEN (8 bytes), resulting in a new maximum MTU of 1492 being reported by the driver for these switches. I don't have the hardware to test, but I do have a MV88E6390 switch on which I can simulate this by commenting out its .port_set_jumbo_size definition from mv88e6390_ops. The result is this set of messages at probe time: mv88e6085 d0032004.mdio-mii:10: nonfatal error -34 setting MTU to 1500 on port 1 mv88e6085 d0032004.mdio-mii:10: nonfatal error -34 setting MTU to 1500 on port 2 mv88e6085 d0032004.mdio-mii:10: nonfatal error -34 setting MTU to 1500 on port 3 mv88e6085 d0032004.mdio-mii:10: nonfatal error -34 setting MTU to 1500 on port 4 mv88e6085 d0032004.mdio-mii:10: nonfatal error -34 setting MTU to 1500 on port 5 mv88e6085 d0032004.mdio-mii:10: nonfatal error -34 setting MTU to 1500 on port 6 mv88e6085 d0032004.mdio-mii:10: nonfatal error -34 setting MTU to 1500 on port 7 mv88e6085 d0032004.mdio-mii:10: nonfatal error -34 setting MTU to 1500 on port 8 It is highly implausible that there exist Ethernet switches which don't support the standard MTU of 1500 octets, and this is what the DSA framework says as well - the error comes from dsa_slave_create() -> dsa_slave_change_mtu(slave_dev, ETH_DATA_LEN). But the error messages are alarming, and it would be good to suppress them. As a consequence of this unlikeliness, we reimplement mv88e6xxx_get_max_mtu() and mv88e6xxx_change_mtu() on switches from the 3rd category as follows: the maximum supported MTU is 1500, and any request to set the MTU to a value larger than that fails in dev_validate_mtu(). Fixes: b9c587fed61c ("dsa: mv88e6xxx: Include tagger overhead when setting MTU for DSA and CPU ports") Signed-off-by: Vladimir Oltean Reviewed-by: Simon Horman Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 0a5d6c7bb128d..30383c4f8fd0e 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -3549,7 +3549,7 @@ static int mv88e6xxx_get_max_mtu(struct dsa_switch *ds, int port) return 10240 - VLAN_ETH_HLEN - EDSA_HLEN - ETH_FCS_LEN; else if (chip->info->ops->set_max_frame_size) return 1632 - VLAN_ETH_HLEN - EDSA_HLEN - ETH_FCS_LEN; - return 1522 - VLAN_ETH_HLEN - EDSA_HLEN - ETH_FCS_LEN; + return ETH_DATA_LEN; } static int mv88e6xxx_change_mtu(struct dsa_switch *ds, int port, int new_mtu) @@ -3557,6 +3557,17 @@ static int mv88e6xxx_change_mtu(struct dsa_switch *ds, int port, int new_mtu) struct mv88e6xxx_chip *chip = ds->priv; int ret = 0; + /* For families where we don't know how to alter the MTU, + * just accept any value up to ETH_DATA_LEN + */ + if (!chip->info->ops->port_set_jumbo_size && + !chip->info->ops->set_max_frame_size) { + if (new_mtu > ETH_DATA_LEN) + return -EINVAL; + + return 0; + } + if (dsa_is_dsa_port(ds, port) || dsa_is_cpu_port(ds, port)) new_mtu += EDSA_HLEN; @@ -3565,9 +3576,6 @@ static int mv88e6xxx_change_mtu(struct dsa_switch *ds, int port, int new_mtu) ret = chip->info->ops->port_set_jumbo_size(chip, port, new_mtu); else if (chip->info->ops->set_max_frame_size) ret = chip->info->ops->set_max_frame_size(chip, new_mtu); - else - if (new_mtu > 1522) - ret = -EINVAL; mv88e6xxx_reg_unlock(chip); return ret; From 1a87e641d8a50c30b63b1d90819bc607b4327596 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Tue, 14 Mar 2023 14:18:27 -0500 Subject: [PATCH 423/460] net: 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 of_property_read_bool(). Reviewed-by: Simon Horman Acked-by: Marc Kleine-Budde # for net/can Acked-by: Kalle Valo Acked-by: Nicolas Ferre Acked-by: Francois Romieu Reviewed-by: Wei Fang Signed-off-by: Rob Herring Signed-off-by: David S. Miller --- drivers/net/can/cc770/cc770_platform.c | 12 ++++++------ drivers/net/ethernet/cadence/macb_main.c | 2 +- drivers/net/ethernet/davicom/dm9000.c | 4 ++-- drivers/net/ethernet/freescale/fec_main.c | 2 +- drivers/net/ethernet/freescale/fec_mpc52xx.c | 2 +- drivers/net/ethernet/freescale/gianfar.c | 4 ++-- drivers/net/ethernet/ibm/emac/core.c | 8 ++++---- drivers/net/ethernet/ibm/emac/rgmii.c | 2 +- drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c | 3 +-- drivers/net/ethernet/sun/niu.c | 2 +- drivers/net/ethernet/ti/cpsw-phy-sel.c | 3 +-- drivers/net/ethernet/ti/netcp_ethss.c | 8 +++----- drivers/net/ethernet/via/via-velocity.c | 3 +-- drivers/net/ethernet/via/via-velocity.h | 2 +- drivers/net/ethernet/xilinx/ll_temac_main.c | 9 ++++----- drivers/net/wan/fsl_ucc_hdlc.c | 11 +++-------- drivers/net/wireless/ti/wlcore/spi.c | 3 +-- net/ncsi/ncsi-manage.c | 4 ++-- 18 files changed, 36 insertions(+), 48 deletions(-) diff --git a/drivers/net/can/cc770/cc770_platform.c b/drivers/net/can/cc770/cc770_platform.c index 8d916e2ee6c25..8dcc32e4e30ef 100644 --- a/drivers/net/can/cc770/cc770_platform.c +++ b/drivers/net/can/cc770/cc770_platform.c @@ -93,20 +93,20 @@ static int cc770_get_of_node_data(struct platform_device *pdev, if (priv->can.clock.freq > 8000000) priv->cpu_interface |= CPUIF_DMC; - if (of_get_property(np, "bosch,divide-memory-clock", NULL)) + if (of_property_read_bool(np, "bosch,divide-memory-clock")) priv->cpu_interface |= CPUIF_DMC; - if (of_get_property(np, "bosch,iso-low-speed-mux", NULL)) + if (of_property_read_bool(np, "bosch,iso-low-speed-mux")) priv->cpu_interface |= CPUIF_MUX; if (!of_get_property(np, "bosch,no-comperator-bypass", NULL)) priv->bus_config |= BUSCFG_CBY; - if (of_get_property(np, "bosch,disconnect-rx0-input", NULL)) + if (of_property_read_bool(np, "bosch,disconnect-rx0-input")) priv->bus_config |= BUSCFG_DR0; - if (of_get_property(np, "bosch,disconnect-rx1-input", NULL)) + if (of_property_read_bool(np, "bosch,disconnect-rx1-input")) priv->bus_config |= BUSCFG_DR1; - if (of_get_property(np, "bosch,disconnect-tx1-output", NULL)) + if (of_property_read_bool(np, "bosch,disconnect-tx1-output")) priv->bus_config |= BUSCFG_DT1; - if (of_get_property(np, "bosch,polarity-dominant", NULL)) + if (of_property_read_bool(np, "bosch,polarity-dominant")) priv->bus_config |= BUSCFG_POL; prop = of_get_property(np, "bosch,clock-out-frequency", &prop_size); diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index 6e141a8bbf43c..66e30561569eb 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -4990,7 +4990,7 @@ static int macb_probe(struct platform_device *pdev) bp->jumbo_max_len = macb_config->jumbo_max_len; bp->wol = 0; - if (of_get_property(np, "magic-packet", NULL)) + if (of_property_read_bool(np, "magic-packet")) bp->wol |= MACB_WOL_HAS_MAGIC_PACKET; device_set_wakeup_capable(&pdev->dev, bp->wol & MACB_WOL_HAS_MAGIC_PACKET); diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c index b21e56de61671..05a89ab6766c4 100644 --- a/drivers/net/ethernet/davicom/dm9000.c +++ b/drivers/net/ethernet/davicom/dm9000.c @@ -1393,9 +1393,9 @@ static struct dm9000_plat_data *dm9000_parse_dt(struct device *dev) if (!pdata) return ERR_PTR(-ENOMEM); - if (of_find_property(np, "davicom,ext-phy", NULL)) + if (of_property_read_bool(np, "davicom,ext-phy")) pdata->flags |= DM9000_PLATF_EXT_PHY; - if (of_find_property(np, "davicom,no-eeprom", NULL)) + if (of_property_read_bool(np, "davicom,no-eeprom")) pdata->flags |= DM9000_PLATF_NO_EEPROM; ret = of_get_mac_address(np, pdata->dev_addr); diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index c73e25f8995eb..f3b16a6673e2b 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -4251,7 +4251,7 @@ fec_probe(struct platform_device *pdev) if (ret) goto failed_ipc_init; - if (of_get_property(np, "fsl,magic-packet", NULL)) + if (of_property_read_bool(np, "fsl,magic-packet")) fep->wol_flag |= FEC_WOL_HAS_MAGIC_PACKET; ret = fec_enet_init_stop_mode(fep, np); diff --git a/drivers/net/ethernet/freescale/fec_mpc52xx.c b/drivers/net/ethernet/freescale/fec_mpc52xx.c index a7f4c3c29f3e4..b88816b71ddff 100644 --- a/drivers/net/ethernet/freescale/fec_mpc52xx.c +++ b/drivers/net/ethernet/freescale/fec_mpc52xx.c @@ -937,7 +937,7 @@ static int mpc52xx_fec_probe(struct platform_device *op) priv->phy_node = of_parse_phandle(np, "phy-handle", 0); /* the 7-wire property means don't use MII mode */ - if (of_find_property(np, "fsl,7-wire-mode", NULL)) { + if (of_property_read_bool(np, "fsl,7-wire-mode")) { priv->seven_wire_mode = 1; dev_info(&ndev->dev, "using 7-wire PHY mode\n"); } diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index b2def295523ab..38d5013c6fedf 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c @@ -787,10 +787,10 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev) else priv->interface = gfar_get_interface(dev); - if (of_find_property(np, "fsl,magic-packet", NULL)) + if (of_property_read_bool(np, "fsl,magic-packet")) priv->device_flags |= FSL_GIANFAR_DEV_HAS_MAGIC_PACKET; - if (of_get_property(np, "fsl,wake-on-filer", NULL)) + if (of_property_read_bool(np, "fsl,wake-on-filer")) priv->device_flags |= FSL_GIANFAR_DEV_HAS_WAKE_ON_FILER; priv->phy_node = of_parse_phandle(np, "phy-handle", 0); diff --git a/drivers/net/ethernet/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c index 9b08e41ccc294..c97095abd26ab 100644 --- a/drivers/net/ethernet/ibm/emac/core.c +++ b/drivers/net/ethernet/ibm/emac/core.c @@ -2939,9 +2939,9 @@ static int emac_init_config(struct emac_instance *dev) } /* Fixup some feature bits based on the device tree */ - if (of_get_property(np, "has-inverted-stacr-oc", NULL)) + if (of_property_read_bool(np, "has-inverted-stacr-oc")) dev->features |= EMAC_FTR_STACR_OC_INVERT; - if (of_get_property(np, "has-new-stacr-staopc", NULL)) + if (of_property_read_bool(np, "has-new-stacr-staopc")) dev->features |= EMAC_FTR_HAS_NEW_STACR; /* CAB lacks the appropriate properties */ @@ -3042,7 +3042,7 @@ static int emac_probe(struct platform_device *ofdev) * property here for now, but new flat device trees should set a * status property to "disabled" instead. */ - if (of_get_property(np, "unused", NULL) || !of_device_is_available(np)) + if (of_property_read_bool(np, "unused") || !of_device_is_available(np)) return -ENODEV; /* Find ourselves in the bootlist if we are there */ @@ -3333,7 +3333,7 @@ static void __init emac_make_bootlist(void) if (of_match_node(emac_match, np) == NULL) continue; - if (of_get_property(np, "unused", NULL)) + if (of_property_read_bool(np, "unused")) continue; idx = of_get_property(np, "cell-index", NULL); if (idx == NULL) diff --git a/drivers/net/ethernet/ibm/emac/rgmii.c b/drivers/net/ethernet/ibm/emac/rgmii.c index 242ef976fd15e..50358cf001306 100644 --- a/drivers/net/ethernet/ibm/emac/rgmii.c +++ b/drivers/net/ethernet/ibm/emac/rgmii.c @@ -242,7 +242,7 @@ static int rgmii_probe(struct platform_device *ofdev) } /* Check for RGMII flags */ - if (of_get_property(ofdev->dev.of_node, "has-mdio", NULL)) + if (of_property_read_bool(ofdev->dev.of_node, "has-mdio")) dev->flags |= EMAC_RGMII_FLAG_HAS_MDIO; /* CAB lacks the right properties, fix this up */ diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c index ac8580f501e2e..ac550d1ac0159 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c @@ -213,8 +213,7 @@ imx_dwmac_parse_dt(struct imx_priv_data *dwmac, struct device *dev) struct device_node *np = dev->of_node; int err = 0; - if (of_get_property(np, "snps,rmii_refclk_ext", NULL)) - dwmac->rmii_refclk_ext = true; + dwmac->rmii_refclk_ext = of_property_read_bool(np, "snps,rmii_refclk_ext"); dwmac->clk_tx = devm_clk_get(dev, "tx"); if (IS_ERR(dwmac->clk_tx)) { diff --git a/drivers/net/ethernet/sun/niu.c b/drivers/net/ethernet/sun/niu.c index e6144d963eaaa..ab8b09a9ef61d 100644 --- a/drivers/net/ethernet/sun/niu.c +++ b/drivers/net/ethernet/sun/niu.c @@ -9271,7 +9271,7 @@ static int niu_get_of_props(struct niu *np) if (model) strcpy(np->vpd.model, model); - if (of_find_property(dp, "hot-swappable-phy", NULL)) { + if (of_property_read_bool(dp, "hot-swappable-phy")) { np->flags |= (NIU_FLAGS_10G | NIU_FLAGS_FIBER | NIU_FLAGS_HOTPLUG_PHY); } diff --git a/drivers/net/ethernet/ti/cpsw-phy-sel.c b/drivers/net/ethernet/ti/cpsw-phy-sel.c index e8f38e3f7706e..25e707d7b87ce 100644 --- a/drivers/net/ethernet/ti/cpsw-phy-sel.c +++ b/drivers/net/ethernet/ti/cpsw-phy-sel.c @@ -226,8 +226,7 @@ static int cpsw_phy_sel_probe(struct platform_device *pdev) if (IS_ERR(priv->gmii_sel)) return PTR_ERR(priv->gmii_sel); - if (of_find_property(pdev->dev.of_node, "rmii-clock-ext", NULL)) - priv->rmii_clock_external = true; + priv->rmii_clock_external = of_property_read_bool(pdev->dev.of_node, "rmii-clock-ext"); dev_set_drvdata(&pdev->dev, priv); diff --git a/drivers/net/ethernet/ti/netcp_ethss.c b/drivers/net/ethernet/ti/netcp_ethss.c index 751fb0bc65c50..2adf82a32bf6a 100644 --- a/drivers/net/ethernet/ti/netcp_ethss.c +++ b/drivers/net/ethernet/ti/netcp_ethss.c @@ -3583,13 +3583,11 @@ static int gbe_probe(struct netcp_device *netcp_device, struct device *dev, /* init the hw stats lock */ spin_lock_init(&gbe_dev->hw_stats_lock); - if (of_find_property(node, "enable-ale", NULL)) { - gbe_dev->enable_ale = true; + gbe_dev->enable_ale = of_property_read_bool(node, "enable-ale"); + if (gbe_dev->enable_ale) dev_info(dev, "ALE enabled\n"); - } else { - gbe_dev->enable_ale = false; + else dev_dbg(dev, "ALE bypass enabled*\n"); - } ret = of_property_read_u32(node, "tx-queue", &gbe_dev->tx_queue_id); diff --git a/drivers/net/ethernet/via/via-velocity.c b/drivers/net/ethernet/via/via-velocity.c index a502812ac418a..86f7843b4591c 100644 --- a/drivers/net/ethernet/via/via-velocity.c +++ b/drivers/net/ethernet/via/via-velocity.c @@ -2709,8 +2709,7 @@ static int velocity_get_platform_info(struct velocity_info *vptr) struct resource res; int ret; - if (of_get_property(vptr->dev->of_node, "no-eeprom", NULL)) - vptr->no_eeprom = 1; + vptr->no_eeprom = of_property_read_bool(vptr->dev->of_node, "no-eeprom"); ret = of_address_to_resource(vptr->dev->of_node, 0, &res); if (ret) { diff --git a/drivers/net/ethernet/via/via-velocity.h b/drivers/net/ethernet/via/via-velocity.h index ffdac6fac0549..f64ed39b93d83 100644 --- a/drivers/net/ethernet/via/via-velocity.h +++ b/drivers/net/ethernet/via/via-velocity.h @@ -1383,7 +1383,7 @@ struct velocity_info { struct device *dev; struct pci_dev *pdev; struct net_device *netdev; - int no_eeprom; + bool no_eeprom; unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)]; u8 ip_addr[4]; diff --git a/drivers/net/ethernet/xilinx/ll_temac_main.c b/drivers/net/ethernet/xilinx/ll_temac_main.c index 1066420d6a83a..e0ac1bcd9925c 100644 --- a/drivers/net/ethernet/xilinx/ll_temac_main.c +++ b/drivers/net/ethernet/xilinx/ll_temac_main.c @@ -1455,12 +1455,11 @@ static int temac_probe(struct platform_device *pdev) * endianness mode. Default for OF devices is big-endian. */ little_endian = false; - if (temac_np) { - if (of_get_property(temac_np, "little-endian", NULL)) - little_endian = true; - } else if (pdata) { + if (temac_np) + little_endian = of_property_read_bool(temac_np, "little-endian"); + else if (pdata) little_endian = pdata->reg_little_endian; - } + if (little_endian) { lp->temac_ior = _temac_ior_le; lp->temac_iow = _temac_iow_le; diff --git a/drivers/net/wan/fsl_ucc_hdlc.c b/drivers/net/wan/fsl_ucc_hdlc.c index 1c53b55469270..47c2ad7a3e429 100644 --- a/drivers/net/wan/fsl_ucc_hdlc.c +++ b/drivers/net/wan/fsl_ucc_hdlc.c @@ -1177,14 +1177,9 @@ static int ucc_hdlc_probe(struct platform_device *pdev) uhdlc_priv->dev = &pdev->dev; uhdlc_priv->ut_info = ut_info; - if (of_get_property(np, "fsl,tdm-interface", NULL)) - uhdlc_priv->tsa = 1; - - if (of_get_property(np, "fsl,ucc-internal-loopback", NULL)) - uhdlc_priv->loopback = 1; - - if (of_get_property(np, "fsl,hdlc-bus", NULL)) - uhdlc_priv->hdlc_bus = 1; + uhdlc_priv->tsa = of_property_read_bool(np, "fsl,tdm-interface"); + uhdlc_priv->loopback = of_property_read_bool(np, "fsl,ucc-internal-loopback"); + uhdlc_priv->hdlc_bus = of_property_read_bool(np, "fsl,hdlc-bus"); if (uhdlc_priv->tsa == 1) { utdm = kzalloc(sizeof(*utdm), GFP_KERNEL); diff --git a/drivers/net/wireless/ti/wlcore/spi.c b/drivers/net/wireless/ti/wlcore/spi.c index 2d2edddc77bdd..3f88e6a0a510e 100644 --- a/drivers/net/wireless/ti/wlcore/spi.c +++ b/drivers/net/wireless/ti/wlcore/spi.c @@ -447,8 +447,7 @@ static int wlcore_probe_of(struct spi_device *spi, struct wl12xx_spi_glue *glue, dev_info(&spi->dev, "selected chip family is %s\n", pdev_data->family->name); - if (of_find_property(dt_node, "clock-xtal", NULL)) - pdev_data->ref_clock_xtal = true; + pdev_data->ref_clock_xtal = of_property_read_bool(dt_node, "clock-xtal"); /* optional clock frequency params */ of_property_read_u32(dt_node, "ref-clock-frequency", diff --git a/net/ncsi/ncsi-manage.c b/net/ncsi/ncsi-manage.c index 80713febfac6d..d9da942ad53dd 100644 --- a/net/ncsi/ncsi-manage.c +++ b/net/ncsi/ncsi-manage.c @@ -1803,8 +1803,8 @@ struct ncsi_dev *ncsi_register_dev(struct net_device *dev, pdev = to_platform_device(dev->dev.parent); if (pdev) { np = pdev->dev.of_node; - if (np && (of_get_property(np, "mellanox,multi-host", NULL) || - of_get_property(np, "mlx,multi-host", NULL))) + if (np && (of_property_read_bool(np, "mellanox,multi-host") || + of_property_read_bool(np, "mlx,multi-host"))) ndp->mlx_multi_host = true; } From fa0f1ba7c8233118b6fdaa65e2f5ded563d3e1fa Mon Sep 17 00:00:00 2001 From: Xuan Zhuo Date: Wed, 15 Mar 2023 09:52:22 +0800 Subject: [PATCH 424/460] virtio_net: fix page_to_skb() miss headroom Because headroom is not passed to page_to_skb(), this causes the shinfo exceeds the range. Then the frags of shinfo are changed by other process. [ 157.724634] stack segment: 0000 [#1] PREEMPT SMP NOPTI [ 157.725358] CPU: 3 PID: 679 Comm: xdp_pass_user_f Tainted: G E 6.2.0+ #150 [ 157.726401] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.16.0-0-gd239552ce722-prebuilt.qemu.org 04/01/4 [ 157.727820] RIP: 0010:skb_release_data+0x11b/0x180 [ 157.728449] Code: 44 24 02 48 83 c3 01 39 d8 7e be 48 89 d8 48 c1 e0 04 41 80 7d 7e 00 49 8b 6c 04 30 79 0c 48 89 ef e8 89 b [ 157.730751] RSP: 0018:ffffc90000178b48 EFLAGS: 00010202 [ 157.731383] RAX: 0000000000000010 RBX: 0000000000000001 RCX: 0000000000000000 [ 157.732270] RDX: 0000000000000000 RSI: 0000000000000002 RDI: ffff888100dd0b00 [ 157.733117] RBP: 5d5d76010f6e2408 R08: ffff888100dd0b2c R09: 0000000000000000 [ 157.734013] R10: ffffffff82effd30 R11: 000000000000a14e R12: ffff88810981ffc0 [ 157.734904] R13: ffff888100dd0b00 R14: 0000000000000002 R15: 0000000000002310 [ 157.735793] FS: 00007f06121d9740(0000) GS:ffff88842fcc0000(0000) knlGS:0000000000000000 [ 157.736794] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 157.737522] CR2: 00007ffd9a56c084 CR3: 0000000104bda001 CR4: 0000000000770ee0 [ 157.738420] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 157.739283] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [ 157.740146] PKRU: 55555554 [ 157.740502] Call Trace: [ 157.740843] [ 157.741117] kfree_skb_reason+0x50/0x120 [ 157.741613] __udp4_lib_rcv+0x52b/0x5e0 [ 157.742132] ip_protocol_deliver_rcu+0xaf/0x190 [ 157.742715] ip_local_deliver_finish+0x77/0xa0 [ 157.743280] ip_sublist_rcv_finish+0x80/0x90 [ 157.743834] ip_list_rcv_finish.constprop.0+0x16f/0x190 [ 157.744493] ip_list_rcv+0x126/0x140 [ 157.744952] __netif_receive_skb_list_core+0x29b/0x2c0 [ 157.745602] __netif_receive_skb_list+0xed/0x160 [ 157.746190] ? udp4_gro_receive+0x275/0x350 [ 157.746732] netif_receive_skb_list_internal+0xf2/0x1b0 [ 157.747398] napi_gro_receive+0xd1/0x210 [ 157.747911] virtnet_receive+0x75/0x1c0 [ 157.748422] virtnet_poll+0x48/0x1b0 [ 157.748878] __napi_poll+0x29/0x1b0 [ 157.749330] net_rx_action+0x27a/0x340 [ 157.749812] __do_softirq+0xf3/0x2fb [ 157.750298] do_softirq+0xa2/0xd0 [ 157.750745] [ 157.751563] [ 157.752329] __local_bh_enable_ip+0x6d/0x80 [ 157.753178] virtnet_xdp_set+0x482/0x860 [ 157.754159] ? __pfx_virtnet_xdp+0x10/0x10 [ 157.755129] dev_xdp_install+0xa4/0xe0 [ 157.756033] dev_xdp_attach+0x20b/0x5e0 [ 157.756933] do_setlink+0x82e/0xc90 [ 157.757777] ? __nla_validate_parse+0x12b/0x1e0 [ 157.758744] rtnl_setlink+0xd8/0x170 [ 157.759549] ? mod_objcg_state+0xcb/0x320 [ 157.760328] ? security_capable+0x37/0x60 [ 157.761209] ? security_capable+0x37/0x60 [ 157.762072] rtnetlink_rcv_msg+0x145/0x3d0 [ 157.762929] ? ___slab_alloc+0x327/0x610 [ 157.763754] ? __alloc_skb+0x141/0x170 [ 157.764533] ? __pfx_rtnetlink_rcv_msg+0x10/0x10 [ 157.765422] netlink_rcv_skb+0x58/0x110 [ 157.766229] netlink_unicast+0x21f/0x330 [ 157.766951] netlink_sendmsg+0x240/0x4a0 [ 157.767654] sock_sendmsg+0x93/0xa0 [ 157.768434] ? sockfd_lookup_light+0x12/0x70 [ 157.769245] __sys_sendto+0xfe/0x170 [ 157.770079] ? handle_mm_fault+0xe9/0x2d0 [ 157.770859] ? preempt_count_add+0x51/0xa0 [ 157.771645] ? up_read+0x3c/0x80 [ 157.772340] ? do_user_addr_fault+0x1e9/0x710 [ 157.773166] ? kvm_read_and_reset_apf_flags+0x49/0x60 [ 157.774087] __x64_sys_sendto+0x29/0x30 [ 157.774856] do_syscall_64+0x3c/0x90 [ 157.775518] entry_SYSCALL_64_after_hwframe+0x72/0xdc [ 157.776382] RIP: 0033:0x7f06122def70 Fixes: 18117a842ab0 ("virtio-net: remove xdp related info from page_to_skb()") Signed-off-by: Xuan Zhuo Acked-by: Michael S. Tsirkin Signed-off-by: David S. Miller --- drivers/net/virtio_net.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 1a309cfb4976a..8ecf7a341d543 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -446,7 +446,8 @@ static unsigned int mergeable_ctx_to_truesize(void *mrg_ctx) static struct sk_buff *page_to_skb(struct virtnet_info *vi, struct receive_queue *rq, struct page *page, unsigned int offset, - unsigned int len, unsigned int truesize) + unsigned int len, unsigned int truesize, + unsigned int headroom) { struct sk_buff *skb; struct virtio_net_hdr_mrg_rxbuf *hdr; @@ -464,11 +465,11 @@ static struct sk_buff *page_to_skb(struct virtnet_info *vi, else hdr_padded_len = sizeof(struct padded_vnet_hdr); - buf = p; + buf = p - headroom; len -= hdr_len; offset += hdr_padded_len; p += hdr_padded_len; - tailroom = truesize - hdr_padded_len - len; + tailroom = truesize - headroom - hdr_padded_len - len; shinfo_size = SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); @@ -1009,7 +1010,7 @@ static struct sk_buff *receive_big(struct net_device *dev, { struct page *page = buf; struct sk_buff *skb = - page_to_skb(vi, rq, page, 0, len, PAGE_SIZE); + page_to_skb(vi, rq, page, 0, len, PAGE_SIZE, 0); stats->bytes += len - vi->hdr_len; if (unlikely(!skb)) @@ -1332,7 +1333,7 @@ static struct sk_buff *receive_mergeable(struct net_device *dev, rcu_read_unlock(); skip_xdp: - head_skb = page_to_skb(vi, rq, page, offset, len, truesize); + head_skb = page_to_skb(vi, rq, page, offset, len, truesize, headroom); curr_skb = head_skb; if (unlikely(!curr_skb)) From 1a3bd6eabae35afc5c6dbe2651f21467cf8ad3fd Mon Sep 17 00:00:00 2001 From: Xuan Zhuo Date: Wed, 15 Mar 2023 09:52:23 +0800 Subject: [PATCH 425/460] virtio_net: free xdp shinfo frags when build_skb_from_xdp_buff() fails build_skb_from_xdp_buff() may return NULL, in this case we need to free the frags of xdp shinfo. Fixes: fab89bafa95b ("virtio-net: support multi-buffer xdp") Signed-off-by: Xuan Zhuo Acked-by: Michael S. Tsirkin Reviewed-by: Yunsheng Lin Signed-off-by: David S. Miller --- drivers/net/virtio_net.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 8ecf7a341d543..2396c28c01221 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -1273,9 +1273,12 @@ static struct sk_buff *receive_mergeable(struct net_device *dev, switch (act) { case XDP_PASS: + head_skb = build_skb_from_xdp_buff(dev, vi, &xdp, xdp_frags_truesz); + if (unlikely(!head_skb)) + goto err_xdp_frags; + if (unlikely(xdp_page != page)) put_page(page); - head_skb = build_skb_from_xdp_buff(dev, vi, &xdp, xdp_frags_truesz); rcu_read_unlock(); return head_skb; case XDP_TX: From 7f5ebf5dae42e710162f1c481ebcf28ab7b741c7 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 15 Mar 2023 08:41:14 +0100 Subject: [PATCH 426/460] ravb: avoid PHY being resumed when interface is not up RAVB doesn't need mdiobus suspend/resume, that's why it sets 'mac_managed_pm'. However, setting it needs to be moved from init to probe, so mdiobus PM functions will really never be called (e.g. when the interface is not up yet during suspend/resume). Fixes: 4924c0cdce75 ("net: ravb: Fix PHY state warning splat during system resume") Suggested-by: Heiner Kallweit Signed-off-by: Wolfram Sang Reviewed-by: Michal Kubiak Reviewed-by: Sergey Shtylyov Reviewed-by: Florian Fainelli Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/renesas/ravb_main.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c index 0f54849a38235..894e2690c6437 100644 --- a/drivers/net/ethernet/renesas/ravb_main.c +++ b/drivers/net/ethernet/renesas/ravb_main.c @@ -1455,8 +1455,6 @@ static int ravb_phy_init(struct net_device *ndev) phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_100baseT_Half_BIT); } - /* Indicate that the MAC is responsible for managing PHY PM */ - phydev->mac_managed_pm = true; phy_attached_info(phydev); return 0; @@ -2379,6 +2377,8 @@ static int ravb_mdio_init(struct ravb_private *priv) { struct platform_device *pdev = priv->pdev; struct device *dev = &pdev->dev; + struct phy_device *phydev; + struct device_node *pn; int error; /* Bitbang init */ @@ -2400,6 +2400,14 @@ static int ravb_mdio_init(struct ravb_private *priv) if (error) goto out_free_bus; + pn = of_parse_phandle(dev->of_node, "phy-handle", 0); + phydev = of_phy_find_device(pn); + if (phydev) { + phydev->mac_managed_pm = true; + put_device(&phydev->mdio.dev); + } + of_node_put(pn); + return 0; out_free_bus: From c6be7136afb224a01d4cde2983ddebac8da98693 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 15 Mar 2023 08:41:15 +0100 Subject: [PATCH 427/460] sh_eth: avoid PHY being resumed when interface is not up SH_ETH doesn't need mdiobus suspend/resume, that's why it sets 'mac_managed_pm'. However, setting it needs to be moved from init to probe, so mdiobus PM functions will really never be called (e.g. when the interface is not up yet during suspend/resume). Fixes: 6a1dbfefdae4 ("net: sh_eth: Fix PHY state warning splat during system resume") Suggested-by: Heiner Kallweit Signed-off-by: Wolfram Sang Reviewed-by: Michal Kubiak Reviewed-by: Sergey Shtylyov Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/renesas/sh_eth.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index ed17163d78114..d8ec729825be4 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -2029,8 +2029,6 @@ static int sh_eth_phy_init(struct net_device *ndev) if (mdp->cd->register_type != SH_ETH_REG_GIGABIT) phy_set_max_speed(phydev, SPEED_100); - /* Indicate that the MAC is responsible for managing PHY PM */ - phydev->mac_managed_pm = true; phy_attached_info(phydev); return 0; @@ -3097,6 +3095,8 @@ static int sh_mdio_init(struct sh_eth_private *mdp, struct bb_info *bitbang; struct platform_device *pdev = mdp->pdev; struct device *dev = &mdp->pdev->dev; + struct phy_device *phydev; + struct device_node *pn; /* create bit control struct for PHY */ bitbang = devm_kzalloc(dev, sizeof(struct bb_info), GFP_KERNEL); @@ -3133,6 +3133,14 @@ static int sh_mdio_init(struct sh_eth_private *mdp, if (ret) goto out_free_bus; + pn = of_parse_phandle(dev->of_node, "phy-handle", 0); + phydev = of_phy_find_device(pn); + if (phydev) { + phydev->mac_managed_pm = true; + put_device(&phydev->mdio.dev); + } + of_node_put(pn); + return 0; out_free_bus: From 8a2618e14f81604a9b6ad305d57e0c8da939cd65 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Wed, 15 Mar 2023 14:40:09 +0200 Subject: [PATCH 428/460] ipv4: Fix incorrect table ID in IOCTL path Commit f96a3d74554d ("ipv4: Fix incorrect route flushing when source address is deleted") started to take the table ID field in the FIB info structure into account when determining if two structures are identical or not. This field is initialized using the 'fc_table' field in the route configuration structure, which is not set when adding a route via IOCTL. The above can result in user space being able to install two identical routes that only differ in the table ID field of their associated FIB info. Fix by initializing the table ID field in the route configuration structure in the IOCTL path. Before the fix: # ip route add default via 192.0.2.2 # route add default gw 192.0.2.2 # ip -4 r show default # default via 192.0.2.2 dev dummy10 # default via 192.0.2.2 dev dummy10 After the fix: # ip route add default via 192.0.2.2 # route add default gw 192.0.2.2 SIOCADDRT: File exists # ip -4 r show default default via 192.0.2.2 dev dummy10 Audited the code paths to ensure there are no other paths that do not properly initialize the route configuration structure when installing a route. Fixes: 5a56a0b3a45d ("net: Don't delete routes in different VRFs") Fixes: f96a3d74554d ("ipv4: Fix incorrect route flushing when source address is deleted") Reported-by: gaoxingwang Link: https://lore.kernel.org/netdev/20230314144159.2354729-1-gaoxingwang1@huawei.com/ Tested-by: gaoxingwang Signed-off-by: Ido Schimmel Reviewed-by: David Ahern Link: https://lore.kernel.org/r/20230315124009.4015212-1-idosch@nvidia.com Signed-off-by: Jakub Kicinski --- net/ipv4/fib_frontend.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index b5736ef16ed2d..390f4be7f7bec 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -576,6 +576,9 @@ static int rtentry_to_fib_config(struct net *net, int cmd, struct rtentry *rt, cfg->fc_scope = RT_SCOPE_UNIVERSE; } + if (!cfg->fc_table) + cfg->fc_table = RT_TABLE_MAIN; + if (cmd == SIOCDELRT) return 0; From 43ffe6caccc7a1bb9d7442fbab521efbf6c1378c Mon Sep 17 00:00:00 2001 From: Szymon Heidrich Date: Thu, 16 Mar 2023 12:05:40 +0100 Subject: [PATCH 429/460] net: usb: smsc75xx: Move packet length check to prevent kernel panic in skb_pull Packet length check needs to be located after size and align_count calculation to prevent kernel panic in skb_pull() in case rx_cmd_a & RX_CMD_A_RED evaluates to true. Fixes: d8b228318935 ("net: usb: smsc75xx: Limit packet length to skb->len") Signed-off-by: Szymon Heidrich Link: https://lore.kernel.org/r/20230316110540.77531-1-szymon.heidrich@gmail.com Signed-off-by: Jakub Kicinski --- drivers/net/usb/smsc75xx.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c index db34f8d1d6051..5d6454fedb3f1 100644 --- a/drivers/net/usb/smsc75xx.c +++ b/drivers/net/usb/smsc75xx.c @@ -2200,6 +2200,13 @@ static int smsc75xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) size = (rx_cmd_a & RX_CMD_A_LEN) - RXW_PADDING; align_count = (4 - ((size + RXW_PADDING) % 4)) % 4; + if (unlikely(size > skb->len)) { + netif_dbg(dev, rx_err, dev->net, + "size err rx_cmd_a=0x%08x\n", + rx_cmd_a); + return 0; + } + if (unlikely(rx_cmd_a & RX_CMD_A_RED)) { netif_dbg(dev, rx_err, dev->net, "Error rx_cmd_a=0x%08x\n", rx_cmd_a); @@ -2212,8 +2219,7 @@ static int smsc75xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) dev->net->stats.rx_frame_errors++; } else { /* MAX_SINGLE_PACKET_SIZE + 4(CRC) + 2(COE) + 4(Vlan) */ - if (unlikely(size > (MAX_SINGLE_PACKET_SIZE + ETH_HLEN + 12) || - size > skb->len)) { + if (unlikely(size > (MAX_SINGLE_PACKET_SIZE + ETH_HLEN + 12))) { netif_dbg(dev, rx_err, dev->net, "size err rx_cmd_a=0x%08x\n", rx_cmd_a); From 37d010399f7552add2b68e2b347901c83562dab8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= Date: Wed, 15 Mar 2023 13:55:38 +0100 Subject: [PATCH 430/460] net: atlantic: Fix crash when XDP is enabled but no program is loaded MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The aq_xdp_run_prog() function falls back to the XDP_ABORTED action handler (using a goto) if the operations for any of the other actions fail. The XDP_ABORTED handler in turn calls the bpf_warn_invalid_xdp_action() tracepoint. However, the function also jumps into the XDP_PASS helper if no XDP program is loaded on the device, which means the XDP_ABORTED handler can be run with a NULL program pointer. This results in a NULL pointer deref because the tracepoint dereferences the 'prog' pointer passed to it. This situation can happen in multiple ways: - If a packet arrives between the removal of the program from the interface and the static_branch_dec() in aq_xdp_setup() - If there are multiple devices using the same driver in the system and one of them has an XDP program loaded and the other does not. Fix this by refactoring the aq_xdp_run_prog() function to remove the 'goto pass' handling if there is no XDP program loaded. Instead, factor out the skb building in a separate small helper function. Fixes: 26efaef759a1 ("net: atlantic: Implement xdp data plane") Reported-by: Freysteinn Alfredsson Tested-by: Freysteinn Alfredsson Signed-off-by: Toke Høiland-Jørgensen Link: https://lore.kernel.org/r/20230315125539.103319-1-toke@redhat.com Signed-off-by: Jakub Kicinski --- .../net/ethernet/aquantia/atlantic/aq_ring.c | 28 ++++++++++++++----- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c index 1e8d902e1c8ea..7f933175cbdac 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c @@ -412,6 +412,25 @@ int aq_xdp_xmit(struct net_device *dev, int num_frames, return num_frames - drop; } +static struct sk_buff *aq_xdp_build_skb(struct xdp_buff *xdp, + struct net_device *dev, + struct aq_ring_buff_s *buff) +{ + struct xdp_frame *xdpf; + struct sk_buff *skb; + + xdpf = xdp_convert_buff_to_frame(xdp); + if (unlikely(!xdpf)) + return NULL; + + skb = xdp_build_skb_from_frame(xdpf, dev); + if (!skb) + return NULL; + + aq_get_rxpages_xdp(buff, xdp); + return skb; +} + static struct sk_buff *aq_xdp_run_prog(struct aq_nic_s *aq_nic, struct xdp_buff *xdp, struct aq_ring_s *rx_ring, @@ -431,7 +450,7 @@ static struct sk_buff *aq_xdp_run_prog(struct aq_nic_s *aq_nic, prog = READ_ONCE(rx_ring->xdp_prog); if (!prog) - goto pass; + return aq_xdp_build_skb(xdp, aq_nic->ndev, buff); prefetchw(xdp->data_hard_start); /* xdp_frame write */ @@ -442,17 +461,12 @@ static struct sk_buff *aq_xdp_run_prog(struct aq_nic_s *aq_nic, act = bpf_prog_run_xdp(prog, xdp); switch (act) { case XDP_PASS: -pass: - xdpf = xdp_convert_buff_to_frame(xdp); - if (unlikely(!xdpf)) - goto out_aborted; - skb = xdp_build_skb_from_frame(xdpf, aq_nic->ndev); + skb = aq_xdp_build_skb(xdp, aq_nic->ndev, buff); if (!skb) goto out_aborted; u64_stats_update_begin(&rx_ring->stats.rx.syncp); ++rx_ring->stats.rx.xdp_pass; u64_stats_update_end(&rx_ring->stats.rx.syncp); - aq_get_rxpages_xdp(buff, xdp); return skb; case XDP_TX: xdpf = xdp_convert_buff_to_frame(xdp); From 3d87debb8ed2649608ff432699e7c961c0c6f03b Mon Sep 17 00:00:00 2001 From: Alexandra Winter Date: Wed, 15 Mar 2023 14:14:35 +0100 Subject: [PATCH 431/460] net/iucv: Fix size of interrupt data iucv_irq_data needs to be 4 bytes larger. These bytes are not used by the iucv module, but written by the z/VM hypervisor in case a CPU is deconfigured. Reported as: BUG dma-kmalloc-64 (Not tainted): kmalloc Redzone overwritten ----------------------------------------------------------------------------- 0x0000000000400564-0x0000000000400567 @offset=1380. First byte 0x80 instead of 0xcc Allocated in iucv_cpu_prepare+0x44/0xd0 age=167839 cpu=2 pid=1 __kmem_cache_alloc_node+0x166/0x450 kmalloc_node_trace+0x3a/0x70 iucv_cpu_prepare+0x44/0xd0 cpuhp_invoke_callback+0x156/0x2f0 cpuhp_issue_call+0xf0/0x298 __cpuhp_setup_state_cpuslocked+0x136/0x338 __cpuhp_setup_state+0xf4/0x288 iucv_init+0xf4/0x280 do_one_initcall+0x78/0x390 do_initcalls+0x11a/0x140 kernel_init_freeable+0x25e/0x2a0 kernel_init+0x2e/0x170 __ret_from_fork+0x3c/0x58 ret_from_fork+0xa/0x40 Freed in iucv_init+0x92/0x280 age=167839 cpu=2 pid=1 __kmem_cache_free+0x308/0x358 iucv_init+0x92/0x280 do_one_initcall+0x78/0x390 do_initcalls+0x11a/0x140 kernel_init_freeable+0x25e/0x2a0 kernel_init+0x2e/0x170 __ret_from_fork+0x3c/0x58 ret_from_fork+0xa/0x40 Slab 0x0000037200010000 objects=32 used=30 fp=0x0000000000400640 flags=0x1ffff00000010200(slab|head|node=0|zone=0| Object 0x0000000000400540 @offset=1344 fp=0x0000000000000000 Redzone 0000000000400500: cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc ................ Redzone 0000000000400510: cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc ................ Redzone 0000000000400520: cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc ................ Redzone 0000000000400530: cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc ................ Object 0000000000400540: 00 01 00 03 00 00 00 00 00 00 00 00 00 00 00 00 ................ Object 0000000000400550: f3 86 81 f2 f4 82 f8 82 f0 f0 f0 f0 f0 f0 f0 f2 ................ Object 0000000000400560: 00 00 00 00 80 00 00 00 cc cc cc cc cc cc cc cc ................ Object 0000000000400570: cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc ................ Redzone 0000000000400580: cc cc cc cc cc cc cc cc ........ Padding 00000000004005d4: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a ZZZZZZZZZZZZZZZZ Padding 00000000004005e4: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a ZZZZZZZZZZZZZZZZ Padding 00000000004005f4: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a ZZZZZZZZZZZZ CPU: 6 PID: 121030 Comm: 116-pai-crypto. Not tainted 6.3.0-20230221.rc0.git4.99b8246b2d71.300.fc37.s390x+debug #1 Hardware name: IBM 3931 A01 704 (z/VM 7.3.0) Call Trace: [<000000032aa034ec>] dump_stack_lvl+0xac/0x100 [<0000000329f5a6cc>] check_bytes_and_report+0x104/0x140 [<0000000329f5aa78>] check_object+0x370/0x3c0 [<0000000329f5ede6>] free_debug_processing+0x15e/0x348 [<0000000329f5f06a>] free_to_partial_list+0x9a/0x2f0 [<0000000329f5f4a4>] __slab_free+0x1e4/0x3a8 [<0000000329f61768>] __kmem_cache_free+0x308/0x358 [<000000032a91465c>] iucv_cpu_dead+0x6c/0x88 [<0000000329c2fc66>] cpuhp_invoke_callback+0x156/0x2f0 [<000000032aa062da>] _cpu_down.constprop.0+0x22a/0x5e0 [<0000000329c3243e>] cpu_device_down+0x4e/0x78 [<000000032a61dee0>] device_offline+0xc8/0x118 [<000000032a61e048>] online_store+0x60/0xe0 [<000000032a08b6b0>] kernfs_fop_write_iter+0x150/0x1e8 [<0000000329fab65c>] vfs_write+0x174/0x360 [<0000000329fab9fc>] ksys_write+0x74/0x100 [<000000032aa03a5a>] __do_syscall+0x1da/0x208 [<000000032aa177b2>] system_call+0x82/0xb0 INFO: lockdep is turned off. FIX dma-kmalloc-64: Restoring kmalloc Redzone 0x0000000000400564-0x0000000000400567=0xcc FIX dma-kmalloc-64: Object at 0x0000000000400540 not freed Fixes: 2356f4cb1911 ("[S390]: Rewrite of the IUCV base code, part 2") Signed-off-by: Alexandra Winter Link: https://lore.kernel.org/r/20230315131435.4113889-1-wintera@linux.ibm.com Signed-off-by: Jakub Kicinski --- net/iucv/iucv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c index eb0295d900395..fc3fddeb6f36d 100644 --- a/net/iucv/iucv.c +++ b/net/iucv/iucv.c @@ -83,7 +83,7 @@ struct iucv_irq_data { u16 ippathid; u8 ipflags1; u8 iptype; - u32 res2[8]; + u32 res2[9]; }; struct iucv_irq_list { From f38373345c65529639a01fba3675eb8cb4c579c3 Mon Sep 17 00:00:00 2001 From: Thomas Bogendoerfer Date: Wed, 15 Mar 2023 14:41:17 +0100 Subject: [PATCH 432/460] i825xx: sni_82596: use eth_hw_addr_set() netdev->dev_addr is now const, we can't write to it directly. Copy scrambled mac address octects into an array then eth_hw_addr_set(). Fixes: adeef3e32146 ("net: constify netdev->dev_addr") Signed-off-by: Thomas Bogendoerfer Reviewed-by: Michal Kubiak Link: https://lore.kernel.org/r/20230315134117.79511-1-tsbogend@alpha.franken.de Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/i825xx/sni_82596.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/i825xx/sni_82596.c b/drivers/net/ethernet/i825xx/sni_82596.c index daec9ce04531b..54bb4d9a0d1ea 100644 --- a/drivers/net/ethernet/i825xx/sni_82596.c +++ b/drivers/net/ethernet/i825xx/sni_82596.c @@ -78,6 +78,7 @@ static int sni_82596_probe(struct platform_device *dev) void __iomem *mpu_addr; void __iomem *ca_addr; u8 __iomem *eth_addr; + u8 mac[ETH_ALEN]; res = platform_get_resource(dev, IORESOURCE_MEM, 0); ca = platform_get_resource(dev, IORESOURCE_MEM, 1); @@ -109,12 +110,13 @@ static int sni_82596_probe(struct platform_device *dev) goto probe_failed; /* someone seems to like messed up stuff */ - netdevice->dev_addr[0] = readb(eth_addr + 0x0b); - netdevice->dev_addr[1] = readb(eth_addr + 0x0a); - netdevice->dev_addr[2] = readb(eth_addr + 0x09); - netdevice->dev_addr[3] = readb(eth_addr + 0x08); - netdevice->dev_addr[4] = readb(eth_addr + 0x07); - netdevice->dev_addr[5] = readb(eth_addr + 0x06); + mac[0] = readb(eth_addr + 0x0b); + mac[1] = readb(eth_addr + 0x0a); + mac[2] = readb(eth_addr + 0x09); + mac[3] = readb(eth_addr + 0x08); + mac[4] = readb(eth_addr + 0x07); + mac[5] = readb(eth_addr + 0x06); + eth_hw_addr_set(netdevice, mac); iounmap(eth_addr); if (netdevice->irq < 0) { From 24994513ad13ff2c47ba91d2b5df82c3d496c370 Mon Sep 17 00:00:00 2001 From: Po-Hsu Lin Date: Thu, 16 Mar 2023 00:53:53 +0800 Subject: [PATCH 433/460] selftests: net: devlink_port_split.py: skip test if no suitable device available The `devlink -j port show` command output may not contain the "flavour" key, an example from Ubuntu 22.10 s390x LPAR(5.19.0-37-generic), with mlx4 driver and iproute2-5.15.0: {"port":{"pci/0001:00:00.0/1":{"type":"eth","netdev":"ens301"}, "pci/0001:00:00.0/2":{"type":"eth","netdev":"ens301d1"}, "pci/0002:00:00.0/1":{"type":"eth","netdev":"ens317"}, "pci/0002:00:00.0/2":{"type":"eth","netdev":"ens317d1"}}} This will cause a KeyError exception. Create a validate_devlink_output() to check for this "flavour" from devlink command output to avoid this KeyError exception. Also let it handle the check for `devlink -j dev show` output in main(). Apart from this, if the test was not started because the max lanes of the designated device is 0. The script will still return 0 and thus causing a false-negative test result. Use a found_max_lanes flag to determine if these tests were skipped due to this reason and return KSFT_SKIP to make it more clear. Link: https://bugs.launchpad.net/bugs/1937133 Fixes: f3348a82e727 ("selftests: net: Add port split test") Signed-off-by: Po-Hsu Lin Link: https://lore.kernel.org/r/20230315165353.229590-1-po-hsu.lin@canonical.com Signed-off-by: Jakub Kicinski --- .../selftests/net/devlink_port_split.py | 36 ++++++++++++++++--- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/tools/testing/selftests/net/devlink_port_split.py b/tools/testing/selftests/net/devlink_port_split.py index 2b5d6ff873738..2d84c7a0be6b2 100755 --- a/tools/testing/selftests/net/devlink_port_split.py +++ b/tools/testing/selftests/net/devlink_port_split.py @@ -59,6 +59,8 @@ def get_if_names(dev): assert stderr == "" ports = json.loads(stdout)['port'] + validate_devlink_output(ports, 'flavour') + for port in ports: if dev in port: if ports[port]['flavour'] == 'physical': @@ -220,6 +222,27 @@ def split_splittable_port(port, k, lanes, dev): unsplit(port.bus_info) +def validate_devlink_output(devlink_data, target_property=None): + """ + Determine if test should be skipped by checking: + 1. devlink_data contains values + 2. The target_property exist in devlink_data + """ + skip_reason = None + if any(devlink_data.values()): + if target_property: + skip_reason = "{} not found in devlink output, test skipped".format(target_property) + for key in devlink_data: + if target_property in devlink_data[key]: + skip_reason = None + else: + skip_reason = 'devlink output is empty, test skipped' + + if skip_reason: + print(skip_reason) + sys.exit(KSFT_SKIP) + + def make_parser(): parser = argparse.ArgumentParser(description='A test for port splitting.') parser.add_argument('--dev', @@ -240,12 +263,9 @@ def main(cmdline=None): stdout, stderr = run_command(cmd) assert stderr == "" + validate_devlink_output(json.loads(stdout)) devs = json.loads(stdout)['dev'] - if devs: - dev = list(devs.keys())[0] - else: - print("no devlink device was found, test skipped") - sys.exit(KSFT_SKIP) + dev = list(devs.keys())[0] cmd = "devlink dev show %s" % dev stdout, stderr = run_command(cmd) @@ -255,6 +275,7 @@ def main(cmdline=None): ports = devlink_ports(dev) + found_max_lanes = False for port in ports.if_names: max_lanes = get_max_lanes(port.name) @@ -277,6 +298,11 @@ def main(cmdline=None): split_splittable_port(port, lane, max_lanes, dev) lane //= 2 + found_max_lanes = True + + if not found_max_lanes: + print(f"Test not started, no port of device {dev} reports max_lanes") + sys.exit(KSFT_SKIP) if __name__ == "__main__": From 470efd68a4653d9819d391489886432cd31bcd0b Mon Sep 17 00:00:00 2001 From: Daniil Tatianin Date: Wed, 15 Mar 2023 22:46:18 +0300 Subject: [PATCH 434/460] qed/qed_mng_tlv: correctly zero out ->min instead of ->hour This fixes an issue where ->hour would erroneously get zeroed out instead of ->min because of a bad copy paste. Found by Linux Verification Center (linuxtesting.org) with the SVACE static analysis tool. Fixes: f240b6882211 ("qed: Add support for processing fcoe tlv request.") Signed-off-by: Daniil Tatianin Link: https://lore.kernel.org/r/20230315194618.579286-1-d-tatianin@yandex-team.ru Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/qlogic/qed/qed_mng_tlv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/qlogic/qed/qed_mng_tlv.c b/drivers/net/ethernet/qlogic/qed/qed_mng_tlv.c index 6190adf965bca..f55eed092f25d 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_mng_tlv.c +++ b/drivers/net/ethernet/qlogic/qed/qed_mng_tlv.c @@ -422,7 +422,7 @@ qed_mfw_get_tlv_time_value(struct qed_mfw_tlv_time *p_time, if (p_time->hour > 23) p_time->hour = 0; if (p_time->min > 59) - p_time->hour = 0; + p_time->min = 0; if (p_time->msec > 999) p_time->msec = 0; if (p_time->usec > 999) From 1b0120e4db0bf2838d1ce741195ce4b7cc100b91 Mon Sep 17 00:00:00 2001 From: Matthieu Baerts Date: Wed, 15 Mar 2023 21:25:17 +0100 Subject: [PATCH 435/460] hsr: ratelimit only when errors are printed Recently, when automatically merging -net and net-next in MPTCP devel tree, our CI reported [1] a conflict in hsr, the same as the one reported by Stephen in netdev [2]. When looking at the conflict, I noticed it is in fact the v1 [3] that has been applied in -net and the v2 [4] in net-next. Maybe the v1 was applied by accident. As mentioned by Jakub Kicinski [5], the new condition makes more sense before the net_ratelimit(), not to update net_ratelimit's state which is unnecessary if we're not going to print either way. Here, this modification applies the v2 but in -net. Link: https://github.com/multipath-tcp/mptcp_net-next/actions/runs/4423171069 [1] Link: https://lore.kernel.org/netdev/20230315100914.53fc1760@canb.auug.org.au/ [2] Link: https://lore.kernel.org/netdev/20230307133229.127442-1-koverskeid@gmail.com/ [3] Link: https://lore.kernel.org/netdev/20230309092302.179586-1-koverskeid@gmail.com/ [4] Link: https://lore.kernel.org/netdev/20230308232001.2fb62013@kernel.org/ [5] Fixes: 28e8cabe80f3 ("net: hsr: Don't log netdev_err message on unknown prp dst node") Signed-off-by: Matthieu Baerts Reviewed-by: Steen Hegelund Link: https://lore.kernel.org/r/20230315-net-20230315-hsr_framereg-ratelimit-v1-1-61d2ef176d11@tessares.net Signed-off-by: Jakub Kicinski --- net/hsr/hsr_framereg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/hsr/hsr_framereg.c b/net/hsr/hsr_framereg.c index 865eda39d6014..b77f1189d19d1 100644 --- a/net/hsr/hsr_framereg.c +++ b/net/hsr/hsr_framereg.c @@ -415,7 +415,7 @@ void hsr_addr_subst_dest(struct hsr_node *node_src, struct sk_buff *skb, node_dst = find_node_by_addr_A(&port->hsr->node_db, eth_hdr(skb)->h_dest); if (!node_dst) { - if (net_ratelimit() && port->hsr->prot_version != PRP_V1) + if (port->hsr->prot_version != PRP_V1 && net_ratelimit()) netdev_err(skb->dev, "%s: Unknown node\n", __func__); return; } From 054abb515f346b8f30a0a11953d9f786d3e76813 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Wed, 15 Mar 2023 16:03:49 -0700 Subject: [PATCH 436/460] tools: ynl: make definitions optional again definitions are optional, commit in question breaks cli for ethtool. Fixes: 6517a60b0307 ("tools: ynl: move the enum classes to shared code") Reviewed-by: Chuck Lever Signed-off-by: Jakub Kicinski --- tools/net/ynl/lib/nlspec.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/net/ynl/lib/nlspec.py b/tools/net/ynl/lib/nlspec.py index 960a356e8225e..e01a72d066384 100644 --- a/tools/net/ynl/lib/nlspec.py +++ b/tools/net/ynl/lib/nlspec.py @@ -387,7 +387,8 @@ def _dictify_ops_directional(self): def resolve(self): self.resolve_up(super()) - for elem in self.yaml['definitions']: + definitions = self.yaml.get('definitions', []) + for elem in definitions: if elem['type'] == 'enum' or elem['type'] == 'flags': self.consts[elem['name']] = self.new_enum(elem) else: From 4e16b6a748df52800c90f3ab181aef8129bd332f Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Wed, 15 Mar 2023 16:03:50 -0700 Subject: [PATCH 437/460] ynl: broaden the license even more I relicensed Netlink spec code to GPL-2.0 OR BSD-3-Clause but we still put a slightly different license on the uAPI header than the rest of the code. Use the Linux-syscall-note on all the specs and all generated code. It's moot for kernel code, but should not hurt. This way the licenses match everywhere. Cc: Chuck Lever Fixes: 37d9df224d1e ("ynl: re-license uniformly under GPL-2.0 OR BSD-3-Clause") Reviewed-by: Chuck Lever 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/ynl-gen-c.py | 8 ++++---- 15 files changed, 19 insertions(+), 18 deletions(-) diff --git a/Documentation/netlink/genetlink-c.yaml b/Documentation/netlink/genetlink-c.yaml index f082a5ad7cf1d..5c3642b3f802d 100644 --- a/Documentation/netlink/genetlink-c.yaml +++ b/Documentation/netlink/genetlink-c.yaml @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +# SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) 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 c6b8c77f7d12e..5e98c6d2b9aae 100644 --- a/Documentation/netlink/genetlink-legacy.yaml +++ b/Documentation/netlink/genetlink-legacy.yaml @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +# SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) 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 b2d56ab9e615d..d35dcd6f8d82a 100644 --- a/Documentation/netlink/genetlink.yaml +++ b/Documentation/netlink/genetlink.yaml @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +# SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) 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 18ecb7d90cbe5..4727c067e2ba3 100644 --- a/Documentation/netlink/specs/ethtool.yaml +++ b/Documentation/netlink/specs/ethtool.yaml @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +# SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) name: ethtool diff --git a/Documentation/netlink/specs/fou.yaml b/Documentation/netlink/specs/fou.yaml index cff104288723b..3e13826a3fdf1 100644 --- a/Documentation/netlink/specs/fou.yaml +++ b/Documentation/netlink/specs/fou.yaml @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +# SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) name: fou diff --git a/Documentation/netlink/specs/netdev.yaml b/Documentation/netlink/specs/netdev.yaml index 753e5914a8b7c..b99e7ffef7a15 100644 --- a/Documentation/netlink/specs/netdev.yaml +++ b/Documentation/netlink/specs/netdev.yaml @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +# SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) name: netdev diff --git a/Documentation/userspace-api/netlink/specs.rst b/Documentation/userspace-api/netlink/specs.rst index 2122e0c4a3998..a22442ba1d30b 100644 --- a/Documentation/userspace-api/netlink/specs.rst +++ b/Documentation/userspace-api/netlink/specs.rst @@ -24,7 +24,8 @@ 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`` +All specs must be licensed under +``((GPL-2.0 WITH Linux-syscall-note) 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 5041c35984938..b5cd3e7b3775a 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) OR BSD-3-Clause */ +/* 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 ed134fbdfd32d..639524b59930b 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) OR BSD-3-Clause */ +/* 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 9e10802587fc3..3abab70d66ddc 100644 --- a/net/core/netdev-genl-gen.c +++ b/net/core/netdev-genl-gen.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +// 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 kernel source */ diff --git a/net/core/netdev-genl-gen.h b/net/core/netdev-genl-gen.h index 2c5fc7d1e8a74..74d74fc231679 100644 --- a/net/core/netdev-genl-gen.h +++ b/net/core/netdev-genl-gen.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ +/* 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 kernel header */ diff --git a/net/ipv4/fou_nl.c b/net/ipv4/fou_nl.c index 5c14fe030eda5..6c37c4f98ccab 100644 --- a/net/ipv4/fou_nl.c +++ b/net/ipv4/fou_nl.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +// 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 kernel source */ diff --git a/net/ipv4/fou_nl.h b/net/ipv4/fou_nl.h index 58b1e1ed4b3bb..dbd0780a5d34c 100644 --- a/net/ipv4/fou_nl.h +++ b/net/ipv4/fou_nl.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ +/* 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 kernel header */ diff --git a/tools/include/uapi/linux/netdev.h b/tools/include/uapi/linux/netdev.h index ed134fbdfd32d..639524b59930b 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) OR BSD-3-Clause */ +/* 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/ynl-gen-c.py b/tools/net/ynl/ynl-gen-c.py index d47376f19de72..3b4d03a50fc1b 100755 --- a/tools/net/ynl/ynl-gen-c.py +++ b/tools/net/ynl/ynl-gen-c.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +# SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) import argparse import collections @@ -2068,12 +2068,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) OR BSD-3-Clause */') + 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: GPL-2.0 OR BSD-3-Clause */') + cw.p('/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */') else: - cw.p('// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause') + cw.p('// SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) 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'} */") From cfab77c0b54583816faac5f9abdf588c13895a9d Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Wed, 15 Mar 2023 16:03:51 -0700 Subject: [PATCH 438/460] ynl: make the tooling check the license The (only recently documented) expectation is that all specs are under a certain license, but we don't actually enforce it. What's worse we then go ahead and assume the license was right, outputting the expected license into generated files. Fixes: 37d9df224d1e ("ynl: re-license uniformly under GPL-2.0 OR BSD-3-Clause") Reviewed-by: Chuck Lever Signed-off-by: Jakub Kicinski --- tools/net/ynl/lib/nlspec.py | 8 ++++++++ tools/net/ynl/ynl-gen-c.py | 13 +++++++------ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/tools/net/ynl/lib/nlspec.py b/tools/net/ynl/lib/nlspec.py index e01a72d066384..d04450c2a44af 100644 --- a/tools/net/ynl/lib/nlspec.py +++ b/tools/net/ynl/lib/nlspec.py @@ -274,6 +274,7 @@ class SpecFamily(SpecElement): Attributes: proto protocol type (e.g. genetlink) + license spec license (loaded from an SPDX tag on the spec) attr_sets dict of attribute sets msgs dict of all messages (index by name) @@ -283,6 +284,13 @@ class SpecFamily(SpecElement): """ def __init__(self, spec_path, schema_path=None): with open(spec_path, "r") as stream: + prefix = '# SPDX-License-Identifier: ' + first = stream.readline().strip() + if not first.startswith(prefix): + raise Exception('SPDX license tag required in the spec') + self.license = first[len(prefix):] + + stream.seek(0) spec = yaml.safe_load(stream) self._resolution_list = [] diff --git a/tools/net/ynl/ynl-gen-c.py b/tools/net/ynl/ynl-gen-c.py index 3b4d03a50fc1b..c16671a02621b 100755 --- a/tools/net/ynl/ynl-gen-c.py +++ b/tools/net/ynl/ynl-gen-c.py @@ -2059,6 +2059,10 @@ def main(): try: parsed = Family(args.spec) + if parsed.license != '((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)': + print('Spec license:', parsed.license) + print('License must be: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)') + os.sys.exit(1) except yaml.YAMLError as exc: print(exc) os.sys.exit(1) @@ -2067,13 +2071,10 @@ def main(): cw = CodeWriter(BaseNlLib(), out_file) _, spec_kernel = find_kernel_root(args.spec) - if args.mode == 'uapi': - cw.p('/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */') + if args.mode == 'uapi' or args.header: + cw.p(f'/* SPDX-License-Identifier: {parsed.license} */') else: - if args.header: - cw.p('/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */') - else: - cw.p('// SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)') + cw.p(f'// SPDX-License-Identifier: {parsed.license}') 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'} */") From 5ae06327a3a5bad4ee246d81df203b1b00a7b390 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 16 Mar 2023 01:19:16 +0200 Subject: [PATCH 439/460] net: dsa: microchip: fix RGMII delay configuration on KSZ8765/KSZ8794/KSZ8795 The blamed commit has replaced a ksz_write8() call to address REG_PORT_5_CTRL_6 (0x56) with a ksz_set_xmii() -> ksz_pwrite8() call to regs[P_XMII_CTRL_1], which is also defined as 0x56 for ksz8795_regs[]. The trouble is that, when compared to ksz_write8(), ksz_pwrite8() also adjusts the register offset with the port base address. So in reality, ksz_pwrite8(offset=0x56) accesses register 0x56 + 0x50 = 0xa6, which in this switch appears to be unmapped, and the RGMII delay configuration on the CPU port does nothing. So if the switch wasn't fine with the RGMII delay configuration done through pin strapping and relied on Linux to apply a different one in order to pass traffic, this is now broken. Using the offset translation logic imposed by ksz_pwrite8(), the correct value for regs[P_XMII_CTRL_1] should have been 0x6 on ksz8795_regs[], in order to really end up accessing register 0x56. Static code analysis shows that, despite there being multiple other accesses to regs[P_XMII_CTRL_1] in this driver, the only code path that is applicable to ksz8795_regs[] and ksz8_dev_ops is ksz_set_xmii(). Therefore, the problem is isolated to RGMII delays. In its current form, ksz8795_regs[] contains the same value for P_XMII_CTRL_0 and for P_XMII_CTRL_1, and this raises valid suspicions that writes made by the driver to regs[P_XMII_CTRL_0] might overwrite writes made to regs[P_XMII_CTRL_1] or vice versa. Again, static analysis shows that the only accesses to P_XMII_CTRL_0 from the driver are made from code paths which are not reachable with ksz8_dev_ops. So the accesses made by ksz_set_xmii() are safe for this switch family. [ vladimiroltean: rewrote commit message ] Fixes: c476bede4b0f ("net: dsa: microchip: ksz8795: use common xmii function") Signed-off-by: Marek Vasut Signed-off-by: Vladimir Oltean Acked-by: Arun Ramadoss Reviewed-by: Florian Fainelli Link: https://lore.kernel.org/r/20230315231916.2998480-1-vladimir.oltean@nxp.com Signed-off-by: Jakub Kicinski --- drivers/net/dsa/microchip/ksz_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c index 729b36eeb2c46..7fc2155d93d6e 100644 --- a/drivers/net/dsa/microchip/ksz_common.c +++ b/drivers/net/dsa/microchip/ksz_common.c @@ -319,7 +319,7 @@ static const u16 ksz8795_regs[] = { [S_BROADCAST_CTRL] = 0x06, [S_MULTICAST_CTRL] = 0x04, [P_XMII_CTRL_0] = 0x06, - [P_XMII_CTRL_1] = 0x56, + [P_XMII_CTRL_1] = 0x06, }; static const u32 ksz8795_masks[] = { From 8de2bd02439eb839a452a853c1004c2c45ff6fef Mon Sep 17 00:00:00 2001 From: Hangbin Liu Date: Thu, 16 Mar 2023 11:37:52 +0800 Subject: [PATCH 440/460] Revert "net/sched: act_api: move TCA_EXT_WARN_MSG to the correct hierarchy" This reverts commit 923b2e30dc9cd05931da0f64e2e23d040865c035. This is not a correct fix as TCA_EXT_WARN_MSG is not a hierarchy to TCA_ACT_TAB. I didn't notice the TC actions use different enum when adding TCA_EXT_WARN_MSG. To fix the difference I will add a new WARN enum in TCA_ROOT_MAX as Jamal suggested. Signed-off-by: Hangbin Liu Acked-by: Jamal Hadi Salim Signed-off-by: Jakub Kicinski --- net/sched/act_api.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/sched/act_api.c b/net/sched/act_api.c index 34c5086750416..fce5228860990 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c @@ -1596,12 +1596,12 @@ static int tca_get_fill(struct sk_buff *skb, struct tc_action *actions[], if (tcf_action_dump(skb, actions, bind, ref, false) < 0) goto out_nlmsg_trim; + nla_nest_end(skb, nest); + if (extack && extack->_msg && nla_put_string(skb, TCA_EXT_WARN_MSG, extack->_msg)) goto out_nlmsg_trim; - nla_nest_end(skb, nest); - nlh->nlmsg_len = skb_tail_pointer(skb) - b; return skb->len; From 2f59823fe696caa844249a90bb3f9aeda69cfe5c Mon Sep 17 00:00:00 2001 From: Hangbin Liu Date: Thu, 16 Mar 2023 11:37:53 +0800 Subject: [PATCH 441/460] net/sched: act_api: add specific EXT_WARN_MSG for tc action In my previous commit 0349b8779cc9 ("sched: add new attr TCA_EXT_WARN_MSG to report tc extact message") I didn't notice the tc action use different enum with filter. So we can't use TCA_EXT_WARN_MSG directly for tc action. Let's add a TCA_ROOT_EXT_WARN_MSG for tc action specifically and put this param before going to the TCA_ACT_TAB nest. Fixes: 0349b8779cc9 ("sched: add new attr TCA_EXT_WARN_MSG to report tc extact message") Signed-off-by: Hangbin Liu Acked-by: Jamal Hadi Salim Signed-off-by: Jakub Kicinski --- include/uapi/linux/rtnetlink.h | 1 + net/sched/act_api.c | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h index 25a0af57dd5ed..51c13cf9c5aee 100644 --- a/include/uapi/linux/rtnetlink.h +++ b/include/uapi/linux/rtnetlink.h @@ -789,6 +789,7 @@ enum { TCA_ROOT_FLAGS, TCA_ROOT_COUNT, TCA_ROOT_TIME_DELTA, /* in msecs */ + TCA_ROOT_EXT_WARN_MSG, __TCA_ROOT_MAX, #define TCA_ROOT_MAX (__TCA_ROOT_MAX - 1) }; diff --git a/net/sched/act_api.c b/net/sched/act_api.c index fce5228860990..296fc1afedd82 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c @@ -1589,6 +1589,10 @@ static int tca_get_fill(struct sk_buff *skb, struct tc_action *actions[], t->tca__pad1 = 0; t->tca__pad2 = 0; + if (extack && extack->_msg && + nla_put_string(skb, TCA_ROOT_EXT_WARN_MSG, extack->_msg)) + goto out_nlmsg_trim; + nest = nla_nest_start_noflag(skb, TCA_ACT_TAB); if (!nest) goto out_nlmsg_trim; @@ -1598,10 +1602,6 @@ static int tca_get_fill(struct sk_buff *skb, struct tc_action *actions[], nla_nest_end(skb, nest); - if (extack && extack->_msg && - nla_put_string(skb, TCA_EXT_WARN_MSG, extack->_msg)) - goto out_nlmsg_trim; - nlh->nlmsg_len = skb_tail_pointer(skb) - b; return skb->len; From 769639c1fe8a98129aa97c8ee981639db1e8955c Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Thu, 16 Mar 2023 15:02:34 -0700 Subject: [PATCH 442/460] net: xdp: don't call notifiers during driver init Drivers will commonly perform feature setting during init, if they use the xdp_set_features_flag() helper they'll likely run into an ASSERT_RTNL() inside call_netdevice_notifiers_info(). Don't call the notifier until the device is actually registered. Nothing should be tracking the device until its registered and after its unregistration has started. Fixes: 4d5ab0ad964d ("net/mlx5e: take into account device reconfiguration for xdp_features flag") Link: https://lore.kernel.org/r/20230316220234.598091-1-kuba@kernel.org Signed-off-by: Jakub Kicinski --- net/core/xdp.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/core/xdp.c b/net/core/xdp.c index 87e654b7d06c1..b5737e47ec412 100644 --- a/net/core/xdp.c +++ b/net/core/xdp.c @@ -781,7 +781,9 @@ void xdp_set_features_flag(struct net_device *dev, xdp_features_t val) return; dev->xdp_features = val; - call_netdevice_notifiers(NETDEV_XDP_FEAT_CHANGE, dev); + + if (dev->reg_state == NETREG_REGISTERED) + call_netdevice_notifiers(NETDEV_XDP_FEAT_CHANGE, dev); } EXPORT_SYMBOL_GPL(xdp_set_features_flag); From dd172d0c2cea3c14ca9d007eeab51bec7676ece7 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 16 Mar 2023 09:51:33 -0500 Subject: [PATCH 443/460] net: ipa: reg: include When "reg.h" got created, it included calls to WARN() and WARN_ON(). Those macros are defined via . In addition, it uses is_power_of_2(), which is defined in . Include those files so IPA "reg.h" has access to all definitions it requires. Meanwhile, is included but nothing defined therein is required directly in "reg.h", so get rid of that. Fixes: 81772e444dbe ("net: ipa: start generalizing "ipa_reg"") Signed-off-by: Alex Elder Signed-off-by: Jakub Kicinski --- drivers/net/ipa/reg.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ipa/reg.h b/drivers/net/ipa/reg.h index 57b457f39b6e2..2ee07eebca677 100644 --- a/drivers/net/ipa/reg.h +++ b/drivers/net/ipa/reg.h @@ -6,7 +6,8 @@ #define _REG_H_ #include -#include +#include +#include /** * struct reg - A register descriptor From 55c49e5c94411a82a0ba06dc615ed12b6387dec5 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 16 Mar 2023 09:51:34 -0500 Subject: [PATCH 444/460] net: ipa: add two missing declarations When gsi_reg_init() got added, its declaration was added to "gsi_reg.h" without declaring the two struct pointer types it uses. Add these struct declarations to "gsi_reg.h". Fixes: 3c506add35c7 ("net: ipa: introduce gsi_reg_init()") Signed-off-by: Alex Elder Signed-off-by: Jakub Kicinski --- drivers/net/ipa/gsi_reg.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/ipa/gsi_reg.h b/drivers/net/ipa/gsi_reg.h index f62f0a5c653d1..48fde65fa2e8a 100644 --- a/drivers/net/ipa/gsi_reg.h +++ b/drivers/net/ipa/gsi_reg.h @@ -10,6 +10,10 @@ #include +struct platform_device; + +struct gsi; + /** * DOC: GSI Registers * From 786bbe50e1d5777f0b6ec7b4c2de6189d6f7feb4 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 16 Mar 2023 09:51:35 -0500 Subject: [PATCH 445/460] net: ipa: kill FILT_ROUT_CACHE_CFG IPA register A recent commit defined a few IPA registers used for IPA v5.0+. One of those was a mistake. Although the filter and router caches get *flushed* using a single register, they use distinct registers (ENDP_FILTER_CACHE_CFG and ENDP_ROUTER_CACHE_CFG) for configuration. And although there *exists* a FILT_ROUT_CACHE_CFG register, it is not needed in upstream code. So get rid of definitions related to FILT_ROUT_CACHE_CFG, because they are not needed. Fixes: 8ba59716d16a ("net: ipa: define IPA v5.0+ registers") Signed-off-by: Alex Elder Signed-off-by: Jakub Kicinski --- drivers/net/ipa/ipa_reg.c | 4 ++-- drivers/net/ipa/ipa_reg.h | 9 --------- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/drivers/net/ipa/ipa_reg.c b/drivers/net/ipa/ipa_reg.c index 735fa65916097..463a31dfa9f47 100644 --- a/drivers/net/ipa/ipa_reg.c +++ b/drivers/net/ipa/ipa_reg.c @@ -39,7 +39,8 @@ static bool ipa_reg_id_valid(struct ipa *ipa, enum ipa_reg_id reg_id) return version <= IPA_VERSION_3_1; case ENDP_FILTER_ROUTER_HSH_CFG: - return version != IPA_VERSION_4_2; + return version < IPA_VERSION_5_0 && + version != IPA_VERSION_4_2; case IRQ_SUSPEND_EN: case IRQ_SUSPEND_CLR: @@ -52,7 +53,6 @@ static bool ipa_reg_id_valid(struct ipa *ipa, enum ipa_reg_id reg_id) case QSB_MAX_WRITES: case QSB_MAX_READS: case FILT_ROUT_HASH_EN: - case FILT_ROUT_CACHE_CFG: case FILT_ROUT_HASH_FLUSH: case FILT_ROUT_CACHE_FLUSH: case STATE_AGGR_ACTIVE: diff --git a/drivers/net/ipa/ipa_reg.h b/drivers/net/ipa/ipa_reg.h index 28aa1351dd488..ff2be8be0f683 100644 --- a/drivers/net/ipa/ipa_reg.h +++ b/drivers/net/ipa/ipa_reg.h @@ -61,7 +61,6 @@ enum ipa_reg_id { QSB_MAX_WRITES, QSB_MAX_READS, FILT_ROUT_HASH_EN, /* Not IPA v5.0+ */ - FILT_ROUT_CACHE_CFG, /* IPA v5.0+ */ FILT_ROUT_HASH_FLUSH, /* Not IPA v5.0+ */ FILT_ROUT_CACHE_FLUSH, /* IPA v5.0+ */ STATE_AGGR_ACTIVE, @@ -206,14 +205,6 @@ enum ipa_reg_qsb_max_reads_field_id { GEN_QMB_1_MAX_READS_BEATS, /* IPA v4.0+ */ }; -/* FILT_ROUT_CACHE_CFG register */ -enum ipa_reg_filt_rout_cache_cfg_field_id { - ROUTER_CACHE_EN, - FILTER_CACHE_EN, - LOW_PRI_HASH_HIT_DISABLE, - LRU_EVICTION_THRESHOLD, -}; - /* FILT_ROUT_HASH_EN and FILT_ROUT_HASH_FLUSH registers */ enum ipa_reg_filt_rout_hash_field_id { IPV6_ROUTER_HASH, From 21e8aaca401ce2b45ece1d8fabd29d422de7b48e Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 16 Mar 2023 09:51:36 -0500 Subject: [PATCH 446/460] net: ipa: fix some register validity checks A recent commit defined HW_PARAM_4 as a GSI register ID but did not add it to gsi_reg_id_valid() to indicate it's valid (for IPA v5.0+). Add version checks for the HW_PARAM_2 and INTER_EE IRQ GSI registers there as well. IPA v5.0 supports up to 8 source and destination resource groups. Update the validity check (and the comments where the register IDs are defined) to reflect that. Similarly update comments and validity checks for the hash/cache-related registers. Note that this patch fixes an omission and constrains things further, but these don't technically represent bugs. Fixes: f651334e1ef5 ("net: ipa: add HW_PARAM_4 GSI register") Signed-off-by: Alex Elder Signed-off-by: Jakub Kicinski --- drivers/net/ipa/gsi_reg.c | 9 ++++++++- drivers/net/ipa/ipa_reg.c | 24 ++++++++++++++++-------- drivers/net/ipa/ipa_reg.h | 12 ++++++------ 3 files changed, 30 insertions(+), 15 deletions(-) diff --git a/drivers/net/ipa/gsi_reg.c b/drivers/net/ipa/gsi_reg.c index 1412b67304c8e..1651fbad4bd54 100644 --- a/drivers/net/ipa/gsi_reg.c +++ b/drivers/net/ipa/gsi_reg.c @@ -15,6 +15,14 @@ static bool gsi_reg_id_valid(struct gsi *gsi, enum gsi_reg_id reg_id) switch (reg_id) { case INTER_EE_SRC_CH_IRQ_MSK: case INTER_EE_SRC_EV_CH_IRQ_MSK: + return gsi->version >= IPA_VERSION_3_5; + + case HW_PARAM_2: + return gsi->version >= IPA_VERSION_3_5_1; + + case HW_PARAM_4: + return gsi->version >= IPA_VERSION_5_0; + case CH_C_CNTXT_0: case CH_C_CNTXT_1: case CH_C_CNTXT_2: @@ -43,7 +51,6 @@ static bool gsi_reg_id_valid(struct gsi *gsi, enum gsi_reg_id reg_id) case CH_CMD: case EV_CH_CMD: case GENERIC_CMD: - case HW_PARAM_2: case CNTXT_TYPE_IRQ: case CNTXT_TYPE_IRQ_MSK: case CNTXT_SRC_CH_IRQ: diff --git a/drivers/net/ipa/ipa_reg.c b/drivers/net/ipa/ipa_reg.c index 463a31dfa9f47..3f475428ddddb 100644 --- a/drivers/net/ipa/ipa_reg.c +++ b/drivers/net/ipa/ipa_reg.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 /* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. - * Copyright (C) 2019-2022 Linaro Ltd. + * Copyright (C) 2019-2023 Linaro Ltd. */ #include @@ -15,6 +15,17 @@ static bool ipa_reg_id_valid(struct ipa *ipa, enum ipa_reg_id reg_id) enum ipa_version version = ipa->version; switch (reg_id) { + case FILT_ROUT_HASH_EN: + return version == IPA_VERSION_4_2; + + case FILT_ROUT_HASH_FLUSH: + return version < IPA_VERSION_5_0 && version != IPA_VERSION_4_2; + + case FILT_ROUT_CACHE_FLUSH: + case ENDP_FILTER_CACHE_CFG: + case ENDP_ROUTER_CACHE_CFG: + return version >= IPA_VERSION_5_0; + case IPA_BCR: case COUNTER_CFG: return version < IPA_VERSION_4_5; @@ -32,11 +43,13 @@ static bool ipa_reg_id_valid(struct ipa *ipa, enum ipa_reg_id reg_id) case SRC_RSRC_GRP_45_RSRC_TYPE: case DST_RSRC_GRP_45_RSRC_TYPE: return version <= IPA_VERSION_3_1 || - version == IPA_VERSION_4_5; + version == IPA_VERSION_4_5 || + version == IPA_VERSION_5_0; case SRC_RSRC_GRP_67_RSRC_TYPE: case DST_RSRC_GRP_67_RSRC_TYPE: - return version <= IPA_VERSION_3_1; + return version <= IPA_VERSION_3_1 || + version == IPA_VERSION_5_0; case ENDP_FILTER_ROUTER_HSH_CFG: return version < IPA_VERSION_5_0 && @@ -52,9 +65,6 @@ static bool ipa_reg_id_valid(struct ipa *ipa, enum ipa_reg_id reg_id) case SHARED_MEM_SIZE: case QSB_MAX_WRITES: case QSB_MAX_READS: - case FILT_ROUT_HASH_EN: - case FILT_ROUT_HASH_FLUSH: - case FILT_ROUT_CACHE_FLUSH: case STATE_AGGR_ACTIVE: case LOCAL_PKT_PROC_CNTXT: case AGGR_FORCE_CLOSE: @@ -76,8 +86,6 @@ static bool ipa_reg_id_valid(struct ipa *ipa, enum ipa_reg_id reg_id) case ENDP_INIT_RSRC_GRP: case ENDP_INIT_SEQ: case ENDP_STATUS: - case ENDP_FILTER_CACHE_CFG: - case ENDP_ROUTER_CACHE_CFG: case IPA_IRQ_STTS: case IPA_IRQ_EN: case IPA_IRQ_CLR: diff --git a/drivers/net/ipa/ipa_reg.h b/drivers/net/ipa/ipa_reg.h index ff2be8be0f683..7dd65d39333dd 100644 --- a/drivers/net/ipa/ipa_reg.h +++ b/drivers/net/ipa/ipa_reg.h @@ -60,8 +60,8 @@ enum ipa_reg_id { SHARED_MEM_SIZE, QSB_MAX_WRITES, QSB_MAX_READS, - FILT_ROUT_HASH_EN, /* Not IPA v5.0+ */ - FILT_ROUT_HASH_FLUSH, /* Not IPA v5.0+ */ + FILT_ROUT_HASH_EN, /* IPA v4.2 */ + FILT_ROUT_HASH_FLUSH, /* Not IPA v4.2 nor IPA v5.0+ */ FILT_ROUT_CACHE_FLUSH, /* IPA v5.0+ */ STATE_AGGR_ACTIVE, IPA_BCR, /* Not IPA v4.5+ */ @@ -76,12 +76,12 @@ enum ipa_reg_id { TIMERS_PULSE_GRAN_CFG, /* IPA v4.5+ */ SRC_RSRC_GRP_01_RSRC_TYPE, SRC_RSRC_GRP_23_RSRC_TYPE, - SRC_RSRC_GRP_45_RSRC_TYPE, /* Not IPA v3.5+, IPA v4.5 */ - SRC_RSRC_GRP_67_RSRC_TYPE, /* Not IPA v3.5+ */ + SRC_RSRC_GRP_45_RSRC_TYPE, /* Not IPA v3.5+; IPA v4.5, IPA v5.0 */ + SRC_RSRC_GRP_67_RSRC_TYPE, /* Not IPA v3.5+; IPA v5.0 */ DST_RSRC_GRP_01_RSRC_TYPE, DST_RSRC_GRP_23_RSRC_TYPE, - DST_RSRC_GRP_45_RSRC_TYPE, /* Not IPA v3.5+, IPA v4.5 */ - DST_RSRC_GRP_67_RSRC_TYPE, /* Not IPA v3.5+ */ + DST_RSRC_GRP_45_RSRC_TYPE, /* Not IPA v3.5+; IPA v4.5, IPA v5.0 */ + DST_RSRC_GRP_67_RSRC_TYPE, /* Not IPA v3.5+; IPA v5.0 */ ENDP_INIT_CTRL, /* Not IPA v4.2+ for TX, not IPA v4.0+ for RX */ ENDP_INIT_CFG, ENDP_INIT_NAT, /* TX only */ From c00133a9e87ea5324d0b883d801eb6656f26739b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Thu, 16 Mar 2023 08:26:47 +0100 Subject: [PATCH 447/460] drm/ttm: drop extra ttm_bo_put in ttm_bo_cleanup_refs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit That was accidentially left over when we switched to the delayed delete worker. Suggested-by: Matthew Auld Signed-off-by: Christian König Fixes: 9bff18d13473 ("drm/ttm: use per BO cleanup workers") Reported-by: Steven Rostedt (Google) Tested-by: Steven Rostedt (Google) Reviewed-by: Matthew Auld Signed-off-by: Dave Airlie Link: https://patchwork.freedesktop.org/patch/msgid/20230316072647.406707-1-christian.koenig@amd.com --- drivers/gpu/drm/ttm/ttm_bo.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 326a3d13a8295..c286c6ffe07f6 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -295,8 +295,6 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo, if (unlock_resv) dma_resv_unlock(bo->base.resv); - ttm_bo_put(bo); - return 0; } From 90de546d9a0b3c771667af18bb3f80567eabb89b Mon Sep 17 00:00:00 2001 From: Liang He Date: Wed, 15 Mar 2023 14:00:21 +0800 Subject: [PATCH 448/460] ethernet: sun: add check for the mdesc_grab() In vnet_port_probe() and vsw_port_probe(), we should check the return value of mdesc_grab() as it may return NULL which can caused NPD bugs. Fixes: 5d01fa0c6bd8 ("ldmvsw: Add ldmvsw.c driver code") Fixes: 43fdf27470b2 ("[SPARC64]: Abstract out mdesc accesses for better MD update handling.") Signed-off-by: Liang He Reviewed-by: Piotr Raczynski Signed-off-by: David S. Miller --- drivers/net/ethernet/sun/ldmvsw.c | 3 +++ drivers/net/ethernet/sun/sunvnet.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/drivers/net/ethernet/sun/ldmvsw.c b/drivers/net/ethernet/sun/ldmvsw.c index 8addee6d04bd8..734a817d3c945 100644 --- a/drivers/net/ethernet/sun/ldmvsw.c +++ b/drivers/net/ethernet/sun/ldmvsw.c @@ -287,6 +287,9 @@ static int vsw_port_probe(struct vio_dev *vdev, const struct vio_device_id *id) hp = mdesc_grab(); + if (!hp) + return -ENODEV; + rmac = mdesc_get_property(hp, vdev->mp, remote_macaddr_prop, &len); err = -ENODEV; if (!rmac) { diff --git a/drivers/net/ethernet/sun/sunvnet.c b/drivers/net/ethernet/sun/sunvnet.c index fe86fbd585861..e220620d0ffc9 100644 --- a/drivers/net/ethernet/sun/sunvnet.c +++ b/drivers/net/ethernet/sun/sunvnet.c @@ -433,6 +433,9 @@ static int vnet_port_probe(struct vio_dev *vdev, const struct vio_device_id *id) hp = mdesc_grab(); + if (!hp) + return -ENODEV; + vp = vnet_find_parent(hp, vdev->mp, vdev); if (IS_ERR(vp)) { pr_err("Cannot find port parent vnet\n"); From e05bb97d9c9dd4ba5739a27921044c935a7fb3be Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Wed, 15 Mar 2023 16:04:23 +0900 Subject: [PATCH 449/460] net: renesas: rswitch: Fix the output value of quote from rswitch_rx() If the RX descriptor doesn't have any data, the output value of quote from rswitch_rx() will be increased unexpectedily. So, fix it. Reported-by: Volodymyr Babchuk Fixes: 3590918b5d07 ("net: ethernet: renesas: Add support for "Ethernet Switch"") Signed-off-by: Yoshihiro Shimoda Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/rswitch.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/renesas/rswitch.c b/drivers/net/ethernet/renesas/rswitch.c index 853394e5bb8b9..46d8d9c8fc19f 100644 --- a/drivers/net/ethernet/renesas/rswitch.c +++ b/drivers/net/ethernet/renesas/rswitch.c @@ -702,13 +702,14 @@ static bool rswitch_rx(struct net_device *ndev, int *quota) u16 pkt_len; u32 get_ts; + if (*quota <= 0) + return true; + boguscnt = min_t(int, gq->ring_size, *quota); limit = boguscnt; desc = &gq->rx_ring[gq->cur]; while ((desc->desc.die_dt & DT_MASK) != DT_FEMPTY) { - if (--boguscnt < 0) - break; dma_rmb(); pkt_len = le16_to_cpu(desc->desc.info_ds) & RX_DS; skb = gq->skbs[gq->cur]; @@ -734,6 +735,9 @@ static bool rswitch_rx(struct net_device *ndev, int *quota) gq->cur = rswitch_next_queue_index(gq, true, 1); desc = &gq->rx_ring[gq->cur]; + + if (--boguscnt <= 0) + break; } num = rswitch_get_num_cur_queues(gq); @@ -745,7 +749,7 @@ static bool rswitch_rx(struct net_device *ndev, int *quota) goto err; gq->dirty = rswitch_next_queue_index(gq, false, num); - *quota -= limit - (++boguscnt); + *quota -= limit - boguscnt; return boguscnt <= 0; From 2c59e993c86ad57afde26eaf1beb35694da5fbfe Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Wed, 15 Mar 2023 16:04:24 +0900 Subject: [PATCH 450/460] net: renesas: rswitch: Fix GWTSDIE register handling Since the GWCA has the TX timestamp feature, this driver should not disable it if one of ports is opened. So, fix it. Reported-by: Phong Hoang Fixes: 33f5d733b589 ("net: renesas: rswitch: Improve TX timestamp accuracy") Signed-off-by: Yoshihiro Shimoda Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/rswitch.c | 9 +++++++-- drivers/net/ethernet/renesas/rswitch.h | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/renesas/rswitch.c b/drivers/net/ethernet/renesas/rswitch.c index 46d8d9c8fc19f..c4f93d24c6a42 100644 --- a/drivers/net/ethernet/renesas/rswitch.c +++ b/drivers/net/ethernet/renesas/rswitch.c @@ -1441,7 +1441,10 @@ static int rswitch_open(struct net_device *ndev) rswitch_enadis_data_irq(rdev->priv, rdev->tx_queue->index, true); rswitch_enadis_data_irq(rdev->priv, rdev->rx_queue->index, true); - iowrite32(GWCA_TS_IRQ_BIT, rdev->priv->addr + GWTSDIE); + if (bitmap_empty(rdev->priv->opened_ports, RSWITCH_NUM_PORTS)) + iowrite32(GWCA_TS_IRQ_BIT, rdev->priv->addr + GWTSDIE); + + bitmap_set(rdev->priv->opened_ports, rdev->port, 1); return 0; }; @@ -1452,8 +1455,10 @@ static int rswitch_stop(struct net_device *ndev) struct rswitch_gwca_ts_info *ts_info, *ts_info2; netif_tx_stop_all_queues(ndev); + bitmap_clear(rdev->priv->opened_ports, rdev->port, 1); - iowrite32(GWCA_TS_IRQ_BIT, rdev->priv->addr + GWTSDID); + if (bitmap_empty(rdev->priv->opened_ports, RSWITCH_NUM_PORTS)) + iowrite32(GWCA_TS_IRQ_BIT, rdev->priv->addr + GWTSDID); list_for_each_entry_safe(ts_info, ts_info2, &rdev->priv->gwca.ts_info_list, list) { if (ts_info->port != rdev->port) diff --git a/drivers/net/ethernet/renesas/rswitch.h b/drivers/net/ethernet/renesas/rswitch.h index 27d3d38c055f0..b3e0411b408ef 100644 --- a/drivers/net/ethernet/renesas/rswitch.h +++ b/drivers/net/ethernet/renesas/rswitch.h @@ -998,6 +998,7 @@ struct rswitch_private { struct rcar_gen4_ptp_private *ptp_priv; struct rswitch_device *rdev[RSWITCH_NUM_PORTS]; + DECLARE_BITMAP(opened_ports, RSWITCH_NUM_PORTS); struct rswitch_gwca gwca; struct rswitch_etha etha[RSWITCH_NUM_PORTS]; From 9ec7eb60dcbcb6c41076defbc5df7bbd95ceaba5 Mon Sep 17 00:00:00 2001 From: Nikolay Aleksandrov Date: Wed, 15 Mar 2023 13:18:40 +0200 Subject: [PATCH 451/460] bonding: restore IFF_MASTER/SLAVE flags on bond enslave ether type change Add bond_ether_setup helper which is used to fix ether_setup() calls in the bonding driver. It takes care of both IFF_MASTER and IFF_SLAVE flags, the former is always restored and the latter only if it was set. If the bond enslaves non-ARPHRD_ETHER device (changes its type), then releases it and enslaves ARPHRD_ETHER device (changes back) then we use ether_setup() to restore the bond device type but it also resets its flags and removes IFF_MASTER and IFF_SLAVE[1]. Use the bond_ether_setup helper to restore both after such transition. [1] reproduce (nlmon is non-ARPHRD_ETHER): $ ip l add nlmon0 type nlmon $ ip l add bond2 type bond mode active-backup $ ip l set nlmon0 master bond2 $ ip l set nlmon0 nomaster $ ip l add bond1 type bond (we use bond1 as ARPHRD_ETHER device to restore bond2's mode) $ ip l set bond1 master bond2 $ ip l sh dev bond2 37: bond2: mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/ether be:d7:c5:40:5b:cc brd ff:ff:ff:ff:ff:ff promiscuity 0 minmtu 68 maxmtu 1500 (notice bond2's IFF_MASTER is missing) Fixes: e36b9d16c6a6 ("bonding: clean muticast addresses when device changes type") Signed-off-by: Nikolay Aleksandrov Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 00646aa315c30..4bd911f9d3f95 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1775,6 +1775,19 @@ void bond_lower_state_changed(struct slave *slave) slave_err(bond_dev, slave_dev, "Error: %s\n", errmsg); \ } while (0) +/* The bonding driver uses ether_setup() to convert a master bond device + * to ARPHRD_ETHER, that resets the target netdevice's flags so we always + * have to restore the IFF_MASTER flag, and only restore IFF_SLAVE if it was set + */ +static void bond_ether_setup(struct net_device *bond_dev) +{ + unsigned int slave_flag = bond_dev->flags & IFF_SLAVE; + + ether_setup(bond_dev); + bond_dev->flags |= IFF_MASTER | slave_flag; + bond_dev->priv_flags &= ~IFF_TX_SKB_SHARING; +} + /* enslave device to bond device */ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev, struct netlink_ext_ack *extack) @@ -1866,10 +1879,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev, if (slave_dev->type != ARPHRD_ETHER) bond_setup_by_slave(bond_dev, slave_dev); - else { - ether_setup(bond_dev); - bond_dev->priv_flags &= ~IFF_TX_SKB_SHARING; - } + else + bond_ether_setup(bond_dev); call_netdevice_notifiers(NETDEV_POST_TYPE_CHANGE, bond_dev); From e667d469098671261d558be0cd93dca4d285ce1e Mon Sep 17 00:00:00 2001 From: Nikolay Aleksandrov Date: Wed, 15 Mar 2023 13:18:41 +0200 Subject: [PATCH 452/460] bonding: restore bond's IFF_SLAVE flag if a non-eth dev enslave fails syzbot reported a warning[1] where the bond device itself is a slave and we try to enslave a non-ethernet device as the first slave which fails but then in the error path when ether_setup() restores the bond device it also clears all flags. In my previous fix[2] I restored the IFF_MASTER flag, but I didn't consider the case that the bond device itself might also be a slave with IFF_SLAVE set, so we need to restore that flag as well. Use the bond_ether_setup helper which does the right thing and restores the bond's flags properly. Steps to reproduce using a nlmon dev: $ ip l add nlmon0 type nlmon $ ip l add bond1 type bond $ ip l add bond2 type bond $ ip l set bond1 master bond2 $ ip l set dev nlmon0 master bond1 $ ip -d l sh dev bond1 22: bond1: mtu 1500 qdisc noqueue master bond2 state DOWN mode DEFAULT group default qlen 1000 (now bond1's IFF_SLAVE flag is gone and we'll hit a warning[3] if we try to delete it) [1] https://syzkaller.appspot.com/bug?id=391c7b1f6522182899efba27d891f1743e8eb3ef [2] commit 7d5cd2ce5292 ("bonding: correctly handle bonding type change on enslave failure") [3] example warning: [ 27.008664] bond1: (slave nlmon0): The slave device specified does not support setting the MAC address [ 27.008692] bond1: (slave nlmon0): Error -95 calling set_mac_address [ 32.464639] bond1 (unregistering): Released all slaves [ 32.464685] ------------[ cut here ]------------ [ 32.464686] WARNING: CPU: 1 PID: 2004 at net/core/dev.c:10829 unregister_netdevice_many+0x72a/0x780 [ 32.464694] Modules linked in: br_netfilter bridge bonding virtio_net [ 32.464699] CPU: 1 PID: 2004 Comm: ip Kdump: loaded Not tainted 5.18.0-rc3+ #47 [ 32.464703] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.1-2.fc37 04/01/2014 [ 32.464704] RIP: 0010:unregister_netdevice_many+0x72a/0x780 [ 32.464707] Code: 99 fd ff ff ba 90 1a 00 00 48 c7 c6 f4 02 66 96 48 c7 c7 20 4d 35 96 c6 05 fa c7 2b 02 01 e8 be 6f 4a 00 0f 0b e9 73 fd ff ff <0f> 0b e9 5f fd ff ff 80 3d e3 c7 2b 02 00 0f 85 3b fd ff ff ba 59 [ 32.464710] RSP: 0018:ffffa006422d7820 EFLAGS: 00010206 [ 32.464712] RAX: ffff8f6e077140a0 RBX: ffffa006422d7888 RCX: 0000000000000000 [ 32.464714] RDX: ffff8f6e12edbe58 RSI: 0000000000000296 RDI: ffffffff96d4a520 [ 32.464716] RBP: ffff8f6e07714000 R08: ffffffff96d63600 R09: ffffa006422d7728 [ 32.464717] R10: 0000000000000ec0 R11: ffffffff9698c988 R12: ffff8f6e12edb140 [ 32.464719] R13: dead000000000122 R14: dead000000000100 R15: ffff8f6e12edb140 [ 32.464723] FS: 00007f297c2f1740(0000) GS:ffff8f6e5d900000(0000) knlGS:0000000000000000 [ 32.464725] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 32.464726] CR2: 00007f297bf1c800 CR3: 00000000115e8000 CR4: 0000000000350ee0 [ 32.464730] Call Trace: [ 32.464763] [ 32.464767] rtnl_dellink+0x13e/0x380 [ 32.464776] ? cred_has_capability.isra.0+0x68/0x100 [ 32.464780] ? __rtnl_unlock+0x33/0x60 [ 32.464783] ? bpf_lsm_capset+0x10/0x10 [ 32.464786] ? security_capable+0x36/0x50 [ 32.464790] rtnetlink_rcv_msg+0x14e/0x3b0 [ 32.464792] ? _copy_to_iter+0xb1/0x790 [ 32.464796] ? post_alloc_hook+0xa0/0x160 [ 32.464799] ? rtnl_calcit.isra.0+0x110/0x110 [ 32.464802] netlink_rcv_skb+0x50/0xf0 [ 32.464806] netlink_unicast+0x216/0x340 [ 32.464809] netlink_sendmsg+0x23f/0x480 [ 32.464812] sock_sendmsg+0x5e/0x60 [ 32.464815] ____sys_sendmsg+0x22c/0x270 [ 32.464818] ? import_iovec+0x17/0x20 [ 32.464821] ? sendmsg_copy_msghdr+0x59/0x90 [ 32.464823] ? do_set_pte+0xa0/0xe0 [ 32.464828] ___sys_sendmsg+0x81/0xc0 [ 32.464832] ? mod_objcg_state+0xc6/0x300 [ 32.464835] ? refill_obj_stock+0xa9/0x160 [ 32.464838] ? memcg_slab_free_hook+0x1a5/0x1f0 [ 32.464842] __sys_sendmsg+0x49/0x80 [ 32.464847] do_syscall_64+0x3b/0x90 [ 32.464851] entry_SYSCALL_64_after_hwframe+0x44/0xae [ 32.464865] RIP: 0033:0x7f297bf2e5e7 [ 32.464868] Code: 64 89 02 48 c7 c0 ff ff ff ff eb bb 0f 1f 80 00 00 00 00 f3 0f 1e fa 64 8b 04 25 18 00 00 00 85 c0 75 10 b8 2e 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 51 c3 48 83 ec 28 89 54 24 1c 48 89 74 24 10 [ 32.464869] RSP: 002b:00007ffd96c824c8 EFLAGS: 00000246 ORIG_RAX: 000000000000002e [ 32.464872] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f297bf2e5e7 [ 32.464874] RDX: 0000000000000000 RSI: 00007ffd96c82540 RDI: 0000000000000003 [ 32.464875] RBP: 00000000640f19de R08: 0000000000000001 R09: 000000000000007c [ 32.464876] R10: 00007f297bffabe0 R11: 0000000000000246 R12: 0000000000000001 [ 32.464877] R13: 00007ffd96c82d20 R14: 00007ffd96c82610 R15: 000055bfe38a7020 [ 32.464881] [ 32.464882] ---[ end trace 0000000000000000 ]--- Fixes: 7d5cd2ce5292 ("bonding: correctly handle bonding type change on enslave failure") Reported-by: syzbot+9dfc3f3348729cc82277@syzkaller.appspotmail.com Link: https://syzkaller.appspot.com/bug?id=391c7b1f6522182899efba27d891f1743e8eb3ef Signed-off-by: Nikolay Aleksandrov Reviewed-by: Michal Kubiak Acked-by: Jonathan Toppins Acked-by: Jay Vosburgh Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 4bd911f9d3f95..236e5219c8112 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -2300,9 +2300,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev, eth_hw_addr_random(bond_dev); if (bond_dev->type != ARPHRD_ETHER) { dev_close(bond_dev); - ether_setup(bond_dev); - bond_dev->flags |= IFF_MASTER; - bond_dev->priv_flags &= ~IFF_TX_SKB_SHARING; + bond_ether_setup(bond_dev); } } From 222c94ec0ad48b951f0f692a7cf5bcf7a6bcb6b1 Mon Sep 17 00:00:00 2001 From: Nikolay Aleksandrov Date: Wed, 15 Mar 2023 13:18:42 +0200 Subject: [PATCH 453/460] selftests: bonding: add tests for ether type changes Add new network selftests for the bonding device which exercise the ether type changing call paths. They also test for the recent syzbot bug[1] which causes a warning and results in wrong device flags (IFF_SLAVE missing). The test adds three bond devices and a nlmon device, enslaves one of the bond devices to the other and then uses the nlmon device for successful and unsuccesful enslaves both of which change the bond ether type. Thus we can test for both MASTER and SLAVE flags at the same time. If the flags are properly restored we get: TEST: Change ether type of an enslaved bond device with unsuccessful enslave [ OK ] TEST: Change ether type of an enslaved bond device with successful enslave [ OK ] [1] https://syzkaller.appspot.com/bug?id=391c7b1f6522182899efba27d891f1743e8eb3ef Signed-off-by: Nikolay Aleksandrov Reviewed-by: Michal Kubiak Acked-by: Jonathan Toppins Acked-by: Jay Vosburgh Signed-off-by: David S. Miller --- .../selftests/drivers/net/bonding/Makefile | 3 +- .../net/bonding/bond-eth-type-change.sh | 85 +++++++++++++++++++ 2 files changed, 87 insertions(+), 1 deletion(-) create mode 100755 tools/testing/selftests/drivers/net/bonding/bond-eth-type-change.sh diff --git a/tools/testing/selftests/drivers/net/bonding/Makefile b/tools/testing/selftests/drivers/net/bonding/Makefile index 8e3b786a748f9..a39bb2560d9bf 100644 --- a/tools/testing/selftests/drivers/net/bonding/Makefile +++ b/tools/testing/selftests/drivers/net/bonding/Makefile @@ -8,7 +8,8 @@ TEST_PROGS := \ dev_addr_lists.sh \ mode-1-recovery-updelay.sh \ mode-2-recovery-updelay.sh \ - option_prio.sh + option_prio.sh \ + bond-eth-type-change.sh TEST_FILES := \ lag_lib.sh \ diff --git a/tools/testing/selftests/drivers/net/bonding/bond-eth-type-change.sh b/tools/testing/selftests/drivers/net/bonding/bond-eth-type-change.sh new file mode 100755 index 0000000000000..5cdd22048ba70 --- /dev/null +++ b/tools/testing/selftests/drivers/net/bonding/bond-eth-type-change.sh @@ -0,0 +1,85 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# +# Test bond device ether type changing +# + +ALL_TESTS=" + bond_test_unsuccessful_enslave_type_change + bond_test_successful_enslave_type_change +" +REQUIRE_MZ=no +NUM_NETIFS=0 +lib_dir=$(dirname "$0") +source "$lib_dir"/net_forwarding_lib.sh + +bond_check_flags() +{ + local bonddev=$1 + + ip -d l sh dev "$bonddev" | grep -q "MASTER" + check_err $? "MASTER flag is missing from the bond device" + + ip -d l sh dev "$bonddev" | grep -q "SLAVE" + check_err $? "SLAVE flag is missing from the bond device" +} + +# test enslaved bond dev type change from ARPHRD_ETHER and back +# this allows us to test both MASTER and SLAVE flags at once +bond_test_enslave_type_change() +{ + local test_success=$1 + local devbond0="test-bond0" + local devbond1="test-bond1" + local devbond2="test-bond2" + local nonethdev="test-noneth0" + + # create a non-ARPHRD_ETHER device for testing (e.g. nlmon type) + ip link add name "$nonethdev" type nlmon + check_err $? "could not create a non-ARPHRD_ETHER device (nlmon)" + ip link add name "$devbond0" type bond + if [ $test_success -eq 1 ]; then + # we need devbond0 in active-backup mode to successfully enslave nonethdev + ip link set dev "$devbond0" type bond mode active-backup + check_err $? "could not change bond mode to active-backup" + fi + ip link add name "$devbond1" type bond + ip link add name "$devbond2" type bond + ip link set dev "$devbond0" master "$devbond1" + check_err $? "could not enslave $devbond0 to $devbond1" + # change bond type to non-ARPHRD_ETHER + ip link set dev "$nonethdev" master "$devbond0" 1>/dev/null 2>/dev/null + ip link set dev "$nonethdev" nomaster 1>/dev/null 2>/dev/null + # restore ARPHRD_ETHER type by enslaving such device + ip link set dev "$devbond2" master "$devbond0" + check_err $? "could not enslave $devbond2 to $devbond0" + ip link set dev "$devbond1" nomaster + + bond_check_flags "$devbond0" + + # clean up + ip link del dev "$devbond0" + ip link del dev "$devbond1" + ip link del dev "$devbond2" + ip link del dev "$nonethdev" +} + +bond_test_unsuccessful_enslave_type_change() +{ + RET=0 + + bond_test_enslave_type_change 0 + log_test "Change ether type of an enslaved bond device with unsuccessful enslave" +} + +bond_test_successful_enslave_type_change() +{ + RET=0 + + bond_test_enslave_type_change 1 + log_test "Change ether type of an enslaved bond device with successful enslave" +} + +tests_run + +exit "$EXIT_STATUS" From 884a1f956179b561e7e7f1d29fc331cf53233c89 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Thu, 13 Oct 2022 12:42:29 +0200 Subject: [PATCH 454/460] tools/power turbostat: update dump of SECONDARY_TURBO_RATIO_LIMIT cosmetic only (but useful if you copy/paste) Signed-off-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index aba460410dbd1..7ae3086c5ec0c 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -2538,7 +2538,7 @@ static void dump_turbo_ratio_limits(int trl_msr_offset, int family, int model) get_msr(base_cpu, trl_msr_offset, &msr); fprintf(outf, "cpu%d: MSR_%sTURBO_RATIO_LIMIT: 0x%08llx\n", - base_cpu, trl_msr_offset == MSR_SECONDARY_TURBO_RATIO_LIMIT ? "SECONDARY" : "", msr); + base_cpu, trl_msr_offset == MSR_SECONDARY_TURBO_RATIO_LIMIT ? "SECONDARY_" : "", msr); if (has_turbo_ratio_group_limits(family, model)) { get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT1, &core_counts); From 9c08581728ccadc6b9e4135b7b8d31948e814f6f Mon Sep 17 00:00:00 2001 From: Prarit Bhargava Date: Tue, 18 Oct 2022 15:23:37 -0400 Subject: [PATCH 455/460] tools/power turbostat: Provide better debug messages for failed capabilities accesses turbostat reports some capabilities access errors and not others. Provide the same debug message for all errors. [lenb: remove extra quotes] Cc: David Arcari Signed-off-by: Prarit Bhargava Signed-off-by: Len Brown --- tools/power/x86/turbostat/turbostat.8 | 2 +- tools/power/x86/turbostat/turbostat.c | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tools/power/x86/turbostat/turbostat.8 b/tools/power/x86/turbostat/turbostat.8 index c7b26a3603afe..7dcb4f4f3d55a 100644 --- a/tools/power/x86/turbostat/turbostat.8 +++ b/tools/power/x86/turbostat/turbostat.8 @@ -340,7 +340,7 @@ starts a new interval. must be run as root. Alternatively, non-root users can be enabled to run turbostat this way: -# setcap cap_sys_admin,cap_sys_rawio,cap_sys_nice=+ep ./turbostat +# setcap cap_sys_admin,cap_sys_rawio,cap_sys_nice=+ep path/to/turbostat # chmod +r /dev/cpu/*/msr diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 7ae3086c5ec0c..d246ef6153dc9 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -670,7 +670,8 @@ static int perf_instr_count_open(int cpu_num) /* counter for cpu_num, including user + kernel and all processes */ fd = perf_event_open(&pea, -1, cpu_num, -1, 0); if (fd == -1) { - warn("cpu%d: perf instruction counter", cpu_num); + warnx("capget(CAP_PERFMON) failed, try \"# setcap cap_sys_admin=ep %s\"", + progname); BIC_NOT_PRESENT(BIC_IPC); } @@ -3502,9 +3503,6 @@ void msr_sum_record(void) /* * set_my_sched_priority(pri) * return previous - * - * if non-root, do this: - * # /sbin/setcap cap_sys_rawio,cap_sys_nice=+ep /usr/bin/turbostat */ int set_my_sched_priority(int priority) { @@ -3518,7 +3516,8 @@ int set_my_sched_priority(int priority) retval = setpriority(PRIO_PROCESS, 0, priority); if (retval) - err(retval, "setpriority(%d)", priority); + errx(retval, "capget(CAP_SYS_NICE) failed,try \"# setcap cap_sys_nice=ep %s\"", + progname); errno = 0; retval = getpriority(PRIO_PROCESS, 0); @@ -5476,7 +5475,8 @@ void print_dev_latency(void) fd = open(path, O_RDONLY); if (fd < 0) { - warn("fopen %s\n", path); + warnx("capget(CAP_SYS_ADMIN) failed, try \"# setcap cap_sys_admin=ep %s\"", + progname); return; } From 40aafc7d58d3544f152a863a0e9863014b6d5d8c Mon Sep 17 00:00:00 2001 From: Prarit Bhargava Date: Thu, 15 Dec 2022 10:18:16 -0500 Subject: [PATCH 456/460] tools/power turbostat: Fix /dev/cpu_dma_latency warnings When running as non-root the following error is seen in turbostat: turbostat: fopen /dev/cpu_dma_latency : Permission denied turbostat and the man page have information on how to avoid other permission errors, so these can be fixed the same way. Provide better /dev/cpu_dma_latency warnings that provide instructions on how to avoid the error, and update the man page. Signed-off-by: Prarit Bhargava Cc: linux-pm@vger.kernel.org Signed-off-by: Len Brown --- tools/power/x86/turbostat/turbostat.8 | 2 ++ tools/power/x86/turbostat/turbostat.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/power/x86/turbostat/turbostat.8 b/tools/power/x86/turbostat/turbostat.8 index 7dcb4f4f3d55a..8f08c3fd498d5 100644 --- a/tools/power/x86/turbostat/turbostat.8 +++ b/tools/power/x86/turbostat/turbostat.8 @@ -344,6 +344,8 @@ Alternatively, non-root users can be enabled to run turbostat this way: # chmod +r /dev/cpu/*/msr +# chmod +r /dev/cpu_dma_latency + .B "turbostat " reads hardware counters, but doesn't write them. So it will not interfere with the OS or other programs, including diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index d246ef6153dc9..9aed2620a2d2d 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -5482,7 +5482,7 @@ void print_dev_latency(void) retval = read(fd, (void *)&value, sizeof(int)); if (retval != sizeof(int)) { - warn("read %s\n", path); + warn("read failed %s\n", path); close(fd); return; } From 6cbfedc7afc93a7f06d4a2f7c4d4732b20adfc2b Mon Sep 17 00:00:00 2001 From: Len Brown Date: Fri, 17 Mar 2023 11:25:56 -0400 Subject: [PATCH 457/460] tools/power turbostat: remove stray newlines from warn/warnx strings warn(3) terminates strings with newlines Signed-off-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 9aed2620a2d2d..649b48e53a310 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -5482,7 +5482,7 @@ void print_dev_latency(void) retval = read(fd, (void *)&value, sizeof(int)); if (retval != sizeof(int)) { - warn("read failed %s\n", path); + warn("read failed %s", path); close(fd); return; } @@ -5543,7 +5543,7 @@ void process_cpuid() edx_flags = edx; if (get_msr(sched_getcpu(), MSR_IA32_UCODE_REV, &ucode_patch)) - warnx("get_msr(UCODE)\n"); + warnx("get_msr(UCODE)"); /* * check max extended function levels of CPUID. From 93cac4150727dae0ee89f501dd75413b88eedec0 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Wed, 4 Jan 2023 22:23:53 +0800 Subject: [PATCH 458/460] tools/power turbostat: Introduce support for EMR Introduce support for EMR. Signed-off-by: Zhang Rui Reviewed-by: Artem Bityutskiy Tested-by: Artem Bityutskiy Signed-off-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 649b48e53a310..eba8a20a4b009 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -5462,6 +5462,9 @@ unsigned int intel_model_duplicates(unsigned int model) case INTEL_FAM6_ICELAKE_D: return INTEL_FAM6_ICELAKE_X; + + case INTEL_FAM6_EMERALDRAPIDS_X: + return INTEL_FAM6_SAPPHIRERAPIDS_X; } return model; } From 92c25393586ac799b9b7d9e50434f3c44a7622c4 Mon Sep 17 00:00:00 2001 From: Antti Laakso Date: Wed, 25 Jan 2023 15:17:50 +0200 Subject: [PATCH 459/460] tools/power turbostat: fix decoding of HWP_STATUS The "excursion to minimum" information is in bit2 in HWP_STATUS MSR. Fix the bitmask used for decoding the register. Signed-off-by: Antti Laakso Reviewed-by: Artem Bityutskiy Signed-off-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index eba8a20a4b009..7424c35fe2091 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -4425,7 +4425,7 @@ int print_hwp(struct thread_data *t, struct core_data *c, struct pkg_data *p) fprintf(outf, "cpu%d: MSR_HWP_STATUS: 0x%08llx " "(%sGuaranteed_Perf_Change, %sExcursion_Min)\n", - cpu, msr, ((msr) & 0x1) ? "" : "No-", ((msr) & 0x2) ? "" : "No-"); + cpu, msr, ((msr) & 0x1) ? "" : "No-", ((msr) & 0x4) ? "" : "No-"); return 0; } From de7839ee02c651335db6bf0af24cf5cac3cc4c72 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Fri, 17 Mar 2023 11:34:10 -0400 Subject: [PATCH 460/460] tools/power turbostat: version 2023.03.17 Happy St. Patrick's Day! Signed-off-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 7424c35fe2091..8a36ba5df9f90 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -3,7 +3,7 @@ * turbostat -- show CPU frequency and C-state residency * on modern Intel and AMD processors. * - * Copyright (c) 2022 Intel Corporation. + * Copyright (c) 2023 Intel Corporation. * Len Brown */ @@ -670,8 +670,7 @@ static int perf_instr_count_open(int cpu_num) /* counter for cpu_num, including user + kernel and all processes */ fd = perf_event_open(&pea, -1, cpu_num, -1, 0); if (fd == -1) { - warnx("capget(CAP_PERFMON) failed, try \"# setcap cap_sys_admin=ep %s\"", - progname); + warnx("capget(CAP_PERFMON) failed, try \"# setcap cap_sys_admin=ep %s\"", progname); BIC_NOT_PRESENT(BIC_IPC); } @@ -3516,8 +3515,7 @@ int set_my_sched_priority(int priority) retval = setpriority(PRIO_PROCESS, 0, priority); if (retval) - errx(retval, "capget(CAP_SYS_NICE) failed,try \"# setcap cap_sys_nice=ep %s\"", - progname); + errx(retval, "capget(CAP_SYS_NICE) failed,try \"# setcap cap_sys_nice=ep %s\"", progname); errno = 0; retval = getpriority(PRIO_PROCESS, 0); @@ -5478,8 +5476,7 @@ void print_dev_latency(void) fd = open(path, O_RDONLY); if (fd < 0) { - warnx("capget(CAP_SYS_ADMIN) failed, try \"# setcap cap_sys_admin=ep %s\"", - progname); + warnx("capget(CAP_SYS_ADMIN) failed, try \"# setcap cap_sys_admin=ep %s\"", progname); return; } @@ -6228,7 +6225,7 @@ int get_and_dump_counters(void) void print_version() { - fprintf(outf, "turbostat version 2022.10.04 - Len Brown \n"); + fprintf(outf, "turbostat version 2023.03.17 - Len Brown \n"); } #define COMMAND_LINE_SIZE 2048