It took a long while to get this done, but I'm finally ready to send the first half of the KASAN stack size patches that I did in response to the kernelci.org warnings.
As before, it's worth mentioning that things are generally worse with gcc-7.0.1 because of the addition of -fsanitize-address-use-after-scope that are not present on kernelci, so my randconfig testing found a lot more than kernelci did.
The main areas are:
- READ_ONCE/WRITE_ONCE cause problems in lots of code - typecheck() causes huge problems in a few places - I'm introducing "noinline_for_kasan" and use it in a lot of places that suffer from inline functions with local variables - netlink, as used in various parts of the kernel - a number of drivers/media drivers - a handful of wireless network drivers - kmemcheck conflicts with -fsanitize-address-use-after-scope
This series lets us add back a stack frame warning for 3072 bytes with -fsanitize-address-use-after-scope, or 2048 bytes without it.
I have a follow-up series that further reduces the stack frame warning limit to 1280 bytes for all 64-bit architectures, and 1536 bytes with basic KASAN support (no -fsanitize-address-use-after-scope). For now, I'm only posting the first half, in order to keep it (barely) reviewable.
Both series are tested with many hundred randconfig builds on both x86 and arm64, which are the only architectures supporting KASAN.
Arnd
[PATCH 01/26] compiler: introduce noinline_for_kasan annotation [PATCH 02/26] rewrite READ_ONCE/WRITE_ONCE [PATCH 03/26] typecheck.h: avoid local variables in typecheck() macro [PATCH 04/26] tty: kbd: reduce stack size with KASAN [PATCH 05/26] netlink: mark nla_put_{u8,u16,u32} noinline_for_kasan [PATCH 06/26] rocker: mark rocker_tlv_put_* functions as [PATCH 07/26] brcmsmac: reduce stack size with KASAN [PATCH 08/26] brcmsmac: make some local variables 'static const' to [PATCH 09/26] brcmsmac: split up wlc_phy_workarounds_nphy [PATCH 10/26] brcmsmac: reindent split functions [PATCH 11/26] rtlwifi: reduce stack usage for KASAN [PATCH 12/26] wl3501_cs: reduce stack size for KASAN [PATCH 13/26] rtl8180: reduce stack size for KASAN [PATCH 14/26] [media] dvb-frontends: reduce stack size in i2c access [PATCH 15/26] [media] tuners: i2c: reduce stack usage for [PATCH 16/26] [media] i2c: adv7604: mark register access as [PATCH 17/26] [media] i2c: ks0127: reduce stack frame size for KASAN [PATCH 18/26] [media] i2c: cx25840: avoid stack overflow with KASAN [PATCH 19/26] [media] r820t: mark register functions as [PATCH 20/26] [media] em28xx: split up em28xx_dvb_init to reduce [PATCH 21/26] drm/bridge: ps8622: reduce stack size for KASAN [PATCH 22/26] drm/i915/gvt: don't overflow the kernel stack with [PATCH 23/26] mtd: cfi: reduce stack size with KASAN [PATCH 24/26] ocfs2: reduce stack size with KASAN [PATCH 25/26] isdn: eicon: mark divascapi incompatible with kasan [PATCH 26/26] kasan: rework Kconfig settings
arch/x86/include/asm/switch_to.h | 2 +- drivers/gpu/drm/bridge/parade-ps8622.c | 2 +- drivers/gpu/drm/i915/gvt/mmio.h | 17 +- drivers/isdn/hardware/eicon/Kconfig | 1 + drivers/media/dvb-frontends/ascot2e.c | 3 +- drivers/media/dvb-frontends/cxd2841er.c | 4 +- drivers/media/dvb-frontends/drx39xyj/drxj.c | 14 +- drivers/media/dvb-frontends/helene.c | 4 +- drivers/media/dvb-frontends/horus3a.c | 2 +- drivers/media/dvb-frontends/itd1000.c | 2 +- drivers/media/dvb-frontends/mt312.c | 2 +- drivers/media/dvb-frontends/si2165.c | 14 +- drivers/media/dvb-frontends/stb0899_drv.c | 2 +- drivers/media/dvb-frontends/stb6100.c | 2 +- drivers/media/dvb-frontends/stv0367.c | 2 +- drivers/media/dvb-frontends/stv090x.c | 2 +- drivers/media/dvb-frontends/stv6110.c | 2 +- drivers/media/dvb-frontends/stv6110x.c | 2 +- drivers/media/dvb-frontends/tda8083.c | 2 +- drivers/media/dvb-frontends/zl10039.c | 2 +- drivers/media/i2c/adv7604.c | 4 +- drivers/media/i2c/cx25840/cx25840-core.c | 4 +- drivers/media/i2c/ks0127.c | 2 +- drivers/media/tuners/r820t.c | 4 +- drivers/media/tuners/tuner-i2c.h | 15 +- drivers/media/usb/em28xx/em28xx-dvb.c | 947 +++++++++++++++++++++------------------ drivers/mtd/chips/cfi_cmdset_0020.c | 8 +- drivers/net/ethernet/rocker/rocker_tlv.h | 24 +- drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c | 1860 +++++++++++++++++++++++++++++++++++++---------------------------------------- drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8225se.c | 4 +- drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.c | 41 +- drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c | 26 +- drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c | 34 +- drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.c | 36 +- drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.c | 38 +- drivers/net/wireless/wl3501_cs.c | 10 +- drivers/tty/vt/keyboard.c | 6 +- fs/ocfs2/cluster/masklog.c | 10 +- fs/ocfs2/cluster/masklog.h | 4 +- fs/overlayfs/util.c | 6 +- include/linux/compiler.h | 58 ++- include/linux/mtd/map.h | 8 +- include/linux/typecheck.h | 7 +- include/net/netlink.h | 36 +- lib/Kconfig.debug | 9 +- lib/Kconfig.kasan | 11 +- lib/Kconfig.kmemcheck | 1 + scripts/Makefile.kasan | 3 + 48 files changed, 1670 insertions(+), 1629 deletions(-)
When CONFIG_KASAN is set, we can run into some code that uses incredible amounts of kernel stack:
drivers/staging/dgnc/dgnc_neo.c:1056:1: error: the frame size of 11112 bytes is larger than 2048 bytes [-Werror=frame-larger-than=] drivers/media/i2c/cx25840/cx25840-core.c:4960:1: error: the frame size of 94000 bytes is larger than 2048 bytes [-Werror=frame-larger-than=] drivers/media/dvb-frontends/stv090x.c:3430:1: error: the frame size of 5312 bytes is larger than 3072 bytes [-Werror=frame-larger-than=]
This happens when a sanitizer uses stack memory each time an inline function gets called. This introduces a new annotation for those functions to make them either 'inline' or 'noinline' dependning on the CONFIG_KASAN symbol.
Signed-off-by: Arnd Bergmann arnd@arndb.de --- include/linux/compiler.h | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/include/linux/compiler.h b/include/linux/compiler.h index f8110051188f..56b90897a459 100644 --- a/include/linux/compiler.h +++ b/include/linux/compiler.h @@ -416,6 +416,17 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s */ #define noinline_for_stack noinline
+/* + * CONFIG_KASAN can lead to extreme stack usage with certain patterns when + * one function gets inlined many times and each instance requires a stack + * ckeck. + */ +#ifdef CONFIG_KASAN +#define noinline_for_kasan noinline __maybe_unused +#else +#define noinline_for_kasan inline +#endif + #ifndef __always_inline #define __always_inline inline #endif
On 03/02/2017 07:38 PM, Arnd Bergmann wrote:
When CONFIG_KASAN is set, we can run into some code that uses incredible amounts of kernel stack:
drivers/staging/dgnc/dgnc_neo.c:1056:1: error: the frame size of 11112 bytes is larger than 2048 bytes [-Werror=frame-larger-than=] drivers/media/i2c/cx25840/cx25840-core.c:4960:1: error: the frame size of 94000 bytes is larger than 2048 bytes [-Werror=frame-larger-than=] drivers/media/dvb-frontends/stv090x.c:3430:1: error: the frame size of 5312 bytes is larger than 3072 bytes [-Werror=frame-larger-than=]
This happens when a sanitizer uses stack memory each time an inline function gets called. This introduces a new annotation for those functions to make them either 'inline' or 'noinline' dependning on the CONFIG_KASAN symbol.
Signed-off-by: Arnd Bergmann arnd@arndb.de
include/linux/compiler.h | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/include/linux/compiler.h b/include/linux/compiler.h index f8110051188f..56b90897a459 100644 --- a/include/linux/compiler.h +++ b/include/linux/compiler.h @@ -416,6 +416,17 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s */ #define noinline_for_stack noinline +/*
- CONFIG_KASAN can lead to extreme stack usage with certain patterns when
- one function gets inlined many times and each instance requires a stack
- ckeck.
- */
+#ifdef CONFIG_KASAN +#define noinline_for_kasan noinline __maybe_unused
noinline_iff_kasan might be a better name. noinline_for_kasan gives the impression that we always noinline function for the sake of kasan, while noinline_iff_kasan clearly indicates that function is noinline only if kasan is used.
+#else +#define noinline_for_kasan inline +#endif
#ifndef __always_inline #define __always_inline inline #endif
On Fri, Mar 3, 2017 at 2:50 PM, Andrey Ryabinin aryabinin@virtuozzo.com wrote:
On 03/02/2017 07:38 PM, Arnd Bergmann wrote:
When CONFIG_KASAN is set, we can run into some code that uses incredible amounts of kernel stack:
drivers/staging/dgnc/dgnc_neo.c:1056:1: error: the frame size of 11112 bytes is larger than 2048 bytes [-Werror=frame-larger-than=] drivers/media/i2c/cx25840/cx25840-core.c:4960:1: error: the frame size of 94000 bytes is larger than 2048 bytes [-Werror=frame-larger-than=] drivers/media/dvb-frontends/stv090x.c:3430:1: error: the frame size of 5312 bytes is larger than 3072 bytes [-Werror=frame-larger-than=]
This happens when a sanitizer uses stack memory each time an inline function gets called. This introduces a new annotation for those functions to make them either 'inline' or 'noinline' dependning on the CONFIG_KASAN symbol.
Signed-off-by: Arnd Bergmann arnd@arndb.de
include/linux/compiler.h | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/include/linux/compiler.h b/include/linux/compiler.h index f8110051188f..56b90897a459 100644 --- a/include/linux/compiler.h +++ b/include/linux/compiler.h @@ -416,6 +416,17 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s */ #define noinline_for_stack noinline
+/*
- CONFIG_KASAN can lead to extreme stack usage with certain patterns when
- one function gets inlined many times and each instance requires a stack
- ckeck.
- */
+#ifdef CONFIG_KASAN +#define noinline_for_kasan noinline __maybe_unused
noinline_iff_kasan might be a better name. noinline_for_kasan gives the impression that we always noinline function for the sake of kasan, while noinline_iff_kasan clearly indicates that function is noinline only if kasan is used.
FWIW we may be facing the same problem with other compiler-based tools, e.g. KMSAN (which isn't there yet). So it might be better to choose a macro name that doesn't use the name "KASAN". E.g. noinline_iff_memtool (or noinline_iff_memory_tool if that's not too long). WDYT?
+#else +#define noinline_for_kasan inline +#endif
#ifndef __always_inline #define __always_inline inline #endif
-- You received this message because you are subscribed to the Google Groups "kasan-dev" group. To unsubscribe from this group and stop receiving emails from it, send an email to kasan-dev+unsubscribe@googlegroups.com. To post to this group, send email to kasan-dev@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/kasan-dev/7e7a62de-3b79-6044-72fa-4ade4189.... For more options, visit https://groups.google.com/d/optout.
On Fri, Mar 3, 2017 at 2:55 PM, Alexander Potapenko glider@google.com wrote:
On Fri, Mar 3, 2017 at 2:50 PM, Andrey Ryabinin aryabinin@virtuozzo.com wrote:
@@ -416,6 +416,17 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s */ #define noinline_for_stack noinline
+/*
- CONFIG_KASAN can lead to extreme stack usage with certain patterns when
- one function gets inlined many times and each instance requires a stack
- ckeck.
- */
+#ifdef CONFIG_KASAN +#define noinline_for_kasan noinline __maybe_unused
noinline_iff_kasan might be a better name. noinline_for_kasan gives the impression that we always noinline function for the sake of kasan, while noinline_iff_kasan clearly indicates that function is noinline only if kasan is used.
Fine with me. I actually tried to come up with a name that implies that the symbol is actually "inline" (or even __always_inline_ without KASAN, but couldn't think of any good name for it.
FWIW we may be facing the same problem with other compiler-based tools, e.g. KMSAN (which isn't there yet). So it might be better to choose a macro name that doesn't use the name "KASAN". E.g. noinline_iff_memtool (or noinline_iff_memory_tool if that's not too long). WDYT?
Would KMSAN also force local variables to be non-overlapping the way that asan-stack=1 and -fsanitize-address-use-after-scope do? As I understood it, KMSAN would add extra code for maintaining the uninit bits, but in an example like this
int f(int *); static inline __attribute__((always_inline)) int g(void) { int i; f(&i); return i; } int f(void) { return g()+g()+g()+g(); }
each of the four copies of 'i' could have the same location on the stack and get marked uninitialized again before calling f(). We only need noinline_for_kasan (whatever we end up calling that) for compiler features that force each instance of 'i' to have its own stack redzone.
Arnd
On Fri, Mar 3, 2017 at 3:30 PM, Arnd Bergmann arnd@arndb.de wrote:
On Fri, Mar 3, 2017 at 2:55 PM, Alexander Potapenko glider@google.com wrote:
On Fri, Mar 3, 2017 at 2:50 PM, Andrey Ryabinin aryabinin@virtuozzo.com wrote:
@@ -416,6 +416,17 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s */ #define noinline_for_stack noinline
+/*
- CONFIG_KASAN can lead to extreme stack usage with certain patterns when
- one function gets inlined many times and each instance requires a stack
- ckeck.
- */
+#ifdef CONFIG_KASAN +#define noinline_for_kasan noinline __maybe_unused
noinline_iff_kasan might be a better name. noinline_for_kasan gives the impression that we always noinline function for the sake of kasan, while noinline_iff_kasan clearly indicates that function is noinline only if kasan is used.
Fine with me. I actually tried to come up with a name that implies that the symbol is actually "inline" (or even __always_inline_ without KASAN, but couldn't think of any good name for it.
FWIW we may be facing the same problem with other compiler-based tools, e.g. KMSAN (which isn't there yet). So it might be better to choose a macro name that doesn't use the name "KASAN". E.g. noinline_iff_memtool (or noinline_iff_memory_tool if that's not too long). WDYT?
Would KMSAN also force local variables to be non-overlapping the way that asan-stack=1 and -fsanitize-address-use-after-scope do? As I understood it, KMSAN would add extra code for maintaining the uninit bits, but in an example like this
The thing is that KMSAN (and other tools that insert heavyweight instrumentation) may cause heavy register spilling which will also blow up the stack frames.
int f(int *); static inline __attribute__((always_inline)) int g(void) { int i; f(&i); return i; } int f(void) { return g()+g()+g()+g(); }
each of the four copies of 'i' could have the same location on the stack and get marked uninitialized again before calling f(). We only need noinline_for_kasan (whatever we end up calling that) for compiler features that force each instance of 'i' to have its own stack redzone.
Arnd
On Fri, Mar 3, 2017 at 3:33 PM, Alexander Potapenko glider@google.com wrote:
On Fri, Mar 3, 2017 at 3:30 PM, Arnd Bergmann arnd@arndb.de wrote:
On Fri, Mar 3, 2017 at 2:55 PM, Alexander Potapenko glider@google.com wrote:
Would KMSAN also force local variables to be non-overlapping the way that asan-stack=1 and -fsanitize-address-use-after-scope do? As I understood it, KMSAN would add extra code for maintaining the uninit bits, but in an example like this
The thing is that KMSAN (and other tools that insert heavyweight instrumentation) may cause heavy register spilling which will also blow up the stack frames.
In that case, I would expect a mostly distinct set of functions to have large stack frames with KMSAN, compared to the ones that need noinline_for_kasan. In most cases I patched, the called inline function is actually trivial, but invoked many times from the same caller.
Arnd
From: Andrey Ryabinin
Sent: 03 March 2017 13:50
...
noinline_iff_kasan might be a better name. noinline_for_kasan gives the impression that we always noinline function for the sake of kasan, while noinline_iff_kasan clearly indicates that function is noinline only if kasan is used.
noinline_if_stackbloat
David
When CONFIG_KASAN is enabled, the READ_ONCE/WRITE_ONCE macros cause rather large kernel stacks, e.g.:
mm/vmscan.c: In function 'shrink_page_list': mm/vmscan.c:1333:1: error: the frame size of 3456 bytes is larger than 3072 bytes [-Werror=frame-larger-than=] block/cfq-iosched.c: In function 'cfqg_stats_add_aux': block/cfq-iosched.c:750:1: error: the frame size of 4048 bytes is larger than 3072 bytes [-Werror=frame-larger-than=] fs/btrfs/disk-io.c: In function 'open_ctree': fs/btrfs/disk-io.c:3314:1: error: the frame size of 3136 bytes is larger than 3072 bytes [-Werror=frame-larger-than=] fs/btrfs/relocation.c: In function 'build_backref_tree': fs/btrfs/relocation.c:1193:1: error: the frame size of 4336 bytes is larger than 3072 bytes [-Werror=frame-larger-than=] fs/fscache/stats.c: In function 'fscache_stats_show': fs/fscache/stats.c:287:1: error: the frame size of 6512 bytes is larger than 3072 bytes [-Werror=frame-larger-than=] fs/jbd2/commit.c: In function 'jbd2_journal_commit_transaction': fs/jbd2/commit.c:1139:1: error: the frame size of 3760 bytes is larger than 3072 bytes [-Werror=frame-larger-than=]
This attempts a rewrite of the two macros, using a simpler implementation for the most common case of having a naturally aligned 1, 2, 4, or (on 64-bit architectures) 8 byte object that can be accessed with a single instruction. For these, we go back to a volatile pointer dereference that we had with the ACCESS_ONCE macro.
READ_ONCE/WRITE_ONCE also try to handle unaligned objects and objects of other sizes by forcing either a word-size access (which may trap on some architectures) or doing a non-atomic memcpy. I could not figure out what these are actually used for, but they appear to be done intentionally, so I'm leaving that code untouched.
I had to fix up a couple of files that either use WRITE_ONCE() as an implicit typecast, or ignore the result of READ_ONCE(). In all cases, the modified code seems no worse to me than the original.
Cc: Christian Borntraeger borntraeger@de.ibm.com Cc: Paul McKenney paulmck@linux.vnet.ibm.com Signed-off-by: Arnd Bergmann arnd@arndb.de --- arch/x86/include/asm/switch_to.h | 2 +- fs/overlayfs/util.c | 6 ++--- include/linux/compiler.h | 47 ++++++++++++++++++++++++++++++++-------- 3 files changed, 42 insertions(+), 13 deletions(-)
diff --git a/arch/x86/include/asm/switch_to.h b/arch/x86/include/asm/switch_to.h index fcc5cd387fd1..0c243dd569fe 100644 --- a/arch/x86/include/asm/switch_to.h +++ b/arch/x86/include/asm/switch_to.h @@ -30,7 +30,7 @@ static inline void prepare_switch_to(struct task_struct *prev, * * To minimize cache pollution, just follow the stack pointer. */ - READ_ONCE(*(unsigned char *)next->thread.sp); + (void)READ_ONCE(*(unsigned char *)next->thread.sp); #endif }
diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c index 952286f4826c..1c10632a48bb 100644 --- a/fs/overlayfs/util.c +++ b/fs/overlayfs/util.c @@ -222,8 +222,8 @@ void ovl_dentry_update(struct dentry *dentry, struct dentry *upperdentry)
void ovl_inode_init(struct inode *inode, struct inode *realinode, bool is_upper) { - WRITE_ONCE(inode->i_private, (unsigned long) realinode | - (is_upper ? OVL_ISUPPER_MASK : 0)); + WRITE_ONCE(inode->i_private, (void *)((unsigned long) realinode | + (is_upper ? OVL_ISUPPER_MASK : 0))); }
void ovl_inode_update(struct inode *inode, struct inode *upperinode) @@ -231,7 +231,7 @@ void ovl_inode_update(struct inode *inode, struct inode *upperinode) WARN_ON(!upperinode); WARN_ON(!inode_unhashed(inode)); WRITE_ONCE(inode->i_private, - (unsigned long) upperinode | OVL_ISUPPER_MASK); + (void *)((unsigned long) upperinode | OVL_ISUPPER_MASK)); if (!S_ISDIR(upperinode->i_mode)) __insert_inode_hash(inode, (unsigned long) upperinode); } diff --git a/include/linux/compiler.h b/include/linux/compiler.h index 56b90897a459..b619f5853af8 100644 --- a/include/linux/compiler.h +++ b/include/linux/compiler.h @@ -288,6 +288,10 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s } }
+#define __ALIGNED_WORD(x) \ + ((sizeof(x) == 1 || sizeof(x) == 2 || sizeof(x) == 4 || \ + sizeof(x) == sizeof(long)) && (sizeof(x) == __alignof__(x))) \ + /* * Prevent the compiler from merging or refetching reads or writes. The * compiler is also forbidden from reordering successive instances of @@ -309,8 +313,13 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s * mutilate accesses that either do not require ordering or that interact * with an explicit memory barrier or atomic instruction that provides the * required ordering. + * + * Unaligned data is particularly tricky here: if the type that gets + * passed in is not naturally aligned, we cast to a type of higher + * alignment, which is not well-defined in C. This is fine as long + * as the actual data is aligned, but otherwise might require a trap + * to satisfy the load. */ - #define __READ_ONCE(x, check) \ ({ \ union { typeof(x) __val; char __c[1]; } __u; \ @@ -320,7 +329,32 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s __read_once_size_nocheck(&(x), __u.__c, sizeof(x)); \ __u.__val; \ }) -#define READ_ONCE(x) __READ_ONCE(x, 1) + +#define __WRITE_ONCE(x, val) \ +({ \ + union { typeof(x) __val; char __c[1]; } __u = \ + { .__val = (__force typeof(x)) (val) }; \ + __write_once_size(&(x), __u.__c, sizeof(x)); \ + __u.__val; \ +}) + + +/* + * the common case is simple: x is naturally aligned, not an array, + * and accessible with a single load, avoiding the need for local + * variables. With KASAN, this is important as any call to + *__write_once_size(),__read_once_size_nocheck() or __read_once_size() + * uses significant amounts of stack space for checking that we don't + * overflow the union. + */ +#define __READ_ONCE_SIMPLE(x) \ + (typeof(x))(*(volatile typeof(&(x)))&(x)) + +#define __WRITE_ONCE_SIMPLE(x, val) \ + ({*(volatile typeof(&(x)))&(x) = (val); }) + +#define READ_ONCE(x) __builtin_choose_expr(__ALIGNED_WORD(x), \ + __READ_ONCE_SIMPLE(x), __READ_ONCE(x, 1))
/* * Use READ_ONCE_NOCHECK() instead of READ_ONCE() if you need @@ -328,13 +362,8 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s */ #define READ_ONCE_NOCHECK(x) __READ_ONCE(x, 0)
-#define WRITE_ONCE(x, val) \ -({ \ - union { typeof(x) __val; char __c[1]; } __u = \ - { .__val = (__force typeof(x)) (val) }; \ - __write_once_size(&(x), __u.__c, sizeof(x)); \ - __u.__val; \ -}) +#define WRITE_ONCE(x, val) do { __builtin_choose_expr(__ALIGNED_WORD(x), \ + __WRITE_ONCE_SIMPLE(x, val), __WRITE_ONCE(x, val)); } while (0)
#endif /* __KERNEL__ */
On 03/02/2017 05:38 PM, Arnd Bergmann wrote:
When CONFIG_KASAN is enabled, the READ_ONCE/WRITE_ONCE macros cause rather large kernel stacks, e.g.:
mm/vmscan.c: In function 'shrink_page_list': mm/vmscan.c:1333:1: error: the frame size of 3456 bytes is larger than 3072 bytes [-Werror=frame-larger-than=] block/cfq-iosched.c: In function 'cfqg_stats_add_aux': block/cfq-iosched.c:750:1: error: the frame size of 4048 bytes is larger than 3072 bytes [-Werror=frame-larger-than=] fs/btrfs/disk-io.c: In function 'open_ctree': fs/btrfs/disk-io.c:3314:1: error: the frame size of 3136 bytes is larger than 3072 bytes [-Werror=frame-larger-than=] fs/btrfs/relocation.c: In function 'build_backref_tree': fs/btrfs/relocation.c:1193:1: error: the frame size of 4336 bytes is larger than 3072 bytes [-Werror=frame-larger-than=] fs/fscache/stats.c: In function 'fscache_stats_show': fs/fscache/stats.c:287:1: error: the frame size of 6512 bytes is larger than 3072 bytes [-Werror=frame-larger-than=] fs/jbd2/commit.c: In function 'jbd2_journal_commit_transaction': fs/jbd2/commit.c:1139:1: error: the frame size of 3760 bytes is larger than 3072 bytes [-Werror=frame-larger-than=]
This attempts a rewrite of the two macros, using a simpler implementation for the most common case of having a naturally aligned 1, 2, 4, or (on 64-bit architectures) 8 byte object that can be accessed with a single instruction. For these, we go back to a volatile pointer dereference that we had with the ACCESS_ONCE macro.
We had changed that back then because gcc 4.6 and 4.7 had a bug that could removed the volatile statement on aggregate types like the following one
union ipte_control { unsigned long val; struct { unsigned long k : 1; unsigned long kh : 31; unsigned long kg : 32; }; };
See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58145
If I see that right, your __ALIGNED_WORD(x) macro would say that for above structure sizeof(x) == sizeof(long)) is true, so it would fall back to the old volatile cast and might reintroduce the old compiler bug?
Could you maybe you fence your simple macro for anything older than 4.9? After all there was no kasan support anyway on these older gcc version.
Christian
On Thu, Mar 2, 2017 at 5:51 PM, Christian Borntraeger borntraeger@de.ibm.com wrote:
On 03/02/2017 05:38 PM, Arnd Bergmann wrote:
This attempts a rewrite of the two macros, using a simpler implementation for the most common case of having a naturally aligned 1, 2, 4, or (on 64-bit architectures) 8 byte object that can be accessed with a single instruction. For these, we go back to a volatile pointer dereference that we had with the ACCESS_ONCE macro.
We had changed that back then because gcc 4.6 and 4.7 had a bug that could removed the volatile statement on aggregate types like the following one
union ipte_control { unsigned long val; struct { unsigned long k : 1; unsigned long kh : 31; unsigned long kg : 32; }; };
See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58145
If I see that right, your __ALIGNED_WORD(x) macro would say that for above structure sizeof(x) == sizeof(long)) is true, so it would fall back to the old volatile cast and might reintroduce the old compiler bug?
Ah, right, that's the missing piece. For some reason I didn't find the reference in the source or the git log.
Could you maybe you fence your simple macro for anything older than 4.9? After all there was no kasan support anyway on these older gcc version.
Yes, that should work, thanks!
Arnd
On 03/02/2017 06:55 PM, Arnd Bergmann wrote:
On Thu, Mar 2, 2017 at 5:51 PM, Christian Borntraeger borntraeger@de.ibm.com wrote:
On 03/02/2017 05:38 PM, Arnd Bergmann wrote:
This attempts a rewrite of the two macros, using a simpler implementation for the most common case of having a naturally aligned 1, 2, 4, or (on 64-bit architectures) 8 byte object that can be accessed with a single instruction. For these, we go back to a volatile pointer dereference that we had with the ACCESS_ONCE macro.
We had changed that back then because gcc 4.6 and 4.7 had a bug that could removed the volatile statement on aggregate types like the following one
union ipte_control { unsigned long val; struct { unsigned long k : 1; unsigned long kh : 31; unsigned long kg : 32; }; };
See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58145
If I see that right, your __ALIGNED_WORD(x) macro would say that for above structure sizeof(x) == sizeof(long)) is true, so it would fall back to the old volatile cast and might reintroduce the old compiler bug?
Oh dear, I should double check my sentences in emails before sending...anyway the full story is referenced in
commit 60815cf2e05057db5b78e398d9734c493560b11e Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/borntraeger/linux which has a pointer to http://marc.info/?i=54611D86.4040306%40de.ibm.com which contains the full story.
Ah, right, that's the missing piece. For some reason I didn't find the reference in the source or the git log.
Could you maybe you fence your simple macro for anything older than 4.9? After all there was no kasan support anyway on these older gcc version.
Yes, that should work, thanks!
On Thu, Mar 2, 2017 at 8:00 PM, Christian Borntraeger borntraeger@de.ibm.com wrote:
On 03/02/2017 06:55 PM, Arnd Bergmann wrote:
On Thu, Mar 2, 2017 at 5:51 PM, Christian Borntraeger borntraeger@de.ibm.com wrote:
On 03/02/2017 05:38 PM, Arnd Bergmann wrote:
This attempts a rewrite of the two macros, using a simpler implementation for the most common case of having a naturally aligned 1, 2, 4, or (on 64-bit architectures) 8 byte object that can be accessed with a single instruction. For these, we go back to a volatile pointer dereference that we had with the ACCESS_ONCE macro.
We had changed that back then because gcc 4.6 and 4.7 had a bug that could removed the volatile statement on aggregate types like the following one
union ipte_control { unsigned long val; struct { unsigned long k : 1; unsigned long kh : 31; unsigned long kg : 32; }; };
See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58145
If I see that right, your __ALIGNED_WORD(x) macro would say that for above structure sizeof(x) == sizeof(long)) is true, so it would fall back to the old volatile cast and might reintroduce the old compiler bug?
Oh dear, I should double check my sentences in emails before sending...anyway the full story is referenced in
commit 60815cf2e05057db5b78e398d9734c493560b11e Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/borntraeger/linux which has a pointer to http://marc.info/?i=54611D86.4040306%40de.ibm.com which contains the full story.
Ok, got it. So I guess the behavior of forcing aligned accesses on aligned data is accidental, and allowing non-power-of-two arguments is also not the main purpose. Maybe we could just bail out on new compilers if we get either of those? That might catch code that accidentally does something that is inherently non-atomic or that causes a trap when the intention was to have a simple atomic access.
Arnd
On 03/02/2017 10:45 PM, Arnd Bergmann wrote:
On Thu, Mar 2, 2017 at 8:00 PM, Christian Borntraeger borntraeger@de.ibm.com wrote:
On 03/02/2017 06:55 PM, Arnd Bergmann wrote:
On Thu, Mar 2, 2017 at 5:51 PM, Christian Borntraeger borntraeger@de.ibm.com wrote:
On 03/02/2017 05:38 PM, Arnd Bergmann wrote:
This attempts a rewrite of the two macros, using a simpler implementation for the most common case of having a naturally aligned 1, 2, 4, or (on 64-bit architectures) 8 byte object that can be accessed with a single instruction. For these, we go back to a volatile pointer dereference that we had with the ACCESS_ONCE macro.
We had changed that back then because gcc 4.6 and 4.7 had a bug that could removed the volatile statement on aggregate types like the following one
union ipte_control { unsigned long val; struct { unsigned long k : 1; unsigned long kh : 31; unsigned long kg : 32; }; };
See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58145
If I see that right, your __ALIGNED_WORD(x) macro would say that for above structure sizeof(x) == sizeof(long)) is true, so it would fall back to the old volatile cast and might reintroduce the old compiler bug?
Oh dear, I should double check my sentences in emails before sending...anyway the full story is referenced in
commit 60815cf2e05057db5b78e398d9734c493560b11e Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/borntraeger/linux which has a pointer to http://marc.info/?i=54611D86.4040306%40de.ibm.com which contains the full story.
Ok, got it. So I guess the behavior of forcing aligned accesses on aligned data is accidental, and allowing non-power-of-two arguments is also not the main purpose.
Right. The main purpose is to read/write _ONCE_. You can assume a somewhat atomic access for sizes <= word size. And there are certainly places that rely on that. But the *ONCE thing is mostly used for things where we used barrier() 10 years ago.
Maybe we could just bail out on new compilers if we get
either of those? That might catch code that accidentally does something that is inherently non-atomic or that causes a trap when the intention was to have a simple atomic access.
I think Linus stated that its ok to assume that the compiler is smart enough to uses a single instruction to access aligned and properly sized scalar types for *ONCE.
Back then when I changed ACCESS_ONCE there were many places that did use it for non-atomic, > word size accesses. For example on some architectures a pmd_t is a typedef to an array, for which there is no way to read that atomically. So the focus must be on the "ONCE" part.
If some code uses a properly aligned, word sized object we can also assume atomic access. If the access is not properly sized/aligned we do not get atomicity, but we do get the "ONCE". But adding a check for alignment/size would break the compilation of some code.
On Fri, Mar 3, 2017 at 9:26 AM, Christian Borntraeger borntraeger@de.ibm.com wrote:
On 03/02/2017 10:45 PM, Arnd Bergmann wrote:
Ok, got it. So I guess the behavior of forcing aligned accesses on aligned data is accidental, and allowing non-power-of-two arguments is also not the main purpose.
Right. The main purpose is to read/write _ONCE_. You can assume a somewhat atomic access for sizes <= word size. And there are certainly places that rely on that. But the *ONCE thing is mostly used for things where we used barrier() 10 years ago.
Ok
Maybe we could just bail out on new compilers if we get
either of those? That might catch code that accidentally does something that is inherently non-atomic or that causes a trap when the intention was to have a simple atomic access.
I think Linus stated that its ok to assume that the compiler is smart enough to uses a single instruction to access aligned and properly sized scalar types for *ONCE.
Back then when I changed ACCESS_ONCE there were many places that did use it for non-atomic, > word size accesses. For example on some architectures a pmd_t is a typedef to an array, for which there is no way to read that atomically. So the focus must be on the "ONCE" part.
If some code uses a properly aligned, word sized object we can also assume atomic access. If the access is not properly sized/aligned we do not get atomicity, but we do get the "ONCE". But adding a check for alignment/size would break the compilation of some code.
So what should be the expected behavior for objects that have a smaller alignment? E.g. this structure
struct fourbytes { char bytes[4]; } __packed;
when passed into the current READ_ONCE() will be accessed with a 32-bit load, while reading it with
struct fourbytes local = *(volatile struct fourbytes *)voidpointer;
on architectures like ARMv5 or lower will turn into four single-byte reads to avoid an alignment trap when the pointer is actually unaligned.
I can see arguments for and against either behavior, but what should I do when modifying it for newer compilers? The possible options that I see are
- keep assuming that the pointer will be aligned at runtime and doesn't trap - use the regular gcc behavior and do byte-accesses on those architectures that otherwise might trap - add a runtime alignment check to do atomic accesses whenever possible, but never trap - fail the build
Arnd
On Fri, Mar 03, 2017 at 09:26:50AM +0100, Christian Borntraeger wrote:
Right. The main purpose is to read/write _ONCE_. You can assume a somewhat atomic access for sizes <= word size. And there are certainly places that rely on that. But the *ONCE thing is mostly used for things where we used barrier() 10 years ago.
A lot of code relies on READ/WRITE_ONCE() to generate single instructions for naturally aligned machined word sized loads/stores (something GCC used to guarantee, but does no longer IIRC).
So much so that I would say its a bug if READ/WRITE_ONCE() doesn't generate a single instruction under those conditions.
However, every time I've tried to introduce stricter semantics/primitives to verify things Linus hated it.
On Fri, Mar 03, 2017 at 03:49:38PM +0100, Peter Zijlstra wrote:
On Fri, Mar 03, 2017 at 09:26:50AM +0100, Christian Borntraeger wrote:
Right. The main purpose is to read/write _ONCE_. You can assume a somewhat atomic access for sizes <= word size. And there are certainly places that rely on that. But the *ONCE thing is mostly used for things where we used barrier() 10 years ago.
A lot of code relies on READ/WRITE_ONCE() to generate single instructions for naturally aligned machined word sized loads/stores (something GCC used to guarantee, but does no longer IIRC).
So much so that I would say its a bug if READ/WRITE_ONCE() doesn't generate a single instruction under those conditions.
However, every time I've tried to introduce stricter semantics/primitives to verify things Linus hated it.
See here for the last attempt:
https://marc.info/?l=linux-virtualization&m=148007765918101&w=2
With KASAN enabled, the typecheck macro leads to some serious stack memory, as seen in the rt2xxx drivers:
drivers/net/wireless/ralink/rt2x00/rt2800lib.c: In function 'rt2800_init_registers': drivers/net/wireless/ralink/rt2x00/rt2800lib.c:5068:1: error: the frame size of 23768 bytes is larger than 1024 bytes [-Werror=frame-larger-than=] drivers/net/wireless/ralink/rt2x00/rt2800lib.c: In function 'rt2800_config_txpower_rt3593.isra.1': drivers/net/wireless/ralink/rt2x00/rt2800lib.c:4126:1: error: the frame size of 14184 bytes is larger than 1024 bytes [-Werror=frame-larger-than=] drivers/net/wireless/ralink/rt2x00/rt2800lib.c: In function 'rt2800_config_channel_rf3053.isra.5': drivers/net/wireless/ralink/rt2x00/rt2800lib.c:2585:1: error: the frame size of 7632 bytes is larger than 1024 bytes [-Werror=frame-larger-than=]
If we express the macro in a way that avoids the local variables, this goes away and the stacks are comparable to building without KASAN.
Signed-off-by: Arnd Bergmann arnd@arndb.de --- include/linux/typecheck.h | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-)
diff --git a/include/linux/typecheck.h b/include/linux/typecheck.h index eb5b74a575be..adb1579fa5f0 100644 --- a/include/linux/typecheck.h +++ b/include/linux/typecheck.h @@ -5,12 +5,7 @@ * Check at compile time that something is of a particular type. * Always evaluates to 1 so you may use it easily in comparisons. */ -#define typecheck(type,x) \ -({ type __dummy; \ - typeof(x) __dummy2; \ - (void)(&__dummy == &__dummy2); \ - 1; \ -}) +#define typecheck(type,x) ({(void)((typeof(type) *)NULL == (typeof(x) *)NULL); 1;})
/* * Check at compile time that 'function' is a certain type, or is a pointer
As reported by kernelci, some functions in the VT code use significant amounts of kernel stack when local variables get inlined into the caller multiple times:
drivers/tty/vt/keyboard.c: In function 'kbd_keycode': drivers/tty/vt/keyboard.c:1452:1: error: the frame size of 2240 bytes is larger than 2048 bytes [-Werror=frame-larger-than=]
Annotating those functions as noinline_for_kasan prevents the inlining and reduces the overall stack usage in this driver.
Signed-off-by: Arnd Bergmann arnd@arndb.de --- drivers/tty/vt/keyboard.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c index 397e1509fe51..f8a183c1639f 100644 --- a/drivers/tty/vt/keyboard.c +++ b/drivers/tty/vt/keyboard.c @@ -300,13 +300,13 @@ int kbd_rate(struct kbd_repeat *rpt) /* * Helper Functions. */ -static void put_queue(struct vc_data *vc, int ch) +static noinline_for_kasan void put_queue(struct vc_data *vc, int ch) { tty_insert_flip_char(&vc->port, ch, 0); tty_schedule_flip(&vc->port); }
-static void puts_queue(struct vc_data *vc, char *cp) +static noinline_for_kasan void puts_queue(struct vc_data *vc, char *cp) { while (*cp) { tty_insert_flip_char(&vc->port, *cp, 0); @@ -554,7 +554,7 @@ static void fn_inc_console(struct vc_data *vc) set_console(i); }
-static void fn_send_intr(struct vc_data *vc) +static noinline_for_kasan void fn_send_intr(struct vc_data *vc) { tty_insert_flip_char(&vc->port, 0, TTY_BREAK); tty_schedule_flip(&vc->port);
When CONFIG_KASAN is enabled, the "--param asan-stack=1" causes rather large stack frames in some functions. This goes unnoticed normally because CONFIG_FRAME_WARN is disabled with CONFIG_KASAN by default as of commit 3f181b4d8652 ("lib/Kconfig.debug: disable -Wframe-larger-than warnings with KASAN=y").
The kernelci.org build bot however has the warning enabled and that led me to investigate it a little further, as every build produces these warnings:
net/wireless/nl80211.c:4389:1: warning: the frame size of 2240 bytes is larger than 2048 bytes [-Wframe-larger-than=] net/wireless/nl80211.c:1895:1: warning: the frame size of 3776 bytes is larger than 2048 bytes [-Wframe-larger-than=] net/wireless/nl80211.c:1410:1: warning: the frame size of 2208 bytes is larger than 2048 bytes [-Wframe-larger-than=] net/bridge/br_netlink.c:1282:1: warning: the frame size of 2544 bytes is larger than 2048 bytes [-Wframe-larger-than=]
With the new noinline_for_kasan annotation, we can avoid the problem when KASAN is enabled but not change anything otherwise.
Cc: Andrey Ryabinin aryabinin@virtuozzo.com Cc: Alexander Potapenko glider@google.com Cc: Dmitry Vyukov dvyukov@google.com Cc: kasan-dev@googlegroups.com Signed-off-by: Arnd Bergmann arnd@arndb.de --- include/net/netlink.h | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-)
diff --git a/include/net/netlink.h b/include/net/netlink.h index b239fcd33d80..d84878d8347f 100644 --- a/include/net/netlink.h +++ b/include/net/netlink.h @@ -755,7 +755,7 @@ static inline int nla_parse_nested(struct nlattr *tb[], int maxtype, * @attrtype: attribute type * @value: numeric value */ -static inline int nla_put_u8(struct sk_buff *skb, int attrtype, u8 value) +static noinline_for_kasan int nla_put_u8(struct sk_buff *skb, int attrtype, u8 value) { return nla_put(skb, attrtype, sizeof(u8), &value); } @@ -766,7 +766,7 @@ static inline int nla_put_u8(struct sk_buff *skb, int attrtype, u8 value) * @attrtype: attribute type * @value: numeric value */ -static inline int nla_put_u16(struct sk_buff *skb, int attrtype, u16 value) +static noinline_for_kasan int nla_put_u16(struct sk_buff *skb, int attrtype, u16 value) { return nla_put(skb, attrtype, sizeof(u16), &value); } @@ -777,7 +777,7 @@ static inline int nla_put_u16(struct sk_buff *skb, int attrtype, u16 value) * @attrtype: attribute type * @value: numeric value */ -static inline int nla_put_be16(struct sk_buff *skb, int attrtype, __be16 value) +static noinline_for_kasan int nla_put_be16(struct sk_buff *skb, int attrtype, __be16 value) { return nla_put(skb, attrtype, sizeof(__be16), &value); } @@ -788,7 +788,7 @@ static inline int nla_put_be16(struct sk_buff *skb, int attrtype, __be16 value) * @attrtype: attribute type * @value: numeric value */ -static inline int nla_put_net16(struct sk_buff *skb, int attrtype, __be16 value) +static noinline_for_kasan int nla_put_net16(struct sk_buff *skb, int attrtype, __be16 value) { return nla_put_be16(skb, attrtype | NLA_F_NET_BYTEORDER, value); } @@ -799,7 +799,7 @@ static inline int nla_put_net16(struct sk_buff *skb, int attrtype, __be16 value) * @attrtype: attribute type * @value: numeric value */ -static inline int nla_put_le16(struct sk_buff *skb, int attrtype, __le16 value) +static noinline_for_kasan int nla_put_le16(struct sk_buff *skb, int attrtype, __le16 value) { return nla_put(skb, attrtype, sizeof(__le16), &value); } @@ -810,7 +810,7 @@ static inline int nla_put_le16(struct sk_buff *skb, int attrtype, __le16 value) * @attrtype: attribute type * @value: numeric value */ -static inline int nla_put_u32(struct sk_buff *skb, int attrtype, u32 value) +static noinline_for_kasan int nla_put_u32(struct sk_buff *skb, int attrtype, u32 value) { return nla_put(skb, attrtype, sizeof(u32), &value); } @@ -821,7 +821,7 @@ static inline int nla_put_u32(struct sk_buff *skb, int attrtype, u32 value) * @attrtype: attribute type * @value: numeric value */ -static inline int nla_put_be32(struct sk_buff *skb, int attrtype, __be32 value) +static noinline_for_kasan int nla_put_be32(struct sk_buff *skb, int attrtype, __be32 value) { return nla_put(skb, attrtype, sizeof(__be32), &value); } @@ -832,7 +832,7 @@ static inline int nla_put_be32(struct sk_buff *skb, int attrtype, __be32 value) * @attrtype: attribute type * @value: numeric value */ -static inline int nla_put_net32(struct sk_buff *skb, int attrtype, __be32 value) +static noinline_for_kasan int nla_put_net32(struct sk_buff *skb, int attrtype, __be32 value) { return nla_put_be32(skb, attrtype | NLA_F_NET_BYTEORDER, value); } @@ -843,7 +843,7 @@ static inline int nla_put_net32(struct sk_buff *skb, int attrtype, __be32 value) * @attrtype: attribute type * @value: numeric value */ -static inline int nla_put_le32(struct sk_buff *skb, int attrtype, __le32 value) +static noinline_for_kasan int nla_put_le32(struct sk_buff *skb, int attrtype, __le32 value) { return nla_put(skb, attrtype, sizeof(__le32), &value); } @@ -855,7 +855,7 @@ static inline int nla_put_le32(struct sk_buff *skb, int attrtype, __le32 value) * @value: numeric value * @padattr: attribute type for the padding */ -static inline int nla_put_u64_64bit(struct sk_buff *skb, int attrtype, +static noinline_for_kasan int nla_put_u64_64bit(struct sk_buff *skb, int attrtype, u64 value, int padattr) { return nla_put_64bit(skb, attrtype, sizeof(u64), &value, padattr); @@ -868,7 +868,7 @@ static inline int nla_put_u64_64bit(struct sk_buff *skb, int attrtype, * @value: numeric value * @padattr: attribute type for the padding */ -static inline int nla_put_be64(struct sk_buff *skb, int attrtype, __be64 value, +static noinline_for_kasan int nla_put_be64(struct sk_buff *skb, int attrtype, __be64 value, int padattr) { return nla_put_64bit(skb, attrtype, sizeof(__be64), &value, padattr); @@ -881,7 +881,7 @@ static inline int nla_put_be64(struct sk_buff *skb, int attrtype, __be64 value, * @value: numeric value * @padattr: attribute type for the padding */ -static inline int nla_put_net64(struct sk_buff *skb, int attrtype, __be64 value, +static noinline_for_kasan int nla_put_net64(struct sk_buff *skb, int attrtype, __be64 value, int padattr) { return nla_put_be64(skb, attrtype | NLA_F_NET_BYTEORDER, value, @@ -895,7 +895,7 @@ static inline int nla_put_net64(struct sk_buff *skb, int attrtype, __be64 value, * @value: numeric value * @padattr: attribute type for the padding */ -static inline int nla_put_le64(struct sk_buff *skb, int attrtype, __le64 value, +static noinline_for_kasan int nla_put_le64(struct sk_buff *skb, int attrtype, __le64 value, int padattr) { return nla_put_64bit(skb, attrtype, sizeof(__le64), &value, padattr); @@ -907,7 +907,7 @@ static inline int nla_put_le64(struct sk_buff *skb, int attrtype, __le64 value, * @attrtype: attribute type * @value: numeric value */ -static inline int nla_put_s8(struct sk_buff *skb, int attrtype, s8 value) +static noinline_for_kasan int nla_put_s8(struct sk_buff *skb, int attrtype, s8 value) { return nla_put(skb, attrtype, sizeof(s8), &value); } @@ -918,7 +918,7 @@ static inline int nla_put_s8(struct sk_buff *skb, int attrtype, s8 value) * @attrtype: attribute type * @value: numeric value */ -static inline int nla_put_s16(struct sk_buff *skb, int attrtype, s16 value) +static noinline_for_kasan int nla_put_s16(struct sk_buff *skb, int attrtype, s16 value) { return nla_put(skb, attrtype, sizeof(s16), &value); } @@ -929,7 +929,7 @@ static inline int nla_put_s16(struct sk_buff *skb, int attrtype, s16 value) * @attrtype: attribute type * @value: numeric value */ -static inline int nla_put_s32(struct sk_buff *skb, int attrtype, s32 value) +static noinline_for_kasan int nla_put_s32(struct sk_buff *skb, int attrtype, s32 value) { return nla_put(skb, attrtype, sizeof(s32), &value); } @@ -941,7 +941,7 @@ static inline int nla_put_s32(struct sk_buff *skb, int attrtype, s32 value) * @value: numeric value * @padattr: attribute type for the padding */ -static inline int nla_put_s64(struct sk_buff *skb, int attrtype, s64 value, +static noinline_for_kasan int nla_put_s64(struct sk_buff *skb, int attrtype, s64 value, int padattr) { return nla_put_64bit(skb, attrtype, sizeof(s64), &value, padattr); @@ -976,7 +976,7 @@ static inline int nla_put_flag(struct sk_buff *skb, int attrtype) * @njiffies: number of jiffies to convert to msecs * @padattr: attribute type for the padding */ -static inline int nla_put_msecs(struct sk_buff *skb, int attrtype, +static noinline_for_kasan int nla_put_msecs(struct sk_buff *skb, int attrtype, unsigned long njiffies, int padattr) { u64 tmp = jiffies_to_msecs(njiffies);
Inlining these functions creates lots of stack variables when KASAN is enabled, leading to this warning about potential stack overflow:
drivers/net/ethernet/rocker/rocker_ofdpa.c: In function 'ofdpa_cmd_flow_tbl_add': drivers/net/ethernet/rocker/rocker_ofdpa.c:621:1: error: the frame size of 2752 bytes is larger than 1536 bytes [-Werror=frame-larger-than=]
This marks all of them noinline_for_kasan, which solves the problem by keeping the redzone inside of the separate stack frames.
Signed-off-by: Arnd Bergmann arnd@arndb.de --- drivers/net/ethernet/rocker/rocker_tlv.h | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/drivers/net/ethernet/rocker/rocker_tlv.h b/drivers/net/ethernet/rocker/rocker_tlv.h index a63ef82e7c72..3a9573fe0191 100644 --- a/drivers/net/ethernet/rocker/rocker_tlv.h +++ b/drivers/net/ethernet/rocker/rocker_tlv.h @@ -139,38 +139,38 @@ rocker_tlv_start(struct rocker_desc_info *desc_info) int rocker_tlv_put(struct rocker_desc_info *desc_info, int attrtype, int attrlen, const void *data);
-static inline int rocker_tlv_put_u8(struct rocker_desc_info *desc_info, - int attrtype, u8 value) +static noinline_for_kasan int +rocker_tlv_put_u8(struct rocker_desc_info *desc_info, int attrtype, u8 value) { return rocker_tlv_put(desc_info, attrtype, sizeof(u8), &value); }
-static inline int rocker_tlv_put_u16(struct rocker_desc_info *desc_info, - int attrtype, u16 value) +static noinline_for_kasan int +rocker_tlv_put_u16(struct rocker_desc_info *desc_info, int attrtype, u16 value) { return rocker_tlv_put(desc_info, attrtype, sizeof(u16), &value); }
-static inline int rocker_tlv_put_be16(struct rocker_desc_info *desc_info, - int attrtype, __be16 value) +static noinline_for_kasan int +rocker_tlv_put_be16(struct rocker_desc_info *desc_info, int attrtype, __be16 value) { return rocker_tlv_put(desc_info, attrtype, sizeof(__be16), &value); }
-static inline int rocker_tlv_put_u32(struct rocker_desc_info *desc_info, - int attrtype, u32 value) +static noinline_for_kasan int +rocker_tlv_put_u32(struct rocker_desc_info *desc_info, int attrtype, u32 value) { return rocker_tlv_put(desc_info, attrtype, sizeof(u32), &value); }
-static inline int rocker_tlv_put_be32(struct rocker_desc_info *desc_info, - int attrtype, __be32 value) +static noinline_for_kasan int +rocker_tlv_put_be32(struct rocker_desc_info *desc_info, int attrtype, __be32 value) { return rocker_tlv_put(desc_info, attrtype, sizeof(__be32), &value); }
-static inline int rocker_tlv_put_u64(struct rocker_desc_info *desc_info, - int attrtype, u64 value) +static noinline_for_kasan int +rocker_tlv_put_u64(struct rocker_desc_info *desc_info, int attrtype, u64 value) { return rocker_tlv_put(desc_info, attrtype, sizeof(u64), &value); }
The wlc_phy_table_write_nphy/wlc_phy_table_read_nphy functions always put an object on the stack, which will each require a redzone with KASAN and lead to possible stack overflow:
drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c: In function 'wlc_phy_workarounds_nphy': drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c:17135:1: warning: the frame size of 6312 bytes is larger than 1000 bytes [-Wframe-larger-than=]
This marks the two functions as noinline_for_kasan, avoiding the problem entirely.
Signed-off-by: Arnd Bergmann arnd@arndb.de --- drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c index b3aab2fe96eb..42dc8e1f483d 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c @@ -14157,7 +14157,7 @@ static void wlc_phy_bphy_init_nphy(struct brcms_phy *pi) write_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_STEP, 0x668); }
-void +noinline_for_kasan void wlc_phy_table_write_nphy(struct brcms_phy *pi, u32 id, u32 len, u32 offset, u32 width, const void *data) { @@ -14171,7 +14171,7 @@ wlc_phy_table_write_nphy(struct brcms_phy *pi, u32 id, u32 len, u32 offset, wlc_phy_write_table_nphy(pi, &tbl); }
-void +noinline_for_kasan void wlc_phy_table_read_nphy(struct brcms_phy *pi, u32 id, u32 len, u32 offset, u32 width, void *data) {
On 2-3-2017 17:38, Arnd Bergmann wrote:
The wlc_phy_table_write_nphy/wlc_phy_table_read_nphy functions always put an object on the stack, which will each require a redzone with KASAN and lead to possible stack overflow:
drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c: In function 'wlc_phy_workarounds_nphy': drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c:17135:1: warning: the frame size of 6312 bytes is larger than 1000 bytes [-Wframe-larger-than=]
Looks like this warning text ended up in the wrong commit message. Got me confused for a sec :-p
This marks the two functions as noinline_for_kasan, avoiding the problem entirely.
Frankly I seriously dislike annotating code for the sake of some (dynamic) memory analyzer. To me the whole thing seems rather unnecessary. If the code passes the 2048 stack limit without KASAN it would seem the limit with KASAN should be such that no warning is given. I suspect that it is rather difficult to predict the additional size of the instrumentation code and on some systems there might be a real issue with increased stack usage.
Regards, Arend
Signed-off-by: Arnd Bergmann arnd@arndb.de
drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c index b3aab2fe96eb..42dc8e1f483d 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c @@ -14157,7 +14157,7 @@ static void wlc_phy_bphy_init_nphy(struct brcms_phy *pi) write_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_STEP, 0x668); } -void +noinline_for_kasan void wlc_phy_table_write_nphy(struct brcms_phy *pi, u32 id, u32 len, u32 offset, u32 width, const void *data) { @@ -14171,7 +14171,7 @@ wlc_phy_table_write_nphy(struct brcms_phy *pi, u32 id, u32 len, u32 offset, wlc_phy_write_table_nphy(pi, &tbl); } -void +noinline_for_kasan void wlc_phy_table_read_nphy(struct brcms_phy *pi, u32 id, u32 len, u32 offset, u32 width, void *data) {
On Mon, Mar 6, 2017 at 10:16 AM, Arend Van Spriel arend.vanspriel@broadcom.com wrote:
On 2-3-2017 17:38, Arnd Bergmann wrote:
The wlc_phy_table_write_nphy/wlc_phy_table_read_nphy functions always put an object on the stack, which will each require a redzone with KASAN and lead to possible stack overflow:
drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c: In function 'wlc_phy_workarounds_nphy': drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c:17135:1: warning: the frame size of 6312 bytes is larger than 1000 bytes [-Wframe-larger-than=]
Looks like this warning text ended up in the wrong commit message. Got me confused for a sec :-p
What's wrong about the warning?
This marks the two functions as noinline_for_kasan, avoiding the problem entirely.
Frankly I seriously dislike annotating code for the sake of some (dynamic) memory analyzer. To me the whole thing seems rather unnecessary. If the code passes the 2048 stack limit without KASAN it would seem the limit with KASAN should be such that no warning is given. I suspect that it is rather difficult to predict the additional size of the instrumentation code and on some systems there might be a real issue with increased stack usage.
The frame sizes don't normally change that much. There are a couple of drivers like brcmsmac that repeatedly call an inline function which has a local variable that it passes by reference to an extern function.
While normally those variables share a stack location, KASAN forces each instance to its own location and adds (in this case) 80 bytes of redzone around it to detect out-of-bounds access.
While most drivers are fine with a 1500 byte warning limit, increasing the limit to 7kb would silence brcmsmac (unless more registers are accessed from wlc_phy_workarounds_nphy) but also risk a stack overflow to go unnoticed.
Arnd
On 6-3-2017 11:38, Arnd Bergmann wrote:
On Mon, Mar 6, 2017 at 10:16 AM, Arend Van Spriel arend.vanspriel@broadcom.com wrote:
On 2-3-2017 17:38, Arnd Bergmann wrote:
The wlc_phy_table_write_nphy/wlc_phy_table_read_nphy functions always put an object on the stack, which will each require a redzone with KASAN and lead to possible stack overflow:
drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c: In function 'wlc_phy_workarounds_nphy': drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c:17135:1: warning: the frame size of 6312 bytes is larger than 1000 bytes [-Wframe-larger-than=]
Looks like this warning text ended up in the wrong commit message. Got me confused for a sec :-p
What's wrong about the warning?
The warning is about the function 'wlc_phy_workarounds_nphy' (see PATCH 9/26) and not about wlc_phy_table_write_nphy/wlc_phy_table_read_nphy functions.
This marks the two functions as noinline_for_kasan, avoiding the problem entirely.
Frankly I seriously dislike annotating code for the sake of some (dynamic) memory analyzer. To me the whole thing seems rather unnecessary. If the code passes the 2048 stack limit without KASAN it would seem the limit with KASAN should be such that no warning is given. I suspect that it is rather difficult to predict the additional size of the instrumentation code and on some systems there might be a real issue with increased stack usage.
The frame sizes don't normally change that much. There are a couple of drivers like brcmsmac that repeatedly call an inline function which has a local variable that it passes by reference to an extern function.
While normally those variables share a stack location, KASAN forces each instance to its own location and adds (in this case) 80 bytes of redzone around it to detect out-of-bounds access.
While most drivers are fine with a 1500 byte warning limit, increasing the limit to 7kb would silence brcmsmac (unless more registers are accessed from wlc_phy_workarounds_nphy) but also risk a stack overflow to go unnoticed.
Given the amount of local variables maybe just tag the functions with noinline instead.
Regards, Arend
On Mon, Mar 6, 2017 at 12:02 PM, Arend Van Spriel arend.vanspriel@broadcom.com wrote:
On 6-3-2017 11:38, Arnd Bergmann wrote:
On Mon, Mar 6, 2017 at 10:16 AM, Arend Van Spriel arend.vanspriel@broadcom.com wrote:
On 2-3-2017 17:38, Arnd Bergmann wrote:
The wlc_phy_table_write_nphy/wlc_phy_table_read_nphy functions always put an object on the stack, which will each require a redzone with KASAN and lead to possible stack overflow:
drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c: In function 'wlc_phy_workarounds_nphy': drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c:17135:1: warning: the frame size of 6312 bytes is larger than 1000 bytes [-Wframe-larger-than=]
Looks like this warning text ended up in the wrong commit message. Got me confused for a sec :-p
What's wrong about the warning?
The warning is about the function 'wlc_phy_workarounds_nphy' (see PATCH 9/26) and not about wlc_phy_table_write_nphy/wlc_phy_table_read_nphy functions.
The warning only shows up for wlc_phy_workarounds_nphy, and we have to fix both issues to get the size down enough. If we split it up without uninlining the register access functions, we end up with two or three smaller functions that still exceed the limit.
This marks the two functions as noinline_for_kasan, avoiding the problem entirely.
Frankly I seriously dislike annotating code for the sake of some (dynamic) memory analyzer. To me the whole thing seems rather unnecessary. If the code passes the 2048 stack limit without KASAN it would seem the limit with KASAN should be such that no warning is given. I suspect that it is rather difficult to predict the additional size of the instrumentation code and on some systems there might be a real issue with increased stack usage.
The frame sizes don't normally change that much. There are a couple of drivers like brcmsmac that repeatedly call an inline function which has a local variable that it passes by reference to an extern function.
While normally those variables share a stack location, KASAN forces each instance to its own location and adds (in this case) 80 bytes of redzone around it to detect out-of-bounds access.
While most drivers are fine with a 1500 byte warning limit, increasing the limit to 7kb would silence brcmsmac (unless more registers are accessed from wlc_phy_workarounds_nphy) but also risk a stack overflow to go unnoticed.
Given the amount of local variables maybe just tag the functions with noinline instead.
But that would result in less efficient object code without KASAN, as inlining these by default is a good idea when the stack variables all get folded.
Arnd
On Mon, Mar 6, 2017 at 12:16 PM, Arnd Bergmann arnd@arndb.de wrote:
On Mon, Mar 6, 2017 at 12:02 PM, Arend Van Spriel arend.vanspriel@broadcom.com wrote:
On 6-3-2017 11:38, Arnd Bergmann wrote:
On Mon, Mar 6, 2017 at 10:16 AM, Arend Van Spriel arend.vanspriel@broadcom.com wrote:
Given the amount of local variables maybe just tag the functions with noinline instead.
But that would result in less efficient object code without KASAN, as inlining these by default is a good idea when the stack variables all get folded.
Note that David Laight alread suggested renaming noinline_for_kasan to noinline_if_stackbloat, which makes it a little more obvious what is going on. Would that address your concern as well?
Arnd
With KASAN and a couple of other patches applied, this driver is one of the few remaining ones that actually use more than 2048 bytes of kernel stack:
broadcom/brcm80211/brcmsmac/phy/phy_n.c: In function 'wlc_phy_workarounds_nphy_gainctrl': broadcom/brcm80211/brcmsmac/phy/phy_n.c:16065:1: warning: the frame size of 3264 bytes is larger than 2048 bytes [-Wframe-larger-than=] broadcom/brcm80211/brcmsmac/phy/phy_n.c: In function 'wlc_phy_workarounds_nphy': broadcom/brcm80211/brcmsmac/phy/phy_n.c:17138:1: warning: the frame size of 2864 bytes is larger than 2048 bytes [-Wframe-larger-than=]
Here, I'm reducing the stack size by marking as many local variables as 'static const' as I can without changing the actual code.
Signed-off-by: Arnd Bergmann arnd@arndb.de --- .../broadcom/brcm80211/brcmsmac/phy/phy_n.c | 197 ++++++++++----------- 1 file changed, 97 insertions(+), 100 deletions(-)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c index 42dc8e1f483d..48a4df488d75 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c @@ -14764,8 +14764,8 @@ static void wlc_phy_ipa_restore_tx_digi_filts_nphy(struct brcms_phy *pi) }
static void -wlc_phy_set_rfseq_nphy(struct brcms_phy *pi, u8 cmd, u8 *events, u8 *dlys, - u8 len) +wlc_phy_set_rfseq_nphy(struct brcms_phy *pi, u8 cmd, const u8 *events, + const u8 *dlys, u8 len) { u32 t1_offset, t2_offset; u8 ctr; @@ -15240,16 +15240,16 @@ static void wlc_phy_workarounds_nphy_gainctrl_2057_rev5(struct brcms_phy *pi) static void wlc_phy_workarounds_nphy_gainctrl_2057_rev6(struct brcms_phy *pi) { u16 currband; - s8 lna1G_gain_db_rev7[] = { 9, 14, 19, 24 }; - s8 *lna1_gain_db = NULL; - s8 *lna1_gain_db_2 = NULL; - s8 *lna2_gain_db = NULL; - s8 tiaA_gain_db_rev7[] = { -9, -6, -3, 0, 3, 3, 3, 3, 3, 3 }; - s8 *tia_gain_db; - s8 tiaA_gainbits_rev7[] = { 0, 1, 2, 3, 4, 4, 4, 4, 4, 4 }; - s8 *tia_gainbits; - u16 rfseqA_init_gain_rev7[] = { 0x624f, 0x624f }; - u16 *rfseq_init_gain; + static const s8 lna1G_gain_db_rev7[] = { 9, 14, 19, 24 }; + const s8 *lna1_gain_db = NULL; + const s8 *lna1_gain_db_2 = NULL; + const s8 *lna2_gain_db = NULL; + static const s8 tiaA_gain_db_rev7[] = { -9, -6, -3, 0, 3, 3, 3, 3, 3, 3 }; + const s8 *tia_gain_db; + static const s8 tiaA_gainbits_rev7[] = { 0, 1, 2, 3, 4, 4, 4, 4, 4, 4 }; + const s8 *tia_gainbits; + static const u16 rfseqA_init_gain_rev7[] = { 0x624f, 0x624f }; + const u16 *rfseq_init_gain; u16 init_gaincode; u16 clip1hi_gaincode; u16 clip1md_gaincode = 0; @@ -15310,10 +15310,9 @@ static void wlc_phy_workarounds_nphy_gainctrl_2057_rev6(struct brcms_phy *pi)
if ((freq <= 5080) || (freq == 5825)) {
- s8 lna1A_gain_db_rev7[] = { 11, 16, 20, 24 }; - s8 lna1A_gain_db_2_rev7[] = { - 11, 17, 22, 25}; - s8 lna2A_gain_db_rev7[] = { -1, 6, 10, 14 }; + static const s8 lna1A_gain_db_rev7[] = { 11, 16, 20, 24 }; + static const s8 lna1A_gain_db_2_rev7[] = { 11, 17, 22, 25}; + static const s8 lna2A_gain_db_rev7[] = { -1, 6, 10, 14 };
crsminu_th = 0x3e; lna1_gain_db = lna1A_gain_db_rev7; @@ -15321,10 +15320,9 @@ static void wlc_phy_workarounds_nphy_gainctrl_2057_rev6(struct brcms_phy *pi) lna2_gain_db = lna2A_gain_db_rev7; } else if ((freq >= 5500) && (freq <= 5700)) {
- s8 lna1A_gain_db_rev7[] = { 11, 17, 21, 25 }; - s8 lna1A_gain_db_2_rev7[] = { - 12, 18, 22, 26}; - s8 lna2A_gain_db_rev7[] = { 1, 8, 12, 16 }; + static const s8 lna1A_gain_db_rev7[] = { 11, 17, 21, 25 }; + static const s8 lna1A_gain_db_2_rev7[] = { 12, 18, 22, 26}; + static const s8 lna2A_gain_db_rev7[] = { 1, 8, 12, 16 };
crsminu_th = 0x45; clip1md_gaincode_B = 0x14; @@ -15335,10 +15333,9 @@ static void wlc_phy_workarounds_nphy_gainctrl_2057_rev6(struct brcms_phy *pi) lna2_gain_db = lna2A_gain_db_rev7; } else {
- s8 lna1A_gain_db_rev7[] = { 12, 18, 22, 26 }; - s8 lna1A_gain_db_2_rev7[] = { - 12, 18, 22, 26}; - s8 lna2A_gain_db_rev7[] = { -1, 6, 10, 14 }; + static const s8 lna1A_gain_db_rev7[] = { 12, 18, 22, 26 }; + static const s8 lna1A_gain_db_2_rev7[] = { 12, 18, 22, 26}; + static const s8 lna2A_gain_db_rev7[] = { -1, 6, 10, 14 };
crsminu_th = 0x41; lna1_gain_db = lna1A_gain_db_rev7; @@ -15450,65 +15447,65 @@ static void wlc_phy_workarounds_nphy_gainctrl(struct brcms_phy *pi) NPHY_RFSEQ_CMD_CLR_HIQ_DIS, NPHY_RFSEQ_CMD_SET_HPF_BW }; - u8 rfseq_updategainu_dlys[] = { 10, 30, 1 }; - s8 lna1G_gain_db[] = { 7, 11, 16, 23 }; - s8 lna1G_gain_db_rev4[] = { 8, 12, 17, 25 }; - s8 lna1G_gain_db_rev5[] = { 9, 13, 18, 26 }; - s8 lna1G_gain_db_rev6[] = { 8, 13, 18, 25 }; - s8 lna1G_gain_db_rev6_224B0[] = { 10, 14, 19, 27 }; - s8 lna1A_gain_db[] = { 7, 11, 17, 23 }; - s8 lna1A_gain_db_rev4[] = { 8, 12, 18, 23 }; - s8 lna1A_gain_db_rev5[] = { 6, 10, 16, 21 }; - s8 lna1A_gain_db_rev6[] = { 6, 10, 16, 21 }; - s8 *lna1_gain_db = NULL; - s8 lna2G_gain_db[] = { -5, 6, 10, 14 }; - s8 lna2G_gain_db_rev5[] = { -3, 7, 11, 16 }; - s8 lna2G_gain_db_rev6[] = { -5, 6, 10, 14 }; - s8 lna2G_gain_db_rev6_224B0[] = { -5, 6, 10, 15 }; - s8 lna2A_gain_db[] = { -6, 2, 6, 10 }; - s8 lna2A_gain_db_rev4[] = { -5, 2, 6, 10 }; - s8 lna2A_gain_db_rev5[] = { -7, 0, 4, 8 }; - s8 lna2A_gain_db_rev6[] = { -7, 0, 4, 8 }; - s8 *lna2_gain_db = NULL; - s8 tiaG_gain_db[] = { + static const u8 rfseq_updategainu_dlys[] = { 10, 30, 1 }; + static const s8 lna1G_gain_db[] = { 7, 11, 16, 23 }; + static const s8 lna1G_gain_db_rev4[] = { 8, 12, 17, 25 }; + static const s8 lna1G_gain_db_rev5[] = { 9, 13, 18, 26 }; + static const s8 lna1G_gain_db_rev6[] = { 8, 13, 18, 25 }; + static const s8 lna1G_gain_db_rev6_224B0[] = { 10, 14, 19, 27 }; + static const s8 lna1A_gain_db[] = { 7, 11, 17, 23 }; + static const s8 lna1A_gain_db_rev4[] = { 8, 12, 18, 23 }; + static const s8 lna1A_gain_db_rev5[] = { 6, 10, 16, 21 }; + static const s8 lna1A_gain_db_rev6[] = { 6, 10, 16, 21 }; + const s8 *lna1_gain_db = NULL; + static const s8 lna2G_gain_db[] = { -5, 6, 10, 14 }; + static const s8 lna2G_gain_db_rev5[] = { -3, 7, 11, 16 }; + static const s8 lna2G_gain_db_rev6[] = { -5, 6, 10, 14 }; + static const s8 lna2G_gain_db_rev6_224B0[] = { -5, 6, 10, 15 }; + static const s8 lna2A_gain_db[] = { -6, 2, 6, 10 }; + static const s8 lna2A_gain_db_rev4[] = { -5, 2, 6, 10 }; + static const s8 lna2A_gain_db_rev5[] = { -7, 0, 4, 8 }; + static const s8 lna2A_gain_db_rev6[] = { -7, 0, 4, 8 }; + const s8 *lna2_gain_db = NULL; + static const s8 tiaG_gain_db[] = { 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A }; - s8 tiaA_gain_db[] = { + static const s8 tiaA_gain_db[] = { 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13 }; - s8 tiaA_gain_db_rev4[] = { + static const s8 tiaA_gain_db_rev4[] = { 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d }; - s8 tiaA_gain_db_rev5[] = { + static const s8 tiaA_gain_db_rev5[] = { 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d }; - s8 tiaA_gain_db_rev6[] = { + static const s8 tiaA_gain_db_rev6[] = { 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d }; - s8 *tia_gain_db; - s8 tiaG_gainbits[] = { + const s8 *tia_gain_db; + static const s8 tiaG_gainbits[] = { 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 }; - s8 tiaA_gainbits[] = { + static const s8 tiaA_gainbits[] = { 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06 }; - s8 tiaA_gainbits_rev4[] = { + static const s8 tiaA_gainbits_rev4[] = { 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 }; - s8 tiaA_gainbits_rev5[] = { + static const s8 tiaA_gainbits_rev5[] = { 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 }; - s8 tiaA_gainbits_rev6[] = { + static const s8 tiaA_gainbits_rev6[] = { 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 }; - s8 *tia_gainbits; - s8 lpf_gain_db[] = { 0x00, 0x06, 0x0c, 0x12, 0x12, 0x12 }; - s8 lpf_gainbits[] = { 0x00, 0x01, 0x02, 0x03, 0x03, 0x03 }; - u16 rfseqG_init_gain[] = { 0x613f, 0x613f, 0x613f, 0x613f }; - u16 rfseqG_init_gain_rev4[] = { 0x513f, 0x513f, 0x513f, 0x513f }; - u16 rfseqG_init_gain_rev5[] = { 0x413f, 0x413f, 0x413f, 0x413f }; - u16 rfseqG_init_gain_rev5_elna[] = { + const s8 *tia_gainbits; + static const s8 lpf_gain_db[] = { 0x00, 0x06, 0x0c, 0x12, 0x12, 0x12 }; + static const s8 lpf_gainbits[] = { 0x00, 0x01, 0x02, 0x03, 0x03, 0x03 }; + static const u16 rfseqG_init_gain[] = { 0x613f, 0x613f, 0x613f, 0x613f }; + static const u16 rfseqG_init_gain_rev4[] = { 0x513f, 0x513f, 0x513f, 0x513f }; + static const u16 rfseqG_init_gain_rev5[] = { 0x413f, 0x413f, 0x413f, 0x413f }; + static const u16 rfseqG_init_gain_rev5_elna[] = { 0x013f, 0x013f, 0x013f, 0x013f }; - u16 rfseqG_init_gain_rev6[] = { 0x513f, 0x513f }; - u16 rfseqG_init_gain_rev6_224B0[] = { 0x413f, 0x413f }; - u16 rfseqG_init_gain_rev6_elna[] = { 0x113f, 0x113f }; - u16 rfseqA_init_gain[] = { 0x516f, 0x516f, 0x516f, 0x516f }; - u16 rfseqA_init_gain_rev4[] = { 0x614f, 0x614f, 0x614f, 0x614f }; - u16 rfseqA_init_gain_rev4_elna[] = { + static const u16 rfseqG_init_gain_rev6[] = { 0x513f, 0x513f }; + static const u16 rfseqG_init_gain_rev6_224B0[] = { 0x413f, 0x413f }; + static const u16 rfseqG_init_gain_rev6_elna[] = { 0x113f, 0x113f }; + static const u16 rfseqA_init_gain[] = { 0x516f, 0x516f, 0x516f, 0x516f }; + static const u16 rfseqA_init_gain_rev4[] = { 0x614f, 0x614f, 0x614f, 0x614f }; + static const u16 rfseqA_init_gain_rev4_elna[] = { 0x314f, 0x314f, 0x314f, 0x314f }; - u16 rfseqA_init_gain_rev5[] = { 0x714f, 0x714f, 0x714f, 0x714f }; - u16 rfseqA_init_gain_rev6[] = { 0x714f, 0x714f }; - u16 *rfseq_init_gain; + static const u16 rfseqA_init_gain_rev5[] = { 0x714f, 0x714f, 0x714f, 0x714f }; + static const u16 rfseqA_init_gain_rev6[] = { 0x714f, 0x714f }; + const u16 *rfseq_init_gain; u16 initG_gaincode = 0x627e; u16 initG_gaincode_rev4 = 0x527e; u16 initG_gaincode_rev5 = 0x427e; @@ -15538,10 +15535,10 @@ static void wlc_phy_workarounds_nphy_gainctrl(struct brcms_phy *pi) u16 clip1mdA_gaincode_rev6 = 0x2084; u16 clip1md_gaincode = 0; u16 clip1loG_gaincode = 0x0074; - u16 clip1loG_gaincode_rev5[] = { + static const u16 clip1loG_gaincode_rev5[] = { 0x0062, 0x0064, 0x006a, 0x106a, 0x106c, 0x1074, 0x107c, 0x207c }; - u16 clip1loG_gaincode_rev6[] = { + static const u16 clip1loG_gaincode_rev6[] = { 0x106a, 0x106c, 0x1074, 0x107c, 0x007e, 0x107e, 0x207e, 0x307e }; u16 clip1loG_gaincode_rev6_224B0 = 0x1074; @@ -16066,7 +16063,7 @@ static void wlc_phy_workarounds_nphy_gainctrl(struct brcms_phy *pi)
static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) { - u8 rfseq_rx2tx_events[] = { + static const u8 rfseq_rx2tx_events[] = { NPHY_RFSEQ_CMD_NOP, NPHY_RFSEQ_CMD_RXG_FBW, NPHY_RFSEQ_CMD_TR_SWITCH, @@ -16076,7 +16073,7 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) NPHY_RFSEQ_CMD_EXT_PA }; u8 rfseq_rx2tx_dlys[] = { 8, 6, 6, 2, 4, 60, 1 }; - u8 rfseq_tx2rx_events[] = { + static const u8 rfseq_tx2rx_events[] = { NPHY_RFSEQ_CMD_NOP, NPHY_RFSEQ_CMD_EXT_PA, NPHY_RFSEQ_CMD_TX_GAIN, @@ -16085,8 +16082,8 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) NPHY_RFSEQ_CMD_RXG_FBW, NPHY_RFSEQ_CMD_CLR_HIQ_DIS }; - u8 rfseq_tx2rx_dlys[] = { 8, 6, 2, 4, 4, 6, 1 }; - u8 rfseq_tx2rx_events_rev3[] = { + static const u8 rfseq_tx2rx_dlys[] = { 8, 6, 2, 4, 4, 6, 1 }; + static const u8 rfseq_tx2rx_events_rev3[] = { NPHY_REV3_RFSEQ_CMD_EXT_PA, NPHY_REV3_RFSEQ_CMD_INT_PA_PU, NPHY_REV3_RFSEQ_CMD_TX_GAIN, @@ -16096,7 +16093,7 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS, NPHY_REV3_RFSEQ_CMD_END }; - u8 rfseq_tx2rx_dlys_rev3[] = { 8, 4, 2, 2, 4, 4, 6, 1 }; + static const u8 rfseq_tx2rx_dlys_rev3[] = { 8, 4, 2, 2, 4, 4, 6, 1 }; u8 rfseq_rx2tx_events_rev3[] = { NPHY_REV3_RFSEQ_CMD_NOP, NPHY_REV3_RFSEQ_CMD_RXG_FBW, @@ -16110,7 +16107,7 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) }; u8 rfseq_rx2tx_dlys_rev3[] = { 8, 6, 6, 4, 4, 18, 42, 1, 1 };
- u8 rfseq_rx2tx_events_rev3_ipa[] = { + static const u8 rfseq_rx2tx_events_rev3_ipa[] = { NPHY_REV3_RFSEQ_CMD_NOP, NPHY_REV3_RFSEQ_CMD_RXG_FBW, NPHY_REV3_RFSEQ_CMD_TR_SWITCH, @@ -16121,15 +16118,15 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) NPHY_REV3_RFSEQ_CMD_INT_PA_PU, NPHY_REV3_RFSEQ_CMD_END }; - u8 rfseq_rx2tx_dlys_rev3_ipa[] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 }; - u16 rfseq_rx2tx_dacbufpu_rev7[] = { 0x10f, 0x10f }; + static const u8 rfseq_rx2tx_dlys_rev3_ipa[] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 }; + static const u16 rfseq_rx2tx_dacbufpu_rev7[] = { 0x10f, 0x10f };
s16 alpha0, alpha1, alpha2; s16 beta0, beta1, beta2; u32 leg_data_weights, ht_data_weights, nss1_data_weights, stbc_data_weights; u8 chan_freq_range = 0; - u16 dac_control = 0x0002; + static const u16 dac_control = 0x0002; u16 aux_adc_vmid_rev7_core0[] = { 0x8e, 0x96, 0x96, 0x96 }; u16 aux_adc_vmid_rev7_core1[] = { 0x8f, 0x9f, 0x9f, 0x96 }; u16 aux_adc_vmid_rev4[] = { 0xa2, 0xb4, 0xb4, 0x89 }; @@ -16139,8 +16136,8 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) u16 aux_adc_gain_rev4[] = { 0x02, 0x02, 0x02, 0x00 }; u16 aux_adc_gain_rev3[] = { 0x02, 0x02, 0x02, 0x00 }; u16 *aux_adc_gain; - u16 sk_adc_vmid[] = { 0xb4, 0xb4, 0xb4, 0x24 }; - u16 sk_adc_gain[] = { 0x02, 0x02, 0x02, 0x02 }; + static const u16 sk_adc_vmid[] = { 0xb4, 0xb4, 0xb4, 0x24 }; + static const u16 sk_adc_gain[] = { 0x02, 0x02, 0x02, 0x02 }; s32 min_nvar_val = 0x18d; s32 min_nvar_offset_6mbps = 20; u8 pdetrange; @@ -16151,9 +16148,9 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) u16 rfseq_rx2tx_lpf_h_hpc_rev7 = 0x77; u16 rfseq_tx2rx_lpf_h_hpc_rev7 = 0x77; u16 rfseq_pktgn_lpf_h_hpc_rev7 = 0x77; - u16 rfseq_htpktgn_lpf_hpc_rev7[] = { 0x77, 0x11, 0x11 }; - u16 rfseq_pktgn_lpf_hpc_rev7[] = { 0x11, 0x11 }; - u16 rfseq_cckpktgn_lpf_hpc_rev7[] = { 0x11, 0x11 }; + static const u16 rfseq_htpktgn_lpf_hpc_rev7[] = { 0x77, 0x11, 0x11 }; + static const u16 rfseq_pktgn_lpf_hpc_rev7[] = { 0x11, 0x11 }; + static const u16 rfseq_cckpktgn_lpf_hpc_rev7[] = { 0x11, 0x11 }; u16 ipalvlshift_3p3_war_en = 0; u16 rccal_bcap_val, rccal_scap_val; u16 rccal_tx20_11b_bcap = 0; @@ -24291,13 +24288,13 @@ static void wlc_phy_update_txcal_ladder_nphy(struct brcms_phy *pi, u16 core) u16 bbmult; u16 tblentry;
- struct nphy_txiqcal_ladder ladder_lo[] = { + static const struct nphy_txiqcal_ladder ladder_lo[] = { {3, 0}, {4, 0}, {6, 0}, {9, 0}, {13, 0}, {18, 0}, {25, 0}, {25, 1}, {25, 2}, {25, 3}, {25, 4}, {25, 5}, {25, 6}, {25, 7}, {35, 7}, {50, 7}, {71, 7}, {100, 7} };
- struct nphy_txiqcal_ladder ladder_iq[] = { + static const struct nphy_txiqcal_ladder ladder_iq[] = { {3, 0}, {4, 0}, {6, 0}, {9, 0}, {13, 0}, {18, 0}, {25, 0}, {35, 0}, {50, 0}, {71, 0}, {100, 0}, {100, 1}, {100, 2}, {100, 3}, {100, 4}, {100, 5}, {100, 6}, {100, 7} @@ -25773,67 +25770,67 @@ wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain, u16 cal_gain[2]; struct nphy_iqcal_params cal_params[2]; u32 tbl_len; - void *tbl_ptr; + const void *tbl_ptr; bool ladder_updated[2]; u8 mphase_cal_lastphase = 0; int bcmerror = 0; bool phyhang_avoid_state = false;
- u16 tbl_tx_iqlo_cal_loft_ladder_20[] = { + static const u16 tbl_tx_iqlo_cal_loft_ladder_20[] = { 0x0300, 0x0500, 0x0700, 0x0900, 0x0d00, 0x1100, 0x1900, 0x1901, 0x1902, 0x1903, 0x1904, 0x1905, 0x1906, 0x1907, 0x2407, 0x3207, 0x4607, 0x6407 };
- u16 tbl_tx_iqlo_cal_iqimb_ladder_20[] = { + static const u16 tbl_tx_iqlo_cal_iqimb_ladder_20[] = { 0x0200, 0x0300, 0x0600, 0x0900, 0x0d00, 0x1100, 0x1900, 0x2400, 0x3200, 0x4600, 0x6400, 0x6401, 0x6402, 0x6403, 0x6404, 0x6405, 0x6406, 0x6407 };
- u16 tbl_tx_iqlo_cal_loft_ladder_40[] = { + static const u16 tbl_tx_iqlo_cal_loft_ladder_40[] = { 0x0200, 0x0300, 0x0400, 0x0700, 0x0900, 0x0c00, 0x1200, 0x1201, 0x1202, 0x1203, 0x1204, 0x1205, 0x1206, 0x1207, 0x1907, 0x2307, 0x3207, 0x4707 };
- u16 tbl_tx_iqlo_cal_iqimb_ladder_40[] = { + static const u16 tbl_tx_iqlo_cal_iqimb_ladder_40[] = { 0x0100, 0x0200, 0x0400, 0x0700, 0x0900, 0x0c00, 0x1200, 0x1900, 0x2300, 0x3200, 0x4700, 0x4701, 0x4702, 0x4703, 0x4704, 0x4705, 0x4706, 0x4707 };
- u16 tbl_tx_iqlo_cal_startcoefs[] = { + static const u16 tbl_tx_iqlo_cal_startcoefs[] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 };
- u16 tbl_tx_iqlo_cal_cmds_fullcal[] = { + static const u16 tbl_tx_iqlo_cal_cmds_fullcal[] = { 0x8123, 0x8264, 0x8086, 0x8245, 0x8056, 0x9123, 0x9264, 0x9086, 0x9245, 0x9056 };
- u16 tbl_tx_iqlo_cal_cmds_recal[] = { + static const u16 tbl_tx_iqlo_cal_cmds_recal[] = { 0x8101, 0x8253, 0x8053, 0x8234, 0x8034, 0x9101, 0x9253, 0x9053, 0x9234, 0x9034 };
- u16 tbl_tx_iqlo_cal_startcoefs_nphyrev3[] = { + static const u16 tbl_tx_iqlo_cal_startcoefs_nphyrev3[] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 };
- u16 tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[] = { + static const u16 tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[] = { 0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234, 0x9434, 0x9334, 0x9084, 0x9267, 0x9056, 0x9234 };
- u16 tbl_tx_iqlo_cal_cmds_recal_nphyrev3[] = { + static const u16 tbl_tx_iqlo_cal_cmds_recal_nphyrev3[] = { 0x8423, 0x8323, 0x8073, 0x8256, 0x8045, 0x8223, 0x9423, 0x9323, 0x9073, 0x9256, 0x9045, 0x9223 };
On 2-3-2017 17:38, Arnd Bergmann wrote:
With KASAN and a couple of other patches applied, this driver is one of the few remaining ones that actually use more than 2048 bytes of kernel stack:
broadcom/brcm80211/brcmsmac/phy/phy_n.c: In function 'wlc_phy_workarounds_nphy_gainctrl': broadcom/brcm80211/brcmsmac/phy/phy_n.c:16065:1: warning: the frame size of 3264 bytes is larger than 2048 bytes [-Wframe-larger-than=] broadcom/brcm80211/brcmsmac/phy/phy_n.c: In function 'wlc_phy_workarounds_nphy': broadcom/brcm80211/brcmsmac/phy/phy_n.c:17138:1: warning: the frame size of 2864 bytes is larger than 2048 bytes [-Wframe-larger-than=]
Here, I'm reducing the stack size by marking as many local variables as 'static const' as I can without changing the actual code.
Acked-by: Arend van Spriel arend.vanspriel@broadcom.com
Signed-off-by: Arnd Bergmann arnd@arndb.de
.../broadcom/brcm80211/brcmsmac/phy/phy_n.c | 197 ++++++++++----------- 1 file changed, 97 insertions(+), 100 deletions(-)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c index 42dc8e1f483d..48a4df488d75 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c @@ -14764,8 +14764,8 @@ static void wlc_phy_ipa_restore_tx_digi_filts_nphy(struct brcms_phy *pi) } static void -wlc_phy_set_rfseq_nphy(struct brcms_phy *pi, u8 cmd, u8 *events, u8 *dlys,
u8 len)
+wlc_phy_set_rfseq_nphy(struct brcms_phy *pi, u8 cmd, const u8 *events,
const u8 *dlys, u8 len)
{ u32 t1_offset, t2_offset; u8 ctr; @@ -15240,16 +15240,16 @@ static void wlc_phy_workarounds_nphy_gainctrl_2057_rev5(struct brcms_phy *pi) static void wlc_phy_workarounds_nphy_gainctrl_2057_rev6(struct brcms_phy *pi) { u16 currband;
- s8 lna1G_gain_db_rev7[] = { 9, 14, 19, 24 };
- s8 *lna1_gain_db = NULL;
- s8 *lna1_gain_db_2 = NULL;
- s8 *lna2_gain_db = NULL;
- s8 tiaA_gain_db_rev7[] = { -9, -6, -3, 0, 3, 3, 3, 3, 3, 3 };
- s8 *tia_gain_db;
- s8 tiaA_gainbits_rev7[] = { 0, 1, 2, 3, 4, 4, 4, 4, 4, 4 };
- s8 *tia_gainbits;
- u16 rfseqA_init_gain_rev7[] = { 0x624f, 0x624f };
- u16 *rfseq_init_gain;
- static const s8 lna1G_gain_db_rev7[] = { 9, 14, 19, 24 };
- const s8 *lna1_gain_db = NULL;
- const s8 *lna1_gain_db_2 = NULL;
- const s8 *lna2_gain_db = NULL;
- static const s8 tiaA_gain_db_rev7[] = { -9, -6, -3, 0, 3, 3, 3, 3, 3, 3 };
- const s8 *tia_gain_db;
- static const s8 tiaA_gainbits_rev7[] = { 0, 1, 2, 3, 4, 4, 4, 4, 4, 4 };
- const s8 *tia_gainbits;
- static const u16 rfseqA_init_gain_rev7[] = { 0x624f, 0x624f };
- const u16 *rfseq_init_gain; u16 init_gaincode; u16 clip1hi_gaincode; u16 clip1md_gaincode = 0;
@@ -15310,10 +15310,9 @@ static void wlc_phy_workarounds_nphy_gainctrl_2057_rev6(struct brcms_phy *pi) if ((freq <= 5080) || (freq == 5825)) {
s8 lna1A_gain_db_rev7[] = { 11, 16, 20, 24 };
s8 lna1A_gain_db_2_rev7[] = {
11, 17, 22, 25};
s8 lna2A_gain_db_rev7[] = { -1, 6, 10, 14 };
static const s8 lna1A_gain_db_rev7[] = { 11, 16, 20, 24 };
static const s8 lna1A_gain_db_2_rev7[] = { 11, 17, 22, 25};
static const s8 lna2A_gain_db_rev7[] = { -1, 6, 10, 14 };
crsminu_th = 0x3e; lna1_gain_db = lna1A_gain_db_rev7; @@ -15321,10 +15320,9 @@ static void wlc_phy_workarounds_nphy_gainctrl_2057_rev6(struct brcms_phy *pi) lna2_gain_db = lna2A_gain_db_rev7; } else if ((freq >= 5500) && (freq <= 5700)) {
s8 lna1A_gain_db_rev7[] = { 11, 17, 21, 25 };
s8 lna1A_gain_db_2_rev7[] = {
12, 18, 22, 26};
s8 lna2A_gain_db_rev7[] = { 1, 8, 12, 16 };
static const s8 lna1A_gain_db_rev7[] = { 11, 17, 21, 25 };
static const s8 lna1A_gain_db_2_rev7[] = { 12, 18, 22, 26};
static const s8 lna2A_gain_db_rev7[] = { 1, 8, 12, 16 };
crsminu_th = 0x45; clip1md_gaincode_B = 0x14; @@ -15335,10 +15333,9 @@ static void wlc_phy_workarounds_nphy_gainctrl_2057_rev6(struct brcms_phy *pi) lna2_gain_db = lna2A_gain_db_rev7; } else {
s8 lna1A_gain_db_rev7[] = { 12, 18, 22, 26 };
s8 lna1A_gain_db_2_rev7[] = {
12, 18, 22, 26};
s8 lna2A_gain_db_rev7[] = { -1, 6, 10, 14 };
static const s8 lna1A_gain_db_rev7[] = { 12, 18, 22, 26 };
static const s8 lna1A_gain_db_2_rev7[] = { 12, 18, 22, 26};
static const s8 lna2A_gain_db_rev7[] = { -1, 6, 10, 14 };
crsminu_th = 0x41; lna1_gain_db = lna1A_gain_db_rev7; @@ -15450,65 +15447,65 @@ static void wlc_phy_workarounds_nphy_gainctrl(struct brcms_phy *pi) NPHY_RFSEQ_CMD_CLR_HIQ_DIS, NPHY_RFSEQ_CMD_SET_HPF_BW };
- u8 rfseq_updategainu_dlys[] = { 10, 30, 1 };
- s8 lna1G_gain_db[] = { 7, 11, 16, 23 };
- s8 lna1G_gain_db_rev4[] = { 8, 12, 17, 25 };
- s8 lna1G_gain_db_rev5[] = { 9, 13, 18, 26 };
- s8 lna1G_gain_db_rev6[] = { 8, 13, 18, 25 };
- s8 lna1G_gain_db_rev6_224B0[] = { 10, 14, 19, 27 };
- s8 lna1A_gain_db[] = { 7, 11, 17, 23 };
- s8 lna1A_gain_db_rev4[] = { 8, 12, 18, 23 };
- s8 lna1A_gain_db_rev5[] = { 6, 10, 16, 21 };
- s8 lna1A_gain_db_rev6[] = { 6, 10, 16, 21 };
- s8 *lna1_gain_db = NULL;
- s8 lna2G_gain_db[] = { -5, 6, 10, 14 };
- s8 lna2G_gain_db_rev5[] = { -3, 7, 11, 16 };
- s8 lna2G_gain_db_rev6[] = { -5, 6, 10, 14 };
- s8 lna2G_gain_db_rev6_224B0[] = { -5, 6, 10, 15 };
- s8 lna2A_gain_db[] = { -6, 2, 6, 10 };
- s8 lna2A_gain_db_rev4[] = { -5, 2, 6, 10 };
- s8 lna2A_gain_db_rev5[] = { -7, 0, 4, 8 };
- s8 lna2A_gain_db_rev6[] = { -7, 0, 4, 8 };
- s8 *lna2_gain_db = NULL;
- s8 tiaG_gain_db[] = {
- static const u8 rfseq_updategainu_dlys[] = { 10, 30, 1 };
- static const s8 lna1G_gain_db[] = { 7, 11, 16, 23 };
- static const s8 lna1G_gain_db_rev4[] = { 8, 12, 17, 25 };
- static const s8 lna1G_gain_db_rev5[] = { 9, 13, 18, 26 };
- static const s8 lna1G_gain_db_rev6[] = { 8, 13, 18, 25 };
- static const s8 lna1G_gain_db_rev6_224B0[] = { 10, 14, 19, 27 };
- static const s8 lna1A_gain_db[] = { 7, 11, 17, 23 };
- static const s8 lna1A_gain_db_rev4[] = { 8, 12, 18, 23 };
- static const s8 lna1A_gain_db_rev5[] = { 6, 10, 16, 21 };
- static const s8 lna1A_gain_db_rev6[] = { 6, 10, 16, 21 };
- const s8 *lna1_gain_db = NULL;
- static const s8 lna2G_gain_db[] = { -5, 6, 10, 14 };
- static const s8 lna2G_gain_db_rev5[] = { -3, 7, 11, 16 };
- static const s8 lna2G_gain_db_rev6[] = { -5, 6, 10, 14 };
- static const s8 lna2G_gain_db_rev6_224B0[] = { -5, 6, 10, 15 };
- static const s8 lna2A_gain_db[] = { -6, 2, 6, 10 };
- static const s8 lna2A_gain_db_rev4[] = { -5, 2, 6, 10 };
- static const s8 lna2A_gain_db_rev5[] = { -7, 0, 4, 8 };
- static const s8 lna2A_gain_db_rev6[] = { -7, 0, 4, 8 };
- const s8 *lna2_gain_db = NULL;
- static const s8 tiaG_gain_db[] = { 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A };
- s8 tiaA_gain_db[] = {
- static const s8 tiaA_gain_db[] = { 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13 };
- s8 tiaA_gain_db_rev4[] = {
- static const s8 tiaA_gain_db_rev4[] = { 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d };
- s8 tiaA_gain_db_rev5[] = {
- static const s8 tiaA_gain_db_rev5[] = { 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d };
- s8 tiaA_gain_db_rev6[] = {
- static const s8 tiaA_gain_db_rev6[] = { 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d };
- s8 *tia_gain_db;
- s8 tiaG_gainbits[] = {
- const s8 *tia_gain_db;
- static const s8 tiaG_gainbits[] = { 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 };
- s8 tiaA_gainbits[] = {
- static const s8 tiaA_gainbits[] = { 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06 };
- s8 tiaA_gainbits_rev4[] = {
- static const s8 tiaA_gainbits_rev4[] = { 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 };
- s8 tiaA_gainbits_rev5[] = {
- static const s8 tiaA_gainbits_rev5[] = { 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 };
- s8 tiaA_gainbits_rev6[] = {
- static const s8 tiaA_gainbits_rev6[] = { 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 };
- s8 *tia_gainbits;
- s8 lpf_gain_db[] = { 0x00, 0x06, 0x0c, 0x12, 0x12, 0x12 };
- s8 lpf_gainbits[] = { 0x00, 0x01, 0x02, 0x03, 0x03, 0x03 };
- u16 rfseqG_init_gain[] = { 0x613f, 0x613f, 0x613f, 0x613f };
- u16 rfseqG_init_gain_rev4[] = { 0x513f, 0x513f, 0x513f, 0x513f };
- u16 rfseqG_init_gain_rev5[] = { 0x413f, 0x413f, 0x413f, 0x413f };
- u16 rfseqG_init_gain_rev5_elna[] = {
- const s8 *tia_gainbits;
- static const s8 lpf_gain_db[] = { 0x00, 0x06, 0x0c, 0x12, 0x12, 0x12 };
- static const s8 lpf_gainbits[] = { 0x00, 0x01, 0x02, 0x03, 0x03, 0x03 };
- static const u16 rfseqG_init_gain[] = { 0x613f, 0x613f, 0x613f, 0x613f };
- static const u16 rfseqG_init_gain_rev4[] = { 0x513f, 0x513f, 0x513f, 0x513f };
- static const u16 rfseqG_init_gain_rev5[] = { 0x413f, 0x413f, 0x413f, 0x413f };
- static const u16 rfseqG_init_gain_rev5_elna[] = { 0x013f, 0x013f, 0x013f, 0x013f };
- u16 rfseqG_init_gain_rev6[] = { 0x513f, 0x513f };
- u16 rfseqG_init_gain_rev6_224B0[] = { 0x413f, 0x413f };
- u16 rfseqG_init_gain_rev6_elna[] = { 0x113f, 0x113f };
- u16 rfseqA_init_gain[] = { 0x516f, 0x516f, 0x516f, 0x516f };
- u16 rfseqA_init_gain_rev4[] = { 0x614f, 0x614f, 0x614f, 0x614f };
- u16 rfseqA_init_gain_rev4_elna[] = {
- static const u16 rfseqG_init_gain_rev6[] = { 0x513f, 0x513f };
- static const u16 rfseqG_init_gain_rev6_224B0[] = { 0x413f, 0x413f };
- static const u16 rfseqG_init_gain_rev6_elna[] = { 0x113f, 0x113f };
- static const u16 rfseqA_init_gain[] = { 0x516f, 0x516f, 0x516f, 0x516f };
- static const u16 rfseqA_init_gain_rev4[] = { 0x614f, 0x614f, 0x614f, 0x614f };
- static const u16 rfseqA_init_gain_rev4_elna[] = { 0x314f, 0x314f, 0x314f, 0x314f };
- u16 rfseqA_init_gain_rev5[] = { 0x714f, 0x714f, 0x714f, 0x714f };
- u16 rfseqA_init_gain_rev6[] = { 0x714f, 0x714f };
- u16 *rfseq_init_gain;
- static const u16 rfseqA_init_gain_rev5[] = { 0x714f, 0x714f, 0x714f, 0x714f };
- static const u16 rfseqA_init_gain_rev6[] = { 0x714f, 0x714f };
- const u16 *rfseq_init_gain; u16 initG_gaincode = 0x627e; u16 initG_gaincode_rev4 = 0x527e; u16 initG_gaincode_rev5 = 0x427e;
@@ -15538,10 +15535,10 @@ static void wlc_phy_workarounds_nphy_gainctrl(struct brcms_phy *pi) u16 clip1mdA_gaincode_rev6 = 0x2084; u16 clip1md_gaincode = 0; u16 clip1loG_gaincode = 0x0074;
- u16 clip1loG_gaincode_rev5[] = {
- static const u16 clip1loG_gaincode_rev5[] = { 0x0062, 0x0064, 0x006a, 0x106a, 0x106c, 0x1074, 0x107c, 0x207c };
- u16 clip1loG_gaincode_rev6[] = {
- static const u16 clip1loG_gaincode_rev6[] = { 0x106a, 0x106c, 0x1074, 0x107c, 0x007e, 0x107e, 0x207e, 0x307e }; u16 clip1loG_gaincode_rev6_224B0 = 0x1074;
@@ -16066,7 +16063,7 @@ static void wlc_phy_workarounds_nphy_gainctrl(struct brcms_phy *pi) static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) {
- u8 rfseq_rx2tx_events[] = {
- static const u8 rfseq_rx2tx_events[] = { NPHY_RFSEQ_CMD_NOP, NPHY_RFSEQ_CMD_RXG_FBW, NPHY_RFSEQ_CMD_TR_SWITCH,
@@ -16076,7 +16073,7 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) NPHY_RFSEQ_CMD_EXT_PA }; u8 rfseq_rx2tx_dlys[] = { 8, 6, 6, 2, 4, 60, 1 };
- u8 rfseq_tx2rx_events[] = {
- static const u8 rfseq_tx2rx_events[] = { NPHY_RFSEQ_CMD_NOP, NPHY_RFSEQ_CMD_EXT_PA, NPHY_RFSEQ_CMD_TX_GAIN,
@@ -16085,8 +16082,8 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) NPHY_RFSEQ_CMD_RXG_FBW, NPHY_RFSEQ_CMD_CLR_HIQ_DIS };
- u8 rfseq_tx2rx_dlys[] = { 8, 6, 2, 4, 4, 6, 1 };
- u8 rfseq_tx2rx_events_rev3[] = {
- static const u8 rfseq_tx2rx_dlys[] = { 8, 6, 2, 4, 4, 6, 1 };
- static const u8 rfseq_tx2rx_events_rev3[] = { NPHY_REV3_RFSEQ_CMD_EXT_PA, NPHY_REV3_RFSEQ_CMD_INT_PA_PU, NPHY_REV3_RFSEQ_CMD_TX_GAIN,
@@ -16096,7 +16093,7 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS, NPHY_REV3_RFSEQ_CMD_END };
- u8 rfseq_tx2rx_dlys_rev3[] = { 8, 4, 2, 2, 4, 4, 6, 1 };
- static const u8 rfseq_tx2rx_dlys_rev3[] = { 8, 4, 2, 2, 4, 4, 6, 1 }; u8 rfseq_rx2tx_events_rev3[] = { NPHY_REV3_RFSEQ_CMD_NOP, NPHY_REV3_RFSEQ_CMD_RXG_FBW,
@@ -16110,7 +16107,7 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) }; u8 rfseq_rx2tx_dlys_rev3[] = { 8, 6, 6, 4, 4, 18, 42, 1, 1 };
- u8 rfseq_rx2tx_events_rev3_ipa[] = {
- static const u8 rfseq_rx2tx_events_rev3_ipa[] = { NPHY_REV3_RFSEQ_CMD_NOP, NPHY_REV3_RFSEQ_CMD_RXG_FBW, NPHY_REV3_RFSEQ_CMD_TR_SWITCH,
@@ -16121,15 +16118,15 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) NPHY_REV3_RFSEQ_CMD_INT_PA_PU, NPHY_REV3_RFSEQ_CMD_END };
- u8 rfseq_rx2tx_dlys_rev3_ipa[] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 };
- u16 rfseq_rx2tx_dacbufpu_rev7[] = { 0x10f, 0x10f };
- static const u8 rfseq_rx2tx_dlys_rev3_ipa[] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 };
- static const u16 rfseq_rx2tx_dacbufpu_rev7[] = { 0x10f, 0x10f };
s16 alpha0, alpha1, alpha2; s16 beta0, beta1, beta2; u32 leg_data_weights, ht_data_weights, nss1_data_weights, stbc_data_weights; u8 chan_freq_range = 0;
- u16 dac_control = 0x0002;
- static const u16 dac_control = 0x0002; u16 aux_adc_vmid_rev7_core0[] = { 0x8e, 0x96, 0x96, 0x96 }; u16 aux_adc_vmid_rev7_core1[] = { 0x8f, 0x9f, 0x9f, 0x96 }; u16 aux_adc_vmid_rev4[] = { 0xa2, 0xb4, 0xb4, 0x89 };
@@ -16139,8 +16136,8 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) u16 aux_adc_gain_rev4[] = { 0x02, 0x02, 0x02, 0x00 }; u16 aux_adc_gain_rev3[] = { 0x02, 0x02, 0x02, 0x00 }; u16 *aux_adc_gain;
- u16 sk_adc_vmid[] = { 0xb4, 0xb4, 0xb4, 0x24 };
- u16 sk_adc_gain[] = { 0x02, 0x02, 0x02, 0x02 };
- static const u16 sk_adc_vmid[] = { 0xb4, 0xb4, 0xb4, 0x24 };
- static const u16 sk_adc_gain[] = { 0x02, 0x02, 0x02, 0x02 }; s32 min_nvar_val = 0x18d; s32 min_nvar_offset_6mbps = 20; u8 pdetrange;
@@ -16151,9 +16148,9 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) u16 rfseq_rx2tx_lpf_h_hpc_rev7 = 0x77; u16 rfseq_tx2rx_lpf_h_hpc_rev7 = 0x77; u16 rfseq_pktgn_lpf_h_hpc_rev7 = 0x77;
- u16 rfseq_htpktgn_lpf_hpc_rev7[] = { 0x77, 0x11, 0x11 };
- u16 rfseq_pktgn_lpf_hpc_rev7[] = { 0x11, 0x11 };
- u16 rfseq_cckpktgn_lpf_hpc_rev7[] = { 0x11, 0x11 };
- static const u16 rfseq_htpktgn_lpf_hpc_rev7[] = { 0x77, 0x11, 0x11 };
- static const u16 rfseq_pktgn_lpf_hpc_rev7[] = { 0x11, 0x11 };
- static const u16 rfseq_cckpktgn_lpf_hpc_rev7[] = { 0x11, 0x11 }; u16 ipalvlshift_3p3_war_en = 0; u16 rccal_bcap_val, rccal_scap_val; u16 rccal_tx20_11b_bcap = 0;
@@ -24291,13 +24288,13 @@ static void wlc_phy_update_txcal_ladder_nphy(struct brcms_phy *pi, u16 core) u16 bbmult; u16 tblentry;
- struct nphy_txiqcal_ladder ladder_lo[] = {
- static const struct nphy_txiqcal_ladder ladder_lo[] = { {3, 0}, {4, 0}, {6, 0}, {9, 0}, {13, 0}, {18, 0}, {25, 0}, {25, 1}, {25, 2}, {25, 3}, {25, 4}, {25, 5}, {25, 6}, {25, 7}, {35, 7}, {50, 7}, {71, 7}, {100, 7} };
- struct nphy_txiqcal_ladder ladder_iq[] = {
- static const struct nphy_txiqcal_ladder ladder_iq[] = { {3, 0}, {4, 0}, {6, 0}, {9, 0}, {13, 0}, {18, 0}, {25, 0}, {35, 0}, {50, 0}, {71, 0}, {100, 0}, {100, 1}, {100, 2}, {100, 3}, {100, 4}, {100, 5}, {100, 6}, {100, 7}
@@ -25773,67 +25770,67 @@ wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain, u16 cal_gain[2]; struct nphy_iqcal_params cal_params[2]; u32 tbl_len;
- void *tbl_ptr;
- const void *tbl_ptr; bool ladder_updated[2]; u8 mphase_cal_lastphase = 0; int bcmerror = 0; bool phyhang_avoid_state = false;
- u16 tbl_tx_iqlo_cal_loft_ladder_20[] = {
- static const u16 tbl_tx_iqlo_cal_loft_ladder_20[] = { 0x0300, 0x0500, 0x0700, 0x0900, 0x0d00, 0x1100, 0x1900, 0x1901, 0x1902, 0x1903, 0x1904, 0x1905, 0x1906, 0x1907, 0x2407, 0x3207, 0x4607, 0x6407 };
- u16 tbl_tx_iqlo_cal_iqimb_ladder_20[] = {
- static const u16 tbl_tx_iqlo_cal_iqimb_ladder_20[] = { 0x0200, 0x0300, 0x0600, 0x0900, 0x0d00, 0x1100, 0x1900, 0x2400, 0x3200, 0x4600, 0x6400, 0x6401, 0x6402, 0x6403, 0x6404, 0x6405, 0x6406, 0x6407 };
- u16 tbl_tx_iqlo_cal_loft_ladder_40[] = {
- static const u16 tbl_tx_iqlo_cal_loft_ladder_40[] = { 0x0200, 0x0300, 0x0400, 0x0700, 0x0900, 0x0c00, 0x1200, 0x1201, 0x1202, 0x1203, 0x1204, 0x1205, 0x1206, 0x1207, 0x1907, 0x2307, 0x3207, 0x4707 };
- u16 tbl_tx_iqlo_cal_iqimb_ladder_40[] = {
- static const u16 tbl_tx_iqlo_cal_iqimb_ladder_40[] = { 0x0100, 0x0200, 0x0400, 0x0700, 0x0900, 0x0c00, 0x1200, 0x1900, 0x2300, 0x3200, 0x4700, 0x4701, 0x4702, 0x4703, 0x4704, 0x4705, 0x4706, 0x4707 };
- u16 tbl_tx_iqlo_cal_startcoefs[] = {
- static const u16 tbl_tx_iqlo_cal_startcoefs[] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 };
- u16 tbl_tx_iqlo_cal_cmds_fullcal[] = {
- static const u16 tbl_tx_iqlo_cal_cmds_fullcal[] = { 0x8123, 0x8264, 0x8086, 0x8245, 0x8056, 0x9123, 0x9264, 0x9086, 0x9245, 0x9056 };
- u16 tbl_tx_iqlo_cal_cmds_recal[] = {
- static const u16 tbl_tx_iqlo_cal_cmds_recal[] = { 0x8101, 0x8253, 0x8053, 0x8234, 0x8034, 0x9101, 0x9253, 0x9053, 0x9234, 0x9034 };
- u16 tbl_tx_iqlo_cal_startcoefs_nphyrev3[] = {
- static const u16 tbl_tx_iqlo_cal_startcoefs_nphyrev3[] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 };
- u16 tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[] = {
- static const u16 tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[] = { 0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234, 0x9434, 0x9334, 0x9084, 0x9267, 0x9056, 0x9234 };
- u16 tbl_tx_iqlo_cal_cmds_recal_nphyrev3[] = {
- static const u16 tbl_tx_iqlo_cal_cmds_recal_nphyrev3[] = { 0x8423, 0x8323, 0x8073, 0x8256, 0x8045, 0x8223, 0x9423, 0x9323, 0x9073, 0x9256, 0x9045, 0x9223 };
Arend Van Spriel arend.vanspriel@broadcom.com writes:
On 2-3-2017 17:38, Arnd Bergmann wrote:
With KASAN and a couple of other patches applied, this driver is one of the few remaining ones that actually use more than 2048 bytes of kernel stack:
broadcom/brcm80211/brcmsmac/phy/phy_n.c: In function 'wlc_phy_workarounds_nphy_gainctrl': broadcom/brcm80211/brcmsmac/phy/phy_n.c:16065:1: warning: the frame size of 3264 bytes is larger than 2048 bytes [-Wframe-larger-than=] broadcom/brcm80211/brcmsmac/phy/phy_n.c: In function 'wlc_phy_workarounds_nphy': broadcom/brcm80211/brcmsmac/phy/phy_n.c:17138:1: warning: the frame size of 2864 bytes is larger than 2048 bytes [-Wframe-larger-than=]
Here, I'm reducing the stack size by marking as many local variables as 'static const' as I can without changing the actual code.
Acked-by: Arend van Spriel arend.vanspriel@broadcom.com
Arnd, via which tree are you planning to submit these? I'm not sure what I should do with the wireless drivers patches from this series.
On Mon, Mar 6, 2017 at 5:19 PM, Kalle Valo kvalo@codeaurora.org wrote:
Arend Van Spriel arend.vanspriel@broadcom.com writes:
On 2-3-2017 17:38, Arnd Bergmann wrote:
With KASAN and a couple of other patches applied, this driver is one of the few remaining ones that actually use more than 2048 bytes of kernel stack:
broadcom/brcm80211/brcmsmac/phy/phy_n.c: In function 'wlc_phy_workarounds_nphy_gainctrl': broadcom/brcm80211/brcmsmac/phy/phy_n.c:16065:1: warning: the frame size of 3264 bytes is larger than 2048 bytes [-Wframe-larger-than=] broadcom/brcm80211/brcmsmac/phy/phy_n.c: In function 'wlc_phy_workarounds_nphy': broadcom/brcm80211/brcmsmac/phy/phy_n.c:17138:1: warning: the frame size of 2864 bytes is larger than 2048 bytes [-Wframe-larger-than=]
Here, I'm reducing the stack size by marking as many local variables as 'static const' as I can without changing the actual code.
Acked-by: Arend van Spriel arend.vanspriel@broadcom.com
Arnd, via which tree are you planning to submit these? I'm not sure what I should do with the wireless drivers patches from this series.
I'm not quite sure myself yet. I'd probably want the first few patches that do most of the work get merged through Andrew's linux-mm tree once we have come to agreement on them. The driver specific patches like the brcmsmac ones depend on the introduction of noinline_for_kasan or noinline_if_stackbloat and could either go in along with the first set, or as a follow-up through the normal maintainer trees.
Arnd
Arnd Bergmann arnd@arndb.de writes:
On Mon, Mar 6, 2017 at 5:19 PM, Kalle Valo kvalo@codeaurora.org wrote:
Arend Van Spriel arend.vanspriel@broadcom.com writes:
On 2-3-2017 17:38, Arnd Bergmann wrote:
With KASAN and a couple of other patches applied, this driver is one of the few remaining ones that actually use more than 2048 bytes of kernel stack:
broadcom/brcm80211/brcmsmac/phy/phy_n.c: In function 'wlc_phy_workarounds_nphy_gainctrl': broadcom/brcm80211/brcmsmac/phy/phy_n.c:16065:1: warning: the frame size of 3264 bytes is larger than 2048 bytes [-Wframe-larger-than=] broadcom/brcm80211/brcmsmac/phy/phy_n.c: In function 'wlc_phy_workarounds_nphy': broadcom/brcm80211/brcmsmac/phy/phy_n.c:17138:1: warning: the frame size of 2864 bytes is larger than 2048 bytes [-Wframe-larger-than=]
Here, I'm reducing the stack size by marking as many local variables as 'static const' as I can without changing the actual code.
Acked-by: Arend van Spriel arend.vanspriel@broadcom.com
Arnd, via which tree are you planning to submit these? I'm not sure what I should do with the wireless drivers patches from this series.
I'm not quite sure myself yet. I'd probably want the first few patches that do most of the work get merged through Andrew's linux-mm tree once we have come to agreement on them. The driver specific patches like the brcmsmac ones depend on the introduction of noinline_for_kasan or noinline_if_stackbloat and could either go in along with the first set, or as a follow-up through the normal maintainer trees.
Either way is fine for me. Just mark clearly if you want the wireless drivers patches to go through via my tree, otherwise I'll ignore them.
On 7-3-2017 10:44, Kalle Valo wrote:
Arnd Bergmann arnd@arndb.de writes:
On Mon, Mar 6, 2017 at 5:19 PM, Kalle Valo kvalo@codeaurora.org wrote:
Arend Van Spriel arend.vanspriel@broadcom.com writes:
On 2-3-2017 17:38, Arnd Bergmann wrote:
With KASAN and a couple of other patches applied, this driver is one of the few remaining ones that actually use more than 2048 bytes of kernel stack:
broadcom/brcm80211/brcmsmac/phy/phy_n.c: In function 'wlc_phy_workarounds_nphy_gainctrl': broadcom/brcm80211/brcmsmac/phy/phy_n.c:16065:1: warning: the frame size of 3264 bytes is larger than 2048 bytes [-Wframe-larger-than=] broadcom/brcm80211/brcmsmac/phy/phy_n.c: In function 'wlc_phy_workarounds_nphy': broadcom/brcm80211/brcmsmac/phy/phy_n.c:17138:1: warning: the frame size of 2864 bytes is larger than 2048 bytes [-Wframe-larger-than=]
Here, I'm reducing the stack size by marking as many local variables as 'static const' as I can without changing the actual code.
Acked-by: Arend van Spriel arend.vanspriel@broadcom.com
Arnd, via which tree are you planning to submit these? I'm not sure what I should do with the wireless drivers patches from this series.
I'm not quite sure myself yet. I'd probably want the first few patches that do most of the work get merged through Andrew's linux-mm tree once we have come to agreement on them. The driver specific patches like the brcmsmac ones depend on the introduction of noinline_for_kasan or noinline_if_stackbloat and could either go in along with the first set, or as a follow-up through the normal maintainer trees.
Either way is fine for me. Just mark clearly if you want the wireless drivers patches to go through via my tree, otherwise I'll ignore them.
That (dreaded) phy code does not get a lot of changes so I think it does not matter which tree is will go through in terms of risk for conflicts. So going through linux-mm is fine for me as well.
Regards, Arend
The stack consumption in this driver is still relatively high, with one remaining warning if the warning level is lowered to 1536 bytes:
drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c:17135:1: error: the frame size of 1880 bytes is larger than 1536 bytes [-Werror=frame-larger-than=]
The affected function is actually a collection of three separate implementations, and each of them is fairly large by itself. Splitting them up is done easily and improves readability at the same time.
I'm leaving the original indentation to make the review easier.
Signed-off-by: Arnd Bergmann arnd@arndb.de --- .../broadcom/brcm80211/brcmsmac/phy/phy_n.c | 178 ++++++++++++--------- 1 file changed, 104 insertions(+), 74 deletions(-)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c index 48a4df488d75..d76c092bb6b4 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c @@ -16061,52 +16061,8 @@ static void wlc_phy_workarounds_nphy_gainctrl(struct brcms_phy *pi) } }
-static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) +static void wlc_phy_workarounds_nphy_rev7(struct brcms_phy *pi) { - static const u8 rfseq_rx2tx_events[] = { - NPHY_RFSEQ_CMD_NOP, - NPHY_RFSEQ_CMD_RXG_FBW, - NPHY_RFSEQ_CMD_TR_SWITCH, - NPHY_RFSEQ_CMD_CLR_HIQ_DIS, - NPHY_RFSEQ_CMD_RXPD_TXPD, - NPHY_RFSEQ_CMD_TX_GAIN, - NPHY_RFSEQ_CMD_EXT_PA - }; - u8 rfseq_rx2tx_dlys[] = { 8, 6, 6, 2, 4, 60, 1 }; - static const u8 rfseq_tx2rx_events[] = { - NPHY_RFSEQ_CMD_NOP, - NPHY_RFSEQ_CMD_EXT_PA, - NPHY_RFSEQ_CMD_TX_GAIN, - NPHY_RFSEQ_CMD_RXPD_TXPD, - NPHY_RFSEQ_CMD_TR_SWITCH, - NPHY_RFSEQ_CMD_RXG_FBW, - NPHY_RFSEQ_CMD_CLR_HIQ_DIS - }; - static const u8 rfseq_tx2rx_dlys[] = { 8, 6, 2, 4, 4, 6, 1 }; - static const u8 rfseq_tx2rx_events_rev3[] = { - NPHY_REV3_RFSEQ_CMD_EXT_PA, - NPHY_REV3_RFSEQ_CMD_INT_PA_PU, - NPHY_REV3_RFSEQ_CMD_TX_GAIN, - NPHY_REV3_RFSEQ_CMD_RXPD_TXPD, - NPHY_REV3_RFSEQ_CMD_TR_SWITCH, - NPHY_REV3_RFSEQ_CMD_RXG_FBW, - NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS, - NPHY_REV3_RFSEQ_CMD_END - }; - static const u8 rfseq_tx2rx_dlys_rev3[] = { 8, 4, 2, 2, 4, 4, 6, 1 }; - u8 rfseq_rx2tx_events_rev3[] = { - NPHY_REV3_RFSEQ_CMD_NOP, - NPHY_REV3_RFSEQ_CMD_RXG_FBW, - NPHY_REV3_RFSEQ_CMD_TR_SWITCH, - NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS, - NPHY_REV3_RFSEQ_CMD_RXPD_TXPD, - NPHY_REV3_RFSEQ_CMD_TX_GAIN, - NPHY_REV3_RFSEQ_CMD_INT_PA_PU, - NPHY_REV3_RFSEQ_CMD_EXT_PA, - NPHY_REV3_RFSEQ_CMD_END - }; - u8 rfseq_rx2tx_dlys_rev3[] = { 8, 6, 6, 4, 4, 18, 42, 1, 1 }; - static const u8 rfseq_rx2tx_events_rev3_ipa[] = { NPHY_REV3_RFSEQ_CMD_NOP, NPHY_REV3_RFSEQ_CMD_RXG_FBW, @@ -16120,29 +16076,15 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) }; static const u8 rfseq_rx2tx_dlys_rev3_ipa[] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 }; static const u16 rfseq_rx2tx_dacbufpu_rev7[] = { 0x10f, 0x10f }; - - s16 alpha0, alpha1, alpha2; - s16 beta0, beta1, beta2; - u32 leg_data_weights, ht_data_weights, nss1_data_weights, - stbc_data_weights; + u32 leg_data_weights; u8 chan_freq_range = 0; static const u16 dac_control = 0x0002; u16 aux_adc_vmid_rev7_core0[] = { 0x8e, 0x96, 0x96, 0x96 }; u16 aux_adc_vmid_rev7_core1[] = { 0x8f, 0x9f, 0x9f, 0x96 }; - u16 aux_adc_vmid_rev4[] = { 0xa2, 0xb4, 0xb4, 0x89 }; - u16 aux_adc_vmid_rev3[] = { 0xa2, 0xb4, 0xb4, 0x89 }; - u16 *aux_adc_vmid; u16 aux_adc_gain_rev7[] = { 0x02, 0x02, 0x02, 0x02 }; - u16 aux_adc_gain_rev4[] = { 0x02, 0x02, 0x02, 0x00 }; - u16 aux_adc_gain_rev3[] = { 0x02, 0x02, 0x02, 0x00 }; - u16 *aux_adc_gain; - static const u16 sk_adc_vmid[] = { 0xb4, 0xb4, 0xb4, 0x24 }; - static const u16 sk_adc_gain[] = { 0x02, 0x02, 0x02, 0x02 }; s32 min_nvar_val = 0x18d; s32 min_nvar_offset_6mbps = 20; u8 pdetrange; - u8 triso; - u16 regval; u16 afectrl_adc_ctrl1_rev7 = 0x20; u16 afectrl_adc_ctrl2_rev7 = 0x0; u16 rfseq_rx2tx_lpf_h_hpc_rev7 = 0x77; @@ -16171,17 +16113,6 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) u16 freq; int coreNum;
- if (CHSPEC_IS5G(pi->radio_chanspec)) - wlc_phy_classifier_nphy(pi, NPHY_ClassifierCtrl_cck_en, 0); - else - wlc_phy_classifier_nphy(pi, NPHY_ClassifierCtrl_cck_en, 1); - - if (pi->phyhang_avoid) - wlc_phy_stay_in_carriersearch_nphy(pi, true); - - or_phy_reg(pi, 0xb1, NPHY_IQFlip_ADC1 | NPHY_IQFlip_ADC2); - - if (NREV_GE(pi->pubpi.phy_rev, 7)) {
if (NREV_IS(pi->pubpi.phy_rev, 7)) { mod_phy_reg(pi, 0x221, (0x1 << 4), (1 << 4)); @@ -16703,8 +16634,62 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) &aux_adc_gain_rev7); wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x1c, 16, &aux_adc_gain_rev7); +}
- } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { +static void wlc_phy_workarounds_nphy_rev3(struct brcms_phy *pi) +{ + static const u8 rfseq_tx2rx_events_rev3[] = { + NPHY_REV3_RFSEQ_CMD_EXT_PA, + NPHY_REV3_RFSEQ_CMD_INT_PA_PU, + NPHY_REV3_RFSEQ_CMD_TX_GAIN, + NPHY_REV3_RFSEQ_CMD_RXPD_TXPD, + NPHY_REV3_RFSEQ_CMD_TR_SWITCH, + NPHY_REV3_RFSEQ_CMD_RXG_FBW, + NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS, + NPHY_REV3_RFSEQ_CMD_END + }; + static const u8 rfseq_tx2rx_dlys_rev3[] = { 8, 4, 2, 2, 4, 4, 6, 1 }; + u8 rfseq_rx2tx_events_rev3[] = { + NPHY_REV3_RFSEQ_CMD_NOP, + NPHY_REV3_RFSEQ_CMD_RXG_FBW, + NPHY_REV3_RFSEQ_CMD_TR_SWITCH, + NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS, + NPHY_REV3_RFSEQ_CMD_RXPD_TXPD, + NPHY_REV3_RFSEQ_CMD_TX_GAIN, + NPHY_REV3_RFSEQ_CMD_INT_PA_PU, + NPHY_REV3_RFSEQ_CMD_EXT_PA, + NPHY_REV3_RFSEQ_CMD_END + }; + u8 rfseq_rx2tx_dlys_rev3[] = { 8, 6, 6, 4, 4, 18, 42, 1, 1 }; + static const u8 rfseq_rx2tx_events_rev3_ipa[] = { + NPHY_REV3_RFSEQ_CMD_NOP, + NPHY_REV3_RFSEQ_CMD_RXG_FBW, + NPHY_REV3_RFSEQ_CMD_TR_SWITCH, + NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS, + NPHY_REV3_RFSEQ_CMD_RXPD_TXPD, + NPHY_REV3_RFSEQ_CMD_TX_GAIN, + NPHY_REV3_RFSEQ_CMD_CLR_RXRX_BIAS, + NPHY_REV3_RFSEQ_CMD_INT_PA_PU, + NPHY_REV3_RFSEQ_CMD_END + }; + static const u8 rfseq_rx2tx_dlys_rev3_ipa[] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 }; + s16 alpha0, alpha1, alpha2; + s16 beta0, beta1, beta2; + u32 leg_data_weights, ht_data_weights, nss1_data_weights, + stbc_data_weights; + u8 chan_freq_range = 0; + static const u16 dac_control = 0x0002; + u16 aux_adc_vmid_rev4[] = { 0xa2, 0xb4, 0xb4, 0x89 }; + u16 aux_adc_vmid_rev3[] = { 0xa2, 0xb4, 0xb4, 0x89 }; + u16 *aux_adc_vmid; + u16 aux_adc_gain_rev4[] = { 0x02, 0x02, 0x02, 0x00 }; + u16 aux_adc_gain_rev3[] = { 0x02, 0x02, 0x02, 0x00 }; + u16 *aux_adc_gain; + static const u16 sk_adc_vmid[] = { 0xb4, 0xb4, 0xb4, 0x24 }; + static const u16 sk_adc_gain[] = { 0x02, 0x02, 0x02, 0x02 }; + s32 min_nvar_val = 0x18d; + u8 pdetrange; + u8 triso;
write_phy_reg(pi, 0x23f, 0x1f8); write_phy_reg(pi, 0x240, 0x1f8); @@ -17030,7 +17015,33 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) MHF4_BPHY_TXCORE0, MHF4_BPHY_TXCORE0, BRCM_BAND_ALL); } - } else { +} + +void wlc_phy_workarounds_nphy_rev1(struct brcms_phy *pi) +{ + static const u8 rfseq_rx2tx_events[] = { + NPHY_RFSEQ_CMD_NOP, + NPHY_RFSEQ_CMD_RXG_FBW, + NPHY_RFSEQ_CMD_TR_SWITCH, + NPHY_RFSEQ_CMD_CLR_HIQ_DIS, + NPHY_RFSEQ_CMD_RXPD_TXPD, + NPHY_RFSEQ_CMD_TX_GAIN, + NPHY_RFSEQ_CMD_EXT_PA + }; + u8 rfseq_rx2tx_dlys[] = { 8, 6, 6, 2, 4, 60, 1 }; + static const u8 rfseq_tx2rx_events[] = { + NPHY_RFSEQ_CMD_NOP, + NPHY_RFSEQ_CMD_EXT_PA, + NPHY_RFSEQ_CMD_TX_GAIN, + NPHY_RFSEQ_CMD_RXPD_TXPD, + NPHY_RFSEQ_CMD_TR_SWITCH, + NPHY_RFSEQ_CMD_RXG_FBW, + NPHY_RFSEQ_CMD_CLR_HIQ_DIS + }; + static const u8 rfseq_tx2rx_dlys[] = { 8, 6, 2, 4, 4, 6, 1 }; + s16 alpha0, alpha1, alpha2; + s16 beta0, beta1, beta2; + u16 regval;
if (pi->sh->boardflags2 & BFL2_SKWRKFEM_BRD || (pi->sh->boardtype == 0x8b)) { @@ -17128,7 +17139,26 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) mod_phy_reg(pi, 0x221, NPHY_FORCESIG_DECODEGATEDCLKS, NPHY_FORCESIG_DECODEGATEDCLKS); - } +} + +static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) +{ + if (CHSPEC_IS5G(pi->radio_chanspec)) + wlc_phy_classifier_nphy(pi, NPHY_ClassifierCtrl_cck_en, 0); + else + wlc_phy_classifier_nphy(pi, NPHY_ClassifierCtrl_cck_en, 1); + + if (pi->phyhang_avoid) + wlc_phy_stay_in_carriersearch_nphy(pi, true); + + or_phy_reg(pi, 0xb1, NPHY_IQFlip_ADC1 | NPHY_IQFlip_ADC2); + + if (NREV_GE(pi->pubpi.phy_rev, 7)) + wlc_phy_workarounds_nphy_rev7(pi); + else if (NREV_GE(pi->pubpi.phy_rev, 3)) + wlc_phy_workarounds_nphy_rev3(pi); + else + wlc_phy_workarounds_nphy_rev1(pi);
if (pi->phyhang_avoid) wlc_phy_stay_in_carriersearch_nphy(pi, false);
On 2-3-2017 17:38, Arnd Bergmann wrote:
The stack consumption in this driver is still relatively high, with one remaining warning if the warning level is lowered to 1536 bytes:
drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c:17135:1: error: the frame size of 1880 bytes is larger than 1536 bytes [-Werror=frame-larger-than=]
The affected function is actually a collection of three separate implementations, and each of them is fairly large by itself. Splitting them up is done easily and improves readability at the same time.
I'm leaving the original indentation to make the review easier.
Thanks ;-)
Acked-by: Arend van Spriel arend.vanspriel@broadcom.com
Signed-off-by: Arnd Bergmann arnd@arndb.de
.../broadcom/brcm80211/brcmsmac/phy/phy_n.c | 178 ++++++++++++--------- 1 file changed, 104 insertions(+), 74 deletions(-)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c index 48a4df488d75..d76c092bb6b4 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c @@ -16061,52 +16061,8 @@ static void wlc_phy_workarounds_nphy_gainctrl(struct brcms_phy *pi) } } -static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) +static void wlc_phy_workarounds_nphy_rev7(struct brcms_phy *pi) {
- static const u8 rfseq_rx2tx_events[] = {
NPHY_RFSEQ_CMD_NOP,
NPHY_RFSEQ_CMD_RXG_FBW,
NPHY_RFSEQ_CMD_TR_SWITCH,
NPHY_RFSEQ_CMD_CLR_HIQ_DIS,
NPHY_RFSEQ_CMD_RXPD_TXPD,
NPHY_RFSEQ_CMD_TX_GAIN,
NPHY_RFSEQ_CMD_EXT_PA
- };
- u8 rfseq_rx2tx_dlys[] = { 8, 6, 6, 2, 4, 60, 1 };
- static const u8 rfseq_tx2rx_events[] = {
NPHY_RFSEQ_CMD_NOP,
NPHY_RFSEQ_CMD_EXT_PA,
NPHY_RFSEQ_CMD_TX_GAIN,
NPHY_RFSEQ_CMD_RXPD_TXPD,
NPHY_RFSEQ_CMD_TR_SWITCH,
NPHY_RFSEQ_CMD_RXG_FBW,
NPHY_RFSEQ_CMD_CLR_HIQ_DIS
- };
- static const u8 rfseq_tx2rx_dlys[] = { 8, 6, 2, 4, 4, 6, 1 };
- static const u8 rfseq_tx2rx_events_rev3[] = {
NPHY_REV3_RFSEQ_CMD_EXT_PA,
NPHY_REV3_RFSEQ_CMD_INT_PA_PU,
NPHY_REV3_RFSEQ_CMD_TX_GAIN,
NPHY_REV3_RFSEQ_CMD_RXPD_TXPD,
NPHY_REV3_RFSEQ_CMD_TR_SWITCH,
NPHY_REV3_RFSEQ_CMD_RXG_FBW,
NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS,
NPHY_REV3_RFSEQ_CMD_END
- };
- static const u8 rfseq_tx2rx_dlys_rev3[] = { 8, 4, 2, 2, 4, 4, 6, 1 };
- u8 rfseq_rx2tx_events_rev3[] = {
NPHY_REV3_RFSEQ_CMD_NOP,
NPHY_REV3_RFSEQ_CMD_RXG_FBW,
NPHY_REV3_RFSEQ_CMD_TR_SWITCH,
NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS,
NPHY_REV3_RFSEQ_CMD_RXPD_TXPD,
NPHY_REV3_RFSEQ_CMD_TX_GAIN,
NPHY_REV3_RFSEQ_CMD_INT_PA_PU,
NPHY_REV3_RFSEQ_CMD_EXT_PA,
NPHY_REV3_RFSEQ_CMD_END
- };
- u8 rfseq_rx2tx_dlys_rev3[] = { 8, 6, 6, 4, 4, 18, 42, 1, 1 };
- static const u8 rfseq_rx2tx_events_rev3_ipa[] = { NPHY_REV3_RFSEQ_CMD_NOP, NPHY_REV3_RFSEQ_CMD_RXG_FBW,
@@ -16120,29 +16076,15 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) }; static const u8 rfseq_rx2tx_dlys_rev3_ipa[] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 }; static const u16 rfseq_rx2tx_dacbufpu_rev7[] = { 0x10f, 0x10f };
- s16 alpha0, alpha1, alpha2;
- s16 beta0, beta1, beta2;
- u32 leg_data_weights, ht_data_weights, nss1_data_weights,
stbc_data_weights;
- u32 leg_data_weights; u8 chan_freq_range = 0; static const u16 dac_control = 0x0002; u16 aux_adc_vmid_rev7_core0[] = { 0x8e, 0x96, 0x96, 0x96 }; u16 aux_adc_vmid_rev7_core1[] = { 0x8f, 0x9f, 0x9f, 0x96 };
- u16 aux_adc_vmid_rev4[] = { 0xa2, 0xb4, 0xb4, 0x89 };
- u16 aux_adc_vmid_rev3[] = { 0xa2, 0xb4, 0xb4, 0x89 };
- u16 *aux_adc_vmid; u16 aux_adc_gain_rev7[] = { 0x02, 0x02, 0x02, 0x02 };
- u16 aux_adc_gain_rev4[] = { 0x02, 0x02, 0x02, 0x00 };
- u16 aux_adc_gain_rev3[] = { 0x02, 0x02, 0x02, 0x00 };
- u16 *aux_adc_gain;
- static const u16 sk_adc_vmid[] = { 0xb4, 0xb4, 0xb4, 0x24 };
- static const u16 sk_adc_gain[] = { 0x02, 0x02, 0x02, 0x02 }; s32 min_nvar_val = 0x18d; s32 min_nvar_offset_6mbps = 20; u8 pdetrange;
- u8 triso;
- u16 regval; u16 afectrl_adc_ctrl1_rev7 = 0x20; u16 afectrl_adc_ctrl2_rev7 = 0x0; u16 rfseq_rx2tx_lpf_h_hpc_rev7 = 0x77;
@@ -16171,17 +16113,6 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) u16 freq; int coreNum;
- if (CHSPEC_IS5G(pi->radio_chanspec))
wlc_phy_classifier_nphy(pi, NPHY_ClassifierCtrl_cck_en, 0);
- else
wlc_phy_classifier_nphy(pi, NPHY_ClassifierCtrl_cck_en, 1);
- if (pi->phyhang_avoid)
wlc_phy_stay_in_carriersearch_nphy(pi, true);
- or_phy_reg(pi, 0xb1, NPHY_IQFlip_ADC1 | NPHY_IQFlip_ADC2);
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
if (NREV_IS(pi->pubpi.phy_rev, 7)) { mod_phy_reg(pi, 0x221, (0x1 << 4), (1 << 4)); @@ -16703,8 +16634,62 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) &aux_adc_gain_rev7); wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x1c, 16, &aux_adc_gain_rev7); +}
- } else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+static void wlc_phy_workarounds_nphy_rev3(struct brcms_phy *pi) +{
- static const u8 rfseq_tx2rx_events_rev3[] = {
NPHY_REV3_RFSEQ_CMD_EXT_PA,
NPHY_REV3_RFSEQ_CMD_INT_PA_PU,
NPHY_REV3_RFSEQ_CMD_TX_GAIN,
NPHY_REV3_RFSEQ_CMD_RXPD_TXPD,
NPHY_REV3_RFSEQ_CMD_TR_SWITCH,
NPHY_REV3_RFSEQ_CMD_RXG_FBW,
NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS,
NPHY_REV3_RFSEQ_CMD_END
- };
- static const u8 rfseq_tx2rx_dlys_rev3[] = { 8, 4, 2, 2, 4, 4, 6, 1 };
- u8 rfseq_rx2tx_events_rev3[] = {
NPHY_REV3_RFSEQ_CMD_NOP,
NPHY_REV3_RFSEQ_CMD_RXG_FBW,
NPHY_REV3_RFSEQ_CMD_TR_SWITCH,
NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS,
NPHY_REV3_RFSEQ_CMD_RXPD_TXPD,
NPHY_REV3_RFSEQ_CMD_TX_GAIN,
NPHY_REV3_RFSEQ_CMD_INT_PA_PU,
NPHY_REV3_RFSEQ_CMD_EXT_PA,
NPHY_REV3_RFSEQ_CMD_END
- };
- u8 rfseq_rx2tx_dlys_rev3[] = { 8, 6, 6, 4, 4, 18, 42, 1, 1 };
- static const u8 rfseq_rx2tx_events_rev3_ipa[] = {
NPHY_REV3_RFSEQ_CMD_NOP,
NPHY_REV3_RFSEQ_CMD_RXG_FBW,
NPHY_REV3_RFSEQ_CMD_TR_SWITCH,
NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS,
NPHY_REV3_RFSEQ_CMD_RXPD_TXPD,
NPHY_REV3_RFSEQ_CMD_TX_GAIN,
NPHY_REV3_RFSEQ_CMD_CLR_RXRX_BIAS,
NPHY_REV3_RFSEQ_CMD_INT_PA_PU,
NPHY_REV3_RFSEQ_CMD_END
- };
- static const u8 rfseq_rx2tx_dlys_rev3_ipa[] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 };
- s16 alpha0, alpha1, alpha2;
- s16 beta0, beta1, beta2;
- u32 leg_data_weights, ht_data_weights, nss1_data_weights,
stbc_data_weights;
- u8 chan_freq_range = 0;
- static const u16 dac_control = 0x0002;
- u16 aux_adc_vmid_rev4[] = { 0xa2, 0xb4, 0xb4, 0x89 };
- u16 aux_adc_vmid_rev3[] = { 0xa2, 0xb4, 0xb4, 0x89 };
- u16 *aux_adc_vmid;
- u16 aux_adc_gain_rev4[] = { 0x02, 0x02, 0x02, 0x00 };
- u16 aux_adc_gain_rev3[] = { 0x02, 0x02, 0x02, 0x00 };
- u16 *aux_adc_gain;
- static const u16 sk_adc_vmid[] = { 0xb4, 0xb4, 0xb4, 0x24 };
- static const u16 sk_adc_gain[] = { 0x02, 0x02, 0x02, 0x02 };
- s32 min_nvar_val = 0x18d;
- u8 pdetrange;
- u8 triso;
write_phy_reg(pi, 0x23f, 0x1f8); write_phy_reg(pi, 0x240, 0x1f8); @@ -17030,7 +17015,33 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) MHF4_BPHY_TXCORE0, MHF4_BPHY_TXCORE0, BRCM_BAND_ALL); }
- } else {
+}
+void wlc_phy_workarounds_nphy_rev1(struct brcms_phy *pi) +{
- static const u8 rfseq_rx2tx_events[] = {
NPHY_RFSEQ_CMD_NOP,
NPHY_RFSEQ_CMD_RXG_FBW,
NPHY_RFSEQ_CMD_TR_SWITCH,
NPHY_RFSEQ_CMD_CLR_HIQ_DIS,
NPHY_RFSEQ_CMD_RXPD_TXPD,
NPHY_RFSEQ_CMD_TX_GAIN,
NPHY_RFSEQ_CMD_EXT_PA
- };
- u8 rfseq_rx2tx_dlys[] = { 8, 6, 6, 2, 4, 60, 1 };
- static const u8 rfseq_tx2rx_events[] = {
NPHY_RFSEQ_CMD_NOP,
NPHY_RFSEQ_CMD_EXT_PA,
NPHY_RFSEQ_CMD_TX_GAIN,
NPHY_RFSEQ_CMD_RXPD_TXPD,
NPHY_RFSEQ_CMD_TR_SWITCH,
NPHY_RFSEQ_CMD_RXG_FBW,
NPHY_RFSEQ_CMD_CLR_HIQ_DIS
- };
- static const u8 rfseq_tx2rx_dlys[] = { 8, 6, 2, 4, 4, 6, 1 };
- s16 alpha0, alpha1, alpha2;
- s16 beta0, beta1, beta2;
- u16 regval;
if (pi->sh->boardflags2 & BFL2_SKWRKFEM_BRD || (pi->sh->boardtype == 0x8b)) { @@ -17128,7 +17139,26 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) mod_phy_reg(pi, 0x221, NPHY_FORCESIG_DECODEGATEDCLKS, NPHY_FORCESIG_DECODEGATEDCLKS);
- }
+}
+static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) +{
- if (CHSPEC_IS5G(pi->radio_chanspec))
wlc_phy_classifier_nphy(pi, NPHY_ClassifierCtrl_cck_en, 0);
- else
wlc_phy_classifier_nphy(pi, NPHY_ClassifierCtrl_cck_en, 1);
- if (pi->phyhang_avoid)
wlc_phy_stay_in_carriersearch_nphy(pi, true);
- or_phy_reg(pi, 0xb1, NPHY_IQFlip_ADC1 | NPHY_IQFlip_ADC2);
- if (NREV_GE(pi->pubpi.phy_rev, 7))
wlc_phy_workarounds_nphy_rev7(pi);
- else if (NREV_GE(pi->pubpi.phy_rev, 3))
wlc_phy_workarounds_nphy_rev3(pi);
- else
wlc_phy_workarounds_nphy_rev1(pi);
if (pi->phyhang_avoid) wlc_phy_stay_in_carriersearch_nphy(pi, false);
In the previous commit I left the indentation alone to help reviewing the patch, this one now runs the three new functions through 'indent -kr -8' with some manual fixups to avoid silliness.
No changes other than whitespace are intended here.
Signed-off-by: Arnd Bergmann arnd@arndb.de --- .../broadcom/brcm80211/brcmsmac/phy/phy_n.c | 1507 +++++++++----------- 1 file changed, 697 insertions(+), 810 deletions(-)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c index d76c092bb6b4..9b39789c673d 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c @@ -16074,7 +16074,8 @@ static void wlc_phy_workarounds_nphy_rev7(struct brcms_phy *pi) NPHY_REV3_RFSEQ_CMD_INT_PA_PU, NPHY_REV3_RFSEQ_CMD_END }; - static const u8 rfseq_rx2tx_dlys_rev3_ipa[] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 }; + static const u8 rfseq_rx2tx_dlys_rev3_ipa[] = + { 8, 6, 6, 4, 4, 16, 43, 1, 1 }; static const u16 rfseq_rx2tx_dacbufpu_rev7[] = { 0x10f, 0x10f }; u32 leg_data_weights; u8 chan_freq_range = 0; @@ -16114,526 +16115,452 @@ static void wlc_phy_workarounds_nphy_rev7(struct brcms_phy *pi) int coreNum;
- if (NREV_IS(pi->pubpi.phy_rev, 7)) { - mod_phy_reg(pi, 0x221, (0x1 << 4), (1 << 4)); - - mod_phy_reg(pi, 0x160, (0x7f << 0), (32 << 0)); - mod_phy_reg(pi, 0x160, (0x7f << 8), (39 << 8)); - mod_phy_reg(pi, 0x161, (0x7f << 0), (46 << 0)); - mod_phy_reg(pi, 0x161, (0x7f << 8), (51 << 8)); - mod_phy_reg(pi, 0x162, (0x7f << 0), (55 << 0)); - mod_phy_reg(pi, 0x162, (0x7f << 8), (58 << 8)); - mod_phy_reg(pi, 0x163, (0x7f << 0), (60 << 0)); - mod_phy_reg(pi, 0x163, (0x7f << 8), (62 << 8)); - mod_phy_reg(pi, 0x164, (0x7f << 0), (62 << 0)); - mod_phy_reg(pi, 0x164, (0x7f << 8), (63 << 8)); - mod_phy_reg(pi, 0x165, (0x7f << 0), (63 << 0)); - mod_phy_reg(pi, 0x165, (0x7f << 8), (64 << 8)); - mod_phy_reg(pi, 0x166, (0x7f << 0), (64 << 0)); - mod_phy_reg(pi, 0x166, (0x7f << 8), (64 << 8)); - mod_phy_reg(pi, 0x167, (0x7f << 0), (64 << 0)); - mod_phy_reg(pi, 0x167, (0x7f << 8), (64 << 8)); - } - - if (NREV_LE(pi->pubpi.phy_rev, 8)) { - write_phy_reg(pi, 0x23f, 0x1b0); - write_phy_reg(pi, 0x240, 0x1b0); - } + if (NREV_IS(pi->pubpi.phy_rev, 7)) { + mod_phy_reg(pi, 0x221, (0x1 << 4), (1 << 4)); + + mod_phy_reg(pi, 0x160, (0x7f << 0), (32 << 0)); + mod_phy_reg(pi, 0x160, (0x7f << 8), (39 << 8)); + mod_phy_reg(pi, 0x161, (0x7f << 0), (46 << 0)); + mod_phy_reg(pi, 0x161, (0x7f << 8), (51 << 8)); + mod_phy_reg(pi, 0x162, (0x7f << 0), (55 << 0)); + mod_phy_reg(pi, 0x162, (0x7f << 8), (58 << 8)); + mod_phy_reg(pi, 0x163, (0x7f << 0), (60 << 0)); + mod_phy_reg(pi, 0x163, (0x7f << 8), (62 << 8)); + mod_phy_reg(pi, 0x164, (0x7f << 0), (62 << 0)); + mod_phy_reg(pi, 0x164, (0x7f << 8), (63 << 8)); + mod_phy_reg(pi, 0x165, (0x7f << 0), (63 << 0)); + mod_phy_reg(pi, 0x165, (0x7f << 8), (64 << 8)); + mod_phy_reg(pi, 0x166, (0x7f << 0), (64 << 0)); + mod_phy_reg(pi, 0x166, (0x7f << 8), (64 << 8)); + mod_phy_reg(pi, 0x167, (0x7f << 0), (64 << 0)); + mod_phy_reg(pi, 0x167, (0x7f << 8), (64 << 8)); + }
- if (NREV_GE(pi->pubpi.phy_rev, 8)) - mod_phy_reg(pi, 0xbd, (0xff << 0), (114 << 0)); + if (NREV_LE(pi->pubpi.phy_rev, 8)) { + write_phy_reg(pi, 0x23f, 0x1b0); + write_phy_reg(pi, 0x240, 0x1b0); + }
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x00, 16, - &dac_control); - wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x10, 16, - &dac_control); + if (NREV_GE(pi->pubpi.phy_rev, 8)) + mod_phy_reg(pi, 0xbd, (0xff << 0), (114 << 0));
- wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL, - 1, 0, 32, &leg_data_weights); - leg_data_weights = leg_data_weights & 0xffffff; - wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL, - 1, 0, 32, &leg_data_weights); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x00, 16, + &dac_control); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x10, 16, + &dac_control);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, - 2, 0x15e, 16, - rfseq_rx2tx_dacbufpu_rev7); - wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x16e, 16, - rfseq_rx2tx_dacbufpu_rev7); + wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL, + 1, 0, 32, &leg_data_weights); + leg_data_weights = leg_data_weights & 0xffffff; + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL, + 1, 0, 32, &leg_data_weights);
- if (PHY_IPA(pi)) - wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX, - rfseq_rx2tx_events_rev3_ipa, - rfseq_rx2tx_dlys_rev3_ipa, - ARRAY_SIZE(rfseq_rx2tx_events_rev3_ipa)); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, + 2, 0x15e, 16, rfseq_rx2tx_dacbufpu_rev7); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x16e, 16, + rfseq_rx2tx_dacbufpu_rev7);
- mod_phy_reg(pi, 0x299, (0x3 << 14), (0x1 << 14)); - mod_phy_reg(pi, 0x29d, (0x3 << 14), (0x1 << 14)); + if (PHY_IPA(pi)) + wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX, + rfseq_rx2tx_events_rev3_ipa, + rfseq_rx2tx_dlys_rev3_ipa, + ARRAY_SIZE + (rfseq_rx2tx_events_rev3_ipa));
- tx_lpf_bw_ofdm_20mhz = wlc_phy_read_lpf_bw_ctl_nphy(pi, 0x154); - tx_lpf_bw_ofdm_40mhz = wlc_phy_read_lpf_bw_ctl_nphy(pi, 0x159); - tx_lpf_bw_11b = wlc_phy_read_lpf_bw_ctl_nphy(pi, 0x152); + mod_phy_reg(pi, 0x299, (0x3 << 14), (0x1 << 14)); + mod_phy_reg(pi, 0x29d, (0x3 << 14), (0x1 << 14));
- if (PHY_IPA(pi)) { + tx_lpf_bw_ofdm_20mhz = wlc_phy_read_lpf_bw_ctl_nphy(pi, 0x154); + tx_lpf_bw_ofdm_40mhz = wlc_phy_read_lpf_bw_ctl_nphy(pi, 0x159); + tx_lpf_bw_11b = wlc_phy_read_lpf_bw_ctl_nphy(pi, 0x152);
- if (((pi->pubpi.radiorev == 5) - && (CHSPEC_IS40(pi->radio_chanspec) == 1)) - || (pi->pubpi.radiorev == 7) - || (pi->pubpi.radiorev == 8)) { + if (PHY_IPA(pi)) {
- rccal_bcap_val = - read_radio_reg( - pi, - RADIO_2057_RCCAL_BCAP_VAL); - rccal_scap_val = - read_radio_reg( - pi, - RADIO_2057_RCCAL_SCAP_VAL); + if (((pi->pubpi.radiorev == 5) + && (CHSPEC_IS40(pi->radio_chanspec) == 1)) + || (pi->pubpi.radiorev == 7) + || (pi->pubpi.radiorev == 8)) {
- rccal_tx20_11b_bcap = rccal_bcap_val; - rccal_tx20_11b_scap = rccal_scap_val; + rccal_bcap_val = + read_radio_reg(pi, RADIO_2057_RCCAL_BCAP_VAL); + rccal_scap_val = + read_radio_reg(pi, RADIO_2057_RCCAL_SCAP_VAL);
- if ((pi->pubpi.radiorev == 5) && - (CHSPEC_IS40(pi->radio_chanspec) == 1)) { + rccal_tx20_11b_bcap = rccal_bcap_val; + rccal_tx20_11b_scap = rccal_scap_val;
- rccal_tx20_11n_bcap = rccal_bcap_val; - rccal_tx20_11n_scap = rccal_scap_val; - rccal_tx40_11n_bcap = 0xc; - rccal_tx40_11n_scap = 0xc; + if ((pi->pubpi.radiorev == 5) && + (CHSPEC_IS40(pi->radio_chanspec) == 1)) {
- rccal_ovrd = true; + rccal_tx20_11n_bcap = rccal_bcap_val; + rccal_tx20_11n_scap = rccal_scap_val; + rccal_tx40_11n_bcap = 0xc; + rccal_tx40_11n_scap = 0xc;
- } else if ((pi->pubpi.radiorev == 7) - || (pi->pubpi.radiorev == 8)) { + rccal_ovrd = true;
- tx_lpf_bw_ofdm_20mhz = 4; - tx_lpf_bw_11b = 1; + } else if ((pi->pubpi.radiorev == 7) + || (pi->pubpi.radiorev == 8)) {
- if (CHSPEC_IS2G(pi->radio_chanspec)) { - rccal_tx20_11n_bcap = 0xc; - rccal_tx20_11n_scap = 0xc; - rccal_tx40_11n_bcap = 0xa; - rccal_tx40_11n_scap = 0xa; - } else { - rccal_tx20_11n_bcap = 0x14; - rccal_tx20_11n_scap = 0x14; - rccal_tx40_11n_bcap = 0xf; - rccal_tx40_11n_scap = 0xf; - } + tx_lpf_bw_ofdm_20mhz = 4; + tx_lpf_bw_11b = 1;
- rccal_ovrd = true; + if (CHSPEC_IS2G(pi->radio_chanspec)) { + rccal_tx20_11n_bcap = 0xc; + rccal_tx20_11n_scap = 0xc; + rccal_tx40_11n_bcap = 0xa; + rccal_tx40_11n_scap = 0xa; + } else { + rccal_tx20_11n_bcap = 0x14; + rccal_tx20_11n_scap = 0x14; + rccal_tx40_11n_bcap = 0xf; + rccal_tx40_11n_scap = 0xf; } + + rccal_ovrd = true; } + }
- } else { + } else {
- if (pi->pubpi.radiorev == 5) { + if (pi->pubpi.radiorev == 5) {
- tx_lpf_bw_ofdm_20mhz = 1; - tx_lpf_bw_ofdm_40mhz = 3; + tx_lpf_bw_ofdm_20mhz = 1; + tx_lpf_bw_ofdm_40mhz = 3;
- rccal_bcap_val = - read_radio_reg( - pi, - RADIO_2057_RCCAL_BCAP_VAL); - rccal_scap_val = - read_radio_reg( - pi, - RADIO_2057_RCCAL_SCAP_VAL); + rccal_bcap_val = + read_radio_reg(pi, RADIO_2057_RCCAL_BCAP_VAL); + rccal_scap_val = + read_radio_reg(pi, RADIO_2057_RCCAL_SCAP_VAL);
- rccal_tx20_11b_bcap = rccal_bcap_val; - rccal_tx20_11b_scap = rccal_scap_val; + rccal_tx20_11b_bcap = rccal_bcap_val; + rccal_tx20_11b_scap = rccal_scap_val;
- rccal_tx20_11n_bcap = 0x13; - rccal_tx20_11n_scap = 0x11; - rccal_tx40_11n_bcap = 0x13; - rccal_tx40_11n_scap = 0x11; + rccal_tx20_11n_bcap = 0x13; + rccal_tx20_11n_scap = 0x11; + rccal_tx40_11n_bcap = 0x13; + rccal_tx40_11n_scap = 0x11;
- rccal_ovrd = true; - } + rccal_ovrd = true; } + }
- if (rccal_ovrd) { - - rx2tx_lpf_rc_lut_tx20_11b = - (rccal_tx20_11b_bcap << 8) | - (rccal_tx20_11b_scap << 3) | - tx_lpf_bw_11b; - rx2tx_lpf_rc_lut_tx20_11n = - (rccal_tx20_11n_bcap << 8) | - (rccal_tx20_11n_scap << 3) | - tx_lpf_bw_ofdm_20mhz; - rx2tx_lpf_rc_lut_tx40_11n = - (rccal_tx40_11n_bcap << 8) | - (rccal_tx40_11n_scap << 3) | - tx_lpf_bw_ofdm_40mhz; + if (rccal_ovrd) {
- for (coreNum = 0; coreNum <= 1; coreNum++) { - wlc_phy_table_write_nphy( - pi, NPHY_TBL_ID_RFSEQ, - 1, - 0x152 + coreNum * 0x10, - 16, - &rx2tx_lpf_rc_lut_tx20_11b); - wlc_phy_table_write_nphy( - pi, NPHY_TBL_ID_RFSEQ, - 1, - 0x153 + coreNum * 0x10, - 16, - &rx2tx_lpf_rc_lut_tx20_11n); - wlc_phy_table_write_nphy( - pi, NPHY_TBL_ID_RFSEQ, - 1, - 0x154 + coreNum * 0x10, - 16, - &rx2tx_lpf_rc_lut_tx20_11n); - wlc_phy_table_write_nphy( - pi, NPHY_TBL_ID_RFSEQ, - 1, - 0x155 + coreNum * 0x10, - 16, - &rx2tx_lpf_rc_lut_tx40_11n); - wlc_phy_table_write_nphy( - pi, NPHY_TBL_ID_RFSEQ, - 1, - 0x156 + coreNum * 0x10, - 16, - &rx2tx_lpf_rc_lut_tx40_11n); - wlc_phy_table_write_nphy( - pi, NPHY_TBL_ID_RFSEQ, - 1, - 0x157 + coreNum * 0x10, - 16, - &rx2tx_lpf_rc_lut_tx40_11n); - wlc_phy_table_write_nphy( - pi, NPHY_TBL_ID_RFSEQ, - 1, - 0x158 + coreNum * 0x10, - 16, - &rx2tx_lpf_rc_lut_tx40_11n); - wlc_phy_table_write_nphy( - pi, NPHY_TBL_ID_RFSEQ, - 1, - 0x159 + coreNum * 0x10, - 16, - &rx2tx_lpf_rc_lut_tx40_11n); - } + rx2tx_lpf_rc_lut_tx20_11b = + (rccal_tx20_11b_bcap << 8) | + (rccal_tx20_11b_scap << 3) | tx_lpf_bw_11b; + rx2tx_lpf_rc_lut_tx20_11n = + (rccal_tx20_11n_bcap << 8) | + (rccal_tx20_11n_scap << 3) | tx_lpf_bw_ofdm_20mhz; + rx2tx_lpf_rc_lut_tx40_11n = + (rccal_tx40_11n_bcap << 8) | + (rccal_tx40_11n_scap << 3) | tx_lpf_bw_ofdm_40mhz;
- wlc_phy_rfctrl_override_nphy_rev7( - pi, (0x1 << 4), - 1, 0x3, 0, - NPHY_REV7_RFCTRLOVERRIDE_ID2); + for (coreNum = 0; coreNum <= 1; coreNum++) { + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, + 0x152 + coreNum * 0x10, 16, + &rx2tx_lpf_rc_lut_tx20_11b); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, + 0x153 + coreNum * 0x10, 16, + &rx2tx_lpf_rc_lut_tx20_11n); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, + 0x154 + coreNum * 0x10, 16, + &rx2tx_lpf_rc_lut_tx20_11n); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, + 0x155 + coreNum * 0x10, 16, + &rx2tx_lpf_rc_lut_tx40_11n); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, + 0x156 + coreNum * 0x10, 16, + &rx2tx_lpf_rc_lut_tx40_11n); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, + 0x157 + coreNum * 0x10, 16, + &rx2tx_lpf_rc_lut_tx40_11n); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, + 0x158 + coreNum * 0x10, 16, + &rx2tx_lpf_rc_lut_tx40_11n); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, + 0x159 + coreNum * 0x10, 16, + &rx2tx_lpf_rc_lut_tx40_11n); }
- write_phy_reg(pi, 0x32f, 0x3); + wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4), 1, 0x3, 0, + NPHY_REV7_RFCTRLOVERRIDE_ID2); + }
- if ((pi->pubpi.radiorev == 4) || (pi->pubpi.radiorev == 6)) - wlc_phy_rfctrl_override_nphy_rev7( - pi, (0x1 << 2), - 1, 0x3, 0, - NPHY_REV7_RFCTRLOVERRIDE_ID0); + write_phy_reg(pi, 0x32f, 0x3);
- if ((pi->pubpi.radiorev == 3) || (pi->pubpi.radiorev == 4) || - (pi->pubpi.radiorev == 6)) { - if ((pi->sh->sromrev >= 8) - && (pi->sh->boardflags2 & BFL2_IPALVLSHIFT_3P3)) - ipalvlshift_3p3_war_en = 1; - - if (ipalvlshift_3p3_war_en) { - write_radio_reg(pi, RADIO_2057_GPAIO_CONFIG, - 0x5); - write_radio_reg(pi, RADIO_2057_GPAIO_SEL1, - 0x30); - write_radio_reg(pi, RADIO_2057_GPAIO_SEL0, 0x0); - or_radio_reg(pi, - RADIO_2057_RXTXBIAS_CONFIG_CORE0, - 0x1); - or_radio_reg(pi, - RADIO_2057_RXTXBIAS_CONFIG_CORE1, - 0x1); - - ipa2g_mainbias = 0x1f; - - ipa2g_casconv = 0x6f; - - ipa2g_biasfilt = 0xaa; - } else { + if ((pi->pubpi.radiorev == 4) || (pi->pubpi.radiorev == 6)) + wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), 1, 0x3, 0, + NPHY_REV7_RFCTRLOVERRIDE_ID0);
- ipa2g_mainbias = 0x2b; + if ((pi->pubpi.radiorev == 3) || (pi->pubpi.radiorev == 4) || + (pi->pubpi.radiorev == 6)) { + if ((pi->sh->sromrev >= 8) + && (pi->sh->boardflags2 & BFL2_IPALVLSHIFT_3P3)) + ipalvlshift_3p3_war_en = 1;
- ipa2g_casconv = 0x7f; + if (ipalvlshift_3p3_war_en) { + write_radio_reg(pi, RADIO_2057_GPAIO_CONFIG, 0x5); + write_radio_reg(pi, RADIO_2057_GPAIO_SEL1, 0x30); + write_radio_reg(pi, RADIO_2057_GPAIO_SEL0, 0x0); + or_radio_reg(pi, RADIO_2057_RXTXBIAS_CONFIG_CORE0, 0x1); + or_radio_reg(pi, RADIO_2057_RXTXBIAS_CONFIG_CORE1, 0x1);
- ipa2g_biasfilt = 0xee; - } + ipa2g_mainbias = 0x1f;
- if (CHSPEC_IS2G(pi->radio_chanspec)) { - for (coreNum = 0; coreNum <= 1; coreNum++) { - WRITE_RADIO_REG4(pi, RADIO_2057, CORE, - coreNum, IPA2G_IMAIN, - ipa2g_mainbias); - WRITE_RADIO_REG4(pi, RADIO_2057, CORE, - coreNum, IPA2G_CASCONV, - ipa2g_casconv); - WRITE_RADIO_REG4(pi, RADIO_2057, CORE, - coreNum, - IPA2G_BIAS_FILTER, - ipa2g_biasfilt); - } - } - } + ipa2g_casconv = 0x6f;
- if (PHY_IPA(pi)) { - if (CHSPEC_IS2G(pi->radio_chanspec)) { - if ((pi->pubpi.radiorev == 3) - || (pi->pubpi.radiorev == 4) - || (pi->pubpi.radiorev == 6)) - txgm_idac_bleed = 0x7f; + ipa2g_biasfilt = 0xaa; + } else {
- for (coreNum = 0; coreNum <= 1; coreNum++) { - if (txgm_idac_bleed != 0) - WRITE_RADIO_REG4( - pi, RADIO_2057, - CORE, coreNum, - TXGM_IDAC_BLEED, - txgm_idac_bleed); - } + ipa2g_mainbias = 0x2b;
- if (pi->pubpi.radiorev == 5) { - - for (coreNum = 0; coreNum <= 1; - coreNum++) { - WRITE_RADIO_REG4(pi, RADIO_2057, - CORE, coreNum, - IPA2G_CASCONV, - 0x13); - WRITE_RADIO_REG4(pi, RADIO_2057, - CORE, coreNum, - IPA2G_IMAIN, - 0x1f); - WRITE_RADIO_REG4( - pi, RADIO_2057, - CORE, coreNum, - IPA2G_BIAS_FILTER, - 0xee); - WRITE_RADIO_REG4(pi, RADIO_2057, - CORE, coreNum, - PAD2G_IDACS, - 0x8a); - WRITE_RADIO_REG4( - pi, RADIO_2057, - CORE, coreNum, - PAD_BIAS_FILTER_BWS, - 0x3e); - } + ipa2g_casconv = 0x7f;
- } else if ((pi->pubpi.radiorev == 7) - || (pi->pubpi.radiorev == 8)) { + ipa2g_biasfilt = 0xee; + }
- if (CHSPEC_IS40(pi->radio_chanspec) == - 0) { - WRITE_RADIO_REG4(pi, RADIO_2057, - CORE, 0, - IPA2G_IMAIN, - 0x14); - WRITE_RADIO_REG4(pi, RADIO_2057, - CORE, 1, - IPA2G_IMAIN, - 0x12); - } else { - WRITE_RADIO_REG4(pi, RADIO_2057, - CORE, 0, - IPA2G_IMAIN, - 0x16); - WRITE_RADIO_REG4(pi, RADIO_2057, - CORE, 1, - IPA2G_IMAIN, - 0x16); - } - } + if (CHSPEC_IS2G(pi->radio_chanspec)) { + for (coreNum = 0; coreNum <= 1; coreNum++) { + WRITE_RADIO_REG4(pi, RADIO_2057, CORE, + coreNum, IPA2G_IMAIN, + ipa2g_mainbias); + WRITE_RADIO_REG4(pi, RADIO_2057, CORE, + coreNum, IPA2G_CASCONV, + ipa2g_casconv); + WRITE_RADIO_REG4(pi, RADIO_2057, CORE, + coreNum, + IPA2G_BIAS_FILTER, + ipa2g_biasfilt); + } + } + }
- } else { - freq = CHAN5G_FREQ(CHSPEC_CHANNEL( - pi->radio_chanspec)); - if (((freq >= 5180) && (freq <= 5230)) - || ((freq >= 5745) && (freq <= 5805))) { - WRITE_RADIO_REG4(pi, RADIO_2057, CORE, - 0, IPA5G_BIAS_FILTER, - 0xff); - WRITE_RADIO_REG4(pi, RADIO_2057, CORE, - 1, IPA5G_BIAS_FILTER, - 0xff); - } + if (PHY_IPA(pi)) { + if (CHSPEC_IS2G(pi->radio_chanspec)) { + if ((pi->pubpi.radiorev == 3) + || (pi->pubpi.radiorev == 4) + || (pi->pubpi.radiorev == 6)) + txgm_idac_bleed = 0x7f; + + for (coreNum = 0; coreNum <= 1; coreNum++) { + if (txgm_idac_bleed != 0) + WRITE_RADIO_REG4(pi, RADIO_2057, + CORE, coreNum, + TXGM_IDAC_BLEED, + txgm_idac_bleed); } - } else {
- if (pi->pubpi.radiorev != 5) { + if (pi->pubpi.radiorev == 5) { for (coreNum = 0; coreNum <= 1; coreNum++) { + WRITE_RADIO_REG4(pi, RADIO_2057, + CORE, coreNum, + IPA2G_CASCONV, + 0x13); + WRITE_RADIO_REG4(pi, RADIO_2057, + CORE, coreNum, + IPA2G_IMAIN, + 0x1f); + WRITE_RADIO_REG4(pi, RADIO_2057, + CORE, coreNum, + IPA2G_BIAS_FILTER, + 0xee); + WRITE_RADIO_REG4(pi, RADIO_2057, + CORE, coreNum, + PAD2G_IDACS, + 0x8a); + WRITE_RADIO_REG4(pi, RADIO_2057, + CORE, coreNum, + PAD_BIAS_FILTER_BWS, + 0x3e); + } + } else if ((pi->pubpi.radiorev == 7) || + (pi->pubpi.radiorev == 8)) { + + if (CHSPEC_IS40(pi->radio_chanspec) == 0) { + WRITE_RADIO_REG4(pi, RADIO_2057, CORE, + 0, IPA2G_IMAIN, 0x14); + WRITE_RADIO_REG4(pi, RADIO_2057, CORE, + 1, IPA2G_IMAIN, 0x12); + } else { WRITE_RADIO_REG4(pi, RADIO_2057, CORE, - coreNum, - TXMIX2G_TUNE_BOOST_PU, - 0x61); + 0, IPA2G_IMAIN, 0x16); WRITE_RADIO_REG4(pi, RADIO_2057, CORE, - coreNum, - TXGM_IDAC_BLEED, 0x70); + 1, IPA2G_IMAIN, 0x16); } } - }
- if (pi->pubpi.radiorev == 4) { - wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, - 0x05, 16, - &afectrl_adc_ctrl1_rev7); - wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, - 0x15, 16, - &afectrl_adc_ctrl1_rev7); + } else { + freq = + CHAN5G_FREQ(CHSPEC_CHANNEL + (pi->radio_chanspec)); + if (((freq >= 5180) && (freq <= 5230)) + || ((freq >= 5745) && (freq <= 5805))) { + WRITE_RADIO_REG4(pi, RADIO_2057, CORE, + 0, IPA5G_BIAS_FILTER, 0xff); + WRITE_RADIO_REG4(pi, RADIO_2057, CORE, + 1, IPA5G_BIAS_FILTER, 0xff); + } + } + } else {
+ if (pi->pubpi.radiorev != 5) { for (coreNum = 0; coreNum <= 1; coreNum++) { WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum, - AFE_VCM_CAL_MASTER, 0x0); - WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum, - AFE_SET_VCM_I, 0x3f); + TXMIX2G_TUNE_BOOST_PU, 0x61); WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum, - AFE_SET_VCM_Q, 0x3f); + TXGM_IDAC_BLEED, 0x70); } - } else { - mod_phy_reg(pi, 0xa6, (0x1 << 2), (0x1 << 2)); - mod_phy_reg(pi, 0x8f, (0x1 << 2), (0x1 << 2)); - mod_phy_reg(pi, 0xa7, (0x1 << 2), (0x1 << 2)); - mod_phy_reg(pi, 0xa5, (0x1 << 2), (0x1 << 2)); - - mod_phy_reg(pi, 0xa6, (0x1 << 0), 0); - mod_phy_reg(pi, 0x8f, (0x1 << 0), (0x1 << 0)); - mod_phy_reg(pi, 0xa7, (0x1 << 0), 0); - mod_phy_reg(pi, 0xa5, (0x1 << 0), (0x1 << 0)); - - wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, - 0x05, 16, - &afectrl_adc_ctrl2_rev7); - wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, - 0x15, 16, - &afectrl_adc_ctrl2_rev7); - - mod_phy_reg(pi, 0xa6, (0x1 << 2), 0); - mod_phy_reg(pi, 0x8f, (0x1 << 2), 0); - mod_phy_reg(pi, 0xa7, (0x1 << 2), 0); - mod_phy_reg(pi, 0xa5, (0x1 << 2), 0); } + }
- write_phy_reg(pi, 0x6a, 0x2); + if (pi->pubpi.radiorev == 4) { + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x05, 16, + &afectrl_adc_ctrl1_rev7); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x15, 16, + &afectrl_adc_ctrl1_rev7);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 256, 32, - &min_nvar_offset_6mbps); + for (coreNum = 0; coreNum <= 1; coreNum++) { + WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum, + AFE_VCM_CAL_MASTER, 0x0); + WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum, + AFE_SET_VCM_I, 0x3f); + WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum, + AFE_SET_VCM_Q, 0x3f); + } + } else { + mod_phy_reg(pi, 0xa6, (0x1 << 2), (0x1 << 2)); + mod_phy_reg(pi, 0x8f, (0x1 << 2), (0x1 << 2)); + mod_phy_reg(pi, 0xa7, (0x1 << 2), (0x1 << 2)); + mod_phy_reg(pi, 0xa5, (0x1 << 2), (0x1 << 2));
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x138, 16, - &rfseq_pktgn_lpf_hpc_rev7); + mod_phy_reg(pi, 0xa6, (0x1 << 0), 0); + mod_phy_reg(pi, 0x8f, (0x1 << 0), (0x1 << 0)); + mod_phy_reg(pi, 0xa7, (0x1 << 0), 0); + mod_phy_reg(pi, 0xa5, (0x1 << 0), (0x1 << 0));
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, 0x141, 16, - &rfseq_pktgn_lpf_h_hpc_rev7); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x05, 16, + &afectrl_adc_ctrl2_rev7); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x15, 16, + &afectrl_adc_ctrl2_rev7);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 3, 0x133, 16, - &rfseq_htpktgn_lpf_hpc_rev7); + mod_phy_reg(pi, 0xa6, (0x1 << 2), 0); + mod_phy_reg(pi, 0x8f, (0x1 << 2), 0); + mod_phy_reg(pi, 0xa7, (0x1 << 2), 0); + mod_phy_reg(pi, 0xa5, (0x1 << 2), 0); + }
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x146, 16, - &rfseq_cckpktgn_lpf_hpc_rev7); + write_phy_reg(pi, 0x6a, 0x2);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, 0x123, 16, - &rfseq_tx2rx_lpf_h_hpc_rev7); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 256, 32, + &min_nvar_offset_6mbps);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, 0x12A, 16, - &rfseq_rx2tx_lpf_h_hpc_rev7); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x138, 16, + &rfseq_pktgn_lpf_hpc_rev7);
- if (CHSPEC_IS40(pi->radio_chanspec) == 0) { - wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 3, - 32, &min_nvar_val); - wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, - 127, 32, &min_nvar_val); - } else { - min_nvar_val = noise_var_tbl_rev7[3]; - wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 3, - 32, &min_nvar_val); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, 0x141, 16, + &rfseq_pktgn_lpf_h_hpc_rev7);
- min_nvar_val = noise_var_tbl_rev7[127]; - wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, - 127, 32, &min_nvar_val); - } + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 3, 0x133, 16, + &rfseq_htpktgn_lpf_hpc_rev7);
- wlc_phy_workarounds_nphy_gainctrl(pi); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x146, 16, + &rfseq_cckpktgn_lpf_hpc_rev7);
- pdetrange = - (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g. - pdetrange : pi->srom_fem2g.pdetrange; + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, 0x123, 16, + &rfseq_tx2rx_lpf_h_hpc_rev7);
- if (pdetrange == 0) { - chan_freq_range = - wlc_phy_get_chan_freq_range_nphy(pi, 0); - if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) { - aux_adc_vmid_rev7_core0[3] = 0x70; - aux_adc_vmid_rev7_core1[3] = 0x70; - aux_adc_gain_rev7[3] = 2; - } else { - aux_adc_vmid_rev7_core0[3] = 0x80; - aux_adc_vmid_rev7_core1[3] = 0x80; - aux_adc_gain_rev7[3] = 3; - } - } else if (pdetrange == 1) { - if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) { - aux_adc_vmid_rev7_core0[3] = 0x7c; - aux_adc_vmid_rev7_core1[3] = 0x7c; - aux_adc_gain_rev7[3] = 2; - } else { - aux_adc_vmid_rev7_core0[3] = 0x8c; - aux_adc_vmid_rev7_core1[3] = 0x8c; - aux_adc_gain_rev7[3] = 1; - } - } else if (pdetrange == 2) { - if (pi->pubpi.radioid == BCM2057_ID) { - if ((pi->pubpi.radiorev == 5) - || (pi->pubpi.radiorev == 7) - || (pi->pubpi.radiorev == 8)) { - if (chan_freq_range == - WL_CHAN_FREQ_RANGE_2G) { - aux_adc_vmid_rev7_core0[3] = - 0x8c; - aux_adc_vmid_rev7_core1[3] = - 0x8c; - aux_adc_gain_rev7[3] = 0; - } else { - aux_adc_vmid_rev7_core0[3] = - 0x96; - aux_adc_vmid_rev7_core1[3] = - 0x96; - aux_adc_gain_rev7[3] = 0; - } + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, 0x12A, 16, + &rfseq_rx2tx_lpf_h_hpc_rev7); + + if (CHSPEC_IS40(pi->radio_chanspec) == 0) { + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 3, + 32, &min_nvar_val); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, + 127, 32, &min_nvar_val); + } else { + min_nvar_val = noise_var_tbl_rev7[3]; + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 3, + 32, &min_nvar_val); + + min_nvar_val = noise_var_tbl_rev7[127]; + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, + 127, 32, &min_nvar_val); + } + + wlc_phy_workarounds_nphy_gainctrl(pi); + + pdetrange = (CHSPEC_IS5G(pi->radio_chanspec)) ? + pi->srom_fem5g.pdetrange : pi->srom_fem2g.pdetrange; + + if (pdetrange == 0) { + chan_freq_range = wlc_phy_get_chan_freq_range_nphy(pi, 0); + if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) { + aux_adc_vmid_rev7_core0[3] = 0x70; + aux_adc_vmid_rev7_core1[3] = 0x70; + aux_adc_gain_rev7[3] = 2; + } else { + aux_adc_vmid_rev7_core0[3] = 0x80; + aux_adc_vmid_rev7_core1[3] = 0x80; + aux_adc_gain_rev7[3] = 3; + } + } else if (pdetrange == 1) { + if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) { + aux_adc_vmid_rev7_core0[3] = 0x7c; + aux_adc_vmid_rev7_core1[3] = 0x7c; + aux_adc_gain_rev7[3] = 2; + } else { + aux_adc_vmid_rev7_core0[3] = 0x8c; + aux_adc_vmid_rev7_core1[3] = 0x8c; + aux_adc_gain_rev7[3] = 1; + } + } else if (pdetrange == 2) { + if (pi->pubpi.radioid == BCM2057_ID) { + if ((pi->pubpi.radiorev == 5) + || (pi->pubpi.radiorev == 7) + || (pi->pubpi.radiorev == 8)) { + if (chan_freq_range == + WL_CHAN_FREQ_RANGE_2G) { + aux_adc_vmid_rev7_core0[3] = 0x8c; + aux_adc_vmid_rev7_core1[3] = 0x8c; + aux_adc_gain_rev7[3] = 0; + } else { + aux_adc_vmid_rev7_core0[3] = 0x96; + aux_adc_vmid_rev7_core1[3] = 0x96; + aux_adc_gain_rev7[3] = 0; } } + }
- } else if (pdetrange == 3) { - if (chan_freq_range == WL_CHAN_FREQ_RANGE_2G) { - aux_adc_vmid_rev7_core0[3] = 0x89; - aux_adc_vmid_rev7_core1[3] = 0x89; - aux_adc_gain_rev7[3] = 0; - } + } else if (pdetrange == 3) { + if (chan_freq_range == WL_CHAN_FREQ_RANGE_2G) { + aux_adc_vmid_rev7_core0[3] = 0x89; + aux_adc_vmid_rev7_core1[3] = 0x89; + aux_adc_gain_rev7[3] = 0; + }
- } else if (pdetrange == 5) { + } else if (pdetrange == 5) {
- if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) { - aux_adc_vmid_rev7_core0[3] = 0x80; - aux_adc_vmid_rev7_core1[3] = 0x80; - aux_adc_gain_rev7[3] = 3; - } else { - aux_adc_vmid_rev7_core0[3] = 0x70; - aux_adc_vmid_rev7_core1[3] = 0x70; - aux_adc_gain_rev7[3] = 2; - } + if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) { + aux_adc_vmid_rev7_core0[3] = 0x80; + aux_adc_vmid_rev7_core1[3] = 0x80; + aux_adc_gain_rev7[3] = 3; + } else { + aux_adc_vmid_rev7_core0[3] = 0x70; + aux_adc_vmid_rev7_core1[3] = 0x70; + aux_adc_gain_rev7[3] = 2; } + }
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x08, 16, - &aux_adc_vmid_rev7_core0); - wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x18, 16, - &aux_adc_vmid_rev7_core1); - wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x0c, 16, - &aux_adc_gain_rev7); - wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x1c, 16, - &aux_adc_gain_rev7); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x08, 16, + &aux_adc_vmid_rev7_core0); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x18, 16, + &aux_adc_vmid_rev7_core1); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x0c, 16, + &aux_adc_gain_rev7); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x1c, 16, + &aux_adc_gain_rev7); }
static void wlc_phy_workarounds_nphy_rev3(struct brcms_phy *pi) @@ -16672,7 +16599,8 @@ static void wlc_phy_workarounds_nphy_rev3(struct brcms_phy *pi) NPHY_REV3_RFSEQ_CMD_INT_PA_PU, NPHY_REV3_RFSEQ_CMD_END }; - static const u8 rfseq_rx2tx_dlys_rev3_ipa[] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 }; + static const u8 rfseq_rx2tx_dlys_rev3_ipa[] = + { 8, 6, 6, 4, 4, 16, 43, 1, 1 }; s16 alpha0, alpha1, alpha2; s16 beta0, beta1, beta2; u32 leg_data_weights, ht_data_weights, nss1_data_weights, @@ -16691,330 +16619,290 @@ static void wlc_phy_workarounds_nphy_rev3(struct brcms_phy *pi) u8 pdetrange; u8 triso;
- write_phy_reg(pi, 0x23f, 0x1f8); - write_phy_reg(pi, 0x240, 0x1f8); - - wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL, - 1, 0, 32, &leg_data_weights); - leg_data_weights = leg_data_weights & 0xffffff; - wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL, - 1, 0, 32, &leg_data_weights); - - alpha0 = 293; - alpha1 = 435; - alpha2 = 261; - beta0 = 366; - beta1 = 205; - beta2 = 32; - write_phy_reg(pi, 0x145, alpha0); - write_phy_reg(pi, 0x146, alpha1); - write_phy_reg(pi, 0x147, alpha2); - write_phy_reg(pi, 0x148, beta0); - write_phy_reg(pi, 0x149, beta1); - write_phy_reg(pi, 0x14a, beta2); - - write_phy_reg(pi, 0x38, 0xC); - write_phy_reg(pi, 0x2ae, 0xC); - - wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_TX2RX, - rfseq_tx2rx_events_rev3, - rfseq_tx2rx_dlys_rev3, - ARRAY_SIZE(rfseq_tx2rx_events_rev3)); - - if (PHY_IPA(pi)) - wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX, - rfseq_rx2tx_events_rev3_ipa, - rfseq_rx2tx_dlys_rev3_ipa, - ARRAY_SIZE(rfseq_rx2tx_events_rev3_ipa)); - - if ((pi->sh->hw_phyrxchain != 0x3) && - (pi->sh->hw_phyrxchain != pi->sh->hw_phytxchain)) { - - if (PHY_IPA(pi)) { - rfseq_rx2tx_dlys_rev3[5] = 59; - rfseq_rx2tx_dlys_rev3[6] = 1; - rfseq_rx2tx_events_rev3[7] = - NPHY_REV3_RFSEQ_CMD_END; - } - - wlc_phy_set_rfseq_nphy( - pi, NPHY_RFSEQ_RX2TX, - rfseq_rx2tx_events_rev3, - rfseq_rx2tx_dlys_rev3, - ARRAY_SIZE(rfseq_rx2tx_events_rev3)); - } + write_phy_reg(pi, 0x23f, 0x1f8); + write_phy_reg(pi, 0x240, 0x1f8); + + wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL, + 1, 0, 32, &leg_data_weights); + leg_data_weights = leg_data_weights & 0xffffff; + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL, + 1, 0, 32, &leg_data_weights); + + alpha0 = 293; + alpha1 = 435; + alpha2 = 261; + beta0 = 366; + beta1 = 205; + beta2 = 32; + write_phy_reg(pi, 0x145, alpha0); + write_phy_reg(pi, 0x146, alpha1); + write_phy_reg(pi, 0x147, alpha2); + write_phy_reg(pi, 0x148, beta0); + write_phy_reg(pi, 0x149, beta1); + write_phy_reg(pi, 0x14a, beta2); + + write_phy_reg(pi, 0x38, 0xC); + write_phy_reg(pi, 0x2ae, 0xC); + + wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_TX2RX, + rfseq_tx2rx_events_rev3, + rfseq_tx2rx_dlys_rev3, + ARRAY_SIZE(rfseq_tx2rx_events_rev3));
- if (CHSPEC_IS2G(pi->radio_chanspec)) - write_phy_reg(pi, 0x6a, 0x2); - else - write_phy_reg(pi, 0x6a, 0x9c40); - - mod_phy_reg(pi, 0x294, (0xf << 8), (7 << 8)); + if (PHY_IPA(pi)) + wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX, + rfseq_rx2tx_events_rev3_ipa, + rfseq_rx2tx_dlys_rev3_ipa, + ARRAY_SIZE (rfseq_rx2tx_events_rev3_ipa));
- if (CHSPEC_IS40(pi->radio_chanspec) == 0) { - wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 3, - 32, &min_nvar_val); - wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, - 127, 32, &min_nvar_val); - } else { - min_nvar_val = noise_var_tbl_rev3[3]; - wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 3, - 32, &min_nvar_val); + if ((pi->sh->hw_phyrxchain != 0x3) && + (pi->sh->hw_phyrxchain != pi->sh->hw_phytxchain)) {
- min_nvar_val = noise_var_tbl_rev3[127]; - wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, - 127, 32, &min_nvar_val); + if (PHY_IPA(pi)) { + rfseq_rx2tx_dlys_rev3[5] = 59; + rfseq_rx2tx_dlys_rev3[6] = 1; + rfseq_rx2tx_events_rev3[7] = NPHY_REV3_RFSEQ_CMD_END; }
- wlc_phy_workarounds_nphy_gainctrl(pi); + wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX, + rfseq_rx2tx_events_rev3, + rfseq_rx2tx_dlys_rev3, + ARRAY_SIZE (rfseq_rx2tx_events_rev3)); + }
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x00, 16, - &dac_control); - wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x10, 16, - &dac_control); + if (CHSPEC_IS2G(pi->radio_chanspec)) + write_phy_reg(pi, 0x6a, 0x2); + else + write_phy_reg(pi, 0x6a, 0x9c40);
- pdetrange = - (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g. - pdetrange : pi->srom_fem2g.pdetrange; + mod_phy_reg(pi, 0x294, (0xf << 8), (7 << 8));
- if (pdetrange == 0) { - if (NREV_GE(pi->pubpi.phy_rev, 4)) { - aux_adc_vmid = aux_adc_vmid_rev4; - aux_adc_gain = aux_adc_gain_rev4; - } else { - aux_adc_vmid = aux_adc_vmid_rev3; - aux_adc_gain = aux_adc_gain_rev3; - } - chan_freq_range = - wlc_phy_get_chan_freq_range_nphy(pi, 0); - if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) { - switch (chan_freq_range) { - case WL_CHAN_FREQ_RANGE_5GL: - aux_adc_vmid[3] = 0x89; - aux_adc_gain[3] = 0; - break; - case WL_CHAN_FREQ_RANGE_5GM: - aux_adc_vmid[3] = 0x89; - aux_adc_gain[3] = 0; - break; - case WL_CHAN_FREQ_RANGE_5GH: - aux_adc_vmid[3] = 0x89; - aux_adc_gain[3] = 0; - break; - default: - break; - } - } - wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, - 0x08, 16, aux_adc_vmid); - wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, - 0x18, 16, aux_adc_vmid); - wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, - 0x0c, 16, aux_adc_gain); - wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, - 0x1c, 16, aux_adc_gain); - } else if (pdetrange == 1) { - wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, - 0x08, 16, sk_adc_vmid); - wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, - 0x18, 16, sk_adc_vmid); - wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, - 0x0c, 16, sk_adc_gain); - wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, - 0x1c, 16, sk_adc_gain); - } else if (pdetrange == 2) { + if (CHSPEC_IS40(pi->radio_chanspec) == 0) { + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 3, + 32, &min_nvar_val); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, + 127, 32, &min_nvar_val); + } else { + min_nvar_val = noise_var_tbl_rev3[3]; + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 3, + 32, &min_nvar_val);
- u16 bcm_adc_vmid[] = { 0xa2, 0xb4, 0xb4, 0x74 }; - u16 bcm_adc_gain[] = { 0x02, 0x02, 0x02, 0x04 }; + min_nvar_val = noise_var_tbl_rev3[127]; + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, + 127, 32, &min_nvar_val); + }
- if (NREV_GE(pi->pubpi.phy_rev, 6)) { - chan_freq_range = - wlc_phy_get_chan_freq_range_nphy(pi, 0); - if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) { - bcm_adc_vmid[3] = 0x8e; - bcm_adc_gain[3] = 0x03; - } else { - bcm_adc_vmid[3] = 0x94; - bcm_adc_gain[3] = 0x03; - } - } else if (NREV_IS(pi->pubpi.phy_rev, 5)) { - bcm_adc_vmid[3] = 0x84; - bcm_adc_gain[3] = 0x02; - } + wlc_phy_workarounds_nphy_gainctrl(pi);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, - 0x08, 16, bcm_adc_vmid); - wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, - 0x18, 16, bcm_adc_vmid); - wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, - 0x0c, 16, bcm_adc_gain); - wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, - 0x1c, 16, bcm_adc_gain); - } else if (pdetrange == 3) { - chan_freq_range = - wlc_phy_get_chan_freq_range_nphy(pi, 0); - if ((NREV_GE(pi->pubpi.phy_rev, 4)) - && (chan_freq_range == WL_CHAN_FREQ_RANGE_2G)) { + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x00, 16, + &dac_control); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x10, 16, + &dac_control);
- u16 auxadc_vmid[] = { - 0xa2, 0xb4, 0xb4, 0x270 - }; - u16 auxadc_gain[] = { - 0x02, 0x02, 0x02, 0x00 - }; + pdetrange = (CHSPEC_IS5G(pi->radio_chanspec)) ? + pi->srom_fem5g.pdetrange : pi->srom_fem2g.pdetrange;
- wlc_phy_table_write_nphy(pi, - NPHY_TBL_ID_AFECTRL, 4, - 0x08, 16, auxadc_vmid); - wlc_phy_table_write_nphy(pi, - NPHY_TBL_ID_AFECTRL, 4, - 0x18, 16, auxadc_vmid); - wlc_phy_table_write_nphy(pi, - NPHY_TBL_ID_AFECTRL, 4, - 0x0c, 16, auxadc_gain); - wlc_phy_table_write_nphy(pi, - NPHY_TBL_ID_AFECTRL, 4, - 0x1c, 16, auxadc_gain); + if (pdetrange == 0) { + if (NREV_GE(pi->pubpi.phy_rev, 4)) { + aux_adc_vmid = aux_adc_vmid_rev4; + aux_adc_gain = aux_adc_gain_rev4; + } else { + aux_adc_vmid = aux_adc_vmid_rev3; + aux_adc_gain = aux_adc_gain_rev3; + } + chan_freq_range = wlc_phy_get_chan_freq_range_nphy(pi, 0); + if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) { + switch (chan_freq_range) { + case WL_CHAN_FREQ_RANGE_5GL: + aux_adc_vmid[3] = 0x89; + aux_adc_gain[3] = 0; + break; + case WL_CHAN_FREQ_RANGE_5GM: + aux_adc_vmid[3] = 0x89; + aux_adc_gain[3] = 0; + break; + case WL_CHAN_FREQ_RANGE_5GH: + aux_adc_vmid[3] = 0x89; + aux_adc_gain[3] = 0; + break; + default: + break; } - } else if ((pdetrange == 4) || (pdetrange == 5)) { - u16 bcm_adc_vmid[] = { 0xa2, 0xb4, 0xb4, 0x0 }; - u16 bcm_adc_gain[] = { 0x02, 0x02, 0x02, 0x0 }; - u16 Vmid[2], Av[2]; + } + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, + 0x08, 16, aux_adc_vmid); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, + 0x18, 16, aux_adc_vmid); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, + 0x0c, 16, aux_adc_gain); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, + 0x1c, 16, aux_adc_gain); + } else if (pdetrange == 1) { + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, + 0x08, 16, sk_adc_vmid); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, + 0x18, 16, sk_adc_vmid); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, + 0x0c, 16, sk_adc_gain); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, + 0x1c, 16, sk_adc_gain); + } else if (pdetrange == 2) { + + u16 bcm_adc_vmid[] = { 0xa2, 0xb4, 0xb4, 0x74 }; + u16 bcm_adc_gain[] = { 0x02, 0x02, 0x02, 0x04 };
+ if (NREV_GE(pi->pubpi.phy_rev, 6)) { chan_freq_range = - wlc_phy_get_chan_freq_range_nphy(pi, 0); + wlc_phy_get_chan_freq_range_nphy(pi, 0); if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) { - Vmid[0] = (pdetrange == 4) ? 0x8e : 0x89; - Vmid[1] = (pdetrange == 4) ? 0x96 : 0x89; - Av[0] = (pdetrange == 4) ? 2 : 0; - Av[1] = (pdetrange == 4) ? 2 : 0; + bcm_adc_vmid[3] = 0x8e; + bcm_adc_gain[3] = 0x03; } else { - Vmid[0] = (pdetrange == 4) ? 0x89 : 0x74; - Vmid[1] = (pdetrange == 4) ? 0x8b : 0x70; - Av[0] = (pdetrange == 4) ? 2 : 0; - Av[1] = (pdetrange == 4) ? 2 : 0; + bcm_adc_vmid[3] = 0x94; + bcm_adc_gain[3] = 0x03; } + } else if (NREV_IS(pi->pubpi.phy_rev, 5)) { + bcm_adc_vmid[3] = 0x84; + bcm_adc_gain[3] = 0x02; + } + + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, + 0x08, 16, bcm_adc_vmid); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, + 0x18, 16, bcm_adc_vmid); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, + 0x0c, 16, bcm_adc_gain); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, + 0x1c, 16, bcm_adc_gain); + } else if (pdetrange == 3) { + chan_freq_range = wlc_phy_get_chan_freq_range_nphy(pi, 0); + if ((NREV_GE(pi->pubpi.phy_rev, 4)) && + (chan_freq_range == WL_CHAN_FREQ_RANGE_2G)) { + u16 auxadc_vmid[] = { 0xa2, 0xb4, 0xb4, 0x270 }; + u16 auxadc_gain[] = { 0x02, 0x02, 0x02, 0x00 };
- bcm_adc_vmid[3] = Vmid[0]; - bcm_adc_gain[3] = Av[0]; wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, - 0x08, 16, bcm_adc_vmid); + 0x08, 16, auxadc_vmid); wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, - 0x0c, 16, bcm_adc_gain); - - bcm_adc_vmid[3] = Vmid[1]; - bcm_adc_gain[3] = Av[1]; + 0x18, 16, auxadc_vmid); wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, - 0x18, 16, bcm_adc_vmid); + 0x0c, 16, auxadc_gain); wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, - 0x1c, 16, bcm_adc_gain); + 0x1c, 16, auxadc_gain); } + } else if ((pdetrange == 4) || (pdetrange == 5)) { + u16 bcm_adc_vmid[] = { 0xa2, 0xb4, 0xb4, 0x0 }; + u16 bcm_adc_gain[] = { 0x02, 0x02, 0x02, 0x0 }; + u16 Vmid[2], Av[2];
- write_radio_reg(pi, - (RADIO_2056_RX_MIXA_MAST_BIAS | RADIO_2056_RX0), - 0x0); - write_radio_reg(pi, - (RADIO_2056_RX_MIXA_MAST_BIAS | RADIO_2056_RX1), - 0x0); + chan_freq_range = wlc_phy_get_chan_freq_range_nphy(pi, 0); + if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) { + Vmid[0] = (pdetrange == 4) ? 0x8e : 0x89; + Vmid[1] = (pdetrange == 4) ? 0x96 : 0x89; + Av[0] = (pdetrange == 4) ? 2 : 0; + Av[1] = (pdetrange == 4) ? 2 : 0; + } else { + Vmid[0] = (pdetrange == 4) ? 0x89 : 0x74; + Vmid[1] = (pdetrange == 4) ? 0x8b : 0x70; + Av[0] = (pdetrange == 4) ? 2 : 0; + Av[1] = (pdetrange == 4) ? 2 : 0; + }
- write_radio_reg(pi, - (RADIO_2056_RX_MIXA_BIAS_MAIN | RADIO_2056_RX0), - 0x6); - write_radio_reg(pi, - (RADIO_2056_RX_MIXA_BIAS_MAIN | RADIO_2056_RX1), - 0x6); + bcm_adc_vmid[3] = Vmid[0]; + bcm_adc_gain[3] = Av[0]; + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, + 0x08, 16, bcm_adc_vmid); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, + 0x0c, 16, bcm_adc_gain); + + bcm_adc_vmid[3] = Vmid[1]; + bcm_adc_gain[3] = Av[1]; + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, + 0x18, 16, bcm_adc_vmid); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, + 0x1c, 16, bcm_adc_gain); + }
- write_radio_reg(pi, - (RADIO_2056_RX_MIXA_BIAS_AUX | RADIO_2056_RX0), - 0x7); - write_radio_reg(pi, - (RADIO_2056_RX_MIXA_BIAS_AUX | RADIO_2056_RX1), - 0x7); + write_radio_reg(pi, (RADIO_2056_RX_MIXA_MAST_BIAS | RADIO_2056_RX0), 0x0); + write_radio_reg(pi, (RADIO_2056_RX_MIXA_MAST_BIAS | RADIO_2056_RX1), 0x0);
- write_radio_reg(pi, - (RADIO_2056_RX_MIXA_LOB_BIAS | RADIO_2056_RX0), - 0x88); - write_radio_reg(pi, - (RADIO_2056_RX_MIXA_LOB_BIAS | RADIO_2056_RX1), - 0x88); + write_radio_reg(pi, (RADIO_2056_RX_MIXA_BIAS_MAIN | RADIO_2056_RX0), 0x6); + write_radio_reg(pi, (RADIO_2056_RX_MIXA_BIAS_MAIN | RADIO_2056_RX1), 0x6);
- write_radio_reg(pi, - (RADIO_2056_RX_MIXA_CMFB_IDAC | RADIO_2056_RX0), - 0x0); - write_radio_reg(pi, - (RADIO_2056_RX_MIXA_CMFB_IDAC | RADIO_2056_RX1), - 0x0); + write_radio_reg(pi, (RADIO_2056_RX_MIXA_BIAS_AUX | RADIO_2056_RX0), 0x7); + write_radio_reg(pi, (RADIO_2056_RX_MIXA_BIAS_AUX | RADIO_2056_RX1), 0x7);
- write_radio_reg(pi, - (RADIO_2056_RX_MIXG_CMFB_IDAC | RADIO_2056_RX0), - 0x0); - write_radio_reg(pi, - (RADIO_2056_RX_MIXG_CMFB_IDAC | RADIO_2056_RX1), - 0x0); + write_radio_reg(pi, (RADIO_2056_RX_MIXA_LOB_BIAS | RADIO_2056_RX0), 0x88); + write_radio_reg(pi, (RADIO_2056_RX_MIXA_LOB_BIAS | RADIO_2056_RX1), 0x88);
- triso = - (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g. - triso : pi->srom_fem2g.triso; - if (triso == 7) { - wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_0); - wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_1); - } + write_radio_reg(pi, (RADIO_2056_RX_MIXA_CMFB_IDAC | RADIO_2056_RX0), 0x0); + write_radio_reg(pi, (RADIO_2056_RX_MIXA_CMFB_IDAC | RADIO_2056_RX1), 0x0);
- wlc_phy_war_txchain_upd_nphy(pi, pi->sh->hw_phytxchain); + write_radio_reg(pi, (RADIO_2056_RX_MIXG_CMFB_IDAC | RADIO_2056_RX0), 0x0); + write_radio_reg(pi, (RADIO_2056_RX_MIXG_CMFB_IDAC | RADIO_2056_RX1), 0x0);
- if (((pi->sh->boardflags2 & BFL2_APLL_WAR) && - (CHSPEC_IS5G(pi->radio_chanspec))) || - (((pi->sh->boardflags2 & BFL2_GPLL_WAR) || - (pi->sh->boardflags2 & BFL2_GPLL_WAR2)) && - (CHSPEC_IS2G(pi->radio_chanspec)))) { - nss1_data_weights = 0x00088888; - ht_data_weights = 0x00088888; - stbc_data_weights = 0x00088888; - } else { - nss1_data_weights = 0x88888888; - ht_data_weights = 0x88888888; - stbc_data_weights = 0x88888888; - } - wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL, - 1, 1, 32, &nss1_data_weights); - wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL, - 1, 2, 32, &ht_data_weights); - wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL, - 1, 3, 32, &stbc_data_weights); - - if (NREV_IS(pi->pubpi.phy_rev, 4)) { - if (CHSPEC_IS5G(pi->radio_chanspec)) { - write_radio_reg(pi, - RADIO_2056_TX_GMBB_IDAC | - RADIO_2056_TX0, 0x70); - write_radio_reg(pi, - RADIO_2056_TX_GMBB_IDAC | - RADIO_2056_TX1, 0x70); - } - } + triso = (CHSPEC_IS5G(pi->radio_chanspec)) ? + pi->srom_fem5g.triso : pi->srom_fem2g.triso; + if (triso == 7) { + wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_0); + wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_1); + }
- if (!pi->edcrs_threshold_lock) { - write_phy_reg(pi, 0x224, 0x3eb); - write_phy_reg(pi, 0x225, 0x3eb); - write_phy_reg(pi, 0x226, 0x341); - write_phy_reg(pi, 0x227, 0x341); - write_phy_reg(pi, 0x228, 0x42b); - write_phy_reg(pi, 0x229, 0x42b); - write_phy_reg(pi, 0x22a, 0x381); - write_phy_reg(pi, 0x22b, 0x381); - write_phy_reg(pi, 0x22c, 0x42b); - write_phy_reg(pi, 0x22d, 0x42b); - write_phy_reg(pi, 0x22e, 0x381); - write_phy_reg(pi, 0x22f, 0x381); + wlc_phy_war_txchain_upd_nphy(pi, pi->sh->hw_phytxchain); + + if (((pi->sh->boardflags2 & BFL2_APLL_WAR) && + (CHSPEC_IS5G(pi->radio_chanspec))) || + (((pi->sh->boardflags2 & BFL2_GPLL_WAR) || + (pi->sh->boardflags2 & BFL2_GPLL_WAR2)) && + (CHSPEC_IS2G(pi->radio_chanspec)))) { + nss1_data_weights = 0x00088888; + ht_data_weights = 0x00088888; + stbc_data_weights = 0x00088888; + } else { + nss1_data_weights = 0x88888888; + ht_data_weights = 0x88888888; + stbc_data_weights = 0x88888888; + } + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL, + 1, 1, 32, &nss1_data_weights); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL, + 1, 2, 32, &ht_data_weights); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL, + 1, 3, 32, &stbc_data_weights); + + if (NREV_IS(pi->pubpi.phy_rev, 4)) { + if (CHSPEC_IS5G(pi->radio_chanspec)) { + write_radio_reg(pi, + RADIO_2056_TX_GMBB_IDAC | + RADIO_2056_TX0, 0x70); + write_radio_reg(pi, + RADIO_2056_TX_GMBB_IDAC | + RADIO_2056_TX1, 0x70); } + }
- if (NREV_GE(pi->pubpi.phy_rev, 6)) { + if (!pi->edcrs_threshold_lock) { + write_phy_reg(pi, 0x224, 0x3eb); + write_phy_reg(pi, 0x225, 0x3eb); + write_phy_reg(pi, 0x226, 0x341); + write_phy_reg(pi, 0x227, 0x341); + write_phy_reg(pi, 0x228, 0x42b); + write_phy_reg(pi, 0x229, 0x42b); + write_phy_reg(pi, 0x22a, 0x381); + write_phy_reg(pi, 0x22b, 0x381); + write_phy_reg(pi, 0x22c, 0x42b); + write_phy_reg(pi, 0x22d, 0x42b); + write_phy_reg(pi, 0x22e, 0x381); + write_phy_reg(pi, 0x22f, 0x381); + }
- if (pi->sh->boardflags2 & BFL2_SINGLEANT_CCK) - wlapi_bmac_mhf(pi->sh->physhim, MHF4, - MHF4_BPHY_TXCORE0, - MHF4_BPHY_TXCORE0, BRCM_BAND_ALL); - } + if (NREV_GE(pi->pubpi.phy_rev, 6)) { + + if (pi->sh->boardflags2 & BFL2_SINGLEANT_CCK) + wlapi_bmac_mhf(pi->sh->physhim, MHF4, + MHF4_BPHY_TXCORE0, + MHF4_BPHY_TXCORE0, BRCM_BAND_ALL); + } }
void wlc_phy_workarounds_nphy_rev1(struct brcms_phy *pi) @@ -17043,102 +16931,101 @@ void wlc_phy_workarounds_nphy_rev1(struct brcms_phy *pi) s16 beta0, beta1, beta2; u16 regval;
- if (pi->sh->boardflags2 & BFL2_SKWRKFEM_BRD || - (pi->sh->boardtype == 0x8b)) { - uint i; - u8 war_dlys[] = { 1, 6, 6, 2, 4, 20, 1 }; - for (i = 0; i < ARRAY_SIZE(rfseq_rx2tx_dlys); i++) - rfseq_rx2tx_dlys[i] = war_dlys[i]; - } + if (pi->sh->boardflags2 & BFL2_SKWRKFEM_BRD || + (pi->sh->boardtype == 0x8b)) { + uint i; + u8 war_dlys[] = { 1, 6, 6, 2, 4, 20, 1 }; + for (i = 0; i < ARRAY_SIZE(rfseq_rx2tx_dlys); i++) + rfseq_rx2tx_dlys[i] = war_dlys[i]; + }
- if (CHSPEC_IS5G(pi->radio_chanspec) && pi->phy_5g_pwrgain) { - and_radio_reg(pi, RADIO_2055_CORE1_TX_RF_SPARE, 0xf7); - and_radio_reg(pi, RADIO_2055_CORE2_TX_RF_SPARE, 0xf7); - } else { - or_radio_reg(pi, RADIO_2055_CORE1_TX_RF_SPARE, 0x8); - or_radio_reg(pi, RADIO_2055_CORE2_TX_RF_SPARE, 0x8); - } + if (CHSPEC_IS5G(pi->radio_chanspec) && pi->phy_5g_pwrgain) { + and_radio_reg(pi, RADIO_2055_CORE1_TX_RF_SPARE, 0xf7); + and_radio_reg(pi, RADIO_2055_CORE2_TX_RF_SPARE, 0xf7); + } else { + or_radio_reg(pi, RADIO_2055_CORE1_TX_RF_SPARE, 0x8); + or_radio_reg(pi, RADIO_2055_CORE2_TX_RF_SPARE, 0x8); + }
- regval = 0x000a; - wlc_phy_table_write_nphy(pi, 8, 1, 0, 16, ®val); - wlc_phy_table_write_nphy(pi, 8, 1, 0x10, 16, ®val); + regval = 0x000a; + wlc_phy_table_write_nphy(pi, 8, 1, 0, 16, ®val); + wlc_phy_table_write_nphy(pi, 8, 1, 0x10, 16, ®val);
- if (NREV_LT(pi->pubpi.phy_rev, 3)) { - regval = 0xcdaa; - wlc_phy_table_write_nphy(pi, 8, 1, 0x02, 16, ®val); - wlc_phy_table_write_nphy(pi, 8, 1, 0x12, 16, ®val); - } + if (NREV_LT(pi->pubpi.phy_rev, 3)) { + regval = 0xcdaa; + wlc_phy_table_write_nphy(pi, 8, 1, 0x02, 16, ®val); + wlc_phy_table_write_nphy(pi, 8, 1, 0x12, 16, ®val); + }
- if (NREV_LT(pi->pubpi.phy_rev, 2)) { - regval = 0x0000; - wlc_phy_table_write_nphy(pi, 8, 1, 0x08, 16, ®val); - wlc_phy_table_write_nphy(pi, 8, 1, 0x18, 16, ®val); + if (NREV_LT(pi->pubpi.phy_rev, 2)) { + regval = 0x0000; + wlc_phy_table_write_nphy(pi, 8, 1, 0x08, 16, ®val); + wlc_phy_table_write_nphy(pi, 8, 1, 0x18, 16, ®val);
- regval = 0x7aab; - wlc_phy_table_write_nphy(pi, 8, 1, 0x07, 16, ®val); - wlc_phy_table_write_nphy(pi, 8, 1, 0x17, 16, ®val); + regval = 0x7aab; + wlc_phy_table_write_nphy(pi, 8, 1, 0x07, 16, ®val); + wlc_phy_table_write_nphy(pi, 8, 1, 0x17, 16, ®val);
- regval = 0x0800; - wlc_phy_table_write_nphy(pi, 8, 1, 0x06, 16, ®val); - wlc_phy_table_write_nphy(pi, 8, 1, 0x16, 16, ®val); - } + regval = 0x0800; + wlc_phy_table_write_nphy(pi, 8, 1, 0x06, 16, ®val); + wlc_phy_table_write_nphy(pi, 8, 1, 0x16, 16, ®val); + }
- write_phy_reg(pi, 0xf8, 0x02d8); - write_phy_reg(pi, 0xf9, 0x0301); - write_phy_reg(pi, 0xfa, 0x02d8); - write_phy_reg(pi, 0xfb, 0x0301); + write_phy_reg(pi, 0xf8, 0x02d8); + write_phy_reg(pi, 0xf9, 0x0301); + write_phy_reg(pi, 0xfa, 0x02d8); + write_phy_reg(pi, 0xfb, 0x0301);
- wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX, rfseq_rx2tx_events, - rfseq_rx2tx_dlys, - ARRAY_SIZE(rfseq_rx2tx_events)); + wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX, rfseq_rx2tx_events, + rfseq_rx2tx_dlys, + ARRAY_SIZE(rfseq_rx2tx_events));
- wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_TX2RX, rfseq_tx2rx_events, - rfseq_tx2rx_dlys, - ARRAY_SIZE(rfseq_tx2rx_events)); + wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_TX2RX, rfseq_tx2rx_events, + rfseq_tx2rx_dlys, + ARRAY_SIZE(rfseq_tx2rx_events));
- wlc_phy_workarounds_nphy_gainctrl(pi); + wlc_phy_workarounds_nphy_gainctrl(pi);
- if (NREV_LT(pi->pubpi.phy_rev, 2)) { + if (NREV_LT(pi->pubpi.phy_rev, 2)) {
- if (read_phy_reg(pi, 0xa0) & NPHY_MLenable) - wlapi_bmac_mhf(pi->sh->physhim, MHF3, - MHF3_NPHY_MLADV_WAR, - MHF3_NPHY_MLADV_WAR, - BRCM_BAND_ALL); + if (read_phy_reg(pi, 0xa0) & NPHY_MLenable) + wlapi_bmac_mhf(pi->sh->physhim, MHF3, + MHF3_NPHY_MLADV_WAR, + MHF3_NPHY_MLADV_WAR, BRCM_BAND_ALL);
- } else if (NREV_IS(pi->pubpi.phy_rev, 2)) { - write_phy_reg(pi, 0x1e3, 0x0); - write_phy_reg(pi, 0x1e4, 0x0); - } + } else if (NREV_IS(pi->pubpi.phy_rev, 2)) { + write_phy_reg(pi, 0x1e3, 0x0); + write_phy_reg(pi, 0x1e4, 0x0); + }
- if (NREV_LT(pi->pubpi.phy_rev, 2)) - mod_phy_reg(pi, 0x90, (0x1 << 7), 0); - - alpha0 = 293; - alpha1 = 435; - alpha2 = 261; - beta0 = 366; - beta1 = 205; - beta2 = 32; - write_phy_reg(pi, 0x145, alpha0); - write_phy_reg(pi, 0x146, alpha1); - write_phy_reg(pi, 0x147, alpha2); - write_phy_reg(pi, 0x148, beta0); - write_phy_reg(pi, 0x149, beta1); - write_phy_reg(pi, 0x14a, beta2); - - if (NREV_LT(pi->pubpi.phy_rev, 3)) { - mod_phy_reg(pi, 0x142, (0xf << 12), 0); - - write_phy_reg(pi, 0x192, 0xb5); - write_phy_reg(pi, 0x193, 0xa4); - write_phy_reg(pi, 0x194, 0x0); - } + if (NREV_LT(pi->pubpi.phy_rev, 2)) + mod_phy_reg(pi, 0x90, (0x1 << 7), 0); + + alpha0 = 293; + alpha1 = 435; + alpha2 = 261; + beta0 = 366; + beta1 = 205; + beta2 = 32; + write_phy_reg(pi, 0x145, alpha0); + write_phy_reg(pi, 0x146, alpha1); + write_phy_reg(pi, 0x147, alpha2); + write_phy_reg(pi, 0x148, beta0); + write_phy_reg(pi, 0x149, beta1); + write_phy_reg(pi, 0x14a, beta2); + + if (NREV_LT(pi->pubpi.phy_rev, 3)) { + mod_phy_reg(pi, 0x142, (0xf << 12), 0); + + write_phy_reg(pi, 0x192, 0xb5); + write_phy_reg(pi, 0x193, 0xa4); + write_phy_reg(pi, 0x194, 0x0); + }
- if (NREV_IS(pi->pubpi.phy_rev, 2)) - mod_phy_reg(pi, 0x221, - NPHY_FORCESIG_DECODEGATEDCLKS, - NPHY_FORCESIG_DECODEGATEDCLKS); + if (NREV_IS(pi->pubpi.phy_rev, 2)) + mod_phy_reg(pi, 0x221, + NPHY_FORCESIG_DECODEGATEDCLKS, + NPHY_FORCESIG_DECODEGATEDCLKS); }
static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
On 2-3-2017 17:38, Arnd Bergmann wrote:
In the previous commit I left the indentation alone to help reviewing the patch, this one now runs the three new functions through 'indent -kr -8' with some manual fixups to avoid silliness.
No changes other than whitespace are intended here.
Acked-by: Arend van Spriel arend.vanspriel@broadcom.com
Signed-off-by: Arnd Bergmann arnd@arndb.de
.../broadcom/brcm80211/brcmsmac/phy/phy_n.c | 1507 +++++++++----------- 1 file changed, 697 insertions(+), 810 deletions(-)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c index d76c092bb6b4..9b39789c673d 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c @@ -16074,7 +16074,8 @@ static void wlc_phy_workarounds_nphy_rev7(struct brcms_phy *pi) NPHY_REV3_RFSEQ_CMD_INT_PA_PU, NPHY_REV3_RFSEQ_CMD_END };
- static const u8 rfseq_rx2tx_dlys_rev3_ipa[] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 };
- static const u8 rfseq_rx2tx_dlys_rev3_ipa[] =
static const u16 rfseq_rx2tx_dacbufpu_rev7[] = { 0x10f, 0x10f }; u32 leg_data_weights; u8 chan_freq_range = 0;{ 8, 6, 6, 4, 4, 16, 43, 1, 1 };
@@ -16114,526 +16115,452 @@ static void wlc_phy_workarounds_nphy_rev7(struct brcms_phy *pi) int coreNum;
if (NREV_IS(pi->pubpi.phy_rev, 7)) {
mod_phy_reg(pi, 0x221, (0x1 << 4), (1 << 4));
mod_phy_reg(pi, 0x160, (0x7f << 0), (32 << 0));
mod_phy_reg(pi, 0x160, (0x7f << 8), (39 << 8));
mod_phy_reg(pi, 0x161, (0x7f << 0), (46 << 0));
mod_phy_reg(pi, 0x161, (0x7f << 8), (51 << 8));
mod_phy_reg(pi, 0x162, (0x7f << 0), (55 << 0));
mod_phy_reg(pi, 0x162, (0x7f << 8), (58 << 8));
mod_phy_reg(pi, 0x163, (0x7f << 0), (60 << 0));
mod_phy_reg(pi, 0x163, (0x7f << 8), (62 << 8));
mod_phy_reg(pi, 0x164, (0x7f << 0), (62 << 0));
mod_phy_reg(pi, 0x164, (0x7f << 8), (63 << 8));
mod_phy_reg(pi, 0x165, (0x7f << 0), (63 << 0));
mod_phy_reg(pi, 0x165, (0x7f << 8), (64 << 8));
mod_phy_reg(pi, 0x166, (0x7f << 0), (64 << 0));
mod_phy_reg(pi, 0x166, (0x7f << 8), (64 << 8));
mod_phy_reg(pi, 0x167, (0x7f << 0), (64 << 0));
mod_phy_reg(pi, 0x167, (0x7f << 8), (64 << 8));
}
if (NREV_LE(pi->pubpi.phy_rev, 8)) {
write_phy_reg(pi, 0x23f, 0x1b0);
write_phy_reg(pi, 0x240, 0x1b0);
}
- if (NREV_IS(pi->pubpi.phy_rev, 7)) {
mod_phy_reg(pi, 0x221, (0x1 << 4), (1 << 4));
mod_phy_reg(pi, 0x160, (0x7f << 0), (32 << 0));
mod_phy_reg(pi, 0x160, (0x7f << 8), (39 << 8));
mod_phy_reg(pi, 0x161, (0x7f << 0), (46 << 0));
mod_phy_reg(pi, 0x161, (0x7f << 8), (51 << 8));
mod_phy_reg(pi, 0x162, (0x7f << 0), (55 << 0));
mod_phy_reg(pi, 0x162, (0x7f << 8), (58 << 8));
mod_phy_reg(pi, 0x163, (0x7f << 0), (60 << 0));
mod_phy_reg(pi, 0x163, (0x7f << 8), (62 << 8));
mod_phy_reg(pi, 0x164, (0x7f << 0), (62 << 0));
mod_phy_reg(pi, 0x164, (0x7f << 8), (63 << 8));
mod_phy_reg(pi, 0x165, (0x7f << 0), (63 << 0));
mod_phy_reg(pi, 0x165, (0x7f << 8), (64 << 8));
mod_phy_reg(pi, 0x166, (0x7f << 0), (64 << 0));
mod_phy_reg(pi, 0x166, (0x7f << 8), (64 << 8));
mod_phy_reg(pi, 0x167, (0x7f << 0), (64 << 0));
mod_phy_reg(pi, 0x167, (0x7f << 8), (64 << 8));
- }
if (NREV_GE(pi->pubpi.phy_rev, 8))
mod_phy_reg(pi, 0xbd, (0xff << 0), (114 << 0));
- if (NREV_LE(pi->pubpi.phy_rev, 8)) {
write_phy_reg(pi, 0x23f, 0x1b0);
write_phy_reg(pi, 0x240, 0x1b0);
- }
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x00, 16,
&dac_control);
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x10, 16,
&dac_control);
- if (NREV_GE(pi->pubpi.phy_rev, 8))
mod_phy_reg(pi, 0xbd, (0xff << 0), (114 << 0));
wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
1, 0, 32, &leg_data_weights);
leg_data_weights = leg_data_weights & 0xffffff;
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
1, 0, 32, &leg_data_weights);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x00, 16,
&dac_control);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x10, 16,
&dac_control);
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
2, 0x15e, 16,
rfseq_rx2tx_dacbufpu_rev7);
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x16e, 16,
rfseq_rx2tx_dacbufpu_rev7);
- wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
1, 0, 32, &leg_data_weights);
- leg_data_weights = leg_data_weights & 0xffffff;
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
1, 0, 32, &leg_data_weights);
if (PHY_IPA(pi))
wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX,
rfseq_rx2tx_events_rev3_ipa,
rfseq_rx2tx_dlys_rev3_ipa,
ARRAY_SIZE(rfseq_rx2tx_events_rev3_ipa));
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
2, 0x15e, 16, rfseq_rx2tx_dacbufpu_rev7);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x16e, 16,
rfseq_rx2tx_dacbufpu_rev7);
mod_phy_reg(pi, 0x299, (0x3 << 14), (0x1 << 14));
mod_phy_reg(pi, 0x29d, (0x3 << 14), (0x1 << 14));
- if (PHY_IPA(pi))
wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX,
rfseq_rx2tx_events_rev3_ipa,
rfseq_rx2tx_dlys_rev3_ipa,
ARRAY_SIZE
(rfseq_rx2tx_events_rev3_ipa));
tx_lpf_bw_ofdm_20mhz = wlc_phy_read_lpf_bw_ctl_nphy(pi, 0x154);
tx_lpf_bw_ofdm_40mhz = wlc_phy_read_lpf_bw_ctl_nphy(pi, 0x159);
tx_lpf_bw_11b = wlc_phy_read_lpf_bw_ctl_nphy(pi, 0x152);
- mod_phy_reg(pi, 0x299, (0x3 << 14), (0x1 << 14));
- mod_phy_reg(pi, 0x29d, (0x3 << 14), (0x1 << 14));
if (PHY_IPA(pi)) {
- tx_lpf_bw_ofdm_20mhz = wlc_phy_read_lpf_bw_ctl_nphy(pi, 0x154);
- tx_lpf_bw_ofdm_40mhz = wlc_phy_read_lpf_bw_ctl_nphy(pi, 0x159);
- tx_lpf_bw_11b = wlc_phy_read_lpf_bw_ctl_nphy(pi, 0x152);
if (((pi->pubpi.radiorev == 5)
&& (CHSPEC_IS40(pi->radio_chanspec) == 1))
|| (pi->pubpi.radiorev == 7)
|| (pi->pubpi.radiorev == 8)) {
- if (PHY_IPA(pi)) {
rccal_bcap_val =
read_radio_reg(
pi,
RADIO_2057_RCCAL_BCAP_VAL);
rccal_scap_val =
read_radio_reg(
pi,
RADIO_2057_RCCAL_SCAP_VAL);
if (((pi->pubpi.radiorev == 5)
&& (CHSPEC_IS40(pi->radio_chanspec) == 1))
|| (pi->pubpi.radiorev == 7)
|| (pi->pubpi.radiorev == 8)) {
rccal_tx20_11b_bcap = rccal_bcap_val;
rccal_tx20_11b_scap = rccal_scap_val;
rccal_bcap_val =
read_radio_reg(pi, RADIO_2057_RCCAL_BCAP_VAL);
rccal_scap_val =
read_radio_reg(pi, RADIO_2057_RCCAL_SCAP_VAL);
if ((pi->pubpi.radiorev == 5) &&
(CHSPEC_IS40(pi->radio_chanspec) == 1)) {
rccal_tx20_11b_bcap = rccal_bcap_val;
rccal_tx20_11b_scap = rccal_scap_val;
rccal_tx20_11n_bcap = rccal_bcap_val;
rccal_tx20_11n_scap = rccal_scap_val;
rccal_tx40_11n_bcap = 0xc;
rccal_tx40_11n_scap = 0xc;
if ((pi->pubpi.radiorev == 5) &&
(CHSPEC_IS40(pi->radio_chanspec) == 1)) {
rccal_ovrd = true;
rccal_tx20_11n_bcap = rccal_bcap_val;
rccal_tx20_11n_scap = rccal_scap_val;
rccal_tx40_11n_bcap = 0xc;
rccal_tx40_11n_scap = 0xc;
} else if ((pi->pubpi.radiorev == 7)
|| (pi->pubpi.radiorev == 8)) {
rccal_ovrd = true;
tx_lpf_bw_ofdm_20mhz = 4;
tx_lpf_bw_11b = 1;
} else if ((pi->pubpi.radiorev == 7)
|| (pi->pubpi.radiorev == 8)) {
if (CHSPEC_IS2G(pi->radio_chanspec)) {
rccal_tx20_11n_bcap = 0xc;
rccal_tx20_11n_scap = 0xc;
rccal_tx40_11n_bcap = 0xa;
rccal_tx40_11n_scap = 0xa;
} else {
rccal_tx20_11n_bcap = 0x14;
rccal_tx20_11n_scap = 0x14;
rccal_tx40_11n_bcap = 0xf;
rccal_tx40_11n_scap = 0xf;
}
tx_lpf_bw_ofdm_20mhz = 4;
tx_lpf_bw_11b = 1;
rccal_ovrd = true;
if (CHSPEC_IS2G(pi->radio_chanspec)) {
rccal_tx20_11n_bcap = 0xc;
rccal_tx20_11n_scap = 0xc;
rccal_tx40_11n_bcap = 0xa;
rccal_tx40_11n_scap = 0xa;
} else {
rccal_tx20_11n_bcap = 0x14;
rccal_tx20_11n_scap = 0x14;
rccal_tx40_11n_bcap = 0xf;
rccal_tx40_11n_scap = 0xf; }
rccal_ovrd = true; }
}
} else {
- } else {
if (pi->pubpi.radiorev == 5) {
if (pi->pubpi.radiorev == 5) {
tx_lpf_bw_ofdm_20mhz = 1;
tx_lpf_bw_ofdm_40mhz = 3;
tx_lpf_bw_ofdm_20mhz = 1;
tx_lpf_bw_ofdm_40mhz = 3;
rccal_bcap_val =
read_radio_reg(
pi,
RADIO_2057_RCCAL_BCAP_VAL);
rccal_scap_val =
read_radio_reg(
pi,
RADIO_2057_RCCAL_SCAP_VAL);
rccal_bcap_val =
read_radio_reg(pi, RADIO_2057_RCCAL_BCAP_VAL);
rccal_scap_val =
read_radio_reg(pi, RADIO_2057_RCCAL_SCAP_VAL);
rccal_tx20_11b_bcap = rccal_bcap_val;
rccal_tx20_11b_scap = rccal_scap_val;
rccal_tx20_11b_bcap = rccal_bcap_val;
rccal_tx20_11b_scap = rccal_scap_val;
rccal_tx20_11n_bcap = 0x13;
rccal_tx20_11n_scap = 0x11;
rccal_tx40_11n_bcap = 0x13;
rccal_tx40_11n_scap = 0x11;
rccal_tx20_11n_bcap = 0x13;
rccal_tx20_11n_scap = 0x11;
rccal_tx40_11n_bcap = 0x13;
rccal_tx40_11n_scap = 0x11;
rccal_ovrd = true;
}
}rccal_ovrd = true;
- }
if (rccal_ovrd) {
rx2tx_lpf_rc_lut_tx20_11b =
(rccal_tx20_11b_bcap << 8) |
(rccal_tx20_11b_scap << 3) |
tx_lpf_bw_11b;
rx2tx_lpf_rc_lut_tx20_11n =
(rccal_tx20_11n_bcap << 8) |
(rccal_tx20_11n_scap << 3) |
tx_lpf_bw_ofdm_20mhz;
rx2tx_lpf_rc_lut_tx40_11n =
(rccal_tx40_11n_bcap << 8) |
(rccal_tx40_11n_scap << 3) |
tx_lpf_bw_ofdm_40mhz;
- if (rccal_ovrd) {
for (coreNum = 0; coreNum <= 1; coreNum++) {
wlc_phy_table_write_nphy(
pi, NPHY_TBL_ID_RFSEQ,
1,
0x152 + coreNum * 0x10,
16,
&rx2tx_lpf_rc_lut_tx20_11b);
wlc_phy_table_write_nphy(
pi, NPHY_TBL_ID_RFSEQ,
1,
0x153 + coreNum * 0x10,
16,
&rx2tx_lpf_rc_lut_tx20_11n);
wlc_phy_table_write_nphy(
pi, NPHY_TBL_ID_RFSEQ,
1,
0x154 + coreNum * 0x10,
16,
&rx2tx_lpf_rc_lut_tx20_11n);
wlc_phy_table_write_nphy(
pi, NPHY_TBL_ID_RFSEQ,
1,
0x155 + coreNum * 0x10,
16,
&rx2tx_lpf_rc_lut_tx40_11n);
wlc_phy_table_write_nphy(
pi, NPHY_TBL_ID_RFSEQ,
1,
0x156 + coreNum * 0x10,
16,
&rx2tx_lpf_rc_lut_tx40_11n);
wlc_phy_table_write_nphy(
pi, NPHY_TBL_ID_RFSEQ,
1,
0x157 + coreNum * 0x10,
16,
&rx2tx_lpf_rc_lut_tx40_11n);
wlc_phy_table_write_nphy(
pi, NPHY_TBL_ID_RFSEQ,
1,
0x158 + coreNum * 0x10,
16,
&rx2tx_lpf_rc_lut_tx40_11n);
wlc_phy_table_write_nphy(
pi, NPHY_TBL_ID_RFSEQ,
1,
0x159 + coreNum * 0x10,
16,
&rx2tx_lpf_rc_lut_tx40_11n);
}
rx2tx_lpf_rc_lut_tx20_11b =
(rccal_tx20_11b_bcap << 8) |
(rccal_tx20_11b_scap << 3) | tx_lpf_bw_11b;
rx2tx_lpf_rc_lut_tx20_11n =
(rccal_tx20_11n_bcap << 8) |
(rccal_tx20_11n_scap << 3) | tx_lpf_bw_ofdm_20mhz;
rx2tx_lpf_rc_lut_tx40_11n =
(rccal_tx40_11n_bcap << 8) |
(rccal_tx40_11n_scap << 3) | tx_lpf_bw_ofdm_40mhz;
wlc_phy_rfctrl_override_nphy_rev7(
pi, (0x1 << 4),
1, 0x3, 0,
NPHY_REV7_RFCTRLOVERRIDE_ID2);
for (coreNum = 0; coreNum <= 1; coreNum++) {
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1,
0x152 + coreNum * 0x10, 16,
&rx2tx_lpf_rc_lut_tx20_11b);
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1,
0x153 + coreNum * 0x10, 16,
&rx2tx_lpf_rc_lut_tx20_11n);
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1,
0x154 + coreNum * 0x10, 16,
&rx2tx_lpf_rc_lut_tx20_11n);
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1,
0x155 + coreNum * 0x10, 16,
&rx2tx_lpf_rc_lut_tx40_11n);
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1,
0x156 + coreNum * 0x10, 16,
&rx2tx_lpf_rc_lut_tx40_11n);
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1,
0x157 + coreNum * 0x10, 16,
&rx2tx_lpf_rc_lut_tx40_11n);
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1,
0x158 + coreNum * 0x10, 16,
&rx2tx_lpf_rc_lut_tx40_11n);
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1,
0x159 + coreNum * 0x10, 16,
}&rx2tx_lpf_rc_lut_tx40_11n);
write_phy_reg(pi, 0x32f, 0x3);
wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4), 1, 0x3, 0,
NPHY_REV7_RFCTRLOVERRIDE_ID2);
- }
if ((pi->pubpi.radiorev == 4) || (pi->pubpi.radiorev == 6))
wlc_phy_rfctrl_override_nphy_rev7(
pi, (0x1 << 2),
1, 0x3, 0,
NPHY_REV7_RFCTRLOVERRIDE_ID0);
- write_phy_reg(pi, 0x32f, 0x3);
if ((pi->pubpi.radiorev == 3) || (pi->pubpi.radiorev == 4) ||
(pi->pubpi.radiorev == 6)) {
if ((pi->sh->sromrev >= 8)
&& (pi->sh->boardflags2 & BFL2_IPALVLSHIFT_3P3))
ipalvlshift_3p3_war_en = 1;
if (ipalvlshift_3p3_war_en) {
write_radio_reg(pi, RADIO_2057_GPAIO_CONFIG,
0x5);
write_radio_reg(pi, RADIO_2057_GPAIO_SEL1,
0x30);
write_radio_reg(pi, RADIO_2057_GPAIO_SEL0, 0x0);
or_radio_reg(pi,
RADIO_2057_RXTXBIAS_CONFIG_CORE0,
0x1);
or_radio_reg(pi,
RADIO_2057_RXTXBIAS_CONFIG_CORE1,
0x1);
ipa2g_mainbias = 0x1f;
ipa2g_casconv = 0x6f;
ipa2g_biasfilt = 0xaa;
} else {
- if ((pi->pubpi.radiorev == 4) || (pi->pubpi.radiorev == 6))
wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), 1, 0x3, 0,
NPHY_REV7_RFCTRLOVERRIDE_ID0);
ipa2g_mainbias = 0x2b;
- if ((pi->pubpi.radiorev == 3) || (pi->pubpi.radiorev == 4) ||
(pi->pubpi.radiorev == 6)) {
if ((pi->sh->sromrev >= 8)
&& (pi->sh->boardflags2 & BFL2_IPALVLSHIFT_3P3))
ipalvlshift_3p3_war_en = 1;
ipa2g_casconv = 0x7f;
if (ipalvlshift_3p3_war_en) {
write_radio_reg(pi, RADIO_2057_GPAIO_CONFIG, 0x5);
write_radio_reg(pi, RADIO_2057_GPAIO_SEL1, 0x30);
write_radio_reg(pi, RADIO_2057_GPAIO_SEL0, 0x0);
or_radio_reg(pi, RADIO_2057_RXTXBIAS_CONFIG_CORE0, 0x1);
or_radio_reg(pi, RADIO_2057_RXTXBIAS_CONFIG_CORE1, 0x1);
ipa2g_biasfilt = 0xee;
}
ipa2g_mainbias = 0x1f;
if (CHSPEC_IS2G(pi->radio_chanspec)) {
for (coreNum = 0; coreNum <= 1; coreNum++) {
WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
coreNum, IPA2G_IMAIN,
ipa2g_mainbias);
WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
coreNum, IPA2G_CASCONV,
ipa2g_casconv);
WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
coreNum,
IPA2G_BIAS_FILTER,
ipa2g_biasfilt);
}
}
}
ipa2g_casconv = 0x6f;
if (PHY_IPA(pi)) {
if (CHSPEC_IS2G(pi->radio_chanspec)) {
if ((pi->pubpi.radiorev == 3)
|| (pi->pubpi.radiorev == 4)
|| (pi->pubpi.radiorev == 6))
txgm_idac_bleed = 0x7f;
ipa2g_biasfilt = 0xaa;
} else {
for (coreNum = 0; coreNum <= 1; coreNum++) {
if (txgm_idac_bleed != 0)
WRITE_RADIO_REG4(
pi, RADIO_2057,
CORE, coreNum,
TXGM_IDAC_BLEED,
txgm_idac_bleed);
}
ipa2g_mainbias = 0x2b;
if (pi->pubpi.radiorev == 5) {
for (coreNum = 0; coreNum <= 1;
coreNum++) {
WRITE_RADIO_REG4(pi, RADIO_2057,
CORE, coreNum,
IPA2G_CASCONV,
0x13);
WRITE_RADIO_REG4(pi, RADIO_2057,
CORE, coreNum,
IPA2G_IMAIN,
0x1f);
WRITE_RADIO_REG4(
pi, RADIO_2057,
CORE, coreNum,
IPA2G_BIAS_FILTER,
0xee);
WRITE_RADIO_REG4(pi, RADIO_2057,
CORE, coreNum,
PAD2G_IDACS,
0x8a);
WRITE_RADIO_REG4(
pi, RADIO_2057,
CORE, coreNum,
PAD_BIAS_FILTER_BWS,
0x3e);
}
ipa2g_casconv = 0x7f;
} else if ((pi->pubpi.radiorev == 7)
|| (pi->pubpi.radiorev == 8)) {
ipa2g_biasfilt = 0xee;
}
if (CHSPEC_IS40(pi->radio_chanspec) ==
0) {
WRITE_RADIO_REG4(pi, RADIO_2057,
CORE, 0,
IPA2G_IMAIN,
0x14);
WRITE_RADIO_REG4(pi, RADIO_2057,
CORE, 1,
IPA2G_IMAIN,
0x12);
} else {
WRITE_RADIO_REG4(pi, RADIO_2057,
CORE, 0,
IPA2G_IMAIN,
0x16);
WRITE_RADIO_REG4(pi, RADIO_2057,
CORE, 1,
IPA2G_IMAIN,
0x16);
}
}
if (CHSPEC_IS2G(pi->radio_chanspec)) {
for (coreNum = 0; coreNum <= 1; coreNum++) {
WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
coreNum, IPA2G_IMAIN,
ipa2g_mainbias);
WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
coreNum, IPA2G_CASCONV,
ipa2g_casconv);
WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
coreNum,
IPA2G_BIAS_FILTER,
ipa2g_biasfilt);
}
}
- }
} else {
freq = CHAN5G_FREQ(CHSPEC_CHANNEL(
pi->radio_chanspec));
if (((freq >= 5180) && (freq <= 5230))
|| ((freq >= 5745) && (freq <= 5805))) {
WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
0, IPA5G_BIAS_FILTER,
0xff);
WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
1, IPA5G_BIAS_FILTER,
0xff);
}
- if (PHY_IPA(pi)) {
if (CHSPEC_IS2G(pi->radio_chanspec)) {
if ((pi->pubpi.radiorev == 3)
|| (pi->pubpi.radiorev == 4)
|| (pi->pubpi.radiorev == 6))
txgm_idac_bleed = 0x7f;
for (coreNum = 0; coreNum <= 1; coreNum++) {
if (txgm_idac_bleed != 0)
WRITE_RADIO_REG4(pi, RADIO_2057,
CORE, coreNum,
TXGM_IDAC_BLEED,
txgm_idac_bleed); }
} else {
if (pi->pubpi.radiorev != 5) {
if (pi->pubpi.radiorev == 5) { for (coreNum = 0; coreNum <= 1; coreNum++) {
WRITE_RADIO_REG4(pi, RADIO_2057,
CORE, coreNum,
IPA2G_CASCONV,
0x13);
WRITE_RADIO_REG4(pi, RADIO_2057,
CORE, coreNum,
IPA2G_IMAIN,
0x1f);
WRITE_RADIO_REG4(pi, RADIO_2057,
CORE, coreNum,
IPA2G_BIAS_FILTER,
0xee);
WRITE_RADIO_REG4(pi, RADIO_2057,
CORE, coreNum,
PAD2G_IDACS,
0x8a);
WRITE_RADIO_REG4(pi, RADIO_2057,
CORE, coreNum,
PAD_BIAS_FILTER_BWS,
0x3e);
}
} else if ((pi->pubpi.radiorev == 7) ||
(pi->pubpi.radiorev == 8)) {
if (CHSPEC_IS40(pi->radio_chanspec) == 0) {
WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
0, IPA2G_IMAIN, 0x14);
WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
1, IPA2G_IMAIN, 0x12);
} else { WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
coreNum,
TXMIX2G_TUNE_BOOST_PU,
0x61);
0, IPA2G_IMAIN, 0x16); WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
coreNum,
TXGM_IDAC_BLEED, 0x70);
1, IPA2G_IMAIN, 0x16); } }
}
if (pi->pubpi.radiorev == 4) {
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1,
0x05, 16,
&afectrl_adc_ctrl1_rev7);
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1,
0x15, 16,
&afectrl_adc_ctrl1_rev7);
} else {
freq =
CHAN5G_FREQ(CHSPEC_CHANNEL
(pi->radio_chanspec));
if (((freq >= 5180) && (freq <= 5230))
|| ((freq >= 5745) && (freq <= 5805))) {
WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
0, IPA5G_BIAS_FILTER, 0xff);
WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
1, IPA5G_BIAS_FILTER, 0xff);
}
}
- } else {
if (pi->pubpi.radiorev != 5) { for (coreNum = 0; coreNum <= 1; coreNum++) { WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum,
AFE_VCM_CAL_MASTER, 0x0);
WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum,
AFE_SET_VCM_I, 0x3f);
TXMIX2G_TUNE_BOOST_PU, 0x61); WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum,
AFE_SET_VCM_Q, 0x3f);
TXGM_IDAC_BLEED, 0x70); }
} else {
mod_phy_reg(pi, 0xa6, (0x1 << 2), (0x1 << 2));
mod_phy_reg(pi, 0x8f, (0x1 << 2), (0x1 << 2));
mod_phy_reg(pi, 0xa7, (0x1 << 2), (0x1 << 2));
mod_phy_reg(pi, 0xa5, (0x1 << 2), (0x1 << 2));
mod_phy_reg(pi, 0xa6, (0x1 << 0), 0);
mod_phy_reg(pi, 0x8f, (0x1 << 0), (0x1 << 0));
mod_phy_reg(pi, 0xa7, (0x1 << 0), 0);
mod_phy_reg(pi, 0xa5, (0x1 << 0), (0x1 << 0));
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1,
0x05, 16,
&afectrl_adc_ctrl2_rev7);
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1,
0x15, 16,
&afectrl_adc_ctrl2_rev7);
mod_phy_reg(pi, 0xa6, (0x1 << 2), 0);
mod_phy_reg(pi, 0x8f, (0x1 << 2), 0);
mod_phy_reg(pi, 0xa7, (0x1 << 2), 0);
}mod_phy_reg(pi, 0xa5, (0x1 << 2), 0);
- }
write_phy_reg(pi, 0x6a, 0x2);
- if (pi->pubpi.radiorev == 4) {
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x05, 16,
&afectrl_adc_ctrl1_rev7);
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x15, 16,
&afectrl_adc_ctrl1_rev7);
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 256, 32,
&min_nvar_offset_6mbps);
for (coreNum = 0; coreNum <= 1; coreNum++) {
WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum,
AFE_VCM_CAL_MASTER, 0x0);
WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum,
AFE_SET_VCM_I, 0x3f);
WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum,
AFE_SET_VCM_Q, 0x3f);
}
- } else {
mod_phy_reg(pi, 0xa6, (0x1 << 2), (0x1 << 2));
mod_phy_reg(pi, 0x8f, (0x1 << 2), (0x1 << 2));
mod_phy_reg(pi, 0xa7, (0x1 << 2), (0x1 << 2));
mod_phy_reg(pi, 0xa5, (0x1 << 2), (0x1 << 2));
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x138, 16,
&rfseq_pktgn_lpf_hpc_rev7);
mod_phy_reg(pi, 0xa6, (0x1 << 0), 0);
mod_phy_reg(pi, 0x8f, (0x1 << 0), (0x1 << 0));
mod_phy_reg(pi, 0xa7, (0x1 << 0), 0);
mod_phy_reg(pi, 0xa5, (0x1 << 0), (0x1 << 0));
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, 0x141, 16,
&rfseq_pktgn_lpf_h_hpc_rev7);
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x05, 16,
&afectrl_adc_ctrl2_rev7);
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x15, 16,
&afectrl_adc_ctrl2_rev7);
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 3, 0x133, 16,
&rfseq_htpktgn_lpf_hpc_rev7);
mod_phy_reg(pi, 0xa6, (0x1 << 2), 0);
mod_phy_reg(pi, 0x8f, (0x1 << 2), 0);
mod_phy_reg(pi, 0xa7, (0x1 << 2), 0);
mod_phy_reg(pi, 0xa5, (0x1 << 2), 0);
- }
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x146, 16,
&rfseq_cckpktgn_lpf_hpc_rev7);
- write_phy_reg(pi, 0x6a, 0x2);
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, 0x123, 16,
&rfseq_tx2rx_lpf_h_hpc_rev7);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 256, 32,
&min_nvar_offset_6mbps);
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, 0x12A, 16,
&rfseq_rx2tx_lpf_h_hpc_rev7);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x138, 16,
&rfseq_pktgn_lpf_hpc_rev7);
if (CHSPEC_IS40(pi->radio_chanspec) == 0) {
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 3,
32, &min_nvar_val);
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
127, 32, &min_nvar_val);
} else {
min_nvar_val = noise_var_tbl_rev7[3];
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 3,
32, &min_nvar_val);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, 0x141, 16,
&rfseq_pktgn_lpf_h_hpc_rev7);
min_nvar_val = noise_var_tbl_rev7[127];
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
127, 32, &min_nvar_val);
}
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 3, 0x133, 16,
&rfseq_htpktgn_lpf_hpc_rev7);
wlc_phy_workarounds_nphy_gainctrl(pi);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x146, 16,
&rfseq_cckpktgn_lpf_hpc_rev7);
pdetrange =
(CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g.
pdetrange : pi->srom_fem2g.pdetrange;
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, 0x123, 16,
&rfseq_tx2rx_lpf_h_hpc_rev7);
if (pdetrange == 0) {
chan_freq_range =
wlc_phy_get_chan_freq_range_nphy(pi, 0);
if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
aux_adc_vmid_rev7_core0[3] = 0x70;
aux_adc_vmid_rev7_core1[3] = 0x70;
aux_adc_gain_rev7[3] = 2;
} else {
aux_adc_vmid_rev7_core0[3] = 0x80;
aux_adc_vmid_rev7_core1[3] = 0x80;
aux_adc_gain_rev7[3] = 3;
}
} else if (pdetrange == 1) {
if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
aux_adc_vmid_rev7_core0[3] = 0x7c;
aux_adc_vmid_rev7_core1[3] = 0x7c;
aux_adc_gain_rev7[3] = 2;
} else {
aux_adc_vmid_rev7_core0[3] = 0x8c;
aux_adc_vmid_rev7_core1[3] = 0x8c;
aux_adc_gain_rev7[3] = 1;
}
} else if (pdetrange == 2) {
if (pi->pubpi.radioid == BCM2057_ID) {
if ((pi->pubpi.radiorev == 5)
|| (pi->pubpi.radiorev == 7)
|| (pi->pubpi.radiorev == 8)) {
if (chan_freq_range ==
WL_CHAN_FREQ_RANGE_2G) {
aux_adc_vmid_rev7_core0[3] =
0x8c;
aux_adc_vmid_rev7_core1[3] =
0x8c;
aux_adc_gain_rev7[3] = 0;
} else {
aux_adc_vmid_rev7_core0[3] =
0x96;
aux_adc_vmid_rev7_core1[3] =
0x96;
aux_adc_gain_rev7[3] = 0;
}
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, 0x12A, 16,
&rfseq_rx2tx_lpf_h_hpc_rev7);
- if (CHSPEC_IS40(pi->radio_chanspec) == 0) {
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 3,
32, &min_nvar_val);
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
127, 32, &min_nvar_val);
- } else {
min_nvar_val = noise_var_tbl_rev7[3];
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 3,
32, &min_nvar_val);
min_nvar_val = noise_var_tbl_rev7[127];
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
127, 32, &min_nvar_val);
- }
- wlc_phy_workarounds_nphy_gainctrl(pi);
- pdetrange = (CHSPEC_IS5G(pi->radio_chanspec)) ?
pi->srom_fem5g.pdetrange : pi->srom_fem2g.pdetrange;
- if (pdetrange == 0) {
chan_freq_range = wlc_phy_get_chan_freq_range_nphy(pi, 0);
if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
aux_adc_vmid_rev7_core0[3] = 0x70;
aux_adc_vmid_rev7_core1[3] = 0x70;
aux_adc_gain_rev7[3] = 2;
} else {
aux_adc_vmid_rev7_core0[3] = 0x80;
aux_adc_vmid_rev7_core1[3] = 0x80;
aux_adc_gain_rev7[3] = 3;
}
- } else if (pdetrange == 1) {
if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
aux_adc_vmid_rev7_core0[3] = 0x7c;
aux_adc_vmid_rev7_core1[3] = 0x7c;
aux_adc_gain_rev7[3] = 2;
} else {
aux_adc_vmid_rev7_core0[3] = 0x8c;
aux_adc_vmid_rev7_core1[3] = 0x8c;
aux_adc_gain_rev7[3] = 1;
}
- } else if (pdetrange == 2) {
if (pi->pubpi.radioid == BCM2057_ID) {
if ((pi->pubpi.radiorev == 5)
|| (pi->pubpi.radiorev == 7)
|| (pi->pubpi.radiorev == 8)) {
if (chan_freq_range ==
WL_CHAN_FREQ_RANGE_2G) {
aux_adc_vmid_rev7_core0[3] = 0x8c;
aux_adc_vmid_rev7_core1[3] = 0x8c;
aux_adc_gain_rev7[3] = 0;
} else {
aux_adc_vmid_rev7_core0[3] = 0x96;
aux_adc_vmid_rev7_core1[3] = 0x96;
aux_adc_gain_rev7[3] = 0; } }
}
} else if (pdetrange == 3) {
if (chan_freq_range == WL_CHAN_FREQ_RANGE_2G) {
aux_adc_vmid_rev7_core0[3] = 0x89;
aux_adc_vmid_rev7_core1[3] = 0x89;
aux_adc_gain_rev7[3] = 0;
}
- } else if (pdetrange == 3) {
if (chan_freq_range == WL_CHAN_FREQ_RANGE_2G) {
aux_adc_vmid_rev7_core0[3] = 0x89;
aux_adc_vmid_rev7_core1[3] = 0x89;
aux_adc_gain_rev7[3] = 0;
}
} else if (pdetrange == 5) {
- } else if (pdetrange == 5) {
if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
aux_adc_vmid_rev7_core0[3] = 0x80;
aux_adc_vmid_rev7_core1[3] = 0x80;
aux_adc_gain_rev7[3] = 3;
} else {
aux_adc_vmid_rev7_core0[3] = 0x70;
aux_adc_vmid_rev7_core1[3] = 0x70;
aux_adc_gain_rev7[3] = 2;
}
if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
aux_adc_vmid_rev7_core0[3] = 0x80;
aux_adc_vmid_rev7_core1[3] = 0x80;
aux_adc_gain_rev7[3] = 3;
} else {
aux_adc_vmid_rev7_core0[3] = 0x70;
aux_adc_vmid_rev7_core1[3] = 0x70;
}aux_adc_gain_rev7[3] = 2;
- }
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x08, 16,
&aux_adc_vmid_rev7_core0);
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x18, 16,
&aux_adc_vmid_rev7_core1);
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x0c, 16,
&aux_adc_gain_rev7);
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x1c, 16,
&aux_adc_gain_rev7);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x08, 16,
&aux_adc_vmid_rev7_core0);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x18, 16,
&aux_adc_vmid_rev7_core1);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x0c, 16,
&aux_adc_gain_rev7);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x1c, 16,
&aux_adc_gain_rev7);
} static void wlc_phy_workarounds_nphy_rev3(struct brcms_phy *pi) @@ -16672,7 +16599,8 @@ static void wlc_phy_workarounds_nphy_rev3(struct brcms_phy *pi) NPHY_REV3_RFSEQ_CMD_INT_PA_PU, NPHY_REV3_RFSEQ_CMD_END };
- static const u8 rfseq_rx2tx_dlys_rev3_ipa[] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 };
- static const u8 rfseq_rx2tx_dlys_rev3_ipa[] =
s16 alpha0, alpha1, alpha2; s16 beta0, beta1, beta2; u32 leg_data_weights, ht_data_weights, nss1_data_weights,{ 8, 6, 6, 4, 4, 16, 43, 1, 1 };
@@ -16691,330 +16619,290 @@ static void wlc_phy_workarounds_nphy_rev3(struct brcms_phy *pi) u8 pdetrange; u8 triso;
write_phy_reg(pi, 0x23f, 0x1f8);
write_phy_reg(pi, 0x240, 0x1f8);
wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
1, 0, 32, &leg_data_weights);
leg_data_weights = leg_data_weights & 0xffffff;
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
1, 0, 32, &leg_data_weights);
alpha0 = 293;
alpha1 = 435;
alpha2 = 261;
beta0 = 366;
beta1 = 205;
beta2 = 32;
write_phy_reg(pi, 0x145, alpha0);
write_phy_reg(pi, 0x146, alpha1);
write_phy_reg(pi, 0x147, alpha2);
write_phy_reg(pi, 0x148, beta0);
write_phy_reg(pi, 0x149, beta1);
write_phy_reg(pi, 0x14a, beta2);
write_phy_reg(pi, 0x38, 0xC);
write_phy_reg(pi, 0x2ae, 0xC);
wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_TX2RX,
rfseq_tx2rx_events_rev3,
rfseq_tx2rx_dlys_rev3,
ARRAY_SIZE(rfseq_tx2rx_events_rev3));
if (PHY_IPA(pi))
wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX,
rfseq_rx2tx_events_rev3_ipa,
rfseq_rx2tx_dlys_rev3_ipa,
ARRAY_SIZE(rfseq_rx2tx_events_rev3_ipa));
if ((pi->sh->hw_phyrxchain != 0x3) &&
(pi->sh->hw_phyrxchain != pi->sh->hw_phytxchain)) {
if (PHY_IPA(pi)) {
rfseq_rx2tx_dlys_rev3[5] = 59;
rfseq_rx2tx_dlys_rev3[6] = 1;
rfseq_rx2tx_events_rev3[7] =
NPHY_REV3_RFSEQ_CMD_END;
}
wlc_phy_set_rfseq_nphy(
pi, NPHY_RFSEQ_RX2TX,
rfseq_rx2tx_events_rev3,
rfseq_rx2tx_dlys_rev3,
ARRAY_SIZE(rfseq_rx2tx_events_rev3));
}
- write_phy_reg(pi, 0x23f, 0x1f8);
- write_phy_reg(pi, 0x240, 0x1f8);
- wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
1, 0, 32, &leg_data_weights);
- leg_data_weights = leg_data_weights & 0xffffff;
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
1, 0, 32, &leg_data_weights);
- alpha0 = 293;
- alpha1 = 435;
- alpha2 = 261;
- beta0 = 366;
- beta1 = 205;
- beta2 = 32;
- write_phy_reg(pi, 0x145, alpha0);
- write_phy_reg(pi, 0x146, alpha1);
- write_phy_reg(pi, 0x147, alpha2);
- write_phy_reg(pi, 0x148, beta0);
- write_phy_reg(pi, 0x149, beta1);
- write_phy_reg(pi, 0x14a, beta2);
- write_phy_reg(pi, 0x38, 0xC);
- write_phy_reg(pi, 0x2ae, 0xC);
- wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_TX2RX,
rfseq_tx2rx_events_rev3,
rfseq_tx2rx_dlys_rev3,
ARRAY_SIZE(rfseq_tx2rx_events_rev3));
if (CHSPEC_IS2G(pi->radio_chanspec))
write_phy_reg(pi, 0x6a, 0x2);
else
write_phy_reg(pi, 0x6a, 0x9c40);
mod_phy_reg(pi, 0x294, (0xf << 8), (7 << 8));
- if (PHY_IPA(pi))
wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX,
rfseq_rx2tx_events_rev3_ipa,
rfseq_rx2tx_dlys_rev3_ipa,
ARRAY_SIZE (rfseq_rx2tx_events_rev3_ipa));
if (CHSPEC_IS40(pi->radio_chanspec) == 0) {
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 3,
32, &min_nvar_val);
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
127, 32, &min_nvar_val);
} else {
min_nvar_val = noise_var_tbl_rev3[3];
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 3,
32, &min_nvar_val);
- if ((pi->sh->hw_phyrxchain != 0x3) &&
(pi->sh->hw_phyrxchain != pi->sh->hw_phytxchain)) {
min_nvar_val = noise_var_tbl_rev3[127];
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
127, 32, &min_nvar_val);
if (PHY_IPA(pi)) {
rfseq_rx2tx_dlys_rev3[5] = 59;
rfseq_rx2tx_dlys_rev3[6] = 1;
}rfseq_rx2tx_events_rev3[7] = NPHY_REV3_RFSEQ_CMD_END;
wlc_phy_workarounds_nphy_gainctrl(pi);
wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX,
rfseq_rx2tx_events_rev3,
rfseq_rx2tx_dlys_rev3,
ARRAY_SIZE (rfseq_rx2tx_events_rev3));
- }
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x00, 16,
&dac_control);
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x10, 16,
&dac_control);
- if (CHSPEC_IS2G(pi->radio_chanspec))
write_phy_reg(pi, 0x6a, 0x2);
- else
write_phy_reg(pi, 0x6a, 0x9c40);
pdetrange =
(CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g.
pdetrange : pi->srom_fem2g.pdetrange;
- mod_phy_reg(pi, 0x294, (0xf << 8), (7 << 8));
if (pdetrange == 0) {
if (NREV_GE(pi->pubpi.phy_rev, 4)) {
aux_adc_vmid = aux_adc_vmid_rev4;
aux_adc_gain = aux_adc_gain_rev4;
} else {
aux_adc_vmid = aux_adc_vmid_rev3;
aux_adc_gain = aux_adc_gain_rev3;
}
chan_freq_range =
wlc_phy_get_chan_freq_range_nphy(pi, 0);
if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
switch (chan_freq_range) {
case WL_CHAN_FREQ_RANGE_5GL:
aux_adc_vmid[3] = 0x89;
aux_adc_gain[3] = 0;
break;
case WL_CHAN_FREQ_RANGE_5GM:
aux_adc_vmid[3] = 0x89;
aux_adc_gain[3] = 0;
break;
case WL_CHAN_FREQ_RANGE_5GH:
aux_adc_vmid[3] = 0x89;
aux_adc_gain[3] = 0;
break;
default:
break;
}
}
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
0x08, 16, aux_adc_vmid);
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
0x18, 16, aux_adc_vmid);
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
0x0c, 16, aux_adc_gain);
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
0x1c, 16, aux_adc_gain);
} else if (pdetrange == 1) {
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
0x08, 16, sk_adc_vmid);
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
0x18, 16, sk_adc_vmid);
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
0x0c, 16, sk_adc_gain);
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
0x1c, 16, sk_adc_gain);
} else if (pdetrange == 2) {
- if (CHSPEC_IS40(pi->radio_chanspec) == 0) {
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 3,
32, &min_nvar_val);
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
127, 32, &min_nvar_val);
- } else {
min_nvar_val = noise_var_tbl_rev3[3];
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 3,
32, &min_nvar_val);
u16 bcm_adc_vmid[] = { 0xa2, 0xb4, 0xb4, 0x74 };
u16 bcm_adc_gain[] = { 0x02, 0x02, 0x02, 0x04 };
min_nvar_val = noise_var_tbl_rev3[127];
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
127, 32, &min_nvar_val);
- }
if (NREV_GE(pi->pubpi.phy_rev, 6)) {
chan_freq_range =
wlc_phy_get_chan_freq_range_nphy(pi, 0);
if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
bcm_adc_vmid[3] = 0x8e;
bcm_adc_gain[3] = 0x03;
} else {
bcm_adc_vmid[3] = 0x94;
bcm_adc_gain[3] = 0x03;
}
} else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
bcm_adc_vmid[3] = 0x84;
bcm_adc_gain[3] = 0x02;
}
- wlc_phy_workarounds_nphy_gainctrl(pi);
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
0x08, 16, bcm_adc_vmid);
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
0x18, 16, bcm_adc_vmid);
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
0x0c, 16, bcm_adc_gain);
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
0x1c, 16, bcm_adc_gain);
} else if (pdetrange == 3) {
chan_freq_range =
wlc_phy_get_chan_freq_range_nphy(pi, 0);
if ((NREV_GE(pi->pubpi.phy_rev, 4))
&& (chan_freq_range == WL_CHAN_FREQ_RANGE_2G)) {
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x00, 16,
&dac_control);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x10, 16,
&dac_control);
u16 auxadc_vmid[] = {
0xa2, 0xb4, 0xb4, 0x270
};
u16 auxadc_gain[] = {
0x02, 0x02, 0x02, 0x00
};
- pdetrange = (CHSPEC_IS5G(pi->radio_chanspec)) ?
pi->srom_fem5g.pdetrange : pi->srom_fem2g.pdetrange;
wlc_phy_table_write_nphy(pi,
NPHY_TBL_ID_AFECTRL, 4,
0x08, 16, auxadc_vmid);
wlc_phy_table_write_nphy(pi,
NPHY_TBL_ID_AFECTRL, 4,
0x18, 16, auxadc_vmid);
wlc_phy_table_write_nphy(pi,
NPHY_TBL_ID_AFECTRL, 4,
0x0c, 16, auxadc_gain);
wlc_phy_table_write_nphy(pi,
NPHY_TBL_ID_AFECTRL, 4,
0x1c, 16, auxadc_gain);
- if (pdetrange == 0) {
if (NREV_GE(pi->pubpi.phy_rev, 4)) {
aux_adc_vmid = aux_adc_vmid_rev4;
aux_adc_gain = aux_adc_gain_rev4;
} else {
aux_adc_vmid = aux_adc_vmid_rev3;
aux_adc_gain = aux_adc_gain_rev3;
}
chan_freq_range = wlc_phy_get_chan_freq_range_nphy(pi, 0);
if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
switch (chan_freq_range) {
case WL_CHAN_FREQ_RANGE_5GL:
aux_adc_vmid[3] = 0x89;
aux_adc_gain[3] = 0;
break;
case WL_CHAN_FREQ_RANGE_5GM:
aux_adc_vmid[3] = 0x89;
aux_adc_gain[3] = 0;
break;
case WL_CHAN_FREQ_RANGE_5GH:
aux_adc_vmid[3] = 0x89;
aux_adc_gain[3] = 0;
break;
default:
break; }
} else if ((pdetrange == 4) || (pdetrange == 5)) {
u16 bcm_adc_vmid[] = { 0xa2, 0xb4, 0xb4, 0x0 };
u16 bcm_adc_gain[] = { 0x02, 0x02, 0x02, 0x0 };
u16 Vmid[2], Av[2];
}
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
0x08, 16, aux_adc_vmid);
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
0x18, 16, aux_adc_vmid);
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
0x0c, 16, aux_adc_gain);
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
0x1c, 16, aux_adc_gain);
- } else if (pdetrange == 1) {
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
0x08, 16, sk_adc_vmid);
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
0x18, 16, sk_adc_vmid);
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
0x0c, 16, sk_adc_gain);
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
0x1c, 16, sk_adc_gain);
- } else if (pdetrange == 2) {
u16 bcm_adc_vmid[] = { 0xa2, 0xb4, 0xb4, 0x74 };
u16 bcm_adc_gain[] = { 0x02, 0x02, 0x02, 0x04 };
if (NREV_GE(pi->pubpi.phy_rev, 6)) { chan_freq_range =
wlc_phy_get_chan_freq_range_nphy(pi, 0);
wlc_phy_get_chan_freq_range_nphy(pi, 0); if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
Vmid[0] = (pdetrange == 4) ? 0x8e : 0x89;
Vmid[1] = (pdetrange == 4) ? 0x96 : 0x89;
Av[0] = (pdetrange == 4) ? 2 : 0;
Av[1] = (pdetrange == 4) ? 2 : 0;
bcm_adc_vmid[3] = 0x8e;
bcm_adc_gain[3] = 0x03; } else {
Vmid[0] = (pdetrange == 4) ? 0x89 : 0x74;
Vmid[1] = (pdetrange == 4) ? 0x8b : 0x70;
Av[0] = (pdetrange == 4) ? 2 : 0;
Av[1] = (pdetrange == 4) ? 2 : 0;
bcm_adc_vmid[3] = 0x94;
bcm_adc_gain[3] = 0x03; }
} else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
bcm_adc_vmid[3] = 0x84;
bcm_adc_gain[3] = 0x02;
}
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
0x08, 16, bcm_adc_vmid);
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
0x18, 16, bcm_adc_vmid);
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
0x0c, 16, bcm_adc_gain);
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
0x1c, 16, bcm_adc_gain);
- } else if (pdetrange == 3) {
chan_freq_range = wlc_phy_get_chan_freq_range_nphy(pi, 0);
if ((NREV_GE(pi->pubpi.phy_rev, 4)) &&
(chan_freq_range == WL_CHAN_FREQ_RANGE_2G)) {
u16 auxadc_vmid[] = { 0xa2, 0xb4, 0xb4, 0x270 };
u16 auxadc_gain[] = { 0x02, 0x02, 0x02, 0x00 };
bcm_adc_vmid[3] = Vmid[0];
bcm_adc_gain[3] = Av[0]; wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
0x08, 16, bcm_adc_vmid);
0x08, 16, auxadc_vmid); wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
0x0c, 16, bcm_adc_gain);
bcm_adc_vmid[3] = Vmid[1];
bcm_adc_gain[3] = Av[1];
0x18, 16, auxadc_vmid); wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
0x18, 16, bcm_adc_vmid);
0x0c, 16, auxadc_gain); wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
0x1c, 16, bcm_adc_gain);
}0x1c, 16, auxadc_gain);
- } else if ((pdetrange == 4) || (pdetrange == 5)) {
u16 bcm_adc_vmid[] = { 0xa2, 0xb4, 0xb4, 0x0 };
u16 bcm_adc_gain[] = { 0x02, 0x02, 0x02, 0x0 };
u16 Vmid[2], Av[2];
write_radio_reg(pi,
(RADIO_2056_RX_MIXA_MAST_BIAS | RADIO_2056_RX0),
0x0);
write_radio_reg(pi,
(RADIO_2056_RX_MIXA_MAST_BIAS | RADIO_2056_RX1),
0x0);
chan_freq_range = wlc_phy_get_chan_freq_range_nphy(pi, 0);
if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
Vmid[0] = (pdetrange == 4) ? 0x8e : 0x89;
Vmid[1] = (pdetrange == 4) ? 0x96 : 0x89;
Av[0] = (pdetrange == 4) ? 2 : 0;
Av[1] = (pdetrange == 4) ? 2 : 0;
} else {
Vmid[0] = (pdetrange == 4) ? 0x89 : 0x74;
Vmid[1] = (pdetrange == 4) ? 0x8b : 0x70;
Av[0] = (pdetrange == 4) ? 2 : 0;
Av[1] = (pdetrange == 4) ? 2 : 0;
}
write_radio_reg(pi,
(RADIO_2056_RX_MIXA_BIAS_MAIN | RADIO_2056_RX0),
0x6);
write_radio_reg(pi,
(RADIO_2056_RX_MIXA_BIAS_MAIN | RADIO_2056_RX1),
0x6);
bcm_adc_vmid[3] = Vmid[0];
bcm_adc_gain[3] = Av[0];
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
0x08, 16, bcm_adc_vmid);
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
0x0c, 16, bcm_adc_gain);
bcm_adc_vmid[3] = Vmid[1];
bcm_adc_gain[3] = Av[1];
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
0x18, 16, bcm_adc_vmid);
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
0x1c, 16, bcm_adc_gain);
- }
write_radio_reg(pi,
(RADIO_2056_RX_MIXA_BIAS_AUX | RADIO_2056_RX0),
0x7);
write_radio_reg(pi,
(RADIO_2056_RX_MIXA_BIAS_AUX | RADIO_2056_RX1),
0x7);
- write_radio_reg(pi, (RADIO_2056_RX_MIXA_MAST_BIAS | RADIO_2056_RX0), 0x0);
- write_radio_reg(pi, (RADIO_2056_RX_MIXA_MAST_BIAS | RADIO_2056_RX1), 0x0);
write_radio_reg(pi,
(RADIO_2056_RX_MIXA_LOB_BIAS | RADIO_2056_RX0),
0x88);
write_radio_reg(pi,
(RADIO_2056_RX_MIXA_LOB_BIAS | RADIO_2056_RX1),
0x88);
- write_radio_reg(pi, (RADIO_2056_RX_MIXA_BIAS_MAIN | RADIO_2056_RX0), 0x6);
- write_radio_reg(pi, (RADIO_2056_RX_MIXA_BIAS_MAIN | RADIO_2056_RX1), 0x6);
write_radio_reg(pi,
(RADIO_2056_RX_MIXA_CMFB_IDAC | RADIO_2056_RX0),
0x0);
write_radio_reg(pi,
(RADIO_2056_RX_MIXA_CMFB_IDAC | RADIO_2056_RX1),
0x0);
- write_radio_reg(pi, (RADIO_2056_RX_MIXA_BIAS_AUX | RADIO_2056_RX0), 0x7);
- write_radio_reg(pi, (RADIO_2056_RX_MIXA_BIAS_AUX | RADIO_2056_RX1), 0x7);
write_radio_reg(pi,
(RADIO_2056_RX_MIXG_CMFB_IDAC | RADIO_2056_RX0),
0x0);
write_radio_reg(pi,
(RADIO_2056_RX_MIXG_CMFB_IDAC | RADIO_2056_RX1),
0x0);
- write_radio_reg(pi, (RADIO_2056_RX_MIXA_LOB_BIAS | RADIO_2056_RX0), 0x88);
- write_radio_reg(pi, (RADIO_2056_RX_MIXA_LOB_BIAS | RADIO_2056_RX1), 0x88);
triso =
(CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g.
triso : pi->srom_fem2g.triso;
if (triso == 7) {
wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_0);
wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_1);
}
- write_radio_reg(pi, (RADIO_2056_RX_MIXA_CMFB_IDAC | RADIO_2056_RX0), 0x0);
- write_radio_reg(pi, (RADIO_2056_RX_MIXA_CMFB_IDAC | RADIO_2056_RX1), 0x0);
wlc_phy_war_txchain_upd_nphy(pi, pi->sh->hw_phytxchain);
- write_radio_reg(pi, (RADIO_2056_RX_MIXG_CMFB_IDAC | RADIO_2056_RX0), 0x0);
- write_radio_reg(pi, (RADIO_2056_RX_MIXG_CMFB_IDAC | RADIO_2056_RX1), 0x0);
if (((pi->sh->boardflags2 & BFL2_APLL_WAR) &&
(CHSPEC_IS5G(pi->radio_chanspec))) ||
(((pi->sh->boardflags2 & BFL2_GPLL_WAR) ||
(pi->sh->boardflags2 & BFL2_GPLL_WAR2)) &&
(CHSPEC_IS2G(pi->radio_chanspec)))) {
nss1_data_weights = 0x00088888;
ht_data_weights = 0x00088888;
stbc_data_weights = 0x00088888;
} else {
nss1_data_weights = 0x88888888;
ht_data_weights = 0x88888888;
stbc_data_weights = 0x88888888;
}
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
1, 1, 32, &nss1_data_weights);
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
1, 2, 32, &ht_data_weights);
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
1, 3, 32, &stbc_data_weights);
if (NREV_IS(pi->pubpi.phy_rev, 4)) {
if (CHSPEC_IS5G(pi->radio_chanspec)) {
write_radio_reg(pi,
RADIO_2056_TX_GMBB_IDAC |
RADIO_2056_TX0, 0x70);
write_radio_reg(pi,
RADIO_2056_TX_GMBB_IDAC |
RADIO_2056_TX1, 0x70);
}
}
- triso = (CHSPEC_IS5G(pi->radio_chanspec)) ?
pi->srom_fem5g.triso : pi->srom_fem2g.triso;
- if (triso == 7) {
wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_0);
wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_1);
- }
if (!pi->edcrs_threshold_lock) {
write_phy_reg(pi, 0x224, 0x3eb);
write_phy_reg(pi, 0x225, 0x3eb);
write_phy_reg(pi, 0x226, 0x341);
write_phy_reg(pi, 0x227, 0x341);
write_phy_reg(pi, 0x228, 0x42b);
write_phy_reg(pi, 0x229, 0x42b);
write_phy_reg(pi, 0x22a, 0x381);
write_phy_reg(pi, 0x22b, 0x381);
write_phy_reg(pi, 0x22c, 0x42b);
write_phy_reg(pi, 0x22d, 0x42b);
write_phy_reg(pi, 0x22e, 0x381);
write_phy_reg(pi, 0x22f, 0x381);
- wlc_phy_war_txchain_upd_nphy(pi, pi->sh->hw_phytxchain);
- if (((pi->sh->boardflags2 & BFL2_APLL_WAR) &&
(CHSPEC_IS5G(pi->radio_chanspec))) ||
(((pi->sh->boardflags2 & BFL2_GPLL_WAR) ||
(pi->sh->boardflags2 & BFL2_GPLL_WAR2)) &&
(CHSPEC_IS2G(pi->radio_chanspec)))) {
nss1_data_weights = 0x00088888;
ht_data_weights = 0x00088888;
stbc_data_weights = 0x00088888;
- } else {
nss1_data_weights = 0x88888888;
ht_data_weights = 0x88888888;
stbc_data_weights = 0x88888888;
- }
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
1, 1, 32, &nss1_data_weights);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
1, 2, 32, &ht_data_weights);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
1, 3, 32, &stbc_data_weights);
- if (NREV_IS(pi->pubpi.phy_rev, 4)) {
if (CHSPEC_IS5G(pi->radio_chanspec)) {
write_radio_reg(pi,
RADIO_2056_TX_GMBB_IDAC |
RADIO_2056_TX0, 0x70);
write_radio_reg(pi,
RADIO_2056_TX_GMBB_IDAC |
}RADIO_2056_TX1, 0x70);
- }
if (NREV_GE(pi->pubpi.phy_rev, 6)) {
- if (!pi->edcrs_threshold_lock) {
write_phy_reg(pi, 0x224, 0x3eb);
write_phy_reg(pi, 0x225, 0x3eb);
write_phy_reg(pi, 0x226, 0x341);
write_phy_reg(pi, 0x227, 0x341);
write_phy_reg(pi, 0x228, 0x42b);
write_phy_reg(pi, 0x229, 0x42b);
write_phy_reg(pi, 0x22a, 0x381);
write_phy_reg(pi, 0x22b, 0x381);
write_phy_reg(pi, 0x22c, 0x42b);
write_phy_reg(pi, 0x22d, 0x42b);
write_phy_reg(pi, 0x22e, 0x381);
write_phy_reg(pi, 0x22f, 0x381);
- }
if (pi->sh->boardflags2 & BFL2_SINGLEANT_CCK)
wlapi_bmac_mhf(pi->sh->physhim, MHF4,
MHF4_BPHY_TXCORE0,
MHF4_BPHY_TXCORE0, BRCM_BAND_ALL);
}
- if (NREV_GE(pi->pubpi.phy_rev, 6)) {
if (pi->sh->boardflags2 & BFL2_SINGLEANT_CCK)
wlapi_bmac_mhf(pi->sh->physhim, MHF4,
MHF4_BPHY_TXCORE0,
MHF4_BPHY_TXCORE0, BRCM_BAND_ALL);
- }
} void wlc_phy_workarounds_nphy_rev1(struct brcms_phy *pi) @@ -17043,102 +16931,101 @@ void wlc_phy_workarounds_nphy_rev1(struct brcms_phy *pi) s16 beta0, beta1, beta2; u16 regval;
if (pi->sh->boardflags2 & BFL2_SKWRKFEM_BRD ||
(pi->sh->boardtype == 0x8b)) {
uint i;
u8 war_dlys[] = { 1, 6, 6, 2, 4, 20, 1 };
for (i = 0; i < ARRAY_SIZE(rfseq_rx2tx_dlys); i++)
rfseq_rx2tx_dlys[i] = war_dlys[i];
}
- if (pi->sh->boardflags2 & BFL2_SKWRKFEM_BRD ||
(pi->sh->boardtype == 0x8b)) {
uint i;
u8 war_dlys[] = { 1, 6, 6, 2, 4, 20, 1 };
for (i = 0; i < ARRAY_SIZE(rfseq_rx2tx_dlys); i++)
rfseq_rx2tx_dlys[i] = war_dlys[i];
- }
if (CHSPEC_IS5G(pi->radio_chanspec) && pi->phy_5g_pwrgain) {
and_radio_reg(pi, RADIO_2055_CORE1_TX_RF_SPARE, 0xf7);
and_radio_reg(pi, RADIO_2055_CORE2_TX_RF_SPARE, 0xf7);
} else {
or_radio_reg(pi, RADIO_2055_CORE1_TX_RF_SPARE, 0x8);
or_radio_reg(pi, RADIO_2055_CORE2_TX_RF_SPARE, 0x8);
}
- if (CHSPEC_IS5G(pi->radio_chanspec) && pi->phy_5g_pwrgain) {
and_radio_reg(pi, RADIO_2055_CORE1_TX_RF_SPARE, 0xf7);
and_radio_reg(pi, RADIO_2055_CORE2_TX_RF_SPARE, 0xf7);
- } else {
or_radio_reg(pi, RADIO_2055_CORE1_TX_RF_SPARE, 0x8);
or_radio_reg(pi, RADIO_2055_CORE2_TX_RF_SPARE, 0x8);
- }
regval = 0x000a;
wlc_phy_table_write_nphy(pi, 8, 1, 0, 16, ®val);
wlc_phy_table_write_nphy(pi, 8, 1, 0x10, 16, ®val);
- regval = 0x000a;
- wlc_phy_table_write_nphy(pi, 8, 1, 0, 16, ®val);
- wlc_phy_table_write_nphy(pi, 8, 1, 0x10, 16, ®val);
if (NREV_LT(pi->pubpi.phy_rev, 3)) {
regval = 0xcdaa;
wlc_phy_table_write_nphy(pi, 8, 1, 0x02, 16, ®val);
wlc_phy_table_write_nphy(pi, 8, 1, 0x12, 16, ®val);
}
- if (NREV_LT(pi->pubpi.phy_rev, 3)) {
regval = 0xcdaa;
wlc_phy_table_write_nphy(pi, 8, 1, 0x02, 16, ®val);
wlc_phy_table_write_nphy(pi, 8, 1, 0x12, 16, ®val);
- }
if (NREV_LT(pi->pubpi.phy_rev, 2)) {
regval = 0x0000;
wlc_phy_table_write_nphy(pi, 8, 1, 0x08, 16, ®val);
wlc_phy_table_write_nphy(pi, 8, 1, 0x18, 16, ®val);
- if (NREV_LT(pi->pubpi.phy_rev, 2)) {
regval = 0x0000;
wlc_phy_table_write_nphy(pi, 8, 1, 0x08, 16, ®val);
wlc_phy_table_write_nphy(pi, 8, 1, 0x18, 16, ®val);
regval = 0x7aab;
wlc_phy_table_write_nphy(pi, 8, 1, 0x07, 16, ®val);
wlc_phy_table_write_nphy(pi, 8, 1, 0x17, 16, ®val);
regval = 0x7aab;
wlc_phy_table_write_nphy(pi, 8, 1, 0x07, 16, ®val);
wlc_phy_table_write_nphy(pi, 8, 1, 0x17, 16, ®val);
regval = 0x0800;
wlc_phy_table_write_nphy(pi, 8, 1, 0x06, 16, ®val);
wlc_phy_table_write_nphy(pi, 8, 1, 0x16, 16, ®val);
}
regval = 0x0800;
wlc_phy_table_write_nphy(pi, 8, 1, 0x06, 16, ®val);
wlc_phy_table_write_nphy(pi, 8, 1, 0x16, 16, ®val);
- }
write_phy_reg(pi, 0xf8, 0x02d8);
write_phy_reg(pi, 0xf9, 0x0301);
write_phy_reg(pi, 0xfa, 0x02d8);
write_phy_reg(pi, 0xfb, 0x0301);
- write_phy_reg(pi, 0xf8, 0x02d8);
- write_phy_reg(pi, 0xf9, 0x0301);
- write_phy_reg(pi, 0xfa, 0x02d8);
- write_phy_reg(pi, 0xfb, 0x0301);
wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX, rfseq_rx2tx_events,
rfseq_rx2tx_dlys,
ARRAY_SIZE(rfseq_rx2tx_events));
- wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX, rfseq_rx2tx_events,
rfseq_rx2tx_dlys,
ARRAY_SIZE(rfseq_rx2tx_events));
wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_TX2RX, rfseq_tx2rx_events,
rfseq_tx2rx_dlys,
ARRAY_SIZE(rfseq_tx2rx_events));
- wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_TX2RX, rfseq_tx2rx_events,
rfseq_tx2rx_dlys,
ARRAY_SIZE(rfseq_tx2rx_events));
wlc_phy_workarounds_nphy_gainctrl(pi);
- wlc_phy_workarounds_nphy_gainctrl(pi);
if (NREV_LT(pi->pubpi.phy_rev, 2)) {
- if (NREV_LT(pi->pubpi.phy_rev, 2)) {
if (read_phy_reg(pi, 0xa0) & NPHY_MLenable)
wlapi_bmac_mhf(pi->sh->physhim, MHF3,
MHF3_NPHY_MLADV_WAR,
MHF3_NPHY_MLADV_WAR,
BRCM_BAND_ALL);
if (read_phy_reg(pi, 0xa0) & NPHY_MLenable)
wlapi_bmac_mhf(pi->sh->physhim, MHF3,
MHF3_NPHY_MLADV_WAR,
MHF3_NPHY_MLADV_WAR, BRCM_BAND_ALL);
} else if (NREV_IS(pi->pubpi.phy_rev, 2)) {
write_phy_reg(pi, 0x1e3, 0x0);
write_phy_reg(pi, 0x1e4, 0x0);
}
- } else if (NREV_IS(pi->pubpi.phy_rev, 2)) {
write_phy_reg(pi, 0x1e3, 0x0);
write_phy_reg(pi, 0x1e4, 0x0);
- }
if (NREV_LT(pi->pubpi.phy_rev, 2))
mod_phy_reg(pi, 0x90, (0x1 << 7), 0);
alpha0 = 293;
alpha1 = 435;
alpha2 = 261;
beta0 = 366;
beta1 = 205;
beta2 = 32;
write_phy_reg(pi, 0x145, alpha0);
write_phy_reg(pi, 0x146, alpha1);
write_phy_reg(pi, 0x147, alpha2);
write_phy_reg(pi, 0x148, beta0);
write_phy_reg(pi, 0x149, beta1);
write_phy_reg(pi, 0x14a, beta2);
if (NREV_LT(pi->pubpi.phy_rev, 3)) {
mod_phy_reg(pi, 0x142, (0xf << 12), 0);
write_phy_reg(pi, 0x192, 0xb5);
write_phy_reg(pi, 0x193, 0xa4);
write_phy_reg(pi, 0x194, 0x0);
}
- if (NREV_LT(pi->pubpi.phy_rev, 2))
mod_phy_reg(pi, 0x90, (0x1 << 7), 0);
- alpha0 = 293;
- alpha1 = 435;
- alpha2 = 261;
- beta0 = 366;
- beta1 = 205;
- beta2 = 32;
- write_phy_reg(pi, 0x145, alpha0);
- write_phy_reg(pi, 0x146, alpha1);
- write_phy_reg(pi, 0x147, alpha2);
- write_phy_reg(pi, 0x148, beta0);
- write_phy_reg(pi, 0x149, beta1);
- write_phy_reg(pi, 0x14a, beta2);
- if (NREV_LT(pi->pubpi.phy_rev, 3)) {
mod_phy_reg(pi, 0x142, (0xf << 12), 0);
write_phy_reg(pi, 0x192, 0xb5);
write_phy_reg(pi, 0x193, 0xa4);
write_phy_reg(pi, 0x194, 0x0);
- }
if (NREV_IS(pi->pubpi.phy_rev, 2))
mod_phy_reg(pi, 0x221,
NPHY_FORCESIG_DECODEGATEDCLKS,
NPHY_FORCESIG_DECODEGATEDCLKS);
- if (NREV_IS(pi->pubpi.phy_rev, 2))
mod_phy_reg(pi, 0x221,
NPHY_FORCESIG_DECODEGATEDCLKS,
NPHY_FORCESIG_DECODEGATEDCLKS);
} static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
Arend Van Spriel arend.vanspriel@broadcom.com writes:
On 2-3-2017 17:38, Arnd Bergmann wrote:
In the previous commit I left the indentation alone to help reviewing the patch, this one now runs the three new functions through 'indent -kr -8' with some manual fixups to avoid silliness.
No changes other than whitespace are intended here.
Acked-by: Arend van Spriel arend.vanspriel@broadcom.com
Signed-off-by: Arnd Bergmann arnd@arndb.de
.../broadcom/brcm80211/brcmsmac/phy/phy_n.c | 1507 +++++++++----------- 1 file changed, 697 insertions(+), 810 deletions(-)
Arend, please edit your quotes. Leaving 1000 lines of unnecessary quotes in your reply makes my use of patchwork horrible:
https://patchwork.kernel.org/patch/9601155/
When CONFIG_KASAN is set, we use a large amount of stack in the btcoexist code, presumably due to lots of inlining of functions that each add to the kernel stack.
net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.c:3762:1: error: the frame size of 4032 bytes is larger than 3072 bytes net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c:3076:1: error: the frame size of 4104 bytes is larger than 3072 bytes net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.c:3740:1: error: the frame size of 3408 bytes is larger than 3072 bytes
I went through these recursively and marked functions as noinline_for_kasan until no function used more than a kilobyte. While I saw the warning only for three of the five files, I'm changing all five the same way for consistency. This should help in case gcc later makes different inlining decisions.
Signed-off-by: Arnd Bergmann arnd@arndb.de --- .../realtek/rtlwifi/btcoexist/halbtc8192e2ant.c | 41 +++++++++++----------- .../realtek/rtlwifi/btcoexist/halbtc8723b1ant.c | 26 +++++++------- .../realtek/rtlwifi/btcoexist/halbtc8723b2ant.c | 34 +++++++++--------- .../realtek/rtlwifi/btcoexist/halbtc8821a1ant.c | 36 +++++++++---------- .../realtek/rtlwifi/btcoexist/halbtc8821a2ant.c | 38 ++++++++++---------- 5 files changed, 88 insertions(+), 87 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.c index ffa1f438424d..8433c406a3c0 100644 --- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.c +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.c @@ -455,7 +455,7 @@ static void halbtc8192e2ant_querybt_info(struct btc_coexist *btcoexist) btcoexist->btc_fill_h2c(btcoexist, 0x61, 1, h2c_parameter); }
-static void halbtc8192e2ant_update_btlink_info(struct btc_coexist *btcoexist) +static noinline_for_kasan void halbtc8192e2ant_update_btlink_info(struct btc_coexist *btcoexist) { struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info; bool bt_hson = false; @@ -751,7 +751,7 @@ static void halbtc8192e2ant_set_fwdec_btpwr(struct btc_coexist *btcoexist, btcoexist->btc_fill_h2c(btcoexist, 0x62, 1, h2c_parameter); }
-static void halbtc8192e2ant_dec_btpwr(struct btc_coexist *btcoexist, +static noinline_for_kasan void halbtc8192e2ant_dec_btpwr(struct btc_coexist *btcoexist, bool force_exec, u8 dec_btpwr_lvl) { struct rtl_priv *rtlpriv = btcoexist->adapter; @@ -817,7 +817,7 @@ static void halbtc8192e2ant_bt_autoreport(struct btc_coexist *btcoexist, coex_dm->pre_bt_auto_report = coex_dm->cur_bt_auto_report; }
-static void halbtc8192e2ant_fw_dac_swinglvl(struct btc_coexist *btcoexist, +static noinline_for_kasan void halbtc8192e2ant_fw_dac_swinglvl(struct btc_coexist *btcoexist, bool force_exec, u8 fw_dac_swinglvl) { struct rtl_priv *rtlpriv = btcoexist->adapter; @@ -1145,8 +1145,9 @@ static void halbtc8192e2ant_IgnoreWlanAct(struct btc_coexist *btcoexist, coex_dm->pre_ignore_wlan_act = coex_dm->cur_ignore_wlan_act; }
-static void halbtc8192e2ant_SetFwPstdma(struct btc_coexist *btcoexist, u8 byte1, - u8 byte2, u8 byte3, u8 byte4, u8 byte5) +static noinline_for_kasan void +halbtc8192e2ant_SetFwPstdma(struct btc_coexist *btcoexist, u8 byte1, + u8 byte2, u8 byte3, u8 byte4, u8 byte5) { struct rtl_priv *rtlpriv = btcoexist->adapter;
@@ -1328,7 +1329,7 @@ static void halbtc8192e2ant_ps_tdma(struct btc_coexist *btcoexist, coex_dm->pre_ps_tdma = coex_dm->cur_ps_tdma; }
-static void halbtc8192e2ant_set_switch_sstype(struct btc_coexist *btcoexist, +static noinline_for_kasan void halbtc8192e2ant_set_switch_sstype(struct btc_coexist *btcoexist, u8 sstype) { struct rtl_priv *rtlpriv = btcoexist->adapter; @@ -1365,7 +1366,7 @@ static void halbtc8192e2ant_set_switch_sstype(struct btc_coexist *btcoexist, btcoexist->btc_set(btcoexist, BTC_SET_ACT_SEND_MIMO_PS, &mimops); }
-static void halbtc8192e2ant_switch_sstype(struct btc_coexist *btcoexist, +static noinline_for_kasan void halbtc8192e2ant_switch_sstype(struct btc_coexist *btcoexist, bool force_exec, u8 new_sstype) { struct rtl_priv *rtlpriv = btcoexist->adapter; @@ -1432,7 +1433,7 @@ static void halbtc8192e2ant_action_bt_inquiry(struct btc_coexist *btcoexist) btc8192e2ant_sw_mec2(btcoexist, false, false, false, 0x18); }
-static bool halbtc8192e2ant_is_common_action(struct btc_coexist *btcoexist) +static noinline_for_kasan bool halbtc8192e2ant_is_common_action(struct btc_coexist *btcoexist) { struct rtl_priv *rtlpriv = btcoexist->adapter; struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info; @@ -2358,7 +2359,7 @@ static void halbtc8192e2ant_tdma_duration_adjust(struct btc_coexist *btcoexist, }
/* SCO only or SCO+PAN(HS) */ -static void halbtc8192e2ant_action_sco(struct btc_coexist *btcoexist) +static noinline_for_kasan void halbtc8192e2ant_action_sco(struct btc_coexist *btcoexist) { u8 wifirssi_state, btrssi_state = BTC_RSSI_STATE_STAY_LOW; u32 wifi_bw; @@ -2420,7 +2421,7 @@ static void halbtc8192e2ant_action_sco(struct btc_coexist *btcoexist) } }
-static void halbtc8192e2ant_action_sco_pan(struct btc_coexist *btcoexist) +static noinline_for_kasan void halbtc8192e2ant_action_sco_pan(struct btc_coexist *btcoexist) { u8 wifirssi_state, btrssi_state = BTC_RSSI_STATE_STAY_LOW; u32 wifi_bw; @@ -2482,7 +2483,7 @@ static void halbtc8192e2ant_action_sco_pan(struct btc_coexist *btcoexist) } }
-static void halbtc8192e2ant_action_hid(struct btc_coexist *btcoexist) +static noinline_for_kasan void halbtc8192e2ant_action_hid(struct btc_coexist *btcoexist) { u8 wifirssi_state, btrssi_state = BTC_RSSI_STATE_HIGH; u32 wifi_bw; @@ -2544,7 +2545,7 @@ static void halbtc8192e2ant_action_hid(struct btc_coexist *btcoexist) }
/* A2DP only / PAN(EDR) only/ A2DP+PAN(HS) */ -static void halbtc8192e2ant_action_a2dp(struct btc_coexist *btcoexist) +static noinline_for_kasan void halbtc8192e2ant_action_a2dp(struct btc_coexist *btcoexist) { struct rtl_priv *rtlpriv = btcoexist->adapter; u8 wifirssi_state, btrssi_state = BTC_RSSI_STATE_HIGH; @@ -2633,7 +2634,7 @@ static void halbtc8192e2ant_action_a2dp(struct btc_coexist *btcoexist) } }
-static void halbtc8192e2ant_action_a2dp_pan_hs(struct btc_coexist *btcoexist) +static noinline_for_kasan void halbtc8192e2ant_action_a2dp_pan_hs(struct btc_coexist *btcoexist) { u8 wifirssi_state, btrssi_state = BTC_RSSI_STATE_HIGH; u32 wifi_bw; @@ -2694,7 +2695,7 @@ static void halbtc8192e2ant_action_a2dp_pan_hs(struct btc_coexist *btcoexist) } }
-static void halbtc8192e2ant_action_pan_edr(struct btc_coexist *btcoexist) +static noinline_for_kasan void halbtc8192e2ant_action_pan_edr(struct btc_coexist *btcoexist) { u8 wifirssi_state, btrssi_state = BTC_RSSI_STATE_HIGH; u32 wifi_bw; @@ -2755,7 +2756,7 @@ static void halbtc8192e2ant_action_pan_edr(struct btc_coexist *btcoexist) }
/* PAN(HS) only */ -static void halbtc8192e2ant_action_pan_hs(struct btc_coexist *btcoexist) +static noinline_for_kasan void halbtc8192e2ant_action_pan_hs(struct btc_coexist *btcoexist) { u8 wifirssi_state, btrssi_state = BTC_RSSI_STATE_HIGH; u32 wifi_bw; @@ -2813,7 +2814,7 @@ static void halbtc8192e2ant_action_pan_hs(struct btc_coexist *btcoexist) }
/* PAN(EDR)+A2DP */ -static void halbtc8192e2ant_action_pan_edr_a2dp(struct btc_coexist *btcoexist) +static noinline_for_kasan void halbtc8192e2ant_action_pan_edr_a2dp(struct btc_coexist *btcoexist) { u8 wifirssi_state, btrssi_state = BTC_RSSI_STATE_HIGH; u32 wifi_bw; @@ -2876,7 +2877,7 @@ static void halbtc8192e2ant_action_pan_edr_a2dp(struct btc_coexist *btcoexist) } }
-static void halbtc8192e2ant_action_pan_edr_hid(struct btc_coexist *btcoexist) +static noinline_for_kasan void halbtc8192e2ant_action_pan_edr_hid(struct btc_coexist *btcoexist) { u8 wifirssi_state, btrssi_state = BTC_RSSI_STATE_HIGH; u32 wifi_bw; @@ -2940,7 +2941,7 @@ static void halbtc8192e2ant_action_pan_edr_hid(struct btc_coexist *btcoexist) }
/* HID+A2DP+PAN(EDR) */ -static void btc8192e2ant_action_hid_a2dp_pan_edr(struct btc_coexist *btcoexist) +static noinline_for_kasan void btc8192e2ant_action_hid_a2dp_pan_edr(struct btc_coexist *btcoexist) { u8 wifirssi_state, btrssi_state = BTC_RSSI_STATE_HIGH; u32 wifi_bw; @@ -3001,7 +3002,7 @@ static void btc8192e2ant_action_hid_a2dp_pan_edr(struct btc_coexist *btcoexist) } }
-static void halbtc8192e2ant_action_hid_a2dp(struct btc_coexist *btcoexist) +static noinline_for_kasan void halbtc8192e2ant_action_hid_a2dp(struct btc_coexist *btcoexist) { u8 wifirssi_state, btrssi_state = BTC_RSSI_STATE_HIGH; u32 wifi_bw; @@ -3060,7 +3061,7 @@ static void halbtc8192e2ant_action_hid_a2dp(struct btc_coexist *btcoexist) } }
-static void halbtc8192e2ant_run_coexist_mechanism(struct btc_coexist *btcoexist) +static noinline_for_kasan void halbtc8192e2ant_run_coexist_mechanism(struct btc_coexist *btcoexist) { struct rtl_priv *rtlpriv = btcoexist->adapter; u8 algorithm = 0; diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c index d67bbfb6ad8e..583933f10af2 100644 --- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c @@ -862,7 +862,7 @@ static void halbtc8723b1ant_SetFwIgnoreWlanAct(struct btc_coexist *btcoexist, btcoexist->btc_fill_h2c(btcoexist, 0x63, 1, h2c_parameter); }
-static void halbtc8723b1ant_ignore_wlan_act(struct btc_coexist *btcoexist, +static noinline_for_kasan void halbtc8723b1ant_ignore_wlan_act(struct btc_coexist *btcoexist, bool force_exec, bool enable) { struct rtl_priv *rtlpriv = btcoexist->adapter; @@ -1407,7 +1407,7 @@ static void halbtc8723b1ant_ps_tdma(struct btc_coexist *btcoexist, coex_dm->pre_ps_tdma = coex_dm->cur_ps_tdma; }
-static bool halbtc8723b1ant_is_common_action(struct btc_coexist *btcoexist) +static noinline_for_kasan bool halbtc8723b1ant_is_common_action(struct btc_coexist *btcoexist) { struct rtl_priv *rtlpriv = btcoexist->adapter; bool commom = false, wifi_connected = false; @@ -1706,56 +1706,56 @@ static void halbtc8723b1ant_power_save_state(struct btc_coexist *btcoexist, * ***************************************************/ /* SCO only or SCO+PAN(HS) */ -static void halbtc8723b1ant_action_sco(struct btc_coexist *btcoexist) +static noinline_for_kasan void halbtc8723b1ant_action_sco(struct btc_coexist *btcoexist) { halbtc8723b1ant_sw_mechanism(btcoexist, true); }
-static void halbtc8723b1ant_action_hid(struct btc_coexist *btcoexist) +static noinline_for_kasan void halbtc8723b1ant_action_hid(struct btc_coexist *btcoexist) { halbtc8723b1ant_sw_mechanism(btcoexist, true); }
/*A2DP only / PAN(EDR) only/ A2DP+PAN(HS) */ -static void halbtc8723b1ant_action_a2dp(struct btc_coexist *btcoexist) +static noinline_for_kasan void halbtc8723b1ant_action_a2dp(struct btc_coexist *btcoexist) { halbtc8723b1ant_sw_mechanism(btcoexist, false); }
-static void halbtc8723b1ant_action_a2dp_pan_hs(struct btc_coexist *btcoexist) +static noinline_for_kasan noinline_for_kasan void halbtc8723b1ant_action_a2dp_pan_hs(struct btc_coexist *btcoexist) { halbtc8723b1ant_sw_mechanism(btcoexist, false); }
-static void halbtc8723b1ant_action_pan_edr(struct btc_coexist *btcoexist) +static noinline_for_kasan void halbtc8723b1ant_action_pan_edr(struct btc_coexist *btcoexist) { halbtc8723b1ant_sw_mechanism(btcoexist, false); }
/* PAN(HS) only */ -static void halbtc8723b1ant_action_pan_hs(struct btc_coexist *btcoexist) +static noinline_for_kasan void halbtc8723b1ant_action_pan_hs(struct btc_coexist *btcoexist) { halbtc8723b1ant_sw_mechanism(btcoexist, false); }
/*PAN(EDR)+A2DP */ -static void halbtc8723b1ant_action_pan_edr_a2dp(struct btc_coexist *btcoexist) +static noinline_for_kasan noinline_for_kasan void halbtc8723b1ant_action_pan_edr_a2dp(struct btc_coexist *btcoexist) { halbtc8723b1ant_sw_mechanism(btcoexist, false); }
-static void halbtc8723b1ant_action_pan_edr_hid(struct btc_coexist *btcoexist) +static noinline_for_kasan noinline_for_kasan void halbtc8723b1ant_action_pan_edr_hid(struct btc_coexist *btcoexist) { halbtc8723b1ant_sw_mechanism(btcoexist, true); }
/* HID+A2DP+PAN(EDR) */ -static void btc8723b1ant_action_hid_a2dp_pan_edr(struct btc_coexist *btcoexist) +static noinline_for_kasan void btc8723b1ant_action_hid_a2dp_pan_edr(struct btc_coexist *btcoexist) { halbtc8723b1ant_sw_mechanism(btcoexist, true); }
-static void halbtc8723b1ant_action_hid_a2dp(struct btc_coexist *btcoexist) +static noinline_for_kasan noinline_for_kasan void halbtc8723b1ant_action_hid_a2dp(struct btc_coexist *btcoexist) { halbtc8723b1ant_sw_mechanism(btcoexist, true); } @@ -2178,7 +2178,7 @@ static void btc8723b1ant_run_sw_coex_mech(struct btc_coexist *btcoexist) } }
-static void halbtc8723b1ant_run_coexist_mechanism(struct btc_coexist *btcoexist) +static noinline_for_kasan void halbtc8723b1ant_run_coexist_mechanism(struct btc_coexist *btcoexist) { struct rtl_priv *rtlpriv = btcoexist->adapter; struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info; diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c index 12125966a911..8459add3576f 100644 --- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c @@ -659,7 +659,7 @@ static void btc8723b2ant_set_fw_dec_bt_pwr(struct btc_coexist *btcoexist, btcoexist->btc_fill_h2c(btcoexist, 0x62, 1, h2c_parameter); }
-static void btc8723b2ant_dec_bt_pwr(struct btc_coexist *btcoexist, +static noinline_for_kasan void btc8723b2ant_dec_bt_pwr(struct btc_coexist *btcoexist, bool force_exec, bool dec_bt_pwr) { struct rtl_priv *rtlpriv = btcoexist->adapter; @@ -1087,7 +1087,7 @@ static void btc8723b_coex_tbl_type(struct btc_coexist *btcoexist, } }
-static void btc8723b2ant_set_fw_ignore_wlan_act(struct btc_coexist *btcoexist, +static noinline_for_kasan void btc8723b2ant_set_fw_ignore_wlan_act(struct btc_coexist *btcoexist, bool enable) { struct rtl_priv *rtlpriv = btcoexist->adapter; @@ -1103,7 +1103,7 @@ static void btc8723b2ant_set_fw_ignore_wlan_act(struct btc_coexist *btcoexist, btcoexist->btc_fill_h2c(btcoexist, 0x63, 1, h2c_parameter); }
-static void btc8723b2ant_ignore_wlan_act(struct btc_coexist *btcoexist, +static noinline_for_kasan void btc8723b2ant_ignore_wlan_act(struct btc_coexist *btcoexist, bool force_exec, bool enable) { struct rtl_priv *rtlpriv = btcoexist->adapter; @@ -1128,7 +1128,7 @@ static void btc8723b2ant_ignore_wlan_act(struct btc_coexist *btcoexist, coex_dm->pre_ignore_wlan_act = coex_dm->cur_ignore_wlan_act; }
-static void btc8723b2ant_set_fw_ps_tdma(struct btc_coexist *btcoexist, u8 byte1, +static noinline_for_kasan void btc8723b2ant_set_fw_ps_tdma(struct btc_coexist *btcoexist, u8 byte1, u8 byte2, u8 byte3, u8 byte4, u8 byte5) { struct rtl_priv *rtlpriv = btcoexist->adapter; @@ -1398,7 +1398,7 @@ static void btc8723b2ant_ps_tdma(struct btc_coexist *btcoexist, bool force_exec, coex_dm->pre_ps_tdma = coex_dm->cur_ps_tdma; }
-static void btc8723b2ant_coex_alloff(struct btc_coexist *btcoexist) +static noinline_for_kasan void btc8723b2ant_coex_alloff(struct btc_coexist *btcoexist) { /* fw all off */ btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 1); @@ -1456,7 +1456,7 @@ static void btc8723b2ant_action_bt_inquiry(struct btc_coexist *btcoexist) false, false); }
-static bool btc8723b2ant_is_common_action(struct btc_coexist *btcoexist) +static noinline_for_kasan bool btc8723b2ant_is_common_action(struct btc_coexist *btcoexist) { struct rtl_priv *rtlpriv = btcoexist->adapter; bool common = false, wifi_connected = false; @@ -2333,7 +2333,7 @@ static void btc8723b2ant_tdma_duration_adjust(struct btc_coexist *btcoexist, }
/* SCO only or SCO+PAN(HS) */ -static void btc8723b2ant_action_sco(struct btc_coexist *btcoexist) +static noinline_for_kasan void btc8723b2ant_action_sco(struct btc_coexist *btcoexist) { u8 wifi_rssi_state; u32 wifi_bw; @@ -2391,7 +2391,7 @@ static void btc8723b2ant_action_sco(struct btc_coexist *btcoexist) } }
-static void btc8723b2ant_action_hid(struct btc_coexist *btcoexist) +static noinline_for_kasan void btc8723b2ant_action_hid(struct btc_coexist *btcoexist) { u8 wifi_rssi_state, bt_rssi_state; u32 wifi_bw; @@ -2453,7 +2453,7 @@ static void btc8723b2ant_action_hid(struct btc_coexist *btcoexist) }
/*A2DP only / PAN(EDR) only/ A2DP+PAN(HS)*/ -static void btc8723b2ant_action_a2dp(struct btc_coexist *btcoexist) +static noinline_for_kasan void btc8723b2ant_action_a2dp(struct btc_coexist *btcoexist) { u8 wifi_rssi_state, wifi_rssi_state1, bt_rssi_state; u32 wifi_bw; @@ -2542,7 +2542,7 @@ static void btc8723b2ant_action_a2dp(struct btc_coexist *btcoexist) } }
-static void btc8723b2ant_action_a2dp_pan_hs(struct btc_coexist *btcoexist) +static noinline_for_kasan void btc8723b2ant_action_a2dp_pan_hs(struct btc_coexist *btcoexist) { u8 wifi_rssi_state; u32 wifi_bw; @@ -2595,7 +2595,7 @@ static void btc8723b2ant_action_a2dp_pan_hs(struct btc_coexist *btcoexist) } }
-static void btc8723b2ant_action_pan_edr(struct btc_coexist *btcoexist) +static noinline_for_kasan void btc8723b2ant_action_pan_edr(struct btc_coexist *btcoexist) { u8 wifi_rssi_state, bt_rssi_state; u32 wifi_bw; @@ -2653,7 +2653,7 @@ static void btc8723b2ant_action_pan_edr(struct btc_coexist *btcoexist) }
/*PAN(HS) only*/ -static void btc8723b2ant_action_pan_hs(struct btc_coexist *btcoexist) +static noinline_for_kasan void btc8723b2ant_action_pan_hs(struct btc_coexist *btcoexist) { u8 wifi_rssi_state; u32 wifi_bw; @@ -2706,7 +2706,7 @@ static void btc8723b2ant_action_pan_hs(struct btc_coexist *btcoexist) }
/*PAN(EDR)+A2DP*/ -static void btc8723b2ant_action_pan_edr_a2dp(struct btc_coexist *btcoexist) +static noinline_for_kasan void btc8723b2ant_action_pan_edr_a2dp(struct btc_coexist *btcoexist) { u8 wifi_rssi_state, bt_rssi_state; u32 wifi_bw; @@ -2770,7 +2770,7 @@ static void btc8723b2ant_action_pan_edr_a2dp(struct btc_coexist *btcoexist) } }
-static void btc8723b2ant_action_pan_edr_hid(struct btc_coexist *btcoexist) +static noinline_for_kasan void btc8723b2ant_action_pan_edr_hid(struct btc_coexist *btcoexist) { u8 wifi_rssi_state, bt_rssi_state; u32 wifi_bw; @@ -2840,7 +2840,7 @@ static void btc8723b2ant_action_pan_edr_hid(struct btc_coexist *btcoexist) }
/* HID+A2DP+PAN(EDR) */ -static void btc8723b2ant_action_hid_a2dp_pan_edr(struct btc_coexist *btcoexist) +static noinline_for_kasan void btc8723b2ant_action_hid_a2dp_pan_edr(struct btc_coexist *btcoexist) { u8 wifi_rssi_state, bt_rssi_state; u32 wifi_bw; @@ -2904,7 +2904,7 @@ static void btc8723b2ant_action_hid_a2dp_pan_edr(struct btc_coexist *btcoexist) } }
-static void btc8723b2ant_action_hid_a2dp(struct btc_coexist *btcoexist) +static noinline_for_kasan void btc8723b2ant_action_hid_a2dp(struct btc_coexist *btcoexist) { u8 wifi_rssi_state, bt_rssi_state; u32 wifi_bw; @@ -2962,7 +2962,7 @@ static void btc8723b2ant_action_hid_a2dp(struct btc_coexist *btcoexist) } }
-static void btc8723b2ant_run_coexist_mechanism(struct btc_coexist *btcoexist) +static noinline_for_kasan void btc8723b2ant_run_coexist_mechanism(struct btc_coexist *btcoexist) { struct rtl_priv *rtlpriv = btcoexist->adapter; u8 algorithm = 0; diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.c index 8b689ed9a629..b3f24226f165 100644 --- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.c +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.c @@ -670,7 +670,7 @@ static u8 halbtc8821a1ant_action_algorithm(struct btc_coexist *btcoexist) return algorithm; }
-static void halbtc8821a1ant_set_bt_auto_report(struct btc_coexist *btcoexist, +static noinline_for_kasan void halbtc8821a1ant_set_bt_auto_report(struct btc_coexist *btcoexist, bool enable_auto_report) { struct rtl_priv *rtlpriv = btcoexist->adapter; @@ -689,7 +689,7 @@ static void halbtc8821a1ant_set_bt_auto_report(struct btc_coexist *btcoexist, btcoexist->btc_fill_h2c(btcoexist, 0x68, 1, h2c_parameter); }
-static void halbtc8821a1ant_bt_auto_report(struct btc_coexist *btcoexist, +static noinline_for_kasan void halbtc8821a1ant_bt_auto_report(struct btc_coexist *btcoexist, bool force_exec, bool enable_auto_report) { @@ -849,7 +849,7 @@ static void halbtc8821a1ant_coex_table_with_type(struct btc_coexist *btcoexist, } }
-static void btc8821a1ant_set_fw_ignore_wlan_act(struct btc_coexist *btcoexist, +static noinline_for_kasan void btc8821a1ant_set_fw_ignore_wlan_act(struct btc_coexist *btcoexist, bool enable) { struct rtl_priv *rtlpriv = btcoexist->adapter; @@ -865,7 +865,7 @@ static void btc8821a1ant_set_fw_ignore_wlan_act(struct btc_coexist *btcoexist, btcoexist->btc_fill_h2c(btcoexist, 0x63, 1, h2c_parameter); }
-static void halbtc8821a1ant_ignore_wlan_act(struct btc_coexist *btcoexist, +static noinline_for_kasan void halbtc8821a1ant_ignore_wlan_act(struct btc_coexist *btcoexist, bool force_exec, bool enable) { struct rtl_priv *rtlpriv = btcoexist->adapter; @@ -890,7 +890,7 @@ static void halbtc8821a1ant_ignore_wlan_act(struct btc_coexist *btcoexist, coex_dm->pre_ignore_wlan_act = coex_dm->cur_ignore_wlan_act; }
-static void halbtc8821a1ant_set_fw_pstdma(struct btc_coexist *btcoexist, +static noinline_for_kasan void halbtc8821a1ant_set_fw_pstdma(struct btc_coexist *btcoexist, u8 byte1, u8 byte2, u8 byte3, u8 byte4, u8 byte5) { @@ -1269,7 +1269,7 @@ static void halbtc8821a1ant_ps_tdma(struct btc_coexist *btcoexist, coex_dm->pre_ps_tdma = coex_dm->cur_ps_tdma; }
-static bool halbtc8821a1ant_is_common_action(struct btc_coexist *btcoexist) +static noinline_for_kasan bool halbtc8821a1ant_is_common_action(struct btc_coexist *btcoexist) { struct rtl_priv *rtlpriv = btcoexist->adapter; bool common = false, wifi_connected = false, wifi_busy = false; @@ -1669,56 +1669,56 @@ static void btc8821a1ant_mon_bt_en_dis(struct btc_coexist *btcoexist) /*=============================================*/
/* SCO only or SCO+PAN(HS)*/ -static void halbtc8821a1ant_action_sco(struct btc_coexist *btcoexist) +static noinline_for_kasan void halbtc8821a1ant_action_sco(struct btc_coexist *btcoexist) { halbtc8821a1ant_sw_mechanism(btcoexist, true); }
-static void halbtc8821a1ant_action_hid(struct btc_coexist *btcoexist) +static noinline_for_kasan void halbtc8821a1ant_action_hid(struct btc_coexist *btcoexist) { halbtc8821a1ant_sw_mechanism(btcoexist, true); }
/*A2DP only / PAN(EDR) only/ A2DP+PAN(HS)*/ -static void halbtc8821a1ant_action_a2dp(struct btc_coexist *btcoexist) +static noinline_for_kasan void halbtc8821a1ant_action_a2dp(struct btc_coexist *btcoexist) { halbtc8821a1ant_sw_mechanism(btcoexist, false); }
-static void halbtc8821a1ant_action_a2dp_pan_hs(struct btc_coexist *btcoexist) +static noinline_for_kasan noinline_for_kasan void halbtc8821a1ant_action_a2dp_pan_hs(struct btc_coexist *btcoexist) { halbtc8821a1ant_sw_mechanism(btcoexist, false); }
-static void halbtc8821a1ant_action_pan_edr(struct btc_coexist *btcoexist) +static noinline_for_kasan void halbtc8821a1ant_action_pan_edr(struct btc_coexist *btcoexist) { halbtc8821a1ant_sw_mechanism(btcoexist, false); }
/*PAN(HS) only*/ -static void halbtc8821a1ant_action_pan_hs(struct btc_coexist *btcoexist) +static noinline_for_kasan void halbtc8821a1ant_action_pan_hs(struct btc_coexist *btcoexist) { halbtc8821a1ant_sw_mechanism(btcoexist, false); }
/*PAN(EDR)+A2DP*/ -static void halbtc8821a1ant_action_pan_edr_a2dp(struct btc_coexist *btcoexist) +static noinline_for_kasan noinline_for_kasan void halbtc8821a1ant_action_pan_edr_a2dp(struct btc_coexist *btcoexist) { halbtc8821a1ant_sw_mechanism(btcoexist, false); }
-static void halbtc8821a1ant_action_pan_edr_hid(struct btc_coexist *btcoexist) +static noinline_for_kasan noinline_for_kasan void halbtc8821a1ant_action_pan_edr_hid(struct btc_coexist *btcoexist) { halbtc8821a1ant_sw_mechanism(btcoexist, true); }
/* HID+A2DP+PAN(EDR)*/ -static void btc8821a1ant_action_hid_a2dp_pan_edr(struct btc_coexist *btcoexist) +static noinline_for_kasan void btc8821a1ant_action_hid_a2dp_pan_edr(struct btc_coexist *btcoexist) { halbtc8821a1ant_sw_mechanism(btcoexist, true); }
-static void halbtc8821a1ant_action_hid_a2dp(struct btc_coexist *btcoexist) +static noinline_for_kasan noinline_for_kasan void halbtc8821a1ant_action_hid_a2dp(struct btc_coexist *btcoexist) { halbtc8821a1ant_sw_mechanism(btcoexist, true); } @@ -1991,7 +1991,7 @@ static void halbtc8821a1ant_action_wifi_connected(struct btc_coexist *btcoexist) } }
-static void btc8821a1ant_run_sw_coex_mech(struct btc_coexist *btcoexist) +static noinline_for_kasan void btc8821a1ant_run_sw_coex_mech(struct btc_coexist *btcoexist) { struct rtl_priv *rtlpriv = btcoexist->adapter; u8 algorithm = 0; @@ -2061,7 +2061,7 @@ static void btc8821a1ant_run_sw_coex_mech(struct btc_coexist *btcoexist) } }
-static void halbtc8821a1ant_run_coexist_mechanism(struct btc_coexist *btcoexist) +static noinline_for_kasan void halbtc8821a1ant_run_coexist_mechanism(struct btc_coexist *btcoexist) { struct rtl_priv *rtlpriv = btcoexist->adapter; struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info; diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.c index 1717e9ce96ca..9da9f5df7690 100644 --- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.c +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.c @@ -610,7 +610,7 @@ static void halbtc8821a2ant_set_fw_dec_bt_pwr(struct btc_coexist *btcoexist, btcoexist->btc_fill_h2c(btcoexist, 0x62, 1, h2c_parameter); }
-static void halbtc8821a2ant_dec_bt_pwr(struct btc_coexist *btcoexist, +static noinline_for_kasan void halbtc8821a2ant_dec_bt_pwr(struct btc_coexist *btcoexist, bool force_exec, bool dec_bt_pwr) { struct rtl_priv *rtlpriv = btcoexist->adapter; @@ -722,7 +722,7 @@ static void halbtc8821a2ant_set_bt_psd_mode(struct btc_coexist *btcoexist, coex_dm->pre_bt_psd_mode = coex_dm->cur_bt_psd_mode; }
-static void halbtc8821a2ant_set_bt_auto_report(struct btc_coexist *btcoexist, +static noinline_for_kasan void halbtc8821a2ant_set_bt_auto_report(struct btc_coexist *btcoexist, bool enable_auto_report) { struct rtl_priv *rtlpriv = btcoexist->adapter; @@ -741,7 +741,7 @@ static void halbtc8821a2ant_set_bt_auto_report(struct btc_coexist *btcoexist, btcoexist->btc_fill_h2c(btcoexist, 0x68, 1, h2c_parameter); }
-static void halbtc8821a2ant_bt_auto_report(struct btc_coexist *btcoexist, +static noinline_for_kasan void halbtc8821a2ant_bt_auto_report(struct btc_coexist *btcoexist, bool force_exec, bool enable_auto_report) { @@ -1066,7 +1066,7 @@ static void halbtc8821a2ant_coex_table(struct btc_coexist *btcoexist, coex_dm->pre_val0x6cc = coex_dm->cur_val0x6cc; }
-static void halbtc8821a2ant_set_fw_ignore_wlan_act(struct btc_coexist *btcoex, +static noinline_for_kasan void halbtc8821a2ant_set_fw_ignore_wlan_act(struct btc_coexist *btcoex, bool enable) { struct rtl_priv *rtlpriv = btcoex->adapter; @@ -1082,7 +1082,7 @@ static void halbtc8821a2ant_set_fw_ignore_wlan_act(struct btc_coexist *btcoex, btcoex->btc_fill_h2c(btcoex, 0x63, 1, h2c_parameter); }
-static void halbtc8821a2ant_ignore_wlan_act(struct btc_coexist *btcoexist, +static noinline_for_kasan void halbtc8821a2ant_ignore_wlan_act(struct btc_coexist *btcoexist, bool force_exec, bool enable) { struct rtl_priv *rtlpriv = btcoexist->adapter; @@ -1107,7 +1107,7 @@ static void halbtc8821a2ant_ignore_wlan_act(struct btc_coexist *btcoexist, coex_dm->pre_ignore_wlan_act = coex_dm->cur_ignore_wlan_act; }
-static void halbtc8821a2ant_set_fw_pstdma(struct btc_coexist *btcoexist, +static noinline_for_kasan void halbtc8821a2ant_set_fw_pstdma(struct btc_coexist *btcoexist, u8 byte1, u8 byte2, u8 byte3, u8 byte4, u8 byte5) { @@ -1362,7 +1362,7 @@ static void halbtc8821a2ant_ps_tdma(struct btc_coexist *btcoexist, coex_dm->pre_ps_tdma = coex_dm->cur_ps_tdma; }
-static void halbtc8821a2ant_coex_all_off(struct btc_coexist *btcoexist) +static noinline_for_kasan void halbtc8821a2ant_coex_all_off(struct btc_coexist *btcoexist) { /* fw all off */ halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 1); @@ -1409,7 +1409,7 @@ static void halbtc8821a2ant_bt_inquiry_page(struct btc_coexist *btcoexist) halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 3); }
-static bool halbtc8821a2ant_is_common_action(struct btc_coexist *btcoexist) +static noinline_for_kasan bool halbtc8821a2ant_is_common_action(struct btc_coexist *btcoexist) { struct rtl_priv *rtlpriv = btcoexist->adapter; bool common = false, wifi_connected = false, wifi_busy = false; @@ -2355,7 +2355,7 @@ static void btc8821a2ant_tdma_dur_adj(struct btc_coexist *btcoexist, }
/* SCO only or SCO+PAN(HS)*/ -static void halbtc8821a2ant_action_sco(struct btc_coexist *btcoexist) +static noinline_for_kasan void halbtc8821a2ant_action_sco(struct btc_coexist *btcoexist) { u8 wifi_rssi_state, bt_rssi_state; u32 wifi_bw; @@ -2433,7 +2433,7 @@ static void halbtc8821a2ant_action_sco(struct btc_coexist *btcoexist) } }
-static void halbtc8821a2ant_action_hid(struct btc_coexist *btcoexist) +static noinline_for_kasan void halbtc8821a2ant_action_hid(struct btc_coexist *btcoexist) { u8 wifi_rssi_state, bt_rssi_state; u32 wifi_bw; @@ -2513,7 +2513,7 @@ static void halbtc8821a2ant_action_hid(struct btc_coexist *btcoexist) }
/* A2DP only / PAN(EDR) only/ A2DP+PAN(HS) */ -static void halbtc8821a2ant_action_a2dp(struct btc_coexist *btcoexist) +static noinline_for_kasan void halbtc8821a2ant_action_a2dp(struct btc_coexist *btcoexist) { u8 wifi_rssi_state, bt_rssi_state; u32 wifi_bw; @@ -2580,7 +2580,7 @@ static void halbtc8821a2ant_action_a2dp(struct btc_coexist *btcoexist) } }
-static void halbtc8821a2ant_action_a2dp_pan_hs(struct btc_coexist *btcoexist) +static noinline_for_kasan void halbtc8821a2ant_action_a2dp_pan_hs(struct btc_coexist *btcoexist) { u8 wifi_rssi_state, bt_rssi_state, bt_info_ext; u32 wifi_bw; @@ -2650,7 +2650,7 @@ static void halbtc8821a2ant_action_a2dp_pan_hs(struct btc_coexist *btcoexist) } }
-static void halbtc8821a2ant_action_pan_edr(struct btc_coexist *btcoexist) +static noinline_for_kasan void halbtc8821a2ant_action_pan_edr(struct btc_coexist *btcoexist) { u8 wifi_rssi_state, bt_rssi_state; u32 wifi_bw; @@ -2730,7 +2730,7 @@ static void halbtc8821a2ant_action_pan_edr(struct btc_coexist *btcoexist) }
/* PAN(HS) only */ -static void halbtc8821a2ant_action_pan_hs(struct btc_coexist *btcoexist) +static noinline_for_kasan void halbtc8821a2ant_action_pan_hs(struct btc_coexist *btcoexist) { u8 wifi_rssi_state, bt_rssi_state; u32 wifi_bw; @@ -2798,7 +2798,7 @@ static void halbtc8821a2ant_action_pan_hs(struct btc_coexist *btcoexist) }
/* PAN(EDR)+A2DP */ -static void halbtc8821a2ant_action_pan_edr_a2dp(struct btc_coexist *btcoexist) +static noinline_for_kasan void halbtc8821a2ant_action_pan_edr_a2dp(struct btc_coexist *btcoexist) { u8 wifi_rssi_state, bt_rssi_state, bt_info_ext; u32 wifi_bw; @@ -2867,7 +2867,7 @@ static void halbtc8821a2ant_action_pan_edr_a2dp(struct btc_coexist *btcoexist) } }
-static void halbtc8821a2ant_action_pan_edr_hid(struct btc_coexist *btcoexist) +static noinline_for_kasan void halbtc8821a2ant_action_pan_edr_hid(struct btc_coexist *btcoexist) { u8 wifi_rssi_state, bt_rssi_state; u32 wifi_bw; @@ -2942,7 +2942,7 @@ static void halbtc8821a2ant_action_pan_edr_hid(struct btc_coexist *btcoexist) }
/* HID+A2DP+PAN(EDR) */ -static void btc8821a2ant_act_hid_a2dp_pan_edr(struct btc_coexist *btcoexist) +static noinline_for_kasan void btc8821a2ant_act_hid_a2dp_pan_edr(struct btc_coexist *btcoexist) { u8 wifi_rssi_state, bt_rssi_state, bt_info_ext; u32 wifi_bw; @@ -3022,7 +3022,7 @@ static void btc8821a2ant_act_hid_a2dp_pan_edr(struct btc_coexist *btcoexist) } }
-static void halbtc8821a2ant_action_hid_a2dp(struct btc_coexist *btcoexist) +static noinline_for_kasan void halbtc8821a2ant_action_hid_a2dp(struct btc_coexist *btcoexist) { u8 wifi_rssi_state, bt_rssi_state, bt_info_ext; u32 wifi_bw; @@ -3079,7 +3079,7 @@ static void halbtc8821a2ant_action_hid_a2dp(struct btc_coexist *btcoexist) } }
-static void halbtc8821a2ant_run_coexist_mechanism(struct btc_coexist *btcoexist) +static noinline_for_kasan void halbtc8821a2ant_run_coexist_mechanism(struct btc_coexist *btcoexist) { struct rtl_priv *rtlpriv = btcoexist->adapter; bool wifi_under_5g = false;
Inlining functions with local variables can lead to excessive stack usage with KASAN:
drivers/net/wireless/wl3501_cs.c: In function 'wl3501_rx_interrupt': drivers/net/wireless/wl3501_cs.c:1103:1: error: the frame size of 2232 bytes is larger than 1536 bytes [-Werror=frame-larger-than=]
Marking a few functions as noinline_for_kasan avoids the problem
Signed-off-by: Arnd Bergmann arnd@arndb.de --- drivers/net/wireless/wl3501_cs.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index acec0d9ec422..15dd8e31d373 100644 --- a/drivers/net/wireless/wl3501_cs.c +++ b/drivers/net/wireless/wl3501_cs.c @@ -242,8 +242,8 @@ static int wl3501_get_flash_mac_addr(struct wl3501_card *this) * * Move 'size' bytes from PC to card. (Shouldn't be interrupted) */ -static void wl3501_set_to_wla(struct wl3501_card *this, u16 dest, void *src, - int size) +static noinline_for_kasan void wl3501_set_to_wla(struct wl3501_card *this, + u16 dest, void *src, int size) { /* switch to SRAM Page 0 */ wl3501_switch_page(this, (dest & 0x8000) ? WL3501_BSS_SPAGE1 : @@ -264,8 +264,8 @@ static void wl3501_set_to_wla(struct wl3501_card *this, u16 dest, void *src, * * Move 'size' bytes from card to PC. (Shouldn't be interrupted) */ -static void wl3501_get_from_wla(struct wl3501_card *this, u16 src, void *dest, - int size) +static noinline_for_kasan void wl3501_get_from_wla(struct wl3501_card *this, + u16 src, void *dest, int size) { /* switch to SRAM Page 0 */ wl3501_switch_page(this, (src & 0x8000) ? WL3501_BSS_SPAGE1 : @@ -1037,7 +1037,7 @@ static inline void wl3501_auth_confirm_interrupt(struct wl3501_card *this, wl3501_mgmt_resync(this); }
-static inline void wl3501_rx_interrupt(struct net_device *dev) +static noinline_for_kasan void wl3501_rx_interrupt(struct net_device *dev) { int morepkts; u16 addr;
When CONFIG_KASAN is set, we see overly large stack frames from inlining functions with local variables:
drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8225se.c: In function 'rtl8225se_rf_init': drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8225se.c:431:1: warning: the frame size of 4384 bytes is larger than 3072 bytes [-Wframe-larger-than=]
This marks them noinline_for_kasan.
Signed-off-by: Arnd Bergmann arnd@arndb.de --- drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8225se.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8225se.c b/drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8225se.c index fde89866fa8d..1efa098a2e32 100644 --- a/drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8225se.c +++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8225se.c @@ -174,14 +174,14 @@ static void rtl8187se_three_wire_io(struct ieee80211_hw *dev, u8 *data, } while (0); }
-static u32 rtl8187se_rf_readreg(struct ieee80211_hw *dev, u8 addr) +static noinline_for_kasan u32 rtl8187se_rf_readreg(struct ieee80211_hw *dev, u8 addr) { u32 dataread = addr & 0x0F; rtl8187se_three_wire_io(dev, (u8 *)&dataread, 16, 0); return dataread; }
-static void rtl8187se_rf_writereg(struct ieee80211_hw *dev, u8 addr, u32 data) +static noinline_for_kasan void rtl8187se_rf_writereg(struct ieee80211_hw *dev, u8 addr, u32 data) { u32 outdata = (data << 4) | (u32)(addr & 0x0F); rtl8187se_three_wire_io(dev, (u8 *)&outdata, 16, 1);
A typical code fragment was copied across many dvb-frontend drivers and causes large stack frames when built with -fsanitize-address-use-after-scope, e.g.
drivers/media/dvb-frontends/cxd2841er.c:3225:1: error: the frame size of 3992 bytes is larger than 3072 bytes [-Werror=frame-larger-than=] drivers/media/dvb-frontends/cxd2841er.c:3404:1: error: the frame size of 3136 bytes is larger than 3072 bytes [-Werror=frame-larger-than=] drivers/media/dvb-frontends/stv0367.c:3143:1: error: the frame size of 4016 bytes is larger than 3072 bytes [-Werror=frame-larger-than=] drivers/media/dvb-frontends/stv090x.c:3430:1: error: the frame size of 5312 bytes is larger than 3072 bytes [-Werror=frame-larger-than=] drivers/media/dvb-frontends/stv090x.c:4248:1: error: the frame size of 4872 bytes is larger than 3072 bytes [-Werror=frame-larger-than=]
By marking the register access functions as noinline_for_kasan, we can completely avoid this problem.
Signed-off-by: Arnd Bergmann arnd@arndb.de --- drivers/media/dvb-frontends/ascot2e.c | 3 ++- drivers/media/dvb-frontends/cxd2841er.c | 4 ++-- drivers/media/dvb-frontends/drx39xyj/drxj.c | 14 +++++++------- drivers/media/dvb-frontends/helene.c | 4 ++-- drivers/media/dvb-frontends/horus3a.c | 2 +- drivers/media/dvb-frontends/itd1000.c | 2 +- drivers/media/dvb-frontends/mt312.c | 2 +- drivers/media/dvb-frontends/si2165.c | 14 +++++++------- drivers/media/dvb-frontends/stb0899_drv.c | 2 +- drivers/media/dvb-frontends/stb6100.c | 2 +- drivers/media/dvb-frontends/stv0367.c | 2 +- drivers/media/dvb-frontends/stv090x.c | 2 +- drivers/media/dvb-frontends/stv6110.c | 2 +- drivers/media/dvb-frontends/stv6110x.c | 2 +- drivers/media/dvb-frontends/tda8083.c | 2 +- drivers/media/dvb-frontends/zl10039.c | 2 +- 16 files changed, 31 insertions(+), 30 deletions(-)
diff --git a/drivers/media/dvb-frontends/ascot2e.c b/drivers/media/dvb-frontends/ascot2e.c index 0ee0df53b91b..435eb4d3f3ef 100644 --- a/drivers/media/dvb-frontends/ascot2e.c +++ b/drivers/media/dvb-frontends/ascot2e.c @@ -153,7 +153,8 @@ static int ascot2e_write_regs(struct ascot2e_priv *priv, return 0; }
-static int ascot2e_write_reg(struct ascot2e_priv *priv, u8 reg, u8 val) +static noinline_for_kasan int ascot2e_write_reg(struct ascot2e_priv *priv, + u8 reg, u8 val) { return ascot2e_write_regs(priv, reg, &val, 1); } diff --git a/drivers/media/dvb-frontends/cxd2841er.c b/drivers/media/dvb-frontends/cxd2841er.c index 614bfb3740f1..01f7ec4d42c1 100644 --- a/drivers/media/dvb-frontends/cxd2841er.c +++ b/drivers/media/dvb-frontends/cxd2841er.c @@ -258,7 +258,7 @@ static int cxd2841er_write_regs(struct cxd2841er_priv *priv, return 0; }
-static int cxd2841er_write_reg(struct cxd2841er_priv *priv, +static noinline_for_kasan int cxd2841er_write_reg(struct cxd2841er_priv *priv, u8 addr, u8 reg, u8 val) { return cxd2841er_write_regs(priv, addr, reg, &val, 1); @@ -306,7 +306,7 @@ static int cxd2841er_read_regs(struct cxd2841er_priv *priv, return 0; }
-static int cxd2841er_read_reg(struct cxd2841er_priv *priv, +static noinline_for_kasan int cxd2841er_read_reg(struct cxd2841er_priv *priv, u8 addr, u8 reg, u8 *val) { return cxd2841er_read_regs(priv, addr, reg, val, 1); diff --git a/drivers/media/dvb-frontends/drx39xyj/drxj.c b/drivers/media/dvb-frontends/drx39xyj/drxj.c index daeaf965dd56..0e6540709e09 100644 --- a/drivers/media/dvb-frontends/drx39xyj/drxj.c +++ b/drivers/media/dvb-frontends/drx39xyj/drxj.c @@ -1516,7 +1516,7 @@ static int drxdap_fasi_read_block(struct i2c_device_addr *dev_addr, * ******************************/
-static int drxdap_fasi_read_reg16(struct i2c_device_addr *dev_addr, +static noinline_for_kasan int drxdap_fasi_read_reg16(struct i2c_device_addr *dev_addr, u32 addr, u16 *data, u32 flags) { @@ -1549,7 +1549,7 @@ static int drxdap_fasi_read_reg16(struct i2c_device_addr *dev_addr, * ******************************/
-static int drxdap_fasi_read_reg32(struct i2c_device_addr *dev_addr, +static noinline_for_kasan int drxdap_fasi_read_reg32(struct i2c_device_addr *dev_addr, u32 addr, u32 *data, u32 flags) { @@ -1722,7 +1722,7 @@ static int drxdap_fasi_write_block(struct i2c_device_addr *dev_addr, * ******************************/
-static int drxdap_fasi_write_reg16(struct i2c_device_addr *dev_addr, +static noinline_for_kasan int drxdap_fasi_write_reg16(struct i2c_device_addr *dev_addr, u32 addr, u16 data, u32 flags) { @@ -1795,7 +1795,7 @@ static int drxdap_fasi_read_modify_write_reg16(struct i2c_device_addr *dev_addr, * ******************************/
-static int drxdap_fasi_write_reg32(struct i2c_device_addr *dev_addr, +static noinline_for_kasan int drxdap_fasi_write_reg32(struct i2c_device_addr *dev_addr, u32 addr, u32 data, u32 flags) { @@ -2172,7 +2172,7 @@ int drxj_dap_atomic_read_write_block(struct i2c_device_addr *dev_addr, * \fn int drxj_dap_atomic_read_reg32() * \brief Atomic read of 32 bits words */ -static +static noinline_for_kasan int drxj_dap_atomic_read_reg32(struct i2c_device_addr *dev_addr, u32 addr, u32 *data, u32 flags) @@ -4191,7 +4191,7 @@ int drxj_dap_scu_atomic_read_write_block(struct i2c_device_addr *dev_addr, u32 a * \fn int DRXJ_DAP_AtomicReadReg16() * \brief Atomic read of 16 bits words */ -static +static noinline_for_kasan int drxj_dap_scu_atomic_read_reg16(struct i2c_device_addr *dev_addr, u32 addr, u16 *data, u32 flags) @@ -4219,7 +4219,7 @@ int drxj_dap_scu_atomic_read_reg16(struct i2c_device_addr *dev_addr, * \fn int drxj_dap_scu_atomic_write_reg16() * \brief Atomic read of 16 bits words */ -static +static noinline_for_kasan int drxj_dap_scu_atomic_write_reg16(struct i2c_device_addr *dev_addr, u32 addr, u16 data, u32 flags) diff --git a/drivers/media/dvb-frontends/helene.c b/drivers/media/dvb-frontends/helene.c index 4bf5a551ba40..d984dfc392f0 100644 --- a/drivers/media/dvb-frontends/helene.c +++ b/drivers/media/dvb-frontends/helene.c @@ -329,7 +329,7 @@ static int helene_write_regs(struct helene_priv *priv, return 0; }
-static int helene_write_reg(struct helene_priv *priv, u8 reg, u8 val) +static noinline_for_kasan int helene_write_reg(struct helene_priv *priv, u8 reg, u8 val) { return helene_write_regs(priv, reg, &val, 1); } @@ -374,7 +374,7 @@ static int helene_read_regs(struct helene_priv *priv, return 0; }
-static int helene_read_reg(struct helene_priv *priv, u8 reg, u8 *val) +static noinline_for_kasan int helene_read_reg(struct helene_priv *priv, u8 reg, u8 *val) { return helene_read_regs(priv, reg, val, 1); } diff --git a/drivers/media/dvb-frontends/horus3a.c b/drivers/media/dvb-frontends/horus3a.c index 94bb4f7a2298..9dc6662073a7 100644 --- a/drivers/media/dvb-frontends/horus3a.c +++ b/drivers/media/dvb-frontends/horus3a.c @@ -87,7 +87,7 @@ static int horus3a_write_regs(struct horus3a_priv *priv, return 0; }
-static int horus3a_write_reg(struct horus3a_priv *priv, u8 reg, u8 val) +static noinline_for_kasan int horus3a_write_reg(struct horus3a_priv *priv, u8 reg, u8 val) { return horus3a_write_regs(priv, reg, &val, 1); } diff --git a/drivers/media/dvb-frontends/itd1000.c b/drivers/media/dvb-frontends/itd1000.c index 5bb1e73a10b4..ae0b19c65b9f 100644 --- a/drivers/media/dvb-frontends/itd1000.c +++ b/drivers/media/dvb-frontends/itd1000.c @@ -93,7 +93,7 @@ static int itd1000_read_reg(struct itd1000_state *state, u8 reg) return val; }
-static inline int itd1000_write_reg(struct itd1000_state *state, u8 r, u8 v) +static noinline_for_kasan int itd1000_write_reg(struct itd1000_state *state, u8 r, u8 v) { int ret = itd1000_write_regs(state, r, &v, 1); state->shadow[r] = v; diff --git a/drivers/media/dvb-frontends/mt312.c b/drivers/media/dvb-frontends/mt312.c index 961b9a2508e0..a41d2c719aac 100644 --- a/drivers/media/dvb-frontends/mt312.c +++ b/drivers/media/dvb-frontends/mt312.c @@ -139,7 +139,7 @@ static inline int mt312_readreg(struct mt312_state *state, return mt312_read(state, reg, val, 1); }
-static inline int mt312_writereg(struct mt312_state *state, +static noinline_for_kasan int mt312_writereg(struct mt312_state *state, const enum mt312_reg_addr reg, const u8 val) { return mt312_write(state, reg, &val, 1); diff --git a/drivers/media/dvb-frontends/si2165.c b/drivers/media/dvb-frontends/si2165.c index 528b82a5dd46..1a0997e1db4a 100644 --- a/drivers/media/dvb-frontends/si2165.c +++ b/drivers/media/dvb-frontends/si2165.c @@ -140,7 +140,7 @@ static int si2165_read(struct si2165_state *state, return 0; }
-static int si2165_readreg8(struct si2165_state *state, +static noinline_for_kasan int si2165_readreg8(struct si2165_state *state, const u16 reg, u8 *val) { unsigned int val_tmp; @@ -150,7 +150,7 @@ static int si2165_readreg8(struct si2165_state *state, return ret; }
-static int si2165_readreg16(struct si2165_state *state, +static noinline_for_kasan int si2165_readreg16(struct si2165_state *state, const u16 reg, u16 *val) { u8 buf[2]; @@ -161,26 +161,26 @@ static int si2165_readreg16(struct si2165_state *state, return ret; }
-static int si2165_writereg8(struct si2165_state *state, const u16 reg, u8 val) +static noinline_for_kasan int si2165_writereg8(struct si2165_state *state, const u16 reg, u8 val) { return regmap_write(state->regmap, reg, val); }
-static int si2165_writereg16(struct si2165_state *state, const u16 reg, u16 val) +static noinline_for_kasan int si2165_writereg16(struct si2165_state *state, const u16 reg, u16 val) { u8 buf[2] = { val & 0xff, (val >> 8) & 0xff };
return si2165_write(state, reg, buf, 2); }
-static int si2165_writereg24(struct si2165_state *state, const u16 reg, u32 val) +static noinline_for_kasan int si2165_writereg24(struct si2165_state *state, const u16 reg, u32 val) { u8 buf[3] = { val & 0xff, (val >> 8) & 0xff, (val >> 16) & 0xff };
return si2165_write(state, reg, buf, 3); }
-static int si2165_writereg32(struct si2165_state *state, const u16 reg, u32 val) +static noinline_for_kasan int si2165_writereg32(struct si2165_state *state, const u16 reg, u32 val) { u8 buf[4] = { val & 0xff, @@ -191,7 +191,7 @@ static int si2165_writereg32(struct si2165_state *state, const u16 reg, u32 val) return si2165_write(state, reg, buf, 4); }
-static int si2165_writereg_mask8(struct si2165_state *state, const u16 reg, +static noinline_for_kasan int si2165_writereg_mask8(struct si2165_state *state, const u16 reg, u8 val, u8 mask) { if (mask != 0xff) { diff --git a/drivers/media/dvb-frontends/stb0899_drv.c b/drivers/media/dvb-frontends/stb0899_drv.c index 02347598277a..f638950f1478 100644 --- a/drivers/media/dvb-frontends/stb0899_drv.c +++ b/drivers/media/dvb-frontends/stb0899_drv.c @@ -537,7 +537,7 @@ int stb0899_write_regs(struct stb0899_state *state, unsigned int reg, u8 *data, return 0; }
-int stb0899_write_reg(struct stb0899_state *state, unsigned int reg, u8 data) +noinline_for_kasan int stb0899_write_reg(struct stb0899_state *state, unsigned int reg, u8 data) { return stb0899_write_regs(state, reg, &data, 1); } diff --git a/drivers/media/dvb-frontends/stb6100.c b/drivers/media/dvb-frontends/stb6100.c index 17a955d0031b..2fd6378ebd9a 100644 --- a/drivers/media/dvb-frontends/stb6100.c +++ b/drivers/media/dvb-frontends/stb6100.c @@ -224,7 +224,7 @@ static int stb6100_write_reg_range(struct stb6100_state *state, u8 buf[], int st return 0; }
-static int stb6100_write_reg(struct stb6100_state *state, u8 reg, u8 data) +static noinline_for_kasan int stb6100_write_reg(struct stb6100_state *state, u8 reg, u8 data) { if (unlikely(reg >= STB6100_NUMREGS)) { dprintk(verbose, FE_ERROR, 1, "Invalid register offset 0x%x", reg); diff --git a/drivers/media/dvb-frontends/stv0367.c b/drivers/media/dvb-frontends/stv0367.c index fd49c436a36d..dc7c1e596d29 100644 --- a/drivers/media/dvb-frontends/stv0367.c +++ b/drivers/media/dvb-frontends/stv0367.c @@ -798,7 +798,7 @@ int stv0367_writeregs(struct stv0367_state *state, u16 reg, u8 *data, int len) return (ret != 1) ? -EREMOTEIO : 0; }
-static int stv0367_writereg(struct stv0367_state *state, u16 reg, u8 data) +static noinline_for_kasan int stv0367_writereg(struct stv0367_state *state, u16 reg, u8 data) { return stv0367_writeregs(state, reg, &data, 1); } diff --git a/drivers/media/dvb-frontends/stv090x.c b/drivers/media/dvb-frontends/stv090x.c index 7ef469c0c866..236325ae2580 100644 --- a/drivers/media/dvb-frontends/stv090x.c +++ b/drivers/media/dvb-frontends/stv090x.c @@ -753,7 +753,7 @@ static int stv090x_write_regs(struct stv090x_state *state, unsigned int reg, u8 return 0; }
-static int stv090x_write_reg(struct stv090x_state *state, unsigned int reg, u8 data) +static noinline_for_kasan int stv090x_write_reg(struct stv090x_state *state, unsigned int reg, u8 data) { return stv090x_write_regs(state, reg, &data, 1); } diff --git a/drivers/media/dvb-frontends/stv6110.c b/drivers/media/dvb-frontends/stv6110.c index e4fd9c1b0560..34677f7327d5 100644 --- a/drivers/media/dvb-frontends/stv6110.c +++ b/drivers/media/dvb-frontends/stv6110.c @@ -137,7 +137,7 @@ static int stv6110_read_regs(struct dvb_frontend *fe, u8 regs[], return 0; }
-static int stv6110_read_reg(struct dvb_frontend *fe, int start) +static noinline_for_kasan int stv6110_read_reg(struct dvb_frontend *fe, int start) { u8 buf[] = { 0 }; stv6110_read_regs(fe, buf, start, 1); diff --git a/drivers/media/dvb-frontends/stv6110x.c b/drivers/media/dvb-frontends/stv6110x.c index 66eba38f1014..b8e3c5ac06e2 100644 --- a/drivers/media/dvb-frontends/stv6110x.c +++ b/drivers/media/dvb-frontends/stv6110x.c @@ -95,7 +95,7 @@ static int stv6110x_write_regs(struct stv6110x_state *stv6110x, int start, u8 da return 0; }
-static int stv6110x_write_reg(struct stv6110x_state *stv6110x, u8 reg, u8 data) +static noinline_for_kasan int stv6110x_write_reg(struct stv6110x_state *stv6110x, u8 reg, u8 data) { return stv6110x_write_regs(stv6110x, reg, &data, 1); } diff --git a/drivers/media/dvb-frontends/tda8083.c b/drivers/media/dvb-frontends/tda8083.c index aa3200d3c352..26732db739a5 100644 --- a/drivers/media/dvb-frontends/tda8083.c +++ b/drivers/media/dvb-frontends/tda8083.c @@ -88,7 +88,7 @@ static int tda8083_readregs (struct tda8083_state* state, u8 reg1, u8 *b, u8 len return ret == 2 ? 0 : -1; }
-static inline u8 tda8083_readreg (struct tda8083_state* state, u8 reg) +static noinline_for_kasan u8 tda8083_readreg (struct tda8083_state* state, u8 reg) { u8 val;
diff --git a/drivers/media/dvb-frontends/zl10039.c b/drivers/media/dvb-frontends/zl10039.c index 623355fc2666..713da9e02700 100644 --- a/drivers/media/dvb-frontends/zl10039.c +++ b/drivers/media/dvb-frontends/zl10039.c @@ -130,7 +130,7 @@ static inline int zl10039_readreg(struct zl10039_state *state, return zl10039_read(state, reg, val, 1); }
-static inline int zl10039_writereg(struct zl10039_state *state, +static noinline_for_kasan int zl10039_writereg(struct zl10039_state *state, const enum zl10039_reg_addr reg, const u8 val) {
When CONFIG_KASAN is enabled, we see very large stack usage in some functions, e.g.:
drivers/media/tuners/tda8290.c: In function 'tda8290_set_params': drivers/media/tuners/tda8290.c:310:1: warning: the frame size of 3184 bytes is larger than 1024 bytes [-Wframe-larger-than=] drivers/media/tuners/tda8290.c: In function 'tda829x_probe': drivers/media/tuners/tda8290.c:878:1: warning: the frame size of 1088 bytes is larger than 1024 bytes [-Wframe-larger-than=]
By annotating the helpers as noinline_for_kasan, we can easily avoid this.
Signed-off-by: Arnd Bergmann arnd@arndb.de --- drivers/media/tuners/tuner-i2c.h | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/drivers/media/tuners/tuner-i2c.h b/drivers/media/tuners/tuner-i2c.h index bda67a5a76f2..c8970299799c 100644 --- a/drivers/media/tuners/tuner-i2c.h +++ b/drivers/media/tuners/tuner-i2c.h @@ -33,8 +33,8 @@ struct tuner_i2c_props { char *name; };
-static inline int tuner_i2c_xfer_send(struct tuner_i2c_props *props, - unsigned char *buf, int len) +static noinline_for_kasan int +tuner_i2c_xfer_send(struct tuner_i2c_props *props, unsigned char *buf, int len) { struct i2c_msg msg = { .addr = props->addr, .flags = 0, .buf = buf, .len = len }; @@ -43,8 +43,8 @@ static inline int tuner_i2c_xfer_send(struct tuner_i2c_props *props, return (ret == 1) ? len : ret; }
-static inline int tuner_i2c_xfer_recv(struct tuner_i2c_props *props, - unsigned char *buf, int len) +static noinline_for_kasan int +tuner_i2c_xfer_recv(struct tuner_i2c_props *props, unsigned char *buf, int len) { struct i2c_msg msg = { .addr = props->addr, .flags = I2C_M_RD, .buf = buf, .len = len }; @@ -53,9 +53,10 @@ static inline int tuner_i2c_xfer_recv(struct tuner_i2c_props *props, return (ret == 1) ? len : ret; }
-static inline int tuner_i2c_xfer_send_recv(struct tuner_i2c_props *props, - unsigned char *obuf, int olen, - unsigned char *ibuf, int ilen) +static noinline_for_kasan int +tuner_i2c_xfer_send_recv(struct tuner_i2c_props *props, + unsigned char *obuf, int olen, + unsigned char *ibuf, int ilen) { struct i2c_msg msg[2] = { { .addr = props->addr, .flags = 0, .buf = obuf, .len = olen },
When building with KASAN, we get a stack frame size warning about a function that could potentially cause a stack overflow:
drivers/media/i2c/adv7604.c: In function 'adv76xx_log_status': drivers/media/i2c/adv7604.c:2615:1: error: the frame size of 3248 bytes is larger than 3072 bytes [-Werror=frame-larger-than=]
This is caused by adv76xx_read_check() being inlined repeatedly, and marking this function as noinline_for_kasan solves the problem completely.
Signed-off-by: Arnd Bergmann arnd@arndb.de --- drivers/media/i2c/adv7604.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c index d8bf435db86d..176f46ac85fd 100644 --- a/drivers/media/i2c/adv7604.c +++ b/drivers/media/i2c/adv7604.c @@ -339,8 +339,8 @@ static inline unsigned vtotal(const struct v4l2_bt_timings *t)
/* ----------------------------------------------------------------------- */
-static int adv76xx_read_check(struct adv76xx_state *state, - int client_page, u8 reg) +static noinline_for_kasan int adv76xx_read_check(struct adv76xx_state *state, + int client_page, u8 reg) { struct i2c_client *client = state->i2c_clients[client_page]; int err;
When CONFIG_KASAN is set, inlining of functions with local variables causes excessive stack usage:
drivers/media/i2c/ks0127.c: In function 'ks0127_s_routing': drivers/media/i2c/ks0127.c:541:1: error: the frame size of 3136 bytes is larger than 2048 bytes [-Werror=frame-larger-than=]
Marking one functions as noinline_for_kasan solves the problem in this driver.
Signed-off-by: Arnd Bergmann arnd@arndb.de --- drivers/media/i2c/ks0127.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/media/i2c/ks0127.c b/drivers/media/i2c/ks0127.c index ab536c4a7115..eb2fccdc0602 100644 --- a/drivers/media/i2c/ks0127.c +++ b/drivers/media/i2c/ks0127.c @@ -349,7 +349,7 @@ static void ks0127_write(struct v4l2_subdev *sd, u8 reg, u8 val)
/* generic bit-twiddling */ -static void ks0127_and_or(struct v4l2_subdev *sd, u8 reg, u8 and_v, u8 or_v) +static noinline_for_kasan void ks0127_and_or(struct v4l2_subdev *sd, u8 reg, u8 and_v, u8 or_v) { struct ks0127 *ks = to_ks0127(sd);
With CONFIG_KASAN, this driver has shown a ridiculously large stack frame in one configuration:
drivers/media/i2c/cx25840/cx25840-core.c:4960:1: error: the frame size of 94000 bytes is larger than 2048 bytes [-Werror=frame-larger-than=]
In most builds, it's only about 3300 bytes, but that's still large anough to risk a kernel stack overflow.
Marking the two register access functions as noinline_for_kasan avoids the problem and brings the largest stack frame size down to 232 bytes.
Signed-off-by: Arnd Bergmann arnd@arndb.de --- drivers/media/i2c/cx25840/cx25840-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/media/i2c/cx25840/cx25840-core.c b/drivers/media/i2c/cx25840/cx25840-core.c index b8d3c070bfc1..fd72e5a11cb9 100644 --- a/drivers/media/i2c/cx25840/cx25840-core.c +++ b/drivers/media/i2c/cx25840/cx25840-core.c @@ -81,7 +81,7 @@ MODULE_PARM_DESC(debug, "Debugging messages [0=Off (default) 1=On]"); /* ----------------------------------------------------------------------- */ static void cx23888_std_setup(struct i2c_client *client);
-int cx25840_write(struct i2c_client *client, u16 addr, u8 value) +noinline_for_kasan int cx25840_write(struct i2c_client *client, u16 addr, u8 value) { u8 buffer[3]; buffer[0] = addr >> 8; @@ -90,7 +90,7 @@ int cx25840_write(struct i2c_client *client, u16 addr, u8 value) return i2c_master_send(client, buffer, 3); }
-int cx25840_write4(struct i2c_client *client, u16 addr, u32 value) +noinline_for_kasan int cx25840_write4(struct i2c_client *client, u16 addr, u32 value) { u8 buffer[6]; buffer[0] = addr >> 8;
With KASAN, we get an overly long stack frame due to inlining the register access function:
drivers/media/tuners/r820t.c: In function 'generic_set_freq.isra.7': drivers/media/tuners/r820t.c:1334:1: error: the frame size of 2880 bytes is larger than 2048 bytes [-Werror=frame-larger-than=]
An earlier patch I tried used an open-coded r820t_write_reg() implementation that may have been more efficent, while this version simply adds the annotation, which has a lower risk for regressions.
Signed-off-by: Arnd Bergmann arnd@arndb.de --- drivers/media/tuners/r820t.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/media/tuners/r820t.c b/drivers/media/tuners/r820t.c index ba80376a3b86..0fbfa6416e38 100644 --- a/drivers/media/tuners/r820t.c +++ b/drivers/media/tuners/r820t.c @@ -396,7 +396,7 @@ static int r820t_write(struct r820t_priv *priv, u8 reg, const u8 *val, return 0; }
-static int r820t_write_reg(struct r820t_priv *priv, u8 reg, u8 val) +static noinline_for_kasan int r820t_write_reg(struct r820t_priv *priv, u8 reg, u8 val) { return r820t_write(priv, reg, &val, 1); } @@ -411,7 +411,7 @@ static int r820t_read_cache_reg(struct r820t_priv *priv, int reg) return -EINVAL; }
-static int r820t_write_reg_mask(struct r820t_priv *priv, u8 reg, u8 val, +static noinline_for_kasan int r820t_write_reg_mask(struct r820t_priv *priv, u8 reg, u8 val, u8 bit_mask) { int rc = r820t_read_cache_reg(priv, reg);
With CONFIG_KASAN, the init function uses a large amount of kernel stack:
drivers/media/usb/em28xx/em28xx-dvb.c: In function 'em28xx_dvb_init': drivers/media/usb/em28xx/em28xx-dvb.c:2069:1: error: the frame size of 4280 bytes is larger than 3072 bytes [-Werror=frame-larger-than=]
By splitting out each part of the switch/case statement that has its own local variables into a separate function, no single one of them uses more than 500 bytes, and with a noinline_for_kasan annotation we can ensure that they are not merged back together.
Signed-off-by: Arnd Bergmann arnd@arndb.de --- drivers/media/usb/em28xx/em28xx-dvb.c | 947 ++++++++++++++++++---------------- 1 file changed, 508 insertions(+), 439 deletions(-)
diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c index 82edd37f0d73..83125a05918a 100644 --- a/drivers/media/usb/em28xx/em28xx-dvb.c +++ b/drivers/media/usb/em28xx/em28xx-dvb.c @@ -934,7 +934,7 @@ static struct lgdt3306a_config hauppauge_01595_lgdt3306a_config = {
/* ------------------------------------------------------------------ */
-static int em28xx_attach_xc3028(u8 addr, struct em28xx *dev) +static noinline_for_kasan int em28xx_attach_xc3028(u8 addr, struct em28xx *dev) { struct dvb_frontend *fe; struct xc2028_config cfg; @@ -1126,6 +1126,492 @@ static void em28xx_unregister_dvb(struct em28xx_dvb *dvb) dvb_unregister_adapter(&dvb->adapter); }
+static noinline_for_kasan int em28174_dvb_init_pctv_460e(struct em28xx *dev) +{ + struct em28xx_dvb *dvb = dev->dvb; + struct i2c_client *client; + struct i2c_board_info board_info; + struct tda10071_platform_data tda10071_pdata = {}; + struct a8293_platform_data a8293_pdata = {}; + int result; + + /* attach demod + tuner combo */ + tda10071_pdata.clk = 40444000, /* 40.444 MHz */ + tda10071_pdata.i2c_wr_max = 64, + tda10071_pdata.ts_mode = TDA10071_TS_SERIAL, + tda10071_pdata.pll_multiplier = 20, + tda10071_pdata.tuner_i2c_addr = 0x14, + memset(&board_info, 0, sizeof(board_info)); + strlcpy(board_info.type, "tda10071_cx24118", I2C_NAME_SIZE); + board_info.addr = 0x55; + board_info.platform_data = &tda10071_pdata; + request_module("tda10071"); + client = i2c_new_device(&dev->i2c_adap[dev->def_i2c_bus], &board_info); + if (client == NULL || client->dev.driver == NULL) { + result = -ENODEV; + goto out_free; + } + if (!try_module_get(client->dev.driver->owner)) { + i2c_unregister_device(client); + result = -ENODEV; + goto out_free; + } + dvb->fe[0] = tda10071_pdata.get_dvb_frontend(client); + dvb->i2c_client_demod = client; + + /* attach SEC */ + a8293_pdata.dvb_frontend = dvb->fe[0]; + memset(&board_info, 0, sizeof(board_info)); + strlcpy(board_info.type, "a8293", I2C_NAME_SIZE); + board_info.addr = 0x08; + board_info.platform_data = &a8293_pdata; + request_module("a8293"); + client = i2c_new_device(&dev->i2c_adap[dev->def_i2c_bus], &board_info); + if (client == NULL || client->dev.driver == NULL) { + module_put(dvb->i2c_client_demod->dev.driver->owner); + i2c_unregister_device(dvb->i2c_client_demod); + result = -ENODEV; + goto out_free; + } + if (!try_module_get(client->dev.driver->owner)) { + i2c_unregister_device(client); + module_put(dvb->i2c_client_demod->dev.driver->owner); + i2c_unregister_device(dvb->i2c_client_demod); + result = -ENODEV; + goto out_free; + } + dvb->i2c_client_sec = client; + result = 0; +out_free: + return result; +} + +static noinline_for_kasan int em28178_dvb_init_pctv_461e(struct em28xx *dev) +{ + struct em28xx_dvb *dvb = dev->dvb; + struct i2c_client *client; + struct i2c_adapter *i2c_adapter; + struct i2c_board_info board_info; + struct m88ds3103_platform_data m88ds3103_pdata = {}; + struct ts2020_config ts2020_config = {}; + struct a8293_platform_data a8293_pdata = {}; + int result; + + /* attach demod */ + m88ds3103_pdata.clk = 27000000; + m88ds3103_pdata.i2c_wr_max = 33; + m88ds3103_pdata.ts_mode = M88DS3103_TS_PARALLEL; + m88ds3103_pdata.ts_clk = 16000; + m88ds3103_pdata.ts_clk_pol = 1; + m88ds3103_pdata.agc = 0x99; + memset(&board_info, 0, sizeof(board_info)); + strlcpy(board_info.type, "m88ds3103", I2C_NAME_SIZE); + board_info.addr = 0x68; + board_info.platform_data = &m88ds3103_pdata; + request_module("m88ds3103"); + client = i2c_new_device(&dev->i2c_adap[dev->def_i2c_bus], &board_info); + if (client == NULL || client->dev.driver == NULL) { + result = -ENODEV; + goto out_free; + } + if (!try_module_get(client->dev.driver->owner)) { + i2c_unregister_device(client); + result = -ENODEV; + goto out_free; + } + dvb->fe[0] = m88ds3103_pdata.get_dvb_frontend(client); + i2c_adapter = m88ds3103_pdata.get_i2c_adapter(client); + dvb->i2c_client_demod = client; + + /* attach tuner */ + ts2020_config.fe = dvb->fe[0]; + memset(&board_info, 0, sizeof(board_info)); + strlcpy(board_info.type, "ts2022", I2C_NAME_SIZE); + board_info.addr = 0x60; + board_info.platform_data = &ts2020_config; + request_module("ts2020"); + client = i2c_new_device(i2c_adapter, &board_info); + if (client == NULL || client->dev.driver == NULL) { + module_put(dvb->i2c_client_demod->dev.driver->owner); + i2c_unregister_device(dvb->i2c_client_demod); + result = -ENODEV; + goto out_free; + } + if (!try_module_get(client->dev.driver->owner)) { + i2c_unregister_device(client); + module_put(dvb->i2c_client_demod->dev.driver->owner); + i2c_unregister_device(dvb->i2c_client_demod); + result = -ENODEV; + goto out_free; + } + dvb->i2c_client_tuner = client; + /* delegate signal strength measurement to tuner */ + dvb->fe[0]->ops.read_signal_strength = + dvb->fe[0]->ops.tuner_ops.get_rf_strength; + + /* attach SEC */ + a8293_pdata.dvb_frontend = dvb->fe[0]; + memset(&board_info, 0, sizeof(board_info)); + strlcpy(board_info.type, "a8293", I2C_NAME_SIZE); + board_info.addr = 0x08; + board_info.platform_data = &a8293_pdata; + request_module("a8293"); + client = i2c_new_device(&dev->i2c_adap[dev->def_i2c_bus], &board_info); + if (client == NULL || client->dev.driver == NULL) { + module_put(dvb->i2c_client_tuner->dev.driver->owner); + i2c_unregister_device(dvb->i2c_client_tuner); + module_put(dvb->i2c_client_demod->dev.driver->owner); + i2c_unregister_device(dvb->i2c_client_demod); + result = -ENODEV; + goto out_free; + } + if (!try_module_get(client->dev.driver->owner)) { + i2c_unregister_device(client); + module_put(dvb->i2c_client_tuner->dev.driver->owner); + i2c_unregister_device(dvb->i2c_client_tuner); + module_put(dvb->i2c_client_demod->dev.driver->owner); + i2c_unregister_device(dvb->i2c_client_demod); + result = -ENODEV; + goto out_free; + } + dvb->i2c_client_sec = client; + result = 0; +out_free: + return result; +} + +static noinline_for_kasan int em28178_dvb_init_pctv_292e(struct em28xx *dev) +{ + struct em28xx_dvb *dvb = dev->dvb; + struct i2c_adapter *adapter; + struct i2c_client *client; + struct i2c_board_info info; + struct si2168_config si2168_config; + struct si2157_config si2157_config; + int result; + + /* attach demod */ + memset(&si2168_config, 0, sizeof(si2168_config)); + si2168_config.i2c_adapter = &adapter; + si2168_config.fe = &dvb->fe[0]; + si2168_config.ts_mode = SI2168_TS_PARALLEL; + memset(&info, 0, sizeof(struct i2c_board_info)); + strlcpy(info.type, "si2168", I2C_NAME_SIZE); + info.addr = 0x64; + info.platform_data = &si2168_config; + request_module(info.type); + client = i2c_new_device(&dev->i2c_adap[dev->def_i2c_bus], &info); + if (client == NULL || client->dev.driver == NULL) { + result = -ENODEV; + goto out_free; + } + + if (!try_module_get(client->dev.driver->owner)) { + i2c_unregister_device(client); + result = -ENODEV; + goto out_free; + } + + dvb->i2c_client_demod = client; + + /* attach tuner */ + memset(&si2157_config, 0, sizeof(si2157_config)); + si2157_config.fe = dvb->fe[0]; + si2157_config.if_port = 1; +#ifdef CONFIG_MEDIA_CONTROLLER_DVB + si2157_config.mdev = dev->media_dev; +#endif + memset(&info, 0, sizeof(struct i2c_board_info)); + strlcpy(info.type, "si2157", I2C_NAME_SIZE); + info.addr = 0x60; + info.platform_data = &si2157_config; + request_module(info.type); + client = i2c_new_device(adapter, &info); + if (client == NULL || client->dev.driver == NULL) { + module_put(dvb->i2c_client_demod->dev.driver->owner); + i2c_unregister_device(dvb->i2c_client_demod); + result = -ENODEV; + goto out_free; + } + + if (!try_module_get(client->dev.driver->owner)) { + i2c_unregister_device(client); + module_put(dvb->i2c_client_demod->dev.driver->owner); + i2c_unregister_device(dvb->i2c_client_demod); + result = -ENODEV; + goto out_free; + } + + dvb->i2c_client_tuner = client; + dvb->fe[0]->ops.set_lna = em28xx_pctv_292e_set_lna; + result = 0; +out_free: + return result; +} + +static noinline_for_kasan int em28178_dvb_init_terratec_t2_stick_hd(struct em28xx *dev) +{ + struct em28xx_dvb *dvb = dev->dvb; + struct i2c_adapter *adapter; + struct i2c_client *client; + struct i2c_board_info info; + struct si2168_config si2168_config; + struct si2157_config si2157_config; + int result; + + /* attach demod */ + memset(&si2168_config, 0, sizeof(si2168_config)); + si2168_config.i2c_adapter = &adapter; + si2168_config.fe = &dvb->fe[0]; + si2168_config.ts_mode = SI2168_TS_PARALLEL; + memset(&info, 0, sizeof(struct i2c_board_info)); + strlcpy(info.type, "si2168", I2C_NAME_SIZE); + info.addr = 0x64; + info.platform_data = &si2168_config; + request_module(info.type); + client = i2c_new_device(&dev->i2c_adap[dev->def_i2c_bus], &info); + if (client == NULL || client->dev.driver == NULL) { + result = -ENODEV; + goto out_free; + } + + if (!try_module_get(client->dev.driver->owner)) { + i2c_unregister_device(client); + result = -ENODEV; + goto out_free; + } + + dvb->i2c_client_demod = client; + + /* attach tuner */ + memset(&si2157_config, 0, sizeof(si2157_config)); + si2157_config.fe = dvb->fe[0]; + si2157_config.if_port = 0; +#ifdef CONFIG_MEDIA_CONTROLLER_DVB + si2157_config.mdev = dev->media_dev; +#endif + memset(&info, 0, sizeof(struct i2c_board_info)); + strlcpy(info.type, "si2146", I2C_NAME_SIZE); + info.addr = 0x60; + info.platform_data = &si2157_config; + request_module("si2157"); + client = i2c_new_device(adapter, &info); + if (client == NULL || client->dev.driver == NULL) { + module_put(dvb->i2c_client_demod->dev.driver->owner); + i2c_unregister_device(dvb->i2c_client_demod); + result = -ENODEV; + goto out_free; + } + + if (!try_module_get(client->dev.driver->owner)) { + i2c_unregister_device(client); + module_put(dvb->i2c_client_demod->dev.driver->owner); + i2c_unregister_device(dvb->i2c_client_demod); + result = -ENODEV; + goto out_free; + } + + dvb->i2c_client_tuner = client; + result = 0; +out_free: + return result; +} + +static noinline_for_kasan int em28178_dvb_init_plex_px_bcud(struct em28xx *dev) +{ + struct em28xx_dvb *dvb = dev->dvb; + struct i2c_client *client; + struct i2c_board_info info; + struct tc90522_config tc90522_config; + struct qm1d1c0042_config qm1d1c0042_config; + int result; + + /* attach demod */ + memset(&tc90522_config, 0, sizeof(tc90522_config)); + memset(&info, 0, sizeof(struct i2c_board_info)); + strlcpy(info.type, "tc90522sat", I2C_NAME_SIZE); + info.addr = 0x15; + info.platform_data = &tc90522_config; + request_module("tc90522"); + client = i2c_new_device(&dev->i2c_adap[dev->def_i2c_bus], &info); + if (client == NULL || client->dev.driver == NULL) { + result = -ENODEV; + goto out_free; + } + dvb->i2c_client_demod = client; + if (!try_module_get(client->dev.driver->owner)) { + i2c_unregister_device(client); + result = -ENODEV; + goto out_free; + } + + /* attach tuner */ + memset(&qm1d1c0042_config, 0, + sizeof(qm1d1c0042_config)); + qm1d1c0042_config.fe = tc90522_config.fe; + qm1d1c0042_config.lpf = 1; + memset(&info, 0, sizeof(struct i2c_board_info)); + strlcpy(info.type, "qm1d1c0042", I2C_NAME_SIZE); + info.addr = 0x61; + info.platform_data = &qm1d1c0042_config; + request_module(info.type); + client = i2c_new_device(tc90522_config.tuner_i2c, + &info); + if (client == NULL || client->dev.driver == NULL) { + module_put(dvb->i2c_client_demod->dev.driver->owner); + i2c_unregister_device(dvb->i2c_client_demod); + result = -ENODEV; + goto out_free; + } + dvb->i2c_client_tuner = client; + if (!try_module_get(client->dev.driver->owner)) { + i2c_unregister_device(client); + module_put(dvb->i2c_client_demod->dev.driver->owner); + i2c_unregister_device(dvb->i2c_client_demod); + result = -ENODEV; + goto out_free; + } + dvb->fe[0] = tc90522_config.fe; + px_bcud_init(dev); + result = 0; +out_free: + return result; +} + +static noinline_for_kasan int em28174_dvb_init_hauppauge_wintv_dualhd_dvb(struct em28xx *dev) +{ + struct em28xx_dvb *dvb = dev->dvb; + struct i2c_adapter *adapter; + struct i2c_client *client; + struct i2c_board_info info; + struct si2168_config si2168_config; + struct si2157_config si2157_config; + int result; + + /* attach demod */ + memset(&si2168_config, 0, sizeof(si2168_config)); + si2168_config.i2c_adapter = &adapter; + si2168_config.fe = &dvb->fe[0]; + si2168_config.ts_mode = SI2168_TS_SERIAL; + memset(&info, 0, sizeof(struct i2c_board_info)); + strlcpy(info.type, "si2168", I2C_NAME_SIZE); + info.addr = 0x64; + info.platform_data = &si2168_config; + request_module(info.type); + client = i2c_new_device(&dev->i2c_adap[dev->def_i2c_bus], &info); + if (client == NULL || client->dev.driver == NULL) { + result = -ENODEV; + goto out_free; + } + + if (!try_module_get(client->dev.driver->owner)) { + i2c_unregister_device(client); + result = -ENODEV; + goto out_free; + } + + dvb->i2c_client_demod = client; + + /* attach tuner */ + memset(&si2157_config, 0, sizeof(si2157_config)); + si2157_config.fe = dvb->fe[0]; + si2157_config.if_port = 1; +#ifdef CONFIG_MEDIA_CONTROLLER_DVB + si2157_config.mdev = dev->media_dev; +#endif + memset(&info, 0, sizeof(struct i2c_board_info)); + strlcpy(info.type, "si2157", I2C_NAME_SIZE); + info.addr = 0x60; + info.platform_data = &si2157_config; + request_module(info.type); + client = i2c_new_device(adapter, &info); + if (client == NULL || client->dev.driver == NULL) { + module_put(dvb->i2c_client_demod->dev.driver->owner); + i2c_unregister_device(dvb->i2c_client_demod); + result = -ENODEV; + goto out_free; + } + + if (!try_module_get(client->dev.driver->owner)) { + i2c_unregister_device(client); + module_put(dvb->i2c_client_demod->dev.driver->owner); + i2c_unregister_device(dvb->i2c_client_demod); + result = -ENODEV; + goto out_free; + } + + dvb->i2c_client_tuner = client; + result = 0; +out_free: + return result; +} + +static int em28174_dvb_init_hauppauge_wintv_dualhd_01595(struct em28xx *dev) +{ + struct em28xx_dvb *dvb = dev->dvb; + struct i2c_adapter *adapter; + struct i2c_client *client; + struct i2c_board_info info = {}; + struct lgdt3306a_config lgdt3306a_config; + struct si2157_config si2157_config = {}; + int result; + + /* attach demod */ + lgdt3306a_config = hauppauge_01595_lgdt3306a_config; + lgdt3306a_config.fe = &dvb->fe[0]; + lgdt3306a_config.i2c_adapter = &adapter; + strlcpy(info.type, "lgdt3306a", sizeof(info.type)); + info.addr = 0x59; + info.platform_data = &lgdt3306a_config; + request_module(info.type); + client = i2c_new_device(&dev->i2c_adap[dev->def_i2c_bus], + &info); + if (client == NULL || client->dev.driver == NULL) { + result = -ENODEV; + goto out_free; + } + + if (!try_module_get(client->dev.driver->owner)) { + i2c_unregister_device(client); + result = -ENODEV; + goto out_free; + } + + dvb->i2c_client_demod = client; + + /* attach tuner */ + si2157_config.fe = dvb->fe[0]; + si2157_config.if_port = 1; + si2157_config.inversion = 1; +#ifdef CONFIG_MEDIA_CONTROLLER_DVB + si2157_config.mdev = dev->media_dev; +#endif + memset(&info, 0, sizeof(struct i2c_board_info)); + strlcpy(info.type, "si2157", sizeof(info.type)); + info.addr = 0x60; + info.platform_data = &si2157_config; + request_module(info.type); + + client = i2c_new_device(adapter, &info); + if (client == NULL || client->dev.driver == NULL) { + module_put(dvb->i2c_client_demod->dev.driver->owner); + i2c_unregister_device(dvb->i2c_client_demod); + result = -ENODEV; + goto out_free; + } + if (!try_module_get(client->dev.driver->owner)) { + i2c_unregister_device(client); + module_put(dvb->i2c_client_demod->dev.driver->owner); + i2c_unregister_device(dvb->i2c_client_demod); + result = -ENODEV; + goto out_free; + } + + dvb->i2c_client_tuner = client; + result = 0; +out_free: + return result; +} static int em28xx_dvb_init(struct em28xx *dev) { int result = 0; @@ -1427,60 +1913,11 @@ static int em28xx_dvb_init(struct em28xx *dev) &dev->i2c_adap[dev->def_i2c_bus], &c3tech_duo_tda18271_config); break; - case EM28174_BOARD_PCTV_460E: { - struct i2c_client *client; - struct i2c_board_info board_info; - struct tda10071_platform_data tda10071_pdata = {}; - struct a8293_platform_data a8293_pdata = {}; - - /* attach demod + tuner combo */ - tda10071_pdata.clk = 40444000, /* 40.444 MHz */ - tda10071_pdata.i2c_wr_max = 64, - tda10071_pdata.ts_mode = TDA10071_TS_SERIAL, - tda10071_pdata.pll_multiplier = 20, - tda10071_pdata.tuner_i2c_addr = 0x14, - memset(&board_info, 0, sizeof(board_info)); - strlcpy(board_info.type, "tda10071_cx24118", I2C_NAME_SIZE); - board_info.addr = 0x55; - board_info.platform_data = &tda10071_pdata; - request_module("tda10071"); - client = i2c_new_device(&dev->i2c_adap[dev->def_i2c_bus], &board_info); - if (client == NULL || client->dev.driver == NULL) { - result = -ENODEV; - goto out_free; - } - if (!try_module_get(client->dev.driver->owner)) { - i2c_unregister_device(client); - result = -ENODEV; - goto out_free; - } - dvb->fe[0] = tda10071_pdata.get_dvb_frontend(client); - dvb->i2c_client_demod = client; - - /* attach SEC */ - a8293_pdata.dvb_frontend = dvb->fe[0]; - memset(&board_info, 0, sizeof(board_info)); - strlcpy(board_info.type, "a8293", I2C_NAME_SIZE); - board_info.addr = 0x08; - board_info.platform_data = &a8293_pdata; - request_module("a8293"); - client = i2c_new_device(&dev->i2c_adap[dev->def_i2c_bus], &board_info); - if (client == NULL || client->dev.driver == NULL) { - module_put(dvb->i2c_client_demod->dev.driver->owner); - i2c_unregister_device(dvb->i2c_client_demod); - result = -ENODEV; + case EM28174_BOARD_PCTV_460E: + result = em28174_dvb_init_pctv_460e(dev); + if (result) goto out_free; - } - if (!try_module_get(client->dev.driver->owner)) { - i2c_unregister_device(client); - module_put(dvb->i2c_client_demod->dev.driver->owner); - i2c_unregister_device(dvb->i2c_client_demod); - result = -ENODEV; - goto out_free; - } - dvb->i2c_client_sec = client; break; - } case EM2874_BOARD_DELOCK_61959: case EM2874_BOARD_MAXMEDIA_UB425_TC: /* attach demodulator */ @@ -1626,403 +2063,35 @@ static int em28xx_dvb_init(struct em28xx *dev) } } break; - case EM28178_BOARD_PCTV_461E: { - struct i2c_client *client; - struct i2c_adapter *i2c_adapter; - struct i2c_board_info board_info; - struct m88ds3103_platform_data m88ds3103_pdata = {}; - struct ts2020_config ts2020_config = {}; - struct a8293_platform_data a8293_pdata = {}; - - /* attach demod */ - m88ds3103_pdata.clk = 27000000; - m88ds3103_pdata.i2c_wr_max = 33; - m88ds3103_pdata.ts_mode = M88DS3103_TS_PARALLEL; - m88ds3103_pdata.ts_clk = 16000; - m88ds3103_pdata.ts_clk_pol = 1; - m88ds3103_pdata.agc = 0x99; - memset(&board_info, 0, sizeof(board_info)); - strlcpy(board_info.type, "m88ds3103", I2C_NAME_SIZE); - board_info.addr = 0x68; - board_info.platform_data = &m88ds3103_pdata; - request_module("m88ds3103"); - client = i2c_new_device(&dev->i2c_adap[dev->def_i2c_bus], &board_info); - if (client == NULL || client->dev.driver == NULL) { - result = -ENODEV; + case EM28178_BOARD_PCTV_461E: + result = em28178_dvb_init_pctv_461e(dev); + if (result) goto out_free; - } - if (!try_module_get(client->dev.driver->owner)) { - i2c_unregister_device(client); - result = -ENODEV; - goto out_free; - } - dvb->fe[0] = m88ds3103_pdata.get_dvb_frontend(client); - i2c_adapter = m88ds3103_pdata.get_i2c_adapter(client); - dvb->i2c_client_demod = client; - - /* attach tuner */ - ts2020_config.fe = dvb->fe[0]; - memset(&board_info, 0, sizeof(board_info)); - strlcpy(board_info.type, "ts2022", I2C_NAME_SIZE); - board_info.addr = 0x60; - board_info.platform_data = &ts2020_config; - request_module("ts2020"); - client = i2c_new_device(i2c_adapter, &board_info); - if (client == NULL || client->dev.driver == NULL) { - module_put(dvb->i2c_client_demod->dev.driver->owner); - i2c_unregister_device(dvb->i2c_client_demod); - result = -ENODEV; - goto out_free; - } - if (!try_module_get(client->dev.driver->owner)) { - i2c_unregister_device(client); - module_put(dvb->i2c_client_demod->dev.driver->owner); - i2c_unregister_device(dvb->i2c_client_demod); - result = -ENODEV; - goto out_free; - } - dvb->i2c_client_tuner = client; - /* delegate signal strength measurement to tuner */ - dvb->fe[0]->ops.read_signal_strength = - dvb->fe[0]->ops.tuner_ops.get_rf_strength; - - /* attach SEC */ - a8293_pdata.dvb_frontend = dvb->fe[0]; - memset(&board_info, 0, sizeof(board_info)); - strlcpy(board_info.type, "a8293", I2C_NAME_SIZE); - board_info.addr = 0x08; - board_info.platform_data = &a8293_pdata; - request_module("a8293"); - client = i2c_new_device(&dev->i2c_adap[dev->def_i2c_bus], &board_info); - if (client == NULL || client->dev.driver == NULL) { - module_put(dvb->i2c_client_tuner->dev.driver->owner); - i2c_unregister_device(dvb->i2c_client_tuner); - module_put(dvb->i2c_client_demod->dev.driver->owner); - i2c_unregister_device(dvb->i2c_client_demod); - result = -ENODEV; - goto out_free; - } - if (!try_module_get(client->dev.driver->owner)) { - i2c_unregister_device(client); - module_put(dvb->i2c_client_tuner->dev.driver->owner); - i2c_unregister_device(dvb->i2c_client_tuner); - module_put(dvb->i2c_client_demod->dev.driver->owner); - i2c_unregister_device(dvb->i2c_client_demod); - result = -ENODEV; - goto out_free; - } - dvb->i2c_client_sec = client; break; - } case EM28178_BOARD_PCTV_292E: - { - struct i2c_adapter *adapter; - struct i2c_client *client; - struct i2c_board_info info; - struct si2168_config si2168_config; - struct si2157_config si2157_config; - - /* attach demod */ - memset(&si2168_config, 0, sizeof(si2168_config)); - si2168_config.i2c_adapter = &adapter; - si2168_config.fe = &dvb->fe[0]; - si2168_config.ts_mode = SI2168_TS_PARALLEL; - memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "si2168", I2C_NAME_SIZE); - info.addr = 0x64; - info.platform_data = &si2168_config; - request_module(info.type); - client = i2c_new_device(&dev->i2c_adap[dev->def_i2c_bus], &info); - if (client == NULL || client->dev.driver == NULL) { - result = -ENODEV; - goto out_free; - } - - if (!try_module_get(client->dev.driver->owner)) { - i2c_unregister_device(client); - result = -ENODEV; - goto out_free; - } - - dvb->i2c_client_demod = client; - - /* attach tuner */ - memset(&si2157_config, 0, sizeof(si2157_config)); - si2157_config.fe = dvb->fe[0]; - si2157_config.if_port = 1; -#ifdef CONFIG_MEDIA_CONTROLLER_DVB - si2157_config.mdev = dev->media_dev; -#endif - memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "si2157", I2C_NAME_SIZE); - info.addr = 0x60; - info.platform_data = &si2157_config; - request_module(info.type); - client = i2c_new_device(adapter, &info); - if (client == NULL || client->dev.driver == NULL) { - module_put(dvb->i2c_client_demod->dev.driver->owner); - i2c_unregister_device(dvb->i2c_client_demod); - result = -ENODEV; - goto out_free; - } - - if (!try_module_get(client->dev.driver->owner)) { - i2c_unregister_device(client); - module_put(dvb->i2c_client_demod->dev.driver->owner); - i2c_unregister_device(dvb->i2c_client_demod); - result = -ENODEV; - goto out_free; - } - - dvb->i2c_client_tuner = client; - dvb->fe[0]->ops.set_lna = em28xx_pctv_292e_set_lna; - } + result = em28178_dvb_init_pctv_292e(dev); + if (result) + goto out_free; break; case EM28178_BOARD_TERRATEC_T2_STICK_HD: - { - struct i2c_adapter *adapter; - struct i2c_client *client; - struct i2c_board_info info; - struct si2168_config si2168_config; - struct si2157_config si2157_config; - - /* attach demod */ - memset(&si2168_config, 0, sizeof(si2168_config)); - si2168_config.i2c_adapter = &adapter; - si2168_config.fe = &dvb->fe[0]; - si2168_config.ts_mode = SI2168_TS_PARALLEL; - memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "si2168", I2C_NAME_SIZE); - info.addr = 0x64; - info.platform_data = &si2168_config; - request_module(info.type); - client = i2c_new_device(&dev->i2c_adap[dev->def_i2c_bus], &info); - if (client == NULL || client->dev.driver == NULL) { - result = -ENODEV; - goto out_free; - } - - if (!try_module_get(client->dev.driver->owner)) { - i2c_unregister_device(client); - result = -ENODEV; - goto out_free; - } - - dvb->i2c_client_demod = client; - - /* attach tuner */ - memset(&si2157_config, 0, sizeof(si2157_config)); - si2157_config.fe = dvb->fe[0]; - si2157_config.if_port = 0; -#ifdef CONFIG_MEDIA_CONTROLLER_DVB - si2157_config.mdev = dev->media_dev; -#endif - memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "si2146", I2C_NAME_SIZE); - info.addr = 0x60; - info.platform_data = &si2157_config; - request_module("si2157"); - client = i2c_new_device(adapter, &info); - if (client == NULL || client->dev.driver == NULL) { - module_put(dvb->i2c_client_demod->dev.driver->owner); - i2c_unregister_device(dvb->i2c_client_demod); - result = -ENODEV; - goto out_free; - } - - if (!try_module_get(client->dev.driver->owner)) { - i2c_unregister_device(client); - module_put(dvb->i2c_client_demod->dev.driver->owner); - i2c_unregister_device(dvb->i2c_client_demod); - result = -ENODEV; - goto out_free; - } - - dvb->i2c_client_tuner = client; - } + result = em28178_dvb_init_terratec_t2_stick_hd(dev); + if (result) + goto out_free; break; - case EM28178_BOARD_PLEX_PX_BCUD: - { - struct i2c_client *client; - struct i2c_board_info info; - struct tc90522_config tc90522_config; - struct qm1d1c0042_config qm1d1c0042_config; - - /* attach demod */ - memset(&tc90522_config, 0, sizeof(tc90522_config)); - memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "tc90522sat", I2C_NAME_SIZE); - info.addr = 0x15; - info.platform_data = &tc90522_config; - request_module("tc90522"); - client = i2c_new_device(&dev->i2c_adap[dev->def_i2c_bus], &info); - if (client == NULL || client->dev.driver == NULL) { - result = -ENODEV; - goto out_free; - } - dvb->i2c_client_demod = client; - if (!try_module_get(client->dev.driver->owner)) { - i2c_unregister_device(client); - result = -ENODEV; - goto out_free; - } - - /* attach tuner */ - memset(&qm1d1c0042_config, 0, - sizeof(qm1d1c0042_config)); - qm1d1c0042_config.fe = tc90522_config.fe; - qm1d1c0042_config.lpf = 1; - memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "qm1d1c0042", I2C_NAME_SIZE); - info.addr = 0x61; - info.platform_data = &qm1d1c0042_config; - request_module(info.type); - client = i2c_new_device(tc90522_config.tuner_i2c, - &info); - if (client == NULL || client->dev.driver == NULL) { - module_put(dvb->i2c_client_demod->dev.driver->owner); - i2c_unregister_device(dvb->i2c_client_demod); - result = -ENODEV; - goto out_free; - } - dvb->i2c_client_tuner = client; - if (!try_module_get(client->dev.driver->owner)) { - i2c_unregister_device(client); - module_put(dvb->i2c_client_demod->dev.driver->owner); - i2c_unregister_device(dvb->i2c_client_demod); - result = -ENODEV; - goto out_free; - } - dvb->fe[0] = tc90522_config.fe; - px_bcud_init(dev); - } + result = em28178_dvb_init_plex_px_bcud(dev); + if (result) + goto out_free; break; case EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_DVB: - { - struct i2c_adapter *adapter; - struct i2c_client *client; - struct i2c_board_info info; - struct si2168_config si2168_config; - struct si2157_config si2157_config; - - /* attach demod */ - memset(&si2168_config, 0, sizeof(si2168_config)); - si2168_config.i2c_adapter = &adapter; - si2168_config.fe = &dvb->fe[0]; - si2168_config.ts_mode = SI2168_TS_SERIAL; - memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "si2168", I2C_NAME_SIZE); - info.addr = 0x64; - info.platform_data = &si2168_config; - request_module(info.type); - client = i2c_new_device(&dev->i2c_adap[dev->def_i2c_bus], &info); - if (client == NULL || client->dev.driver == NULL) { - result = -ENODEV; - goto out_free; - } - - if (!try_module_get(client->dev.driver->owner)) { - i2c_unregister_device(client); - result = -ENODEV; - goto out_free; - } - - dvb->i2c_client_demod = client; - - /* attach tuner */ - memset(&si2157_config, 0, sizeof(si2157_config)); - si2157_config.fe = dvb->fe[0]; - si2157_config.if_port = 1; -#ifdef CONFIG_MEDIA_CONTROLLER_DVB - si2157_config.mdev = dev->media_dev; -#endif - memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "si2157", I2C_NAME_SIZE); - info.addr = 0x60; - info.platform_data = &si2157_config; - request_module(info.type); - client = i2c_new_device(adapter, &info); - if (client == NULL || client->dev.driver == NULL) { - module_put(dvb->i2c_client_demod->dev.driver->owner); - i2c_unregister_device(dvb->i2c_client_demod); - result = -ENODEV; - goto out_free; - } - - if (!try_module_get(client->dev.driver->owner)) { - i2c_unregister_device(client); - module_put(dvb->i2c_client_demod->dev.driver->owner); - i2c_unregister_device(dvb->i2c_client_demod); - result = -ENODEV; - goto out_free; - } - - dvb->i2c_client_tuner = client; - - } + result = em28174_dvb_init_hauppauge_wintv_dualhd_dvb(dev); + if (result) + goto out_free; break; case EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_01595: - { - struct i2c_adapter *adapter; - struct i2c_client *client; - struct i2c_board_info info = {}; - struct lgdt3306a_config lgdt3306a_config; - struct si2157_config si2157_config = {}; - - /* attach demod */ - lgdt3306a_config = hauppauge_01595_lgdt3306a_config; - lgdt3306a_config.fe = &dvb->fe[0]; - lgdt3306a_config.i2c_adapter = &adapter; - strlcpy(info.type, "lgdt3306a", sizeof(info.type)); - info.addr = 0x59; - info.platform_data = &lgdt3306a_config; - request_module(info.type); - client = i2c_new_device(&dev->i2c_adap[dev->def_i2c_bus], - &info); - if (client == NULL || client->dev.driver == NULL) { - result = -ENODEV; - goto out_free; - } - - if (!try_module_get(client->dev.driver->owner)) { - i2c_unregister_device(client); - result = -ENODEV; - goto out_free; - } - - dvb->i2c_client_demod = client; - - /* attach tuner */ - si2157_config.fe = dvb->fe[0]; - si2157_config.if_port = 1; - si2157_config.inversion = 1; -#ifdef CONFIG_MEDIA_CONTROLLER_DVB - si2157_config.mdev = dev->media_dev; -#endif - memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "si2157", sizeof(info.type)); - info.addr = 0x60; - info.platform_data = &si2157_config; - request_module(info.type); - - client = i2c_new_device(adapter, &info); - if (client == NULL || client->dev.driver == NULL) { - module_put(dvb->i2c_client_demod->dev.driver->owner); - i2c_unregister_device(dvb->i2c_client_demod); - result = -ENODEV; - goto out_free; - } - if (!try_module_get(client->dev.driver->owner)) { - i2c_unregister_device(client); - module_put(dvb->i2c_client_demod->dev.driver->owner); - i2c_unregister_device(dvb->i2c_client_demod); - result = -ENODEV; - goto out_free; - } - - dvb->i2c_client_tuner = client; - } + result = em28174_dvb_init_hauppauge_wintv_dualhd_01595(dev); + if (result) + goto out_free; break; default: dev_err(&dev->intf->dev,
When CONFIG_KASAN is set, each call to ps8622_set() adds an object to the stack frame, leading to a warning about possible stack overflow:
drivers/gpu/drm/bridge/parade-ps8622.c: In function 'ps8622_send_config': drivers/gpu/drm/bridge/parade-ps8622.c:338:1: error: the frame size of 5872 bytes is larger than 3072 bytes [-Werror=frame-larger-than=]
Marking this as noinline_for_kasan completely avoids the problem.
Signed-off-by: Arnd Bergmann arnd@arndb.de --- drivers/gpu/drm/bridge/parade-ps8622.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/bridge/parade-ps8622.c b/drivers/gpu/drm/bridge/parade-ps8622.c index ac8cc5b50d9f..6b995edd2a46 100644 --- a/drivers/gpu/drm/bridge/parade-ps8622.c +++ b/drivers/gpu/drm/bridge/parade-ps8622.c @@ -79,7 +79,7 @@ static inline struct ps8622_bridge * return container_of(connector, struct ps8622_bridge, connector); }
-static int ps8622_set(struct i2c_client *client, u8 page, u8 reg, u8 val) +static noinline_for_kasan int ps8622_set(struct i2c_client *client, u8 page, u8 reg, u8 val) { int ret; struct i2c_adapter *adap = client->adapter;
Enabling CONFIG_KASAN can lead to an instant stack overflow:
drivers/gpu/drm/i915/gvt/handlers.c: In function 'init_generic_mmio_info': drivers/gpu/drm/i915/gvt/handlers.c:2200:1: error: the frame size of 30464 bytes is larger than 3072 bytes [-Werror=frame-larger-than=] drivers/gpu/drm/i915/gvt/handlers.c: In function 'init_broadwell_mmio_info': drivers/gpu/drm/i915/gvt/handlers.c:2402:1: error: the frame size of 5376 bytes is larger than 3072 bytes [-Werror=frame-larger-than=] drivers/gpu/drm/i915/gvt/handlers.c: In function 'init_skl_mmio_info': drivers/gpu/drm/i915/gvt/handlers.c:2628:1: error: the frame size of 5296 bytes is larger than 3072 bytes [-Werror=frame-larger-than=]
The reason is the INTEL_GVT_MMIO_OFFSET() hack that attempts to convert any type (including i915_reg_t) into a u32 by reading the first four bytes, in combination with the stack sanitizer that adds a redzone around each instance.
Originally, i915_reg_t was introduced to add a little extra type safety by disallowing simple type casts, and INTEL_GVT_MMIO_OFFSET() goes the opposite way by allowing any type as input, including those that are not safe in this context.
I'm replacing it with an implementation that specifically allows the three types that are actually used as input: 'i915_reg_t' (from _MMIO constants), 'int' (from other constants), and 'unsigned int' (from function arguments), and any other type should now provoke a build error. This also solves the stack overflow as we no longer use a local variable for each instance.
Signed-off-by: Arnd Bergmann arnd@arndb.de --- drivers/gpu/drm/i915/gvt/mmio.h | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/i915/gvt/mmio.h b/drivers/gpu/drm/i915/gvt/mmio.h index 3bc620f56f35..bf40100fc626 100644 --- a/drivers/gpu/drm/i915/gvt/mmio.h +++ b/drivers/gpu/drm/i915/gvt/mmio.h @@ -78,13 +78,20 @@ bool intel_gvt_match_device(struct intel_gvt *gvt, unsigned long device); int intel_gvt_setup_mmio_info(struct intel_gvt *gvt); void intel_gvt_clean_mmio_info(struct intel_gvt *gvt);
+static inline u32 intel_gvt_mmio_offset(unsigned int offset) +{ + return offset; +} + struct intel_gvt_mmio_info *intel_gvt_find_mmio_info(struct intel_gvt *gvt, unsigned int offset); -#define INTEL_GVT_MMIO_OFFSET(reg) ({ \ - typeof(reg) __reg = reg; \ - u32 *offset = (u32 *)&__reg; \ - *offset; \ -}) +#define INTEL_GVT_MMIO_OFFSET(reg) \ +__builtin_choose_expr(__builtin_types_compatible_p(typeof(reg), int), intel_gvt_mmio_offset, \ +__builtin_choose_expr(__builtin_types_compatible_p(typeof(reg), unsigned int), intel_gvt_mmio_offset, \ +__builtin_choose_expr(__builtin_types_compatible_p(typeof(reg), i915_reg_t), i915_mmio_reg_offset, \ + (void)(0) \ +)))(reg) +
int intel_vgpu_init_mmio(struct intel_vgpu *vgpu); void intel_vgpu_reset_mmio(struct intel_vgpu *vgpu);
When CONFIG_KASAN is used, we consume a lot of extra stack space:
drivers/mtd/chips/cfi_cmdset_0020.c: In function 'do_write_buffer': drivers/mtd/chips/cfi_cmdset_0020.c:603:1: error: the frame size of 2080 bytes is larger than 1536 bytes [-Werror=frame-larger-than=] drivers/mtd/chips/cfi_cmdset_0020.c: In function 'cfi_staa_erase_varsize': drivers/mtd/chips/cfi_cmdset_0020.c:972:1: error: the frame size of 1936 bytes is larger than 1536 bytes [-Werror=frame-larger-than=] drivers/mtd/chips/cfi_cmdset_0001.c: In function 'do_write_buffer': drivers/mtd/chips/cfi_cmdset_0001.c:1841:1: error: the frame size of 1776 bytes is larger than 1536 bytes [-Werror=frame-larger-than=]
This marks some functions as noinline_for_kasan to keep reduce the overall stack size.
Signed-off-by: Arnd Bergmann arnd@arndb.de --- drivers/mtd/chips/cfi_cmdset_0020.c | 8 ++++---- include/linux/mtd/map.h | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/drivers/mtd/chips/cfi_cmdset_0020.c b/drivers/mtd/chips/cfi_cmdset_0020.c index 94d3eb42c4d5..8a21e030829c 100644 --- a/drivers/mtd/chips/cfi_cmdset_0020.c +++ b/drivers/mtd/chips/cfi_cmdset_0020.c @@ -244,7 +244,7 @@ static struct mtd_info *cfi_staa_setup(struct map_info *map) }
-static inline int do_read_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf) +static noinline_for_kasan int do_read_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf) { map_word status, status_OK; unsigned long timeo; @@ -728,7 +728,7 @@ cfi_staa_writev(struct mtd_info *mtd, const struct kvec *vecs, }
-static inline int do_erase_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr) +static noinline_for_kasan int do_erase_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr) { struct cfi_private *cfi = map->fldrv_priv; map_word status, status_OK; @@ -1029,7 +1029,7 @@ static void cfi_staa_sync (struct mtd_info *mtd) } }
-static inline int do_lock_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr) +static noinline_for_kasan int do_lock_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr) { struct cfi_private *cfi = map->fldrv_priv; map_word status, status_OK; @@ -1175,7 +1175,7 @@ static int cfi_staa_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) } return 0; } -static inline int do_unlock_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr) +static noinline_for_kasan int do_unlock_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr) { struct cfi_private *cfi = map->fldrv_priv; map_word status, status_OK; diff --git a/include/linux/mtd/map.h b/include/linux/mtd/map.h index 3aa56e3104bb..8c2e241f45c7 100644 --- a/include/linux/mtd/map.h +++ b/include/linux/mtd/map.h @@ -316,7 +316,7 @@ static inline map_word map_word_or(struct map_info *map, map_word val1, map_word return r; }
-static inline int map_word_andequal(struct map_info *map, map_word val1, map_word val2, map_word val3) +static noinline_for_kasan int map_word_andequal(struct map_info *map, map_word val1, map_word val2, map_word val3) { int i;
@@ -328,7 +328,7 @@ static inline int map_word_andequal(struct map_info *map, map_word val1, map_wor return 1; }
-static inline int map_word_bitsset(struct map_info *map, map_word val1, map_word val2) +static noinline_for_kasan int map_word_bitsset(struct map_info *map, map_word val1, map_word val2) { int i;
@@ -362,7 +362,7 @@ static inline map_word map_word_load(struct map_info *map, const void *ptr) return r; }
-static inline map_word map_word_load_partial(struct map_info *map, map_word orig, const unsigned char *buf, int start, int len) +static noinline_for_kasan map_word map_word_load_partial(struct map_info *map, map_word orig, const unsigned char *buf, int start, int len) { int i;
@@ -392,7 +392,7 @@ static inline map_word map_word_load_partial(struct map_info *map, map_word orig #define MAP_FF_LIMIT 8 #endif
-static inline map_word map_word_ff(struct map_info *map) +static noinline_for_kasan map_word map_word_ff(struct map_info *map) { map_word r; int i;
The internal logging infrastructure in ocfs2 causes special warning code to be used with KASAN, which produces rather large stack frames:
fs/ocfs2/super.c: In function 'ocfs2_fill_super': fs/ocfs2/super.c:1219:1: error: the frame size of 3264 bytes is larger than 3072 bytes [-Werror=frame-larger-than=]
By simply passing the mask by value instead of reference, we can avoid the problem completely. On 64-bit architectures, this is also more efficient, while on the less common (at least among ocfs2 users) 32-bit architectures, I'm guessing that the resulting code is comparable to what it was before.
The current version was introduced by Joe Perches as an optimization, maybe he can see if my change regresses compared to his.
Cc: Joe Perches joe@perches.com Fixes: 7c2bd2f930ae ("ocfs2: reduce object size of mlog uses") Signed-off-by: Arnd Bergmann arnd@arndb.de --- fs/ocfs2/cluster/masklog.c | 10 +++++----- fs/ocfs2/cluster/masklog.h | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c index d331c2386b94..9720c5443e4d 100644 --- a/fs/ocfs2/cluster/masklog.c +++ b/fs/ocfs2/cluster/masklog.c @@ -64,7 +64,7 @@ static ssize_t mlog_mask_store(u64 mask, const char *buf, size_t count) return count; }
-void __mlog_printk(const u64 *mask, const char *func, int line, +void __mlog_printk(const u64 mask, const char *func, int line, const char *fmt, ...) { struct va_format vaf; @@ -72,14 +72,14 @@ void __mlog_printk(const u64 *mask, const char *func, int line, const char *level; const char *prefix = "";
- if (!__mlog_test_u64(*mask, mlog_and_bits) || - __mlog_test_u64(*mask, mlog_not_bits)) + if (!__mlog_test_u64(mask, mlog_and_bits) || + __mlog_test_u64(mask, mlog_not_bits)) return;
- if (*mask & ML_ERROR) { + if (mask & ML_ERROR) { level = KERN_ERR; prefix = "ERROR: "; - } else if (*mask & ML_NOTICE) { + } else if (mask & ML_NOTICE) { level = KERN_NOTICE; } else { level = KERN_INFO; diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h index 308ea0eb35fd..0d0f4bf2c3d8 100644 --- a/fs/ocfs2/cluster/masklog.h +++ b/fs/ocfs2/cluster/masklog.h @@ -163,7 +163,7 @@ extern struct mlog_bits mlog_and_bits, mlog_not_bits; #endif
__printf(4, 5) -void __mlog_printk(const u64 *m, const char *func, int line, +void __mlog_printk(const u64 m, const char *func, int line, const char *fmt, ...);
/* @@ -174,7 +174,7 @@ void __mlog_printk(const u64 *m, const char *func, int line, do { \ u64 _m = MLOG_MASK_PREFIX | (mask); \ if (_m & ML_ALLOWED_BITS) \ - __mlog_printk(&_m, __func__, __LINE__, fmt, \ + __mlog_printk(_m, __func__, __LINE__, fmt, \ ##__VA_ARGS__); \ } while (0)
On Thu, 2017-03-02 at 17:38 +0100, Arnd Bergmann wrote:
The internal logging infrastructure in ocfs2 causes special warning code to be used with KASAN, which produces rather large stack frames:
fs/ocfs2/super.c: In function 'ocfs2_fill_super': fs/ocfs2/super.c:1219:1: error: the frame size of 3264 bytes is larger than 3072 bytes [-Werror=frame-larger-than=]
At least by default it doesn't seem to.
gcc 6.2 allyesconfig, CONFIG_KASAN=y with either CONFIG_KASAN_INLINE or CONFIG_KASAN_OUTLINE
gcc doesn't emit a stack warning
By simply passing the mask by value instead of reference, we can avoid the problem completely.
Any idea why that's so?
On 64-bit architectures, this is also more efficient,
Efficient true, but the same overall stack no?
while on the less common (at least among ocfs2 users) 32-bit architectures, I'm guessing that the resulting code is comparable to what it was before.
The current version was introduced by Joe Perches as an optimization, maybe he can see if my change regresses compared to his.
I don't see it.
Cc: Joe Perches joe@perches.com Fixes: 7c2bd2f930ae ("ocfs2: reduce object size of mlog uses") Signed-off-by: Arnd Bergmann arnd@arndb.de
fs/ocfs2/cluster/masklog.c | 10 +++++----- fs/o cfs2/cluster/masklog.h | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c index d331c2386b94..9720c5443e4d 100644 --- a/fs/ocfs2/cluster/masklog.c +++ b/fs/ocfs2/cluster/masklog.c @@ -64,7 +64,7 @@ static ssize_t mlog_mask_store(u64 mask, const char *buf, size_t count) return count; } -void __mlog_printk(const u64 *mask, const char *func, int line, +void __mlog_printk(const u64 mask, const char *func, int line, const char *fmt, ...) { struct va_format vaf; @@ -72,14 +72,14 @@ void __mlog_printk(const u64 *mask, const char *func, int line, const char *level; const char *prefix = "";
- if (!__mlog_test_u64(*mask, mlog_and_bits) ||
__mlog_test_u64(*mask, mlog_not_bits))
- if (!__mlog_test_u64(mask, mlog_and_bits) ||
return;__mlog_test_u64(mask, mlog_not_bits))
- if (*mask & ML_ERROR) {
- if (mask & ML_ERROR) { level = KERN_ERR; prefix = "ERROR: ";
- } else if (*mask & ML_NOTICE) {
- } else if (mask & ML_NOTICE) { level = KERN_NOTICE; } else { level = KERN_INFO;
diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h index 308ea0eb35fd..0d0f4bf2c3d8 100644 --- a/fs/ocfs2/cluster/masklog.h +++ b/fs/ocfs2/cluster/masklog.h @@ -163,7 +163,7 @@ extern struct mlog_bits mlog_and_bits, mlog_not_bits; #endif __printf(4, 5) -void __mlog_printk(const u64 *m, const char *func, int line, +void __mlog_printk(const u64 m, const char *func, int line, const char *fmt, ...); /* @@ -174,7 +174,7 @@ void __mlog_printk(const u64 *m, const char *func, int line, do { \ u64 _m = MLOG_MASK_PREFIX | (mask); \ if (_m & ML_ALLOWED_BITS) \
__mlog_printk(&_m, __func__, __LINE__, fmt, \
__mlog_printk(_m, __func__, __LINE__, fmt, \ ##__VA_ARGS__); \
} while (0)
On Thu, Mar 2, 2017 at 6:46 PM, Joe Perches joe@perches.com wrote:
On Thu, 2017-03-02 at 17:38 +0100, Arnd Bergmann wrote:
The internal logging infrastructure in ocfs2 causes special warning code to be used with KASAN, which produces rather large stack frames:
fs/ocfs2/super.c: In function 'ocfs2_fill_super': fs/ocfs2/super.c:1219:1: error: the frame size of 3264 bytes is larger than 3072 bytes [-Werror=frame-larger-than=]
At least by default it doesn't seem to.
gcc 6.2 allyesconfig, CONFIG_KASAN=y with either CONFIG_KASAN_INLINE or CONFIG_KASAN_OUTLINE
gcc doesn't emit a stack warning
The warning is disabled until patch 26/26. which picks the 3072 default. The 3264 number was with gcc-7, which is worse than gcc-6 since it enables an extra check.
By simply passing the mask by value instead of reference, we can avoid the problem completely.
Any idea why that's so?
With KASAN, every time we inline the function, the compiler has to allocate space for another copy of the variable plus a redzone to detect whether passing it by reference into another function causes an overflow at runtime.
On 64-bit architectures, this is also more efficient,
Efficient true, but the same overall stack no?
Here is what I see with CONFIG_FRAME_WARN=300 and x86_64-linux-gcc-6.3.1:
before: fs/ocfs2/super.c: In function 'ocfs2_parse_options.isra.3': fs/ocfs2/super.c:1508:1: error: the frame size of 352 bytes is larger than 300 bytes [-Werror=frame-larger-than=] fs/ocfs2/super.c: In function 'ocfs2_enable_quotas': fs/ocfs2/super.c:974:1: error: the frame size of 344 bytes is larger than 300 bytes [-Werror=frame-larger-than=] fs/ocfs2/super.c: In function 'ocfs2_fill_super': fs/ocfs2/super.c:1219:1: error: the frame size of 552 bytes is larger than 300 bytes [-Werror=frame-larger-than=]
after: fs/ocfs2/super.c: In function 'ocfs2_fill_super': fs/ocfs2/super.c:1219:1: error: the frame size of 472 bytes is larger than 300 bytes [-Werror=frame-larger-than=]
and with gcc-7.0.1 (including -fsanitize-address-use-after-scope), before: fs/ocfs2/super.c: In function 'ocfs2_check_volume': fs/ocfs2/super.c:2512:1: error: the frame size of 768 bytes is larger than 300 bytes [-Werror=frame-larger-than=] fs/ocfs2/super.c: In function 'ocfs2_statfs': fs/ocfs2/super.c:1717:1: error: the frame size of 320 bytes is larger than 300 bytes [-Werror=frame-larger-than=] fs/ocfs2/super.c: In function 'ocfs2_parse_options.isra.3': fs/ocfs2/super.c:1508:1: error: the frame size of 464 bytes is larger than 300 bytes [-Werror=frame-larger-than=] fs/ocfs2/super.c: In function 'ocfs2_enable_quotas': fs/ocfs2/super.c:974:1: error: the frame size of 320 bytes is larger than 300 bytes [-Werror=frame-larger-than=] fs/ocfs2/super.c: In function 'ocfs2_remount': fs/ocfs2/super.c:752:1: error: the frame size of 568 bytes is larger than 300 bytes [-Werror=frame-larger-than=] fs/ocfs2/super.c: In function 'ocfs2_initialize_super.isra.8': fs/ocfs2/super.c:2339:1: error: the frame size of 1712 bytes is larger than 300 bytes [-Werror=frame-larger-than=] fs/ocfs2/super.c: In function 'ocfs2_fill_super': fs/ocfs2/super.c:1219:1: error: the frame size of 3264 bytes is larger than 300 bytes [-Werror=frame-larger-than=]
after: fs/ocfs2/super.c: In function 'ocfs2_fill_super': fs/ocfs2/super.c:1219:1: error: the frame size of 704 bytes is larger than 300 bytes [-Werror=frame-larger-than=]
Arnd
On Thu, 2017-03-02 at 23:22 +0100, Arnd Bergmann wrote:
On Thu, Mar 2, 2017 at 6:46 PM, Joe Perches joe@perches.com wrote:
On Thu, 2017-03-02 at 17:38 +0100, Arnd Bergmann wrote:
The internal logging infrastructure in ocfs2 causes special warning code to be used with KASAN, which produces rather large stack frames: fs/ocfs2/super.c: In function 'ocfs2_fill_super': fs/ocfs2/super.c:1219:1: error: the frame size of 3264 bytes is larger than 3072 bytes [-Werror=frame-larger-than=]
At least by default it doesn't seem to.
gcc 6.2 allyesconfig, CONFIG_KASAN=y with either CONFIG_KASAN_INLINE or CONFIG_KASAN_OUTLINE
gcc doesn't emit a stack warning
The warning is disabled until patch 26/26. which picks the 3072 default. The 3264 number was with gcc-7, which is worse than gcc-6 since it enables an extra check.
By simply passing the mask by value instead of reference, we can avoid the problem completely.
Any idea why that's so?
With KASAN, every time we inline the function, the compiler has to allocate space for another copy of the variable plus a redzone to detect whether passing it by reference into another function causes an overflow at runtime.
These logging functions aren't inlined. You're referring to the stack frame?
On 64-bit architectures, this is also more efficient,
Efficient true, but the same overall stack no?
Here is what I see with CONFIG_FRAME_WARN=300 and x86_64-linux-gcc-6.3.1:
before:
[]
fs/ocfs2/super.c:1219:1: error: the frame size of 552 bytes is larger than 300 bytes [-Werror=frame-larger-than=]
after: fs/ocfs2/super.c: In function 'ocfs2_fill_super': fs/ocfs2/super.c:1219:1: error: the frame size of 472 bytes is larger than 300 bytes [-Werror=frame-larger-than=]
and with gcc-7.0.1 (including -fsanitize-address-use-after-scope), before:
[]
fs/ocfs2/super.c:1219:1: error: the frame size of 3264 bytes is larger than 300 bytes [-Werror=frame-larger-than=]
after: fs/ocfs2/super.c: In function 'ocfs2_fill_super': fs/ocfs2/super.c:1219:1: error: the frame size of 704 bytes is larger than 300 bytes [-Werror=frame-larger-than=]
Still doesn't make sense to me.
None of the logging functions are inlined as they are all EXPORT_SYMBOL.
This just changes a pointer to a u64, which is the same size on x86-64 (and is of course larger on x86-32).
Perhaps KASAN has the odd behavior and working around KASAN's behavior may not be the proper thing to do.
Maybe if CONFIG_KASAN is set, the minimum stack should be increased via THREAD_SIZE_ORDER or some such.
On Thu, Mar 2, 2017 at 11:40 PM, Joe Perches joe@perches.com wrote:
On Thu, 2017-03-02 at 23:22 +0100, Arnd Bergmann wrote:
On Thu, Mar 2, 2017 at 6:46 PM, Joe Perches joe@perches.com wrote:
On Thu, 2017-03-02 at 17:38 +0100, Arnd Bergmann wrote:
The internal logging infrastructure in ocfs2 causes special warning code to be used with KASAN, which produces rather large stack frames: fs/ocfs2/super.c: In function 'ocfs2_fill_super': fs/ocfs2/super.c:1219:1: error: the frame size of 3264 bytes is larger than 3072 bytes [-Werror=frame-larger-than=]
At least by default it doesn't seem to.
gcc 6.2 allyesconfig, CONFIG_KASAN=y with either CONFIG_KASAN_INLINE or CONFIG_KASAN_OUTLINE
gcc doesn't emit a stack warning
The warning is disabled until patch 26/26. which picks the 3072 default. The 3264 number was with gcc-7, which is worse than gcc-6 since it enables an extra check.
By simply passing the mask by value instead of reference, we can avoid the problem completely.
Any idea why that's so?
With KASAN, every time we inline the function, the compiler has to allocate space for another copy of the variable plus a redzone to detect whether passing it by reference into another function causes an overflow at runtime.
These logging functions aren't inlined.
Sorry, my mistake. In this case mlog() is a macro, not an inline functions. The effect is the same though.
You're referring to the stack frame?
The stack frame of the function that calls mlog(), yes.
Still doesn't make sense to me.
None of the logging functions are inlined as they are all EXPORT_SYMBOL.
mlog() is placed in the calling function.
This just changes a pointer to a u64, which is the same size on x86-64 (and is of course larger on x86-32).
KASAN decides that passing a pointer to _m into an extern function (_mlog_printk) is potentially dangerous, as that function might keep a reference to that pointer after it goes out of scope, or it might not know the correct length of the stack object pointed to.
We can see from looking at the __mlog_printk() function definition that it's actually safe, but the compiler cannot see that when looking at another source file.
Perhaps KASAN has the odd behavior and working around KASAN's behavior may not be the proper thing to do.
Turning off KASAN fixes the problem, but the entire purpose of KASAN is to identify code that is potentially dangerous.
Maybe if CONFIG_KASAN is set, the minimum stack should be increased via THREAD_SIZE_ORDER or some such.
This is what happened in 3f181b4d8652 ("lib/Kconfig.debug: disable -Wframe-larger-than warnings with KASAN=y").
I'm trying to revert that patch so we actually get warnings again about functions that are still dangerous. I picked 3072 as an arbitrary limit, as there are only a handful of files that use larger stack frames in the worst case, but we can only use that limit after fixing up all the warnings it shows.
Arnd
On Thu, 2017-03-02 at 23:59 +0100, Arnd Bergmann wrote:
KASAN decides that passing a pointer to _m into an extern function (_mlog_printk) is potentially dangerous, as that function might keep a reference to that pointer after it goes out of scope, or it might not know the correct length of the stack object pointed to.
We can see from looking at the __mlog_printk() function definition that it's actually safe, but the compiler cannot see that when looking at another source file.
OK, thanks.
btw:
changing __mlog_printk can save ~11% (90+KB) of object text size by removing __func__ and __LINE__ and using vsprintf pointer extension %pS, __builtin_return_address(0) as it is already used in dlmmaster.
(defconfig x86-64, with ocfs2)
$ size fs/ocfs2/built-in.o* text data bss dec hex filename 759791 111373 105688 976852 ee7d4 fs/ocfs2/built-in.o.new 852959 111373 105688 1070020 1053c4 fs/ocfs2/built-in.o.old
It's nearly the same output.
---
fs/ocfs2/cluster/masklog.c | 8 ++++---- fs/ocfs2/cluster/masklog.h | 8 +++----- 2 files changed, 7 insertions(+), 9 deletions(-)
diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c index d331c2386b94..a3f080f37108 100644 --- a/fs/ocfs2/cluster/masklog.c +++ b/fs/ocfs2/cluster/masklog.c @@ -64,8 +64,7 @@ static ssize_t mlog_mask_store(u64 mask, const char *buf, size_t count) return count; }
-void __mlog_printk(const u64 *mask, const char *func, int line, - const char *fmt, ...) +void __mlog_printk(const u64 *mask, const char *fmt, ...) { struct va_format vaf; va_list args; @@ -90,9 +89,10 @@ void __mlog_printk(const u64 *mask, const char *func, int line, vaf.fmt = fmt; vaf.va = &args;
- printk("%s(%s,%u,%u):%s:%d %s%pV", + printk("%s(%s,%u,%u):%pS %s%pV", level, current->comm, task_pid_nr(current), - raw_smp_processor_id(), func, line, prefix, &vaf); + raw_smp_processor_id(), __builtin_return_address(0), + prefix, &vaf);
va_end(args); } diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h index 3c16da69605d..56ba5baf625b 100644 --- a/fs/ocfs2/cluster/masklog.h +++ b/fs/ocfs2/cluster/masklog.h @@ -162,9 +162,8 @@ extern struct mlog_bits mlog_and_bits, mlog_not_bits;
#endif
-__printf(4, 5) __nocapture(2) -void __mlog_printk(const u64 *m, const char *func, int line, - const char *fmt, ...); +__printf(2, 3) __nocapture(2) +void __mlog_printk(const u64 *m, const char *fmt, ...);
/* * Testing before the __mlog_printk call lets the compiler eliminate the @@ -174,8 +173,7 @@ void __mlog_printk(const u64 *m, const char *func, int line, do { \ u64 _m = MLOG_MASK_PREFIX | (mask); \ if (_m & ML_ALLOWED_BITS) \ - __mlog_printk(&_m, __func__, __LINE__, fmt, \ - ##__VA_ARGS__); \ + __mlog_printk(&_m, fmt, ##__VA_ARGS__); \ } while (0)
#define mlog_errno(st) ({ \
When CONFIG_KASAN is enabled, we have several functions that use rather large kernel stacks, e.g.
drivers/isdn/hardware/eicon/message.c: In function 'group_optimization': drivers/isdn/hardware/eicon/message.c:14841:1: warning: the frame size of 864 bytes is larger than 500 bytes [-Wframe-larger-than=] drivers/isdn/hardware/eicon/message.c: In function 'add_b1': drivers/isdn/hardware/eicon/message.c:7925:1: warning: the frame size of 1008 bytes is larger than 500 bytes [-Wframe-larger-than=] drivers/isdn/hardware/eicon/message.c: In function 'add_b23': drivers/isdn/hardware/eicon/message.c:8551:1: warning: the frame size of 928 bytes is larger than 500 bytes [-Wframe-larger-than=] drivers/isdn/hardware/eicon/message.c: In function 'sig_ind': drivers/isdn/hardware/eicon/message.c:6113:1: warning: the frame size of 2112 bytes is larger than 500 bytes [-Wframe-larger-than=]
To be on the safe side, and to enable a lower frame size warning limit, let's just mark this driver as broken when KASAN is in use. I have tried to reduce the stack size as I did with dozens of other drivers, but failed to come up with a good solution for this one.
Signed-off-by: Arnd Bergmann arnd@arndb.de --- drivers/isdn/hardware/eicon/Kconfig | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/isdn/hardware/eicon/Kconfig b/drivers/isdn/hardware/eicon/Kconfig index 6082b6a5ced3..b64496062421 100644 --- a/drivers/isdn/hardware/eicon/Kconfig +++ b/drivers/isdn/hardware/eicon/Kconfig @@ -31,6 +31,7 @@ config ISDN_DIVAS_PRIPCI
config ISDN_DIVAS_DIVACAPI tristate "DIVA CAPI2.0 interface support" + depends on !KASAN || BROKEN help You need this to provide the CAPI interface for DIVA Server cards.
On 03/02/2017 07:38 PM, Arnd Bergmann wrote:
When CONFIG_KASAN is enabled, we have several functions that use rather large kernel stacks, e.g.
drivers/isdn/hardware/eicon/message.c: In function 'group_optimization': drivers/isdn/hardware/eicon/message.c:14841:1: warning: the frame size of 864 bytes is larger than 500 bytes [-Wframe-larger-than=] drivers/isdn/hardware/eicon/message.c: In function 'add_b1': drivers/isdn/hardware/eicon/message.c:7925:1: warning: the frame size of 1008 bytes is larger than 500 bytes [-Wframe-larger-than=] drivers/isdn/hardware/eicon/message.c: In function 'add_b23': drivers/isdn/hardware/eicon/message.c:8551:1: warning: the frame size of 928 bytes is larger than 500 bytes [-Wframe-larger-than=] drivers/isdn/hardware/eicon/message.c: In function 'sig_ind': drivers/isdn/hardware/eicon/message.c:6113:1: warning: the frame size of 2112 bytes is larger than 500 bytes [-Wframe-larger-than=]
To be on the safe side, and to enable a lower frame size warning limit, let's just mark this driver as broken when KASAN is in use. I have tried to reduce the stack size as I did with dozens of other drivers, but failed to come up with a good solution for this one.
This is kinda radical solution. Wouldn't be better to just increase -Wframe-larger-than for this driver through Makefile?
Signed-off-by: Arnd Bergmann arnd@arndb.de
drivers/isdn/hardware/eicon/Kconfig | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/isdn/hardware/eicon/Kconfig b/drivers/isdn/hardware/eicon/Kconfig index 6082b6a5ced3..b64496062421 100644 --- a/drivers/isdn/hardware/eicon/Kconfig +++ b/drivers/isdn/hardware/eicon/Kconfig @@ -31,6 +31,7 @@ config ISDN_DIVAS_PRIPCI config ISDN_DIVAS_DIVACAPI tristate "DIVA CAPI2.0 interface support"
- depends on !KASAN || BROKEN help You need this to provide the CAPI interface for DIVA Server cards.
On Fri, Mar 3, 2017 at 3:20 PM, Andrey Ryabinin aryabinin@virtuozzo.com wrote:
On 03/02/2017 07:38 PM, Arnd Bergmann wrote:
When CONFIG_KASAN is enabled, we have several functions that use rather large kernel stacks, e.g.
drivers/isdn/hardware/eicon/message.c: In function 'group_optimization': drivers/isdn/hardware/eicon/message.c:14841:1: warning: the frame size of 864 bytes is larger than 500 bytes [-Wframe-larger-than=] drivers/isdn/hardware/eicon/message.c: In function 'add_b1': drivers/isdn/hardware/eicon/message.c:7925:1: warning: the frame size of 1008 bytes is larger than 500 bytes [-Wframe-larger-than=] drivers/isdn/hardware/eicon/message.c: In function 'add_b23': drivers/isdn/hardware/eicon/message.c:8551:1: warning: the frame size of 928 bytes is larger than 500 bytes [-Wframe-larger-than=] drivers/isdn/hardware/eicon/message.c: In function 'sig_ind': drivers/isdn/hardware/eicon/message.c:6113:1: warning: the frame size of 2112 bytes is larger than 500 bytes [-Wframe-larger-than=]
To be on the safe side, and to enable a lower frame size warning limit, let's just mark this driver as broken when KASAN is in use. I have tried to reduce the stack size as I did with dozens of other drivers, but failed to come up with a good solution for this one.
This is kinda radical solution. Wouldn't be better to just increase -Wframe-larger-than for this driver through Makefile?
I thought about it too, and decided for disabling the driver entirely since I suspected that not only the per-function stack frame is overly large here but also depth of the call chain, which would then lead us to hiding an actual stack overflow.
Note that this driver is almost certainly broken, it hasn't seen any updates other than style and compile-warning fixes in 10 years and doesn't support any of the hardware introduced since 2002 (the company still makes PCIe ISDN adapters, but the driver only supports legacy PCI versions and older buses).
Arnd
On 03/03/2017 05:54 PM, Arnd Bergmann wrote:
On Fri, Mar 3, 2017 at 3:20 PM, Andrey Ryabinin aryabinin@virtuozzo.com wrote:
On 03/02/2017 07:38 PM, Arnd Bergmann wrote:
When CONFIG_KASAN is enabled, we have several functions that use rather large kernel stacks, e.g.
drivers/isdn/hardware/eicon/message.c: In function 'group_optimization': drivers/isdn/hardware/eicon/message.c:14841:1: warning: the frame size of 864 bytes is larger than 500 bytes [-Wframe-larger-than=] drivers/isdn/hardware/eicon/message.c: In function 'add_b1': drivers/isdn/hardware/eicon/message.c:7925:1: warning: the frame size of 1008 bytes is larger than 500 bytes [-Wframe-larger-than=] drivers/isdn/hardware/eicon/message.c: In function 'add_b23': drivers/isdn/hardware/eicon/message.c:8551:1: warning: the frame size of 928 bytes is larger than 500 bytes [-Wframe-larger-than=] drivers/isdn/hardware/eicon/message.c: In function 'sig_ind': drivers/isdn/hardware/eicon/message.c:6113:1: warning: the frame size of 2112 bytes is larger than 500 bytes [-Wframe-larger-than=]
To be on the safe side, and to enable a lower frame size warning limit, let's just mark this driver as broken when KASAN is in use. I have tried to reduce the stack size as I did with dozens of other drivers, but failed to come up with a good solution for this one.
This is kinda radical solution. Wouldn't be better to just increase -Wframe-larger-than for this driver through Makefile?
I thought about it too, and decided for disabling the driver entirely since I suspected that not only the per-function stack frame is overly large here but also depth of the call chain, which would then lead us to hiding an actual stack overflow.
No one complained so far ;) Disabling the driver like you did will throw it out from allmodconfig so it will receive less compile-testing.
Note that this driver is almost certainly broken, it hasn't seen any updates other than style and compile-warning fixes in 10 years and doesn't support any of the hardware introduced since 2002 (the company still makes PCIe ISDN adapters, but the driver only supports legacy PCI versions and older buses).
Which means that it's unlikely that someone will run this driver with KASAN and trigger stack overflow (if it's really possible).
On Fri, Mar 3, 2017 at 4:22 PM, Andrey Ryabinin aryabinin@virtuozzo.com wrote:
On 03/03/2017 05:54 PM, Arnd Bergmann wrote:
On Fri, Mar 3, 2017 at 3:20 PM, Andrey Ryabinin aryabinin@virtuozzo.com wrote:
On 03/02/2017 07:38 PM, Arnd Bergmann wrote:
This is kinda radical solution. Wouldn't be better to just increase -Wframe-larger-than for this driver through Makefile?
I thought about it too, and decided for disabling the driver entirely since I suspected that not only the per-function stack frame is overly large here but also depth of the call chain, which would then lead us to hiding an actual stack overflow.
No one complained so far ;) Disabling the driver like you did will throw it out from allmodconfig so it will receive less compile-testing.
Good point, I'll add a driver specific flag then and leave it there.
Note that this driver is almost certainly broken, it hasn't seen any updates other than style and compile-warning fixes in 10 years and doesn't support any of the hardware introduced since 2002 (the company still makes PCIe ISDN adapters, but the driver only supports legacy PCI versions and older buses).
Which means that it's unlikely that someone will run this driver with KASAN
and trigger stack overflow (if it's really possible).
True.
Arnd
We get a lot of very large stack frames using gcc-7.0.1 with the default -fsanitize-address-use-after-scope --param asan-stack=1 options, which can easily cause an overflow of the kernel stack, e.g.
drivers/acpi/nfit/core.c:2686:1: warning: the frame size of 4080 bytes is larger than 2048 bytes [-Wframe-larger-than=] drivers/gpu/drm/amd/amdgpu/si.c:1756:1: warning: the frame size of 7304 bytes is larger than 2048 bytes [-Wframe-larger-than=] drivers/gpu/drm/i915/gvt/handlers.c:2200:1: warning: the frame size of 43752 bytes is larger than 2048 bytes [-Wframe-larger-than=] drivers/gpu/drm/vmwgfx/vmwgfx_drv.c:952:1: warning: the frame size of 6032 bytes is larger than 2048 bytes [-Wframe-larger-than=] drivers/isdn/hardware/avm/b1.c:637:1: warning: the frame size of 13200 bytes is larger than 2048 bytes [-Wframe-larger-than=] drivers/media/dvb-frontends/stv090x.c:3089:1: warning: the frame size of 5880 bytes is larger than 2048 bytes [-Wframe-larger-than=] drivers/media/i2c/cx25840/cx25840-core.c:4964:1: warning: the frame size of 93992 bytes is larger than 2048 bytes [-Wframe-larger-than=] drivers/net/wireless/ralink/rt2x00/rt2800lib.c:4994:1: warning: the frame size of 23928 bytes is larger than 2048 bytes [-Wframe-larger-than=] drivers/staging/dgnc/dgnc_tty.c:2788:1: warning: the frame size of 7072 bytes is larger than 2048 bytes [-Wframe-larger-than=] fs/ntfs/mft.c:2762:1: warning: the frame size of 7432 bytes is larger than 2048 bytes [-Wframe-larger-than=] lib/atomic64_test.c:242:1: warning: the frame size of 12648 bytes is larger than 2048 bytes [-Wframe-larger-than=]
To reduce this risk, -fsanitize-address-use-after-scope is now split out into a separate Kconfig option, vhich cannot be selected at the same time as KMEMCHECK, leading to stack frames that are smaller than 2 kilobytes most of the time on x86_64. An earlier version of this patch also prevented combining KASAN_EXTRA with KASAN_INLINE, but that is no longer necessary with the latest gcc-7.0.1 snapshot.
A lot of warnings with KASAN_EXTRA go away if we disable KMEMCHECK, as -fsanitize-address-use-after-scope seems to understand the builtin memcpy, but adds checking code around an extern memcpy call. I had to work around a circular dependency, as DEBUG_SLAB/SLUB depended on !KMEMCHECK, while KASAN did it the other way round. Now we handle both the same way.
All patches to get the frame size below 3072 bytes with KASAN_EXTRA, and below 2048 bytes without it have been submitted, so we can make those the default now. Note that KASAN is only supported on arm64 and x86_64 at the moment, and both use 2048 byte stacks by default. This reverts parts of commit commit 3f181b4 ("lib/Kconfig.debug: disable -Wframe-larger-than warnings with KASAN=y").
I experimented a bit more with smaller stack frames and have another follow-up series that reduces the warning limit for 64-bit architectures to 1280 bytes and 1536 when CONFIG_KASAN (but not KASAN_EXTRA) is enabled, this requires another ~25 patches to address the additional warnings.
Signed-off-by: Arnd Bergmann arnd@arndb.de --- lib/Kconfig.debug | 9 ++++----- lib/Kconfig.kasan | 11 ++++++++++- lib/Kconfig.kmemcheck | 1 + scripts/Makefile.kasan | 3 +++ 4 files changed, 18 insertions(+), 6 deletions(-)
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 97d62c2da6c2..27c838c40a36 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -216,10 +216,9 @@ config ENABLE_MUST_CHECK config FRAME_WARN int "Warn for stack frames larger than (needs gcc 4.4)" range 0 8192 - default 0 if KASAN - default 2048 if GCC_PLUGIN_LATENT_ENTROPY + default 3072 if KASAN_EXTRA default 1024 if !64BIT - default 2048 if 64BIT + default 1280 if 64BIT help Tell gcc to warn at build time for stack frames larger than this. Setting this too low will cause a lot of warnings. @@ -499,7 +498,7 @@ config DEBUG_OBJECTS_ENABLE_DEFAULT
config DEBUG_SLAB bool "Debug slab memory allocations" - depends on DEBUG_KERNEL && SLAB && !KMEMCHECK + depends on DEBUG_KERNEL && SLAB && !KMEMCHECK && !KASAN help Say Y here to have the kernel do limited verification on memory allocation as well as poisoning memory on free to catch use of freed @@ -511,7 +510,7 @@ config DEBUG_SLAB_LEAK
config SLUB_DEBUG_ON bool "SLUB debugging on by default" - depends on SLUB && SLUB_DEBUG && !KMEMCHECK + depends on SLUB && SLUB_DEBUG && !KMEMCHECK && !KASAN default n help Boot with debugging on by default. SLUB boots by default with diff --git a/lib/Kconfig.kasan b/lib/Kconfig.kasan index bd38aab05929..e88ce7cc13bb 100644 --- a/lib/Kconfig.kasan +++ b/lib/Kconfig.kasan @@ -5,7 +5,7 @@ if HAVE_ARCH_KASAN
config KASAN bool "KASan: runtime memory debugger" - depends on SLUB || (SLAB && !DEBUG_SLAB) + depends on SLUB || SLAB select CONSTRUCTORS select STACKDEPOT help @@ -20,6 +20,15 @@ config KASAN Currently CONFIG_KASAN doesn't work with CONFIG_DEBUG_SLAB (the resulting kernel does not boot).
+config KASAN_EXTRA + bool "KAsan: extra checks" + depends on KASAN + help + This enables further checks in the kernel address sanitizer, for now + it only includes the address-use-after-scope check which requires the + use of KASAN_OUTLINE to avoid excessive kernel stack frame sizes that + might lead to stack overflows. + choice prompt "Instrumentation type" depends on KASAN diff --git a/lib/Kconfig.kmemcheck b/lib/Kconfig.kmemcheck index 846e039a86b4..58b9f3f81dc8 100644 --- a/lib/Kconfig.kmemcheck +++ b/lib/Kconfig.kmemcheck @@ -7,6 +7,7 @@ menuconfig KMEMCHECK bool "kmemcheck: trap use of uninitialized memory" depends on DEBUG_KERNEL depends on !X86_USE_3DNOW + depends on !KASAN_EXTRA depends on SLUB || SLAB depends on !CC_OPTIMIZE_FOR_SIZE depends on !FUNCTION_TRACER diff --git a/scripts/Makefile.kasan b/scripts/Makefile.kasan index 9576775a86f6..3b3148faf866 100644 --- a/scripts/Makefile.kasan +++ b/scripts/Makefile.kasan @@ -29,5 +29,8 @@ else endif endif
+ifdef CONFIG_KASAN_EXTRA CFLAGS_KASAN += $(call cc-option, -fsanitize-address-use-after-scope) endif + +endif
On 03/02/2017 07:38 PM, Arnd Bergmann wrote:
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 97d62c2da6c2..27c838c40a36 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -216,10 +216,9 @@ config ENABLE_MUST_CHECK config FRAME_WARN int "Warn for stack frames larger than (needs gcc 4.4)" range 0 8192
- default 0 if KASAN
- default 2048 if GCC_PLUGIN_LATENT_ENTROPY
- default 3072 if KASAN_EXTRA default 1024 if !64BIT
- default 2048 if 64BIT
- default 1280 if 64BIT
This looks unrelated. Also, it means that now we have 1280 with KASAN=y && KASAN_EXTRA=n. Judging from changelog I assume that this hunk slipped here from the follow up series.
help Tell gcc to warn at build time for stack frames larger than this. Setting this too low will cause a lot of warnings. @@ -499,7 +498,7 @@ config DEBUG_OBJECTS_ENABLE_DEFAULT config DEBUG_SLAB bool "Debug slab memory allocations"
- depends on DEBUG_KERNEL && SLAB && !KMEMCHECK
- depends on DEBUG_KERNEL && SLAB && !KMEMCHECK && !KASAN help Say Y here to have the kernel do limited verification on memory allocation as well as poisoning memory on free to catch use of freed
@@ -511,7 +510,7 @@ config DEBUG_SLAB_LEAK config SLUB_DEBUG_ON bool "SLUB debugging on by default"
- depends on SLUB && SLUB_DEBUG && !KMEMCHECK
- depends on SLUB && SLUB_DEBUG && !KMEMCHECK && !KASAN
Why? SLUB_DEBUG_ON works with KASAN.
default n help Boot with debugging on by default. SLUB boots by default with
On Fri, Mar 3, 2017 at 3:51 PM, Andrey Ryabinin aryabinin@virtuozzo.com wrote:
On 03/02/2017 07:38 PM, Arnd Bergmann wrote:
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 97d62c2da6c2..27c838c40a36 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -216,10 +216,9 @@ config ENABLE_MUST_CHECK config FRAME_WARN int "Warn for stack frames larger than (needs gcc 4.4)" range 0 8192
default 0 if KASAN
default 2048 if GCC_PLUGIN_LATENT_ENTROPY
default 3072 if KASAN_EXTRA default 1024 if !64BIT
default 2048 if 64BIT
default 1280 if 64BIT
This looks unrelated. Also, it means that now we have 1280 with KASAN=y && KASAN_EXTRA=n. Judging from changelog I assume that this hunk slipped here from the follow up series.
Right, this slipped in by accident, I've already fixed it up locally.
help Tell gcc to warn at build time for stack frames larger than this. Setting this too low will cause a lot of warnings.
@@ -499,7 +498,7 @@ config DEBUG_OBJECTS_ENABLE_DEFAULT
config DEBUG_SLAB bool "Debug slab memory allocations"
depends on DEBUG_KERNEL && SLAB && !KMEMCHECK
depends on DEBUG_KERNEL && SLAB && !KMEMCHECK && !KASAN help Say Y here to have the kernel do limited verification on memory allocation as well as poisoning memory on free to catch use of freed
@@ -511,7 +510,7 @@ config DEBUG_SLAB_LEAK
config SLUB_DEBUG_ON bool "SLUB debugging on by default"
depends on SLUB && SLUB_DEBUG && !KMEMCHECK
depends on SLUB && SLUB_DEBUG && !KMEMCHECK && !KASAN
Why? SLUB_DEBUG_ON works with KASAN.
Ok, will fix. I wrongly guessed that kmemcheck and kasan had the same reason for the two dependencies here.
Arnd
On Thu, Mar 2, 2017 at 5:38 PM, Arnd Bergmann arnd@arndb.de wrote:
It took a long while to get this done, but I'm finally ready to send the first half of the KASAN stack size patches that I did in response to the kernelci.org warnings.
As before, it's worth mentioning that things are generally worse with gcc-7.0.1 because of the addition of -fsanitize-address-use-after-scope that are not present on kernelci, so my randconfig testing found a lot more than kernelci did.
The main areas are:
- READ_ONCE/WRITE_ONCE cause problems in lots of code
- typecheck() causes huge problems in a few places
- I'm introducing "noinline_for_kasan" and use it in a lot of places that suffer from inline functions with local variables
- netlink, as used in various parts of the kernel
- a number of drivers/media drivers
- a handful of wireless network drivers
- kmemcheck conflicts with -fsanitize-address-use-after-scope
This series lets us add back a stack frame warning for 3072 bytes with -fsanitize-address-use-after-scope, or 2048 bytes without it.
I have a follow-up series that further reduces the stack frame warning limit to 1280 bytes for all 64-bit architectures, and 1536 bytes with basic KASAN support (no -fsanitize-address-use-after-scope). For now, I'm only posting the first half, in order to keep it (barely) reviewable.
Can you please elaborate on why do you need this? Are you trying to squeeze KASAN into some embedded device? Noinlines sprayed over the codebase are hard to maintain, and certain compiler changes may cause bloated stack frames in other places. Maybe it should be enough to just increase the stack frame limit in KASAN builds, as Dmitry suggested previously?
Both series are tested with many hundred randconfig builds on both x86 and arm64, which are the only architectures supporting KASAN.
Arnd
[PATCH 01/26] compiler: introduce noinline_for_kasan annotation [PATCH 02/26] rewrite READ_ONCE/WRITE_ONCE [PATCH 03/26] typecheck.h: avoid local variables in typecheck() macro [PATCH 04/26] tty: kbd: reduce stack size with KASAN [PATCH 05/26] netlink: mark nla_put_{u8,u16,u32} noinline_for_kasan [PATCH 06/26] rocker: mark rocker_tlv_put_* functions as [PATCH 07/26] brcmsmac: reduce stack size with KASAN [PATCH 08/26] brcmsmac: make some local variables 'static const' to [PATCH 09/26] brcmsmac: split up wlc_phy_workarounds_nphy [PATCH 10/26] brcmsmac: reindent split functions [PATCH 11/26] rtlwifi: reduce stack usage for KASAN [PATCH 12/26] wl3501_cs: reduce stack size for KASAN [PATCH 13/26] rtl8180: reduce stack size for KASAN [PATCH 14/26] [media] dvb-frontends: reduce stack size in i2c access [PATCH 15/26] [media] tuners: i2c: reduce stack usage for [PATCH 16/26] [media] i2c: adv7604: mark register access as [PATCH 17/26] [media] i2c: ks0127: reduce stack frame size for KASAN [PATCH 18/26] [media] i2c: cx25840: avoid stack overflow with KASAN [PATCH 19/26] [media] r820t: mark register functions as [PATCH 20/26] [media] em28xx: split up em28xx_dvb_init to reduce [PATCH 21/26] drm/bridge: ps8622: reduce stack size for KASAN [PATCH 22/26] drm/i915/gvt: don't overflow the kernel stack with [PATCH 23/26] mtd: cfi: reduce stack size with KASAN [PATCH 24/26] ocfs2: reduce stack size with KASAN [PATCH 25/26] isdn: eicon: mark divascapi incompatible with kasan [PATCH 26/26] kasan: rework Kconfig settings
arch/x86/include/asm/switch_to.h | 2 +- drivers/gpu/drm/bridge/parade-ps8622.c | 2 +- drivers/gpu/drm/i915/gvt/mmio.h | 17 +- drivers/isdn/hardware/eicon/Kconfig | 1 + drivers/media/dvb-frontends/ascot2e.c | 3 +- drivers/media/dvb-frontends/cxd2841er.c | 4 +- drivers/media/dvb-frontends/drx39xyj/drxj.c | 14 +- drivers/media/dvb-frontends/helene.c | 4 +- drivers/media/dvb-frontends/horus3a.c | 2 +- drivers/media/dvb-frontends/itd1000.c | 2 +- drivers/media/dvb-frontends/mt312.c | 2 +- drivers/media/dvb-frontends/si2165.c | 14 +- drivers/media/dvb-frontends/stb0899_drv.c | 2 +- drivers/media/dvb-frontends/stb6100.c | 2 +- drivers/media/dvb-frontends/stv0367.c | 2 +- drivers/media/dvb-frontends/stv090x.c | 2 +- drivers/media/dvb-frontends/stv6110.c | 2 +- drivers/media/dvb-frontends/stv6110x.c | 2 +- drivers/media/dvb-frontends/tda8083.c | 2 +- drivers/media/dvb-frontends/zl10039.c | 2 +- drivers/media/i2c/adv7604.c | 4 +- drivers/media/i2c/cx25840/cx25840-core.c | 4 +- drivers/media/i2c/ks0127.c | 2 +- drivers/media/tuners/r820t.c | 4 +- drivers/media/tuners/tuner-i2c.h | 15 +- drivers/media/usb/em28xx/em28xx-dvb.c | 947 +++++++++++++++++++++------------------ drivers/mtd/chips/cfi_cmdset_0020.c | 8 +- drivers/net/ethernet/rocker/rocker_tlv.h | 24 +- drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c | 1860 +++++++++++++++++++++++++++++++++++++---------------------------------------- drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8225se.c | 4 +- drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.c | 41 +- drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c | 26 +- drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c | 34 +- drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.c | 36 +- drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.c | 38 +- drivers/net/wireless/wl3501_cs.c | 10 +- drivers/tty/vt/keyboard.c | 6 +- fs/ocfs2/cluster/masklog.c | 10 +- fs/ocfs2/cluster/masklog.h | 4 +- fs/overlayfs/util.c | 6 +- include/linux/compiler.h | 58 ++- include/linux/mtd/map.h | 8 +- include/linux/typecheck.h | 7 +- include/net/netlink.h | 36 +- lib/Kconfig.debug | 9 +- lib/Kconfig.kasan | 11 +- lib/Kconfig.kmemcheck | 1 + scripts/Makefile.kasan | 3 + 48 files changed, 1670 insertions(+), 1629 deletions(-)
On Fri, Mar 3, 2017 at 1:25 PM, Alexander Potapenko glider@google.com wrote:
On Thu, Mar 2, 2017 at 5:38 PM, Arnd Bergmann arnd@arndb.de wrote:
It took a long while to get this done, but I'm finally ready to send the first half of the KASAN stack size patches that I did in response to the kernelci.org warnings.
As before, it's worth mentioning that things are generally worse with gcc-7.0.1 because of the addition of -fsanitize-address-use-after-scope that are not present on kernelci, so my randconfig testing found a lot more than kernelci did.
The main areas are:
- READ_ONCE/WRITE_ONCE cause problems in lots of code
- typecheck() causes huge problems in a few places
- I'm introducing "noinline_for_kasan" and use it in a lot of places that suffer from inline functions with local variables
- netlink, as used in various parts of the kernel
- a number of drivers/media drivers
- a handful of wireless network drivers
- kmemcheck conflicts with -fsanitize-address-use-after-scope
This series lets us add back a stack frame warning for 3072 bytes with -fsanitize-address-use-after-scope, or 2048 bytes without it.
I have a follow-up series that further reduces the stack frame warning limit to 1280 bytes for all 64-bit architectures, and 1536 bytes with basic KASAN support (no -fsanitize-address-use-after-scope). For now, I'm only posting the first half, in order to keep it (barely) reviewable.
Can you please elaborate on why do you need this? Are you trying to squeeze KASAN into some embedded device? Noinlines sprayed over the codebase are hard to maintain, and certain compiler changes may cause bloated stack frames in other places. Maybe it should be enough to just increase the stack frame limit in KASAN builds, as Dmitry suggested previously?
The current state of mainline has doubled the kernel stack size with KASAN, and completely turned off the warning for per-function stack frames. In some cases, this is completely broken as we have functions that exceed even the 32kb per-thread stacks by themselves, so I want to turn on the warning again and fix all the outliers.
The hard part is deciding what size is reasonable for a given function, as smaller limits cause more harmless warnings while larger limits can hide more actual problems. Before running into the KASAN problem, I had already determined that we can lower the warning limit for 64-bit architectures from 2048 bytes to 1280 with just a handful of patches that are generally a good cleanup anyway.
This led me to picking three separate warning limits, based on what I found reasonable to work around in the code:
3072 bytes with -fsanitize-address-use-after-scope 1536 bytes with KASAN but without -fsanitize-address-use-after-scope 1280 bytes on 64-bit without KASAN 1024 bytes on 32-bit architectures
If we use higher limits, the patch series will get a bit shorter. For the limits above, I needed a total of 51 patches, while this shorter series of 26 patches has slightly laxer limits:
3072 bytes with -fsanitize-address-use-after-scope 2048 bytes on 64-bit architectures with or without KASAN, but without -fsanitize-address-use-after-scope 1024 bytes on 32-bit architectures
The individual patches should list the highest frame size I ran into, so I can try to reduce the number of patches if you have a suggestion for a different set of limits.
Arnd
kernel-build-reports@lists.linaro.org