2017-06-14 21:16:25

by Arnd Bergmann

[permalink] [raw]
Subject: [PATCH v2 00/11] bring back stack frame warning with KASAN

This is a new version of patches I originally submitted back in
March [1], this time reducing the size of the series even further.

This minimal set of patches only makes sure that we do get
frame size warnings in allmodconfig for x86_64 and arm64 again,
even with KASAN enabled.

The changes this time are reduced to:

- I'm introducing "noinline_if_stackbloat" and use it in a number
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
- a rework for the brcmsmac driver
- -fsanitize-address-use-after-scope is moved to a separate
CONFIG_KASAN_EXTRA option that increases the warning limit
- CONFIG_KASAN_EXTRA is disabled with CONFIG_COMPILE_TEST,
improving compile speed and disabling code that leads to
valid warnings on gcc-7.0.1
- kmemcheck conflicts with CONFIG_KASAN_EXTRA

Compared to the previous version, I no longer have patches
to fix all the CONFIG_KASAN_EXTRA warnings:

- READ_ONCE/WRITE_ONCE cause problems in lots of code
- typecheck() causes huge problems in a few places
- many more uses of noinline_if_stackbloat

This series lets us add back a stack frame warning for the regular
2048 bytes without CONFIG_KASAN_EXTRA. I set the warning limit with
KASAN_EXTRA to 3072, since I have an additional set of patches
to address all files that surpass that limit. We can debate whether
we want to apply those as a follow-up, or instead remove the option
entirely.

Another follow-up series I have reduces the warning limit with
KASAN to 1536, and without KASAN to 1280 for 64-bit architectures.

I hope that Andrew can pick up the entire series for mmotm, and
we can eventually backport most of it to stable kernels and
address the warnings that kernelci still reports for this problem [2].

Arnd

[1] https://lkml.org/lkml/2017/3/2/508
[2] https://kernelci.org/build/id/593f89a659b51463306b958d/logs/

kasan: rework Kconfig settings
brcmsmac: reindent split functions
brcmsmac: split up wlc_phy_workarounds_nphy
brcmsmac: make some local variables 'static const' to reduce stack size
r820t: mark register functions as noinline_if_stackbloat
dvb-frontends: reduce stack size in i2c access
mtd: cfi: reduce stack size with KASAN
rocker: mark rocker_tlv_put_* functions as noinline_if_stackbloat
tty: kbd: reduce stack size with KASAN
netlink: mark nla_put_{u8,u16,u32} noinline_if_stackbloat
compiler: introduce noinline_if_stackbloat annotation

Arnd Bergmann (11):
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/tuners/r820t.c | 4 +-
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 | 1856 +++++++++++++++++++++++-------------------------
drivers/tty/vt/keyboard.c | 6 +-
include/linux/compiler.h | 11 +
include/linux/mtd/map.h | 8 +-
include/net/netlink.h | 36 +-
lib/Kconfig.debug | 4 +-
lib/Kconfig.kasan | 11 +-
lib/Kconfig.kmemcheck | 1 +
scripts/Makefile.kasan | 3 +
28 files changed, 986 insertions(+), 1047 deletions(-)

--
2.9.0


2017-06-14 21:17:29

by Arnd Bergmann

[permalink] [raw]
Subject: [PATCH v2 01/11] compiler: introduce noinline_if_stackbloat annotation

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' depending on the CONFIG_KASAN symbol.

Signed-off-by: Arnd Bergmann <[email protected]>
---
include/linux/compiler.h | 11 +++++++++++
1 file changed, 11 insertions(+)

diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index 219f82f3ec1a..a402c43c07d2 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -412,6 +412,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_if_stackbloat noinline __maybe_unused
+#else
+#define noinline_if_stackbloat inline
+#endif
+
#ifndef __always_inline
#define __always_inline inline
#endif
--
2.9.0

2017-06-14 21:18:24

by Arnd Bergmann

[permalink] [raw]
Subject: [PATCH v2 02/11] netlink: mark nla_put_{u8,u16,u32} noinline_if_stackbloat

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_if_stackbloat annotation, we can avoid the problem
when KASAN is enabled but not change anything otherwise.

Cc: Andrey Ryabinin <[email protected]>
Cc: Alexander Potapenko <[email protected]>
Cc: Dmitry Vyukov <[email protected]>
Cc: [email protected]
Signed-off-by: Arnd Bergmann <[email protected]>
---
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 01709172b3d3..24b4badd6eaf 100644
--- a/include/net/netlink.h
+++ b/include/net/netlink.h
@@ -766,7 +766,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_if_stackbloat int nla_put_u8(struct sk_buff *skb, int attrtype, u8 value)
{
return nla_put(skb, attrtype, sizeof(u8), &value);
}
@@ -777,7 +777,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_if_stackbloat int nla_put_u16(struct sk_buff *skb, int attrtype, u16 value)
{
return nla_put(skb, attrtype, sizeof(u16), &value);
}
@@ -788,7 +788,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_if_stackbloat int nla_put_be16(struct sk_buff *skb, int attrtype, __be16 value)
{
return nla_put(skb, attrtype, sizeof(__be16), &value);
}
@@ -799,7 +799,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_if_stackbloat int nla_put_net16(struct sk_buff *skb, int attrtype, __be16 value)
{
return nla_put_be16(skb, attrtype | NLA_F_NET_BYTEORDER, value);
}
@@ -810,7 +810,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_if_stackbloat int nla_put_le16(struct sk_buff *skb, int attrtype, __le16 value)
{
return nla_put(skb, attrtype, sizeof(__le16), &value);
}
@@ -821,7 +821,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_if_stackbloat int nla_put_u32(struct sk_buff *skb, int attrtype, u32 value)
{
return nla_put(skb, attrtype, sizeof(u32), &value);
}
@@ -832,7 +832,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_if_stackbloat int nla_put_be32(struct sk_buff *skb, int attrtype, __be32 value)
{
return nla_put(skb, attrtype, sizeof(__be32), &value);
}
@@ -843,7 +843,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_if_stackbloat int nla_put_net32(struct sk_buff *skb, int attrtype, __be32 value)
{
return nla_put_be32(skb, attrtype | NLA_F_NET_BYTEORDER, value);
}
@@ -854,7 +854,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_if_stackbloat int nla_put_le32(struct sk_buff *skb, int attrtype, __le32 value)
{
return nla_put(skb, attrtype, sizeof(__le32), &value);
}
@@ -866,7 +866,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_if_stackbloat 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);
@@ -879,7 +879,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_if_stackbloat int nla_put_be64(struct sk_buff *skb, int attrtype, __be64 value,
int padattr)
{
return nla_put_64bit(skb, attrtype, sizeof(__be64), &value, padattr);
@@ -892,7 +892,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_if_stackbloat 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,
@@ -906,7 +906,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_if_stackbloat int nla_put_le64(struct sk_buff *skb, int attrtype, __le64 value,
int padattr)
{
return nla_put_64bit(skb, attrtype, sizeof(__le64), &value, padattr);
@@ -918,7 +918,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_if_stackbloat int nla_put_s8(struct sk_buff *skb, int attrtype, s8 value)
{
return nla_put(skb, attrtype, sizeof(s8), &value);
}
@@ -929,7 +929,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_if_stackbloat int nla_put_s16(struct sk_buff *skb, int attrtype, s16 value)
{
return nla_put(skb, attrtype, sizeof(s16), &value);
}
@@ -940,7 +940,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_if_stackbloat int nla_put_s32(struct sk_buff *skb, int attrtype, s32 value)
{
return nla_put(skb, attrtype, sizeof(s32), &value);
}
@@ -952,7 +952,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_if_stackbloat int nla_put_s64(struct sk_buff *skb, int attrtype, s64 value,
int padattr)
{
return nla_put_64bit(skb, attrtype, sizeof(s64), &value, padattr);
@@ -987,7 +987,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_if_stackbloat int nla_put_msecs(struct sk_buff *skb, int attrtype,
unsigned long njiffies, int padattr)
{
u64 tmp = jiffies_to_msecs(njiffies);
--
2.9.0

2017-06-14 21:18:38

by Arnd Bergmann

[permalink] [raw]
Subject: [PATCH v2 04/11] rocker: mark rocker_tlv_put_* functions as noinline_if_stackbloat

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_if_stackbloat, which solves the problem by
keeping the redzone inside of the separate stack frames.

Signed-off-by: Arnd Bergmann <[email protected]>
---
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..8970a414eb5b 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_if_stackbloat 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_if_stackbloat 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_if_stackbloat 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_if_stackbloat 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_if_stackbloat 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_if_stackbloat 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);
}
--
2.9.0

2017-06-14 21:19:31

by Arnd Bergmann

[permalink] [raw]
Subject: [PATCH v2 03/11] tty: kbd: reduce stack size with KASAN

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_if_stackbloat prevents the inlining
and reduces the overall stack usage in this driver.

Signed-off-by: Arnd Bergmann <[email protected]>
---
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 f4166263bb3a..c0d111444a0e 100644
--- a/drivers/tty/vt/keyboard.c
+++ b/drivers/tty/vt/keyboard.c
@@ -301,13 +301,13 @@ int kbd_rate(struct kbd_repeat *rpt)
/*
* Helper Functions.
*/
-static void put_queue(struct vc_data *vc, int ch)
+static noinline_if_stackbloat 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_if_stackbloat void puts_queue(struct vc_data *vc, char *cp)
{
while (*cp) {
tty_insert_flip_char(&vc->port, *cp, 0);
@@ -555,7 +555,7 @@ static void fn_inc_console(struct vc_data *vc)
set_console(i);
}

-static void fn_send_intr(struct vc_data *vc)
+static noinline_if_stackbloat void fn_send_intr(struct vc_data *vc)
{
tty_insert_flip_char(&vc->port, 0, TTY_BREAK);
tty_schedule_flip(&vc->port);
--
2.9.0

2017-06-14 21:19:56

by Arnd Bergmann

[permalink] [raw]
Subject: [PATCH v2 05/11] mtd: cfi: reduce stack size with KASAN

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 2184 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_if_stackbloat to keep reduce the
overall stack size.

Signed-off-by: Arnd Bergmann <[email protected]>
---
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 7d342965f392..5eee5e883f55 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_if_stackbloat 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_if_stackbloat 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_if_stackbloat 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_if_stackbloat 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..29db74314db8 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_if_stackbloat 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_if_stackbloat 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_if_stackbloat 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_if_stackbloat map_word map_word_ff(struct map_info *map)
{
map_word r;
int i;
--
2.9.0

2017-06-14 21:20:39

by Arnd Bergmann

[permalink] [raw]
Subject: [PATCH v2 06/11] dvb-frontends: reduce stack size in i2c access

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_if_stackbloat,
we can completely avoid this problem.

Signed-off-by: Arnd Bergmann <[email protected]>
---
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..da1d1fc03c5e 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_if_stackbloat 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 ce37dc2e89c7..6b851a948ce0 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_if_stackbloat 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_if_stackbloat 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 14040c915dbb..ec5b13ca630b 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_if_stackbloat 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_if_stackbloat 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_if_stackbloat 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_if_stackbloat 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_if_stackbloat
int drxj_dap_atomic_read_reg32(struct i2c_device_addr *dev_addr,
u32 addr,
u32 *data, u32 flags)
@@ -4192,7 +4192,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_if_stackbloat
int drxj_dap_scu_atomic_read_reg16(struct i2c_device_addr *dev_addr,
u32 addr,
u16 *data, u32 flags)
@@ -4220,7 +4220,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_if_stackbloat
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..849a18a837d0 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_if_stackbloat 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_if_stackbloat 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 68d759c4c52e..f879af6c3188 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_if_stackbloat 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..8bd6d04362cc 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_if_stackbloat 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..d7a701da598a 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_if_stackbloat 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..8b1ac134f9d8 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_if_stackbloat 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_if_stackbloat 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_if_stackbloat 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_if_stackbloat 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_if_stackbloat 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_if_stackbloat 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_if_stackbloat 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..9258085b8d35 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_if_stackbloat 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..675dffe1ef20 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_if_stackbloat 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..2316c0bb3e21 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_if_stackbloat 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..8afecc2e3637 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_if_stackbloat 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..ddef3a912615 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_if_stackbloat 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..80c7024971de 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_if_stackbloat 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..646f22aab24e 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_if_stackbloat 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..0075725cb161 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_if_stackbloat int zl10039_writereg(struct zl10039_state *state,
const enum zl10039_reg_addr reg,
const u8 val)
{
--
2.9.0

2017-06-14 21:21:10

by Arnd Bergmann

[permalink] [raw]
Subject: [PATCH v2 07/11] r820t: mark register functions as noinline_if_stackbloat

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 <[email protected]>
---
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..a26d0eb64555 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_if_stackbloat 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_if_stackbloat int r820t_write_reg_mask(struct r820t_priv *priv, u8 reg, u8 val,
u8 bit_mask)
{
int rc = r820t_read_cache_reg(priv, reg);
--
2.9.0

2017-06-14 21:21:22

by Arnd Bergmann

[permalink] [raw]
Subject: [PATCH v2 08/11] brcmsmac: make some local variables 'static const' to reduce stack size

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 <[email protected]>
Signed-off-by: Arnd Bergmann <[email protected]>
---
.../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 b3aab2fe96eb..ef685465f80a 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
};
--
2.9.0

2017-06-14 21:21:53

by Arnd Bergmann

[permalink] [raw]
Subject: [PATCH v2 09/11] brcmsmac: split up wlc_phy_workarounds_nphy

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.

Acked-by: Arend van Spriel <[email protected]>
Signed-off-by: Arnd Bergmann <[email protected]>
---
.../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 ef685465f80a..ed409a80f3d2 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);
--
2.9.0

2017-06-14 21:22:04

by Arnd Bergmann

[permalink] [raw]
Subject: [PATCH v2 10/11] brcmsmac: reindent split functions

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 <[email protected]>
Acked-by: Arend van Spriel <[email protected]>
---
.../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 ed409a80f3d2..763e8ba6b178 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, &regval);
- wlc_phy_table_write_nphy(pi, 8, 1, 0x10, 16, &regval);
+ regval = 0x000a;
+ wlc_phy_table_write_nphy(pi, 8, 1, 0, 16, &regval);
+ wlc_phy_table_write_nphy(pi, 8, 1, 0x10, 16, &regval);

- if (NREV_LT(pi->pubpi.phy_rev, 3)) {
- regval = 0xcdaa;
- wlc_phy_table_write_nphy(pi, 8, 1, 0x02, 16, &regval);
- wlc_phy_table_write_nphy(pi, 8, 1, 0x12, 16, &regval);
- }
+ if (NREV_LT(pi->pubpi.phy_rev, 3)) {
+ regval = 0xcdaa;
+ wlc_phy_table_write_nphy(pi, 8, 1, 0x02, 16, &regval);
+ wlc_phy_table_write_nphy(pi, 8, 1, 0x12, 16, &regval);
+ }

- if (NREV_LT(pi->pubpi.phy_rev, 2)) {
- regval = 0x0000;
- wlc_phy_table_write_nphy(pi, 8, 1, 0x08, 16, &regval);
- wlc_phy_table_write_nphy(pi, 8, 1, 0x18, 16, &regval);
+ if (NREV_LT(pi->pubpi.phy_rev, 2)) {
+ regval = 0x0000;
+ wlc_phy_table_write_nphy(pi, 8, 1, 0x08, 16, &regval);
+ wlc_phy_table_write_nphy(pi, 8, 1, 0x18, 16, &regval);

- regval = 0x7aab;
- wlc_phy_table_write_nphy(pi, 8, 1, 0x07, 16, &regval);
- wlc_phy_table_write_nphy(pi, 8, 1, 0x17, 16, &regval);
+ regval = 0x7aab;
+ wlc_phy_table_write_nphy(pi, 8, 1, 0x07, 16, &regval);
+ wlc_phy_table_write_nphy(pi, 8, 1, 0x17, 16, &regval);

- regval = 0x0800;
- wlc_phy_table_write_nphy(pi, 8, 1, 0x06, 16, &regval);
- wlc_phy_table_write_nphy(pi, 8, 1, 0x16, 16, &regval);
- }
+ regval = 0x0800;
+ wlc_phy_table_write_nphy(pi, 8, 1, 0x06, 16, &regval);
+ wlc_phy_table_write_nphy(pi, 8, 1, 0x16, 16, &regval);
+ }

- 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)
--
2.9.0

2017-06-14 21:23:05

by Arnd Bergmann

[permalink] [raw]
Subject: [PATCH v2 11/11] kasan: rework Kconfig settings

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 gcc-7.0.1.

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 2048 bytes with CONFIG_KASAN=y
and CONFIG_KASAN_EXTRA=n have been submitted along with this patch,
so we can bring back that default now. KASAN_EXTRA=y still causes lots
of warnings but now defaults to !COMPILE_TEST to disable it in
allmodconfig, and it remains disabled in all other defconfigs since
it is a new option.

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. I also have patches for all KASAN_EXTRA warnings, but we
should look at those separately and then decide whether to remove
it completely, leaving out -fsanitize-address-use-after-scope.

Signed-off-by: Arnd Bergmann <[email protected]>
---
lib/Kconfig.debug | 4 ++--
lib/Kconfig.kasan | 11 ++++++++++-
lib/Kconfig.kmemcheck | 1 +
scripts/Makefile.kasan | 3 +++
4 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index ddbef2cac189..02ec4a4da7b1 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -217,7 +217,7 @@ 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 3072 if KASAN_EXTRA
default 2048 if GCC_PLUGIN_LATENT_ENTROPY
default 1024 if !64BIT
default 2048 if 64BIT
@@ -500,7 +500,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
diff --git a/lib/Kconfig.kasan b/lib/Kconfig.kasan
index bd38aab05929..4d17a8f4742f 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 && !COMPILE_TEST
+ help
+ This enables further checks in the kernel address sanitizer, for now
+ it only includes the address-use-after-scope check that can lead
+ to excessive kernel stack usage, frame size warnings and longer
+ compile time.
+
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
--
2.9.0

2017-06-14 21:28:39

by Samuel Thibault

[permalink] [raw]
Subject: Re: [PATCH v2 03/11] tty: kbd: reduce stack size with KASAN

Hello,

Arnd Bergmann, on mer. 14 juin 2017 23:15:38 +0200, wrote:
> 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_if_stackbloat prevents the inlining
> and reduces the overall stack usage in this driver.


> --- a/drivers/tty/vt/keyboard.c
> +++ b/drivers/tty/vt/keyboard.c
> @@ -301,13 +301,13 @@ int kbd_rate(struct kbd_repeat *rpt)
> /*
> * Helper Functions.
> */
> -static void put_queue(struct vc_data *vc, int ch)
> +static noinline_if_stackbloat void put_queue(struct vc_data *vc, int ch)
> {
> tty_insert_flip_char(&vc->port, ch, 0);
> tty_schedule_flip(&vc->port);
> }

I'm surprised that this be able generate so much stack use: the
tty_insert_flip_char inline only uses a pointer and an int.

And I'm surprised that multiple inlines can accumulate stack usage.

I however agree that it's a bad idea to inline it in functions where
it's called so many times (and we're talking about the keyboard anyway).

> -static void puts_queue(struct vc_data *vc, char *cp)
> +static noinline_if_stackbloat void puts_queue(struct vc_data *vc, char *cp)

I don't see why, it's only called once in the callers. k_fn, however, is
called several times in k_pad, so that could be why, but then it's
rather be the inlining of k_fn which is a bad idea.

> -static void fn_send_intr(struct vc_data *vc)
> +static noinline_if_stackbloat void fn_send_intr(struct vc_data *vc)

This one is only referenced, not called, I don't see how that could pose
problem.

Samuel

2017-06-14 21:56:42

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH v2 03/11] tty: kbd: reduce stack size with KASAN

On Wed, Jun 14, 2017 at 11:28 PM, Samuel Thibault
<[email protected]> wrote:
> Hello,
>
> Arnd Bergmann, on mer. 14 juin 2017 23:15:38 +0200, wrote:
>> 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_if_stackbloat prevents the inlining
>> and reduces the overall stack usage in this driver.
>
>
>> --- a/drivers/tty/vt/keyboard.c
>> +++ b/drivers/tty/vt/keyboard.c
>> @@ -301,13 +301,13 @@ int kbd_rate(struct kbd_repeat *rpt)
>> /*
>> * Helper Functions.
>> */
>> -static void put_queue(struct vc_data *vc, int ch)
>> +static noinline_if_stackbloat void put_queue(struct vc_data *vc, int ch)
>> {
>> tty_insert_flip_char(&vc->port, ch, 0);
>> tty_schedule_flip(&vc->port);
>> }
>
> I'm surprised that this be able generate so much stack use: the
> tty_insert_flip_char inline only uses a pointer and an int.
>
> And I'm surprised that multiple inlines can accumulate stack usage.

The reason is that CONFIG_KASAN forces each local variable
to have a separate location on the stack whenever it gets
passed into an external function (tty_insert_flip_string_flags in this
case), so the sanitizer is able to report exactly which instance
caused the problem.

> I however agree that it's a bad idea to inline it in functions where
> it's called so many times (and we're talking about the keyboard anyway).
>
>> -static void puts_queue(struct vc_data *vc, char *cp)
>> +static noinline_if_stackbloat void puts_queue(struct vc_data *vc, char *cp)
>
> I don't see why, it's only called once in the callers. k_fn, however, is
> called several times in k_pad, so that could be why, but then it's
> rather be the inlining of k_fn which is a bad idea.

It's called by applkey, which in turn is called by k_pad(), and this
all gets inlined by default.

>> -static void fn_send_intr(struct vc_data *vc)
>> +static noinline_if_stackbloat void fn_send_intr(struct vc_data *vc)
>
> This one is only referenced, not called, I don't see how that could pose
> problem.

I was surprised by this as well, but it seems that gcc these days is
smart enough to turn the indirect function calls for k_handler[type]
and/or f_handler[value] into inlines again when it has already
determined the index to be constant.

It's been a while since I looked at the patch, and I'd have to
disassemble it again to figure out the details, but I'm pretty sure
I needed this to get the stack usage down to normal levels.

Arnd

2017-06-14 22:16:50

by Samuel Thibault

[permalink] [raw]
Subject: Re: [PATCH v2 03/11] tty: kbd: reduce stack size with KASAN

Arnd Bergmann, on mer. 14 juin 2017 23:56:39 +0200, wrote:
> > I however agree that it's a bad idea to inline it in functions where
> > it's called so many times (and we're talking about the keyboard anyway).
> >
> >> -static void puts_queue(struct vc_data *vc, char *cp)
> >> +static noinline_if_stackbloat void puts_queue(struct vc_data *vc, char *cp)
> >
> > I don't see why, it's only called once in the callers. k_fn, however, is
> > called several times in k_pad, so that could be why, but then it's
> > rather be the inlining of k_fn which is a bad idea.
>
> It's called by applkey, which in turn is called by k_pad(),

k_pad calls applkey twice only. Is that really to be considered bloat?

> >> -static void fn_send_intr(struct vc_data *vc)
> >> +static noinline_if_stackbloat void fn_send_intr(struct vc_data *vc)
> >
> > This one is only referenced, not called, I don't see how that could pose
> > problem.
>
> I was surprised by this as well, but it seems that gcc these days is
> smart enough to turn the indirect function calls for k_handler[type]
> and/or f_handler[value] into inlines again when it has already
> determined the index to be constant.

Cool :) But I don't see how it can see find it out constant. The only
fn_handler[] caller is k_spec, using value as index. The only caller of
f_handler[] is kbd_keycode, using type as index, and keysym&0xff as
value. That is definitely not constant :) And it's only one caller, I
don't see how that can bloat.

Samuel

2017-06-15 04:52:32

by Greg Kroah-Hartman

[permalink] [raw]
Subject: Re: [PATCH v2 03/11] tty: kbd: reduce stack size with KASAN

On Wed, Jun 14, 2017 at 11:15:38PM +0200, Arnd Bergmann wrote:
> 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_if_stackbloat prevents the inlining
> and reduces the overall stack usage in this driver.
>
> Signed-off-by: Arnd Bergmann <[email protected]>
> ---
> 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 f4166263bb3a..c0d111444a0e 100644
> --- a/drivers/tty/vt/keyboard.c
> +++ b/drivers/tty/vt/keyboard.c
> @@ -301,13 +301,13 @@ int kbd_rate(struct kbd_repeat *rpt)
> /*
> * Helper Functions.
> */
> -static void put_queue(struct vc_data *vc, int ch)
> +static noinline_if_stackbloat void put_queue(struct vc_data *vc, int ch)
> {
> tty_insert_flip_char(&vc->port, ch, 0);
> tty_schedule_flip(&vc->port);
> }

Ugh, really? We have to start telling gcc not to be stupid here?
That's not going to be easy, and will just entail us doing this all over
the place, right?

The code isn't asking to be inlined, so why is gcc allowing it to be
done that way? Doesn't that imply gcc is the problem here?

thanks,

greg k-h

2017-06-15 04:53:58

by Greg Kroah-Hartman

[permalink] [raw]
Subject: Re: [PATCH v2 03/11] tty: kbd: reduce stack size with KASAN

On Thu, Jun 15, 2017 at 06:52:21AM +0200, Greg Kroah-Hartman wrote:
> On Wed, Jun 14, 2017 at 11:15:38PM +0200, Arnd Bergmann wrote:
> > 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_if_stackbloat prevents the inlining
> > and reduces the overall stack usage in this driver.
> >
> > Signed-off-by: Arnd Bergmann <[email protected]>
> > ---
> > 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 f4166263bb3a..c0d111444a0e 100644
> > --- a/drivers/tty/vt/keyboard.c
> > +++ b/drivers/tty/vt/keyboard.c
> > @@ -301,13 +301,13 @@ int kbd_rate(struct kbd_repeat *rpt)
> > /*
> > * Helper Functions.
> > */
> > -static void put_queue(struct vc_data *vc, int ch)
> > +static noinline_if_stackbloat void put_queue(struct vc_data *vc, int ch)
> > {
> > tty_insert_flip_char(&vc->port, ch, 0);
> > tty_schedule_flip(&vc->port);
> > }
>
> Ugh, really? We have to start telling gcc not to be stupid here?
> That's not going to be easy, and will just entail us doing this all over
> the place, right?
>
> The code isn't asking to be inlined, so why is gcc allowing it to be
> done that way? Doesn't that imply gcc is the problem here?

Wait, you are now, in this patch, _asking_ for it to be inlined. How is
that solving anything?

greg k-h

2017-06-15 07:02:30

by Dmitry Vyukov

[permalink] [raw]
Subject: Re: [PATCH v2 11/11] kasan: rework Kconfig settings

On Wed, Jun 14, 2017 at 11:15 PM, Arnd Bergmann <[email protected]> wrote:
> 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 gcc-7.0.1.
>
> 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 2048 bytes with CONFIG_KASAN=y
> and CONFIG_KASAN_EXTRA=n have been submitted along with this patch,
> so we can bring back that default now. KASAN_EXTRA=y still causes lots
> of warnings but now defaults to !COMPILE_TEST to disable it in
> allmodconfig, and it remains disabled in all other defconfigs since
> it is a new option.
>
> 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. I also have patches for all KASAN_EXTRA warnings, but we
> should look at those separately and then decide whether to remove
> it completely, leaving out -fsanitize-address-use-after-scope.
>
> Signed-off-by: Arnd Bergmann <[email protected]>
> ---
> lib/Kconfig.debug | 4 ++--
> lib/Kconfig.kasan | 11 ++++++++++-
> lib/Kconfig.kmemcheck | 1 +
> scripts/Makefile.kasan | 3 +++
> 4 files changed, 16 insertions(+), 3 deletions(-)
>
> diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
> index ddbef2cac189..02ec4a4da7b1 100644
> --- a/lib/Kconfig.debug
> +++ b/lib/Kconfig.debug
> @@ -217,7 +217,7 @@ 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 3072 if KASAN_EXTRA
> default 2048 if GCC_PLUGIN_LATENT_ENTROPY
> default 1024 if !64BIT
> default 2048 if 64BIT
> @@ -500,7 +500,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
> diff --git a/lib/Kconfig.kasan b/lib/Kconfig.kasan
> index bd38aab05929..4d17a8f4742f 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 && !COMPILE_TEST
> + help
> + This enables further checks in the kernel address sanitizer, for now
> + it only includes the address-use-after-scope check that can lead
> + to excessive kernel stack usage, frame size warnings and longer
> + compile time.
> +
> 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


KASAN is not meant to work with KMEMCHECK. I am not sure if it even
works, and it's definitely unmaintained. Even if it works now, I am
not sure what could be the intention of somebody running that
combination.
So I think we should do: depends on !KASAN
Will it make things simper for you?


> 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
> --
> 2.9.0

2017-06-15 14:56:36

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH v2 08/11] brcmsmac: make some local variables 'static const' to reduce stack size

Arnd Bergmann <[email protected]> writes:

> 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 <[email protected]>
> Signed-off-by: Arnd Bergmann <[email protected]>

I found the cover letter from lkml and apparently the plan is that
Andrew will pick these three brcmsmac patches, so I'll drop them in
wireless patchwork.

--
Kalle Valo

2017-06-16 11:42:08

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH v2 11/11] kasan: rework Kconfig settings

On Thu, Jun 15, 2017 at 9:02 AM, Dmitry Vyukov <[email protected]> wrote:
> On Wed, Jun 14, 2017 at 11:15 PM, Arnd Bergmann <[email protected]> wrote:

>> 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
>
>
> KASAN is not meant to work with KMEMCHECK. I am not sure if it even
> works, and it's definitely unmaintained. Even if it works now, I am
> not sure what could be the intention of somebody running that
> combination.
> So I think we should do: depends on !KASAN
> Will it make things simper for you?

I don't think it will change anything for me, other than having to respin the
patch series or adding a patch on top.

I have just checked that KMEMCHECK is already disabled in allmodconfig,
and all but one of the warnings I address in the series show up in
allmodconfig too.

Arnd

2017-06-16 11:45:14

by Dmitry Vyukov

[permalink] [raw]
Subject: Re: [PATCH v2 11/11] kasan: rework Kconfig settings

On Fri, Jun 16, 2017 at 1:42 PM, Arnd Bergmann <[email protected]> wrote:
>>> 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
>>
>>
>> KASAN is not meant to work with KMEMCHECK. I am not sure if it even
>> works, and it's definitely unmaintained. Even if it works now, I am
>> not sure what could be the intention of somebody running that
>> combination.
>> So I think we should do: depends on !KASAN
>> Will it make things simper for you?
>
> I don't think it will change anything for me, other than having to respin the
> patch series or adding a patch on top.
>
> I have just checked that KMEMCHECK is already disabled in allmodconfig,
> and all but one of the warnings I address in the series show up in
> allmodconfig too.

Ack.

We can disable it if/when KASAN+KMEMCHECK combination requires any
additional work, or causes user confusion.

2017-06-16 12:02:00

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH v2 03/11] tty: kbd: reduce stack size with KASAN

On Thu, Jun 15, 2017 at 6:53 AM, Greg Kroah-Hartman
<[email protected]> wrote:
> On Thu, Jun 15, 2017 at 06:52:21AM +0200, Greg Kroah-Hartman wrote:
>> On Wed, Jun 14, 2017 at 11:15:38PM +0200, Arnd Bergmann wrote:
>> > 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_if_stackbloat prevents the inlining
>> > and reduces the overall stack usage in this driver.
>> >
>> > Signed-off-by: Arnd Bergmann <[email protected]>
>> > ---
>> > 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 f4166263bb3a..c0d111444a0e 100644
>> > --- a/drivers/tty/vt/keyboard.c
>> > +++ b/drivers/tty/vt/keyboard.c
>> > @@ -301,13 +301,13 @@ int kbd_rate(struct kbd_repeat *rpt)
>> > /*
>> > * Helper Functions.
>> > */
>> > -static void put_queue(struct vc_data *vc, int ch)
>> > +static noinline_if_stackbloat void put_queue(struct vc_data *vc, int ch)
>> > {
>> > tty_insert_flip_char(&vc->port, ch, 0);
>> > tty_schedule_flip(&vc->port);
>> > }
>>
>> Ugh, really? We have to start telling gcc not to be stupid here?
>> That's not going to be easy, and will just entail us doing this all over
>> the place, right?
>>
>> The code isn't asking to be inlined, so why is gcc allowing it to be
>> done that way? Doesn't that imply gcc is the problem here?
>
> Wait, you are now, in this patch, _asking_ for it to be inlined. How is
> that solving anything?

The three functions that gain the attribute are all those that gcc decided
to inline for itself. Usually gcc makes reasonable inlining decisions, so
I left the existing behavior my marking them as 'inline' without
CONFIG_KASAN and 'noinline' when KASAN is enabled.

Would you rather see this patch instead?

diff --git a/include/linux/tty_flip.h b/include/linux/tty_flip.h
index c28dd523f96e..25348c5ffcb7 100644
--- a/include/linux/tty_flip.h
+++ b/include/linux/tty_flip.h
@@ -13,8 +13,8 @@ extern int tty_prepare_flip_string(struct tty_port *port,
extern void tty_flip_buffer_push(struct tty_port *port);
void tty_schedule_flip(struct tty_port *port);

-static inline int tty_insert_flip_char(struct tty_port *port,
- unsigned char ch, char flag)
+static noinline_if_stackbloat int
+tty_insert_flip_char(struct tty_port *port, unsigned char ch, char flag)
{
struct tty_buffer *tb = port->buf.tail;
int change;

This is just as good at eliminating the crazy stack usage in vt/keyboard.o,
but it will also impact all other users of that function.

Arnd

2017-06-16 13:02:20

by Greg Kroah-Hartman

[permalink] [raw]
Subject: Re: [PATCH v2 03/11] tty: kbd: reduce stack size with KASAN

On Fri, Jun 16, 2017 at 02:01:57PM +0200, Arnd Bergmann wrote:
> On Thu, Jun 15, 2017 at 6:53 AM, Greg Kroah-Hartman
> <[email protected]> wrote:
> > On Thu, Jun 15, 2017 at 06:52:21AM +0200, Greg Kroah-Hartman wrote:
> >> On Wed, Jun 14, 2017 at 11:15:38PM +0200, Arnd Bergmann wrote:
> >> > 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_if_stackbloat prevents the inlining
> >> > and reduces the overall stack usage in this driver.
> >> >
> >> > Signed-off-by: Arnd Bergmann <[email protected]>
> >> > ---
> >> > 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 f4166263bb3a..c0d111444a0e 100644
> >> > --- a/drivers/tty/vt/keyboard.c
> >> > +++ b/drivers/tty/vt/keyboard.c
> >> > @@ -301,13 +301,13 @@ int kbd_rate(struct kbd_repeat *rpt)
> >> > /*
> >> > * Helper Functions.
> >> > */
> >> > -static void put_queue(struct vc_data *vc, int ch)
> >> > +static noinline_if_stackbloat void put_queue(struct vc_data *vc, int ch)
> >> > {
> >> > tty_insert_flip_char(&vc->port, ch, 0);
> >> > tty_schedule_flip(&vc->port);
> >> > }
> >>
> >> Ugh, really? We have to start telling gcc not to be stupid here?
> >> That's not going to be easy, and will just entail us doing this all over
> >> the place, right?
> >>
> >> The code isn't asking to be inlined, so why is gcc allowing it to be
> >> done that way? Doesn't that imply gcc is the problem here?
> >
> > Wait, you are now, in this patch, _asking_ for it to be inlined. How is
> > that solving anything?
>
> The three functions that gain the attribute are all those that gcc decided
> to inline for itself. Usually gcc makes reasonable inlining decisions, so
> I left the existing behavior my marking them as 'inline' without
> CONFIG_KASAN and 'noinline' when KASAN is enabled.

But why should we have to care about this? If gcc wanted to inline
them, and it did so in a way that blows up the stack, that would be a
gcc bug, right? Why do I have to tell gcc "don't inline", when really,
I never told it to inline it in the first place?

> Would you rather see this patch instead?
>
> diff --git a/include/linux/tty_flip.h b/include/linux/tty_flip.h
> index c28dd523f96e..25348c5ffcb7 100644
> --- a/include/linux/tty_flip.h
> +++ b/include/linux/tty_flip.h
> @@ -13,8 +13,8 @@ extern int tty_prepare_flip_string(struct tty_port *port,
> extern void tty_flip_buffer_push(struct tty_port *port);
> void tty_schedule_flip(struct tty_port *port);
>
> -static inline int tty_insert_flip_char(struct tty_port *port,
> - unsigned char ch, char flag)
> +static noinline_if_stackbloat int
> +tty_insert_flip_char(struct tty_port *port, unsigned char ch, char flag)
> {
> struct tty_buffer *tb = port->buf.tail;
> int change;
>
> This is just as good at eliminating the crazy stack usage in vt/keyboard.o,
> but it will also impact all other users of that function.

How is this function blowing up the stack? We have 2 variables being
added, that's it. Are we really that low on stack that 2 words is too
much?

And no, we shouldn't need to do this. It sounds like ksan is the
problem here...

thanks,

greg k-h

2017-06-16 15:41:56

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH v2 03/11] tty: kbd: reduce stack size with KASAN

On Fri, Jun 16, 2017 at 3:02 PM, Greg Kroah-Hartman
<[email protected]> wrote:
> On Fri, Jun 16, 2017 at 02:01:57PM +0200, Arnd Bergmann wrote:
>> On Thu, Jun 15, 2017 at 6:53 AM, Greg Kroah-Hartman
>> <[email protected]> wrote:
>> > On Thu, Jun 15, 2017 at 06:52:21AM +0200, Greg Kroah-Hartman wrote:
>> >> On Wed, Jun 14, 2017 at 11:15:38PM +0200, Arnd Bergmann wrote:
>> >> > -static void put_queue(struct vc_data *vc, int ch)
>> >> > +static noinline_if_stackbloat void put_queue(struct vc_data *vc, int ch)
>> >> > {
>> >> > tty_insert_flip_char(&vc->port, ch, 0);
>> >> > tty_schedule_flip(&vc->port);
>> >> > }
>> >>
>> >> Ugh, really? We have to start telling gcc not to be stupid here?
>> >> That's not going to be easy, and will just entail us doing this all over
>> >> the place, right?
>> >>
>> >> The code isn't asking to be inlined, so why is gcc allowing it to be
>> >> done that way? Doesn't that imply gcc is the problem here?
>> >
>> > Wait, you are now, in this patch, _asking_ for it to be inlined. How is
>> > that solving anything?
>>
>> The three functions that gain the attribute are all those that gcc decided
>> to inline for itself. Usually gcc makes reasonable inlining decisions, so
>> I left the existing behavior my marking them as 'inline' without
>> CONFIG_KASAN and 'noinline' when KASAN is enabled.
>
> But why should we have to care about this? If gcc wanted to inline
> them, and it did so in a way that blows up the stack, that would be a
> gcc bug, right? Why do I have to tell gcc "don't inline", when really,
> I never told it to inline it in the first place?

I don't think gcc takes stack size into account when making the inlining
decisions. Without the address sanitizer, inlining won't normally have
any negative effects on the overall stack size, and may even help save
a few bytes for the caller-saved registers.

You could argue that the gcc inlining algorithm is buggy in combination
with kasan, but what does that help you? In most instances of this
problem, we actually force the inlining (see the other patches in this
series), so making gcc smarter would not help much either.

>> Would you rather see this patch instead?
>>
>> diff --git a/include/linux/tty_flip.h b/include/linux/tty_flip.h
>> index c28dd523f96e..25348c5ffcb7 100644
>> --- a/include/linux/tty_flip.h
>> +++ b/include/linux/tty_flip.h
>> @@ -13,8 +13,8 @@ extern int tty_prepare_flip_string(struct tty_port *port,
>> extern void tty_flip_buffer_push(struct tty_port *port);
>> void tty_schedule_flip(struct tty_port *port);
>>
>> -static inline int tty_insert_flip_char(struct tty_port *port,
>> - unsigned char ch, char flag)
>> +static noinline_if_stackbloat int
>> +tty_insert_flip_char(struct tty_port *port, unsigned char ch, char flag)
>> {
>> struct tty_buffer *tb = port->buf.tail;
>> int change;
>>
>> This is just as good at eliminating the crazy stack usage in vt/keyboard.o,
>> but it will also impact all other users of that function.
>
> How is this function blowing up the stack? We have 2 variables being
> added, that's it. Are we really that low on stack that 2 words is too
> much?

The 'tb' and 'change' variables don't hurt here, they just get optimized
away. The problem are the 'ch' and 'flag' variables that are passed into
tty_insert_flip_char by value, and from there into
tty_insert_flip_string_flags by reference. In this case, kasan tries
to detect whether tty_insert_flip_string_flags() does any out-of-bounds
access on the pointers and adds 64 bytes redzone around each of
the two variables.

gcc-6.3.1 happens to inline 16 calls of tty_insert_flip_char() into
kbd_keycode(), so the stack size grows from 168 bytes to
168+(16*2*64) = 2216 bytes. There are 10 calls to put_queue()
in to_utf8(), 12 in emulate_raw() and another 4 in kbd_keycode()
itself. On ARM64, it happens to decide differently and presumably
doesn't inline tty_insert_flip_char() and kbd_keycode() into
kbd_keycode(), so the maximum stack size isn't as bad, but
the problem still exists.

> And no, we shouldn't need to do this. It sounds like ksan is the
> problem here...

Of course kasan is the problem, but it really just does whatever we
asked it to do, and cannot do any better as long as we inline many
copies of tty_insert_flip_char() into kbd_keycode().

Arnd

2017-06-16 15:59:12

by Samuel Thibault

[permalink] [raw]
Subject: Re: [PATCH v2 03/11] tty: kbd: reduce stack size with KASAN

Arnd Bergmann, on ven. 16 juin 2017 17:41:47 +0200, wrote:
> The problem are the 'ch' and 'flag' variables that are passed into
> tty_insert_flip_char by value, and from there into
> tty_insert_flip_string_flags by reference. In this case, kasan tries
> to detect whether tty_insert_flip_string_flags() does any out-of-bounds
> access on the pointers and adds 64 bytes redzone around each of
> the two variables.

Ouch.

> gcc-6.3.1 happens to inline 16 calls of tty_insert_flip_char() into
> kbd_keycode(), so the stack size grows from 168 bytes to
> 168+(16*2*64) = 2216 bytes. There are 10 calls to put_queue()
> in to_utf8(), 12 in emulate_raw() and another 4 in kbd_keycode()
> itself.

That's why I agreed for put_queue :)

I'm however afraid we'd have to mark a lot of static functions that way,
depending on the aggressivity of gcc... I'd indeed really argue that gcc
should consider stack usage when inlining.

static int f(int foo) {
char c[256];
g(c, foo);
}

is really not something that I'd want to see the compiler to inline.

> > And no, we shouldn't need to do this. It sounds like ksan is the
> > problem here...
>
> Of course kasan is the problem, but it really just does whatever we
> asked it to do, and cannot do any better as long as we inline many
> copies of tty_insert_flip_char() into kbd_keycode().

We didn't ask to inline put_queue into kbd_keycode.

Samuel

2017-06-16 17:12:33

by Andrey Ryabinin

[permalink] [raw]
Subject: Re: [PATCH v2 03/11] tty: kbd: reduce stack size with KASAN

On 06/16/2017 06:41 PM, Arnd Bergmann wrote:
> On Fri, Jun 16, 2017 at 3:02 PM, Greg Kroah-Hartman
> <[email protected]> wrote:
>> On Fri, Jun 16, 2017 at 02:01:57PM +0200, Arnd Bergmann wrote:
>>> On Thu, Jun 15, 2017 at 6:53 AM, Greg Kroah-Hartman
>>> <[email protected]> wrote:
>>>> On Thu, Jun 15, 2017 at 06:52:21AM +0200, Greg Kroah-Hartman wrote:
>>>>> On Wed, Jun 14, 2017 at 11:15:38PM +0200, Arnd Bergmann wrote:
>>>>>> -static void put_queue(struct vc_data *vc, int ch)
>>>>>> +static noinline_if_stackbloat void put_queue(struct vc_data *vc, int ch)
>>>>>> {
>>>>>> tty_insert_flip_char(&vc->port, ch, 0);
>>>>>> tty_schedule_flip(&vc->port);
>>>>>> }
>>>>>
>>>>> Ugh, really? We have to start telling gcc not to be stupid here?
>>>>> That's not going to be easy, and will just entail us doing this all over
>>>>> the place, right?
>>>>>
>>>>> The code isn't asking to be inlined, so why is gcc allowing it to be
>>>>> done that way? Doesn't that imply gcc is the problem here?
>>>>
>>>> Wait, you are now, in this patch, _asking_ for it to be inlined. How is
>>>> that solving anything?
>>>
>>> The three functions that gain the attribute are all those that gcc decided
>>> to inline for itself. Usually gcc makes reasonable inlining decisions, so
>>> I left the existing behavior my marking them as 'inline' without
>>> CONFIG_KASAN and 'noinline' when KASAN is enabled.
>>
>> But why should we have to care about this? If gcc wanted to inline
>> them, and it did so in a way that blows up the stack, that would be a
>> gcc bug, right? Why do I have to tell gcc "don't inline", when really,
>> I never told it to inline it in the first place?
>
> I don't think gcc takes stack size into account when making the inlining
> decisions. Without the address sanitizer, inlining won't normally have
> any negative effects on the overall stack size, and may even help save
> a few bytes for the caller-saved registers.
>

Well, in fact it should take stack into account. Gcc even has following params:

large-stack-frame
The limit specifying large stack frames. While inlining the algorithm is trying to not grow past this limit too much. The default value is 256 bytes.

large-stack-frame-growth
Specifies maximal growth of large stack frames caused by inlining in percents. The default value is 1000 which limits large stack frame growth to 11 times the original size.

However, I've tried both and even with minimal values gcc continued to make bad decisions.

Note, if you're going to try it, make sure that you have CONFIG_OPTIMIZE_INLINING=y
because otherwise 'inline' becomes 'always_inline'


> You could argue that the gcc inlining algorithm is buggy in combination
> with kasan, but what does that help you? In most instances of this
> problem, we actually force the inlining (see the other patches in this
> series), so making gcc smarter would not help much either.
>
>>> Would you rather see this patch instead?
>>>
>>> diff --git a/include/linux/tty_flip.h b/include/linux/tty_flip.h
>>> index c28dd523f96e..25348c5ffcb7 100644
>>> --- a/include/linux/tty_flip.h
>>> +++ b/include/linux/tty_flip.h
>>> @@ -13,8 +13,8 @@ extern int tty_prepare_flip_string(struct tty_port *port,
>>> extern void tty_flip_buffer_push(struct tty_port *port);
>>> void tty_schedule_flip(struct tty_port *port);
>>>
>>> -static inline int tty_insert_flip_char(struct tty_port *port,
>>> - unsigned char ch, char flag)
>>> +static noinline_if_stackbloat int
>>> +tty_insert_flip_char(struct tty_port *port, unsigned char ch, char flag)
>>> {
>>> struct tty_buffer *tb = port->buf.tail;
>>> int change;
>>>
>>> This is just as good at eliminating the crazy stack usage in vt/keyboard.o,
>>> but it will also impact all other users of that function.
>>
>> How is this function blowing up the stack? We have 2 variables being
>> added, that's it. Are we really that low on stack that 2 words is too
>> much?
>
> The 'tb' and 'change' variables don't hurt here, they just get optimized
> away. The problem are the 'ch' and 'flag' variables that are passed into
> tty_insert_flip_char by value, and from there into
> tty_insert_flip_string_flags by reference. In this case, kasan tries
> to detect whether tty_insert_flip_string_flags() does any out-of-bounds
> access on the pointers and adds 64 bytes redzone around each of
> the two variables.
>
> gcc-6.3.1 happens to inline 16 calls of tty_insert_flip_char() into
> kbd_keycode(), so the stack size grows from 168 bytes to
> 168+(16*2*64) = 2216 bytes. There are 10 calls to put_queue()
> in to_utf8(), 12 in emulate_raw() and another 4 in kbd_keycode()
> itself. On ARM64, it happens to decide differently and presumably
> doesn't inline tty_insert_flip_char() and kbd_keycode() into
> kbd_keycode(), so the maximum stack size isn't as bad, but
> the problem still exists.
>
>> And no, we shouldn't need to do this. It sounds like ksan is the
>> problem here...
>
> Of course kasan is the problem, but it really just does whatever we
> asked it to do, and cannot do any better as long as we inline many
> copies of tty_insert_flip_char() into kbd_keycode().
>
> Arnd
>

2017-06-16 17:29:49

by Dmitry Torokhov

[permalink] [raw]
Subject: Re: [PATCH v2 03/11] tty: kbd: reduce stack size with KASAN

On Fri, Jun 16, 2017 at 8:58 AM, Samuel Thibault
<[email protected]> wrote:
> Arnd Bergmann, on ven. 16 juin 2017 17:41:47 +0200, wrote:
>> The problem are the 'ch' and 'flag' variables that are passed into
>> tty_insert_flip_char by value, and from there into
>> tty_insert_flip_string_flags by reference. In this case, kasan tries
>> to detect whether tty_insert_flip_string_flags() does any out-of-bounds
>> access on the pointers and adds 64 bytes redzone around each of
>> the two variables.
>
> Ouch.
>
>> gcc-6.3.1 happens to inline 16 calls of tty_insert_flip_char() into

I wonder if we should stop marking tty_insert_flip_char() as inline.

>> kbd_keycode(), so the stack size grows from 168 bytes to
>> 168+(16*2*64) = 2216 bytes. There are 10 calls to put_queue()
>> in to_utf8(), 12 in emulate_raw() and another 4 in kbd_keycode()
>> itself.
>
> That's why I agreed for put_queue :)
>
> I'm however afraid we'd have to mark a lot of static functions that way,
> depending on the aggressivity of gcc... I'd indeed really argue that gcc
> should consider stack usage when inlining.
>
> static int f(int foo) {
> char c[256];
> g(c, foo);
> }
>
> is really not something that I'd want to see the compiler to inline.

Why would not we want it be inlined? What we do not want us several
calls having _separate_ instances of 'c' generated on the stack, all
inlined calls should share 'c'. And of course if we have f1, f2, and
f3 with c1, c2, and c3, GCC should not blow up the stack inlining and
allocating stack for all 3 of them beforehand.

But this all seems to me issue that should be solved in toolchain, not
trying to play whack-a-mole with kernel sources.

Thanks.

--
Dmitry

2017-06-16 20:56:56

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH v2 03/11] tty: kbd: reduce stack size with KASAN

On Fri, Jun 16, 2017 at 7:29 PM, Dmitry Torokhov
<[email protected]> wrote:
> On Fri, Jun 16, 2017 at 8:58 AM, Samuel Thibault
> <[email protected]> wrote:
>> Arnd Bergmann, on ven. 16 juin 2017 17:41:47 +0200, wrote:
>>> The problem are the 'ch' and 'flag' variables that are passed into
>>> tty_insert_flip_char by value, and from there into
>>> tty_insert_flip_string_flags by reference. In this case, kasan tries
>>> to detect whether tty_insert_flip_string_flags() does any out-of-bounds
>>> access on the pointers and adds 64 bytes redzone around each of
>>> the two variables.
>>
>> Ouch.
>>
>>> gcc-6.3.1 happens to inline 16 calls of tty_insert_flip_char() into
>
> I wonder if we should stop marking tty_insert_flip_char() as inline.

That would be an easy solution, yes. tty_insert_flip_char() was
apparently meant to be optimized for the fast path to completely
avoid calling into another function, but that fast path got a bit more
complex with commit acc0f67f307f ("tty: Halve flip buffer
GFP_ATOMIC memory consumption").

If we move it out of line, the fast path optimization goes away and
we could just have a simple implementation like


int tty_insert_flip_char(struct tty_port *port, unsigned char ch, char flag)
{
struct tty_buffer *tb = port->buf.tail;
int flags = (flag == TTY_NORMAL) ? TTYB_NORMAL : 0;

if (!__tty_buffer_request_room(port, 1, flags))
return 0;

if (~tb->flags & TTYB_NORMAL)
*flag_buf_ptr(tb, tb->used) = flag;
*char_buf_ptr(tb, tb->used++) = ch;

return 1;
}

One rather simple change I found would actually avoid the warning
and would seem to actually give us better runtime behavior even
without KASAN:

diff --git a/include/linux/tty_flip.h b/include/linux/tty_flip.h
index c28dd523f96e..15d03a14ad0f 100644
--- a/include/linux/tty_flip.h
+++ b/include/linux/tty_flip.h
@@ -26,7 +26,7 @@ static inline int tty_insert_flip_char(struct tty_port *port,
*char_buf_ptr(tb, tb->used++) = ch;
return 1;
}
- return tty_insert_flip_string_flags(port, &ch, &flag, 1);
+ return tty_insert_flip_string_fixed_flag(port, &ch, flag, 1);
}

static inline int tty_insert_flip_string(struct tty_port *port,

This reduces the stack frame size for kbd_event() to 1256 bytes,
which is well within the limit, and it lets us keep the flag-less
buffers across a 'tb->used >= tb->size' condition. Calling
into tty_insert_flip_string_flags() today will allocate a flag buffer
if there isn't already one, even when it is not needed.

>> I'm however afraid we'd have to mark a lot of static functions that way,
>> depending on the aggressivity of gcc... I'd indeed really argue that gcc
>> should consider stack usage when inlining.
>>
>> static int f(int foo) {
>> char c[256];
>> g(c, foo);
>> }
>>
>> is really not something that I'd want to see the compiler to inline.
>
> Why would not we want it be inlined? What we do not want us several
> calls having _separate_ instances of 'c' generated on the stack, all
> inlined calls should share 'c'. And of course if we have f1, f2, and
> f3 with c1, c2, and c3, GCC should not blow up the stack inlining and
> allocating stack for all 3 of them beforehand.
>
> But this all seems to me issue that should be solved in toolchain, not
> trying to play whack-a-mole with kernel sources.

The problem for the Samuel's example is that

a) the "--param asan-stack=1" option in KASAN does blow up the
stack, which is why the annotation is now called 'noinline_if_stackbloat'.

b) The toolchain cannot solve the problem, as most instances of the
problem (unlike kbd_put_queue) force the inlining unless you build
with the x86-specific CONFIG_OPTIMIZE_INLINING.

Arnd

2017-06-16 21:07:51

by Dmitry Torokhov

[permalink] [raw]
Subject: Re: [PATCH v2 03/11] tty: kbd: reduce stack size with KASAN

On Fri, Jun 16, 2017 at 1:56 PM, Arnd Bergmann <[email protected]> wrote:
> On Fri, Jun 16, 2017 at 7:29 PM, Dmitry Torokhov
> <[email protected]> wrote:
>> On Fri, Jun 16, 2017 at 8:58 AM, Samuel Thibault
>> <[email protected]> wrote:
>>> I'm however afraid we'd have to mark a lot of static functions that way,
>>> depending on the aggressivity of gcc... I'd indeed really argue that gcc
>>> should consider stack usage when inlining.
>>>
>>> static int f(int foo) {
>>> char c[256];
>>> g(c, foo);
>>> }
>>>
>>> is really not something that I'd want to see the compiler to inline.
>>
>> Why would not we want it be inlined? What we do not want us several
>> calls having _separate_ instances of 'c' generated on the stack, all
>> inlined calls should share 'c'. And of course if we have f1, f2, and
>> f3 with c1, c2, and c3, GCC should not blow up the stack inlining and
>> allocating stack for all 3 of them beforehand.
>>
>> But this all seems to me issue that should be solved in toolchain, not
>> trying to play whack-a-mole with kernel sources.
>
> The problem for the Samuel's example is that
>
> a) the "--param asan-stack=1" option in KASAN does blow up the
> stack, which is why the annotation is now called 'noinline_if_stackbloat'.
>
> b) The toolchain cannot solve the problem, as most instances of the
> problem (unlike kbd_put_queue) force the inlining unless you build
> with the x86-specific CONFIG_OPTIMIZE_INLINING.

If inlining done right there should be no change in stack size,
because if calls are not inlined then stack storage is "shared"
between calls, and it should similarly be shared when calls are
inlined. And that is toolchain issue.

--
Dmitry

2017-06-24 19:49:45

by Mauro Carvalho Chehab

[permalink] [raw]
Subject: Re: [PATCH v2 06/11] dvb-frontends: reduce stack size in i2c access

Em Wed, 14 Jun 2017 23:15:41 +0200
Arnd Bergmann <[email protected]> escreveu:

> 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_if_stackbloat,
> we can completely avoid this problem.
>
> Signed-off-by: Arnd Bergmann <[email protected]>

Feel free to add my ack to patches 6 and 7 of this series:

Acked-by: Mauro Carvalho Chehab <[email protected]>

> ---
> 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..da1d1fc03c5e 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_if_stackbloat 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 ce37dc2e89c7..6b851a948ce0 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_if_stackbloat 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_if_stackbloat 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 14040c915dbb..ec5b13ca630b 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_if_stackbloat 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_if_stackbloat 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_if_stackbloat 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_if_stackbloat 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_if_stackbloat
> int drxj_dap_atomic_read_reg32(struct i2c_device_addr *dev_addr,
> u32 addr,
> u32 *data, u32 flags)
> @@ -4192,7 +4192,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_if_stackbloat
> int drxj_dap_scu_atomic_read_reg16(struct i2c_device_addr *dev_addr,
> u32 addr,
> u16 *data, u32 flags)
> @@ -4220,7 +4220,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_if_stackbloat
> 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..849a18a837d0 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_if_stackbloat 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_if_stackbloat 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 68d759c4c52e..f879af6c3188 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_if_stackbloat 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..8bd6d04362cc 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_if_stackbloat 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..d7a701da598a 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_if_stackbloat 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..8b1ac134f9d8 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_if_stackbloat 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_if_stackbloat 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_if_stackbloat 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_if_stackbloat 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_if_stackbloat 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_if_stackbloat 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_if_stackbloat 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..9258085b8d35 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_if_stackbloat 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..675dffe1ef20 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_if_stackbloat 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..2316c0bb3e21 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_if_stackbloat 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..8afecc2e3637 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_if_stackbloat 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..ddef3a912615 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_if_stackbloat 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..80c7024971de 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_if_stackbloat 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..646f22aab24e 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_if_stackbloat 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..0075725cb161 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_if_stackbloat int zl10039_writereg(struct zl10039_state *state,
> const enum zl10039_reg_addr reg,
> const u8 val)
> {



Thanks,
Mauro

2017-08-04 07:42:58

by Boris Brezillon

[permalink] [raw]
Subject: Re: [PATCH v2 05/11] mtd: cfi: reduce stack size with KASAN

On Wed, 14 Jun 2017 23:15:40 +0200
Arnd Bergmann <[email protected]> wrote:

> 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 2184 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_if_stackbloat to keep reduce the
> overall stack size.
>
> Signed-off-by: Arnd Bergmann <[email protected]>
> ---
> 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 7d342965f392..5eee5e883f55 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_if_stackbloat int do_read_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf)

Why do we even need to mark those functions inline in the first place?
Isn't the compiler smart enough to decide when it should inline things?

> {
> 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_if_stackbloat 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_if_stackbloat 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_if_stackbloat 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..29db74314db8 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_if_stackbloat int map_word_andequal(struct map_info *map, map_word val1, map_word val2, map_word val3)

It's indeed needed for those defined in a header.

> {
> 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_if_stackbloat 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_if_stackbloat 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_if_stackbloat map_word map_word_ff(struct map_info *map)
> {
> map_word r;
> int i;

2017-08-04 09:09:56

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH v2 05/11] mtd: cfi: reduce stack size with KASAN

On Fri, Aug 4, 2017 at 9:42 AM, Boris Brezillon
<[email protected]> wrote:
> On Wed, 14 Jun 2017 23:15:40 +0200
> Arnd Bergmann <[email protected]> wrote:
>
>> 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 2184 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_if_stackbloat to keep reduce the
>> overall stack size.
>>
>> Signed-off-by: Arnd Bergmann <[email protected]>
>> ---
>> 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 7d342965f392..5eee5e883f55 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_if_stackbloat int do_read_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf)
>
> Why do we even need to mark those functions inline in the first place?
> Isn't the compiler smart enough to decide when it should inline things?

I'm pretty sure it doesn't need the 'inline' keywork. I see that the code was
addedlike this in linux-2.4.0-test3pre3 along with the rest of the mtd layer,
so it has always been 'inline' and nobody ever bothered to remove that
during later cleanups.

We could probably just mark this function as 'noinline' here and never
inline it,
but I would rather not add more than one variant of noinline_if_stackbloat:
almost all other users of noinline_if_stackbloat are for functions that have
to be inline in normal builds, so it is defined as being either
'inline' or 'noinline'
depending on whether KASAN is active.

>> diff --git a/include/linux/mtd/map.h b/include/linux/mtd/map.h
>> index 3aa56e3104bb..29db74314db8 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_if_stackbloat int map_word_andequal(struct map_info *map, map_word val1, map_word val2, map_word val3)
>
> It's indeed needed for those defined in a header.

Right.

Arnd

2017-08-04 10:57:08

by Boris Brezillon

[permalink] [raw]
Subject: Re: [PATCH v2 05/11] mtd: cfi: reduce stack size with KASAN

On Fri, 4 Aug 2017 11:09:53 +0200
Arnd Bergmann <[email protected]> wrote:

> On Fri, Aug 4, 2017 at 9:42 AM, Boris Brezillon
> <[email protected]> wrote:
> > On Wed, 14 Jun 2017 23:15:40 +0200
> > Arnd Bergmann <[email protected]> wrote:
> >
> >> 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 2184 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_if_stackbloat to keep reduce the
> >> overall stack size.
> >>
> >> Signed-off-by: Arnd Bergmann <[email protected]>
> >> ---
> >> 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 7d342965f392..5eee5e883f55 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_if_stackbloat int do_read_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf)
> >
> > Why do we even need to mark those functions inline in the first place?
> > Isn't the compiler smart enough to decide when it should inline things?
>
> I'm pretty sure it doesn't need the 'inline' keywork. I see that the code was
> addedlike this in linux-2.4.0-test3pre3 along with the rest of the mtd layer,
> so it has always been 'inline' and nobody ever bothered to remove that
> during later cleanups.
>
> We could probably just mark this function as 'noinline' here and never
> inline it,
> but I would rather not add more than one variant of noinline_if_stackbloat:
> almost all other users of noinline_if_stackbloat are for functions that have
> to be inline in normal builds, so it is defined as being either
> 'inline' or 'noinline'
> depending on whether KASAN is active.

Okay. Let's keep it like that then.

2017-08-04 10:57:43

by Boris Brezillon

[permalink] [raw]
Subject: Re: [PATCH v2 05/11] mtd: cfi: reduce stack size with KASAN

On Wed, 14 Jun 2017 23:15:40 +0200
Arnd Bergmann <[email protected]> wrote:

> 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 2184 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_if_stackbloat to keep reduce the
> overall stack size.
>
> Signed-off-by: Arnd Bergmann <[email protected]>

Acked-by: Boris Brezillon <[email protected]>

> ---
> 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 7d342965f392..5eee5e883f55 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_if_stackbloat 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_if_stackbloat 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_if_stackbloat 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_if_stackbloat 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..29db74314db8 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_if_stackbloat 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_if_stackbloat 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_if_stackbloat 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_if_stackbloat map_word map_word_ff(struct map_info *map)
> {
> map_word r;
> int i;