Linux wireless drivers development
 help / color / mirror / Atom feed
* Re: [PATCH] mac80211: aead api to reduce redundancy
From: Herbert Xu @ 2017-09-25  6:14 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Xiang Gao, David S. Miller, linux-crypto, linux-kernel,
	linux-wireless, netdev
In-Reply-To: <1506316946.2909.8.camel@sipsolutions.net>

On Mon, Sep 25, 2017 at 07:22:26AM +0200, Johannes Berg wrote:
> 
> The code moves to crypto/ though, and I'm not even sure I can vouch for
> the Makefile choice there.

Thanks, I missed that.  I don't think this belongs in crypto.
This proposed helper is only useful for wireless so it should
stay there.

Cheers,
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply

* Re: [PATCH] mac80211: aead api to reduce redundancy
From: Johannes Berg @ 2017-09-25  5:22 UTC (permalink / raw)
  To: Herbert Xu
  Cc: Xiang Gao, David S. Miller, linux-crypto, linux-kernel,
	linux-wireless, netdev
In-Reply-To: <20170925045641.GB22947@gondor.apana.org.au>

On Mon, 2017-09-25 at 12:56 +0800, Herbert Xu wrote:
> On Sun, Sep 24, 2017 at 07:42:46PM +0200, Johannes Berg wrote:
> > 
> > Unrelated to this, I'm not sure whose tree this should go through -
> > probably Herbert's (or DaveM's with his ACK? not sure if there's a
> > crypto tree?) or so?
> 
> Since you're just rearranging code invoking the crypto API, rather
> than touching actual crypto API code, I think you should handle it
> as you do with any other wireless patch.

The code moves to crypto/ though, and I'm not even sure I can vouch for
the Makefile choice there.

johannes

^ permalink raw reply

* Re: [PATCH] mac80211: aead api to reduce redundancy
From: Herbert Xu @ 2017-09-25  4:56 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Xiang Gao, David S. Miller, linux-crypto, linux-kernel,
	linux-wireless, netdev
In-Reply-To: <1506274966.2909.7.camel@sipsolutions.net>

On Sun, Sep 24, 2017 at 07:42:46PM +0200, Johannes Berg wrote:
>
> Unrelated to this, I'm not sure whose tree this should go through -
> probably Herbert's (or DaveM's with his ACK? not sure if there's a
> crypto tree?) or so?

Since you're just rearranging code invoking the crypto API, rather
than touching actual crypto API code, I think you should handle it
as you do with any other wireless patch.

Thanks,
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply

* Re: [PATCH v4 1/9] brcmsmac: make some local variables 'static const' to reduce stack size
From: Kalle Valo @ 2017-09-25  4:33 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Arend van Spriel, Franky Lin, Hante Meuleman, Chi-Hsien Lin,
	Wright Feng, Mauro Carvalho Chehab, Jiri Pirko, David S. Miller,
	Andrey Ryabinin, Alexander Potapenko, Dmitry Vyukov,
	Masahiro Yamada, Michal Marek, Andrew Morton, Kees Cook,
	Geert Uytterhoeven, Greg Kroah-Hartman, linux-media, linux-kernel,
	netdev, linux-wireless, brcm80211-dev-list.pdl,
	brcm80211-dev-list, kasan-dev, linux-kbuild, Jakub Jelinek,
	Martin Liška
In-Reply-To: <20170922212930.620249-2-arnd@arndb.de>

Arnd Bergmann <arnd@arndb.de> 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.
>
> This is the first of three patches to improve the stack usage in this
> driver. It would be good to have this backported to stabl kernels
> to get all drivers in 'allmodconfig' below the 2048 byte limit so
> we can turn on the frame warning again globally, but I realize that
> the patch is larger than the normal limit for stable backports.
>
> The other two patches do not need to be backported.
>
> Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>

I'll queue this and the two following brcmsmac patches for 4.14.

Also I'll add (only for this patch):

Cc: <stable@vger.kernel.org>

-- 
Kalle Valo

^ permalink raw reply

* Re: usb/wireless/rsi_91x: use-after-free write in __run_timers
From: Kalle Valo @ 2017-09-25  4:26 UTC (permalink / raw)
  To: Andrey Konovalov
  Cc: Amitkumar Karwar, Prameela Rani Garnepudi, Karun Eagalapati,
	linux-wireless, netdev, LKML, Dmitry Vyukov, Kostya Serebryany,
	syzkaller
In-Reply-To: <CAAeHK+wXCaLZ8=enfsmjg-+FJsW1UhSCz8GUmSWhFxB4orLQ6w@mail.gmail.com>

Andrey Konovalov <andreyknvl@google.com> writes:

> I've got the following report while fuzzing the kernel with syzkaller.
>
> On commit 6e80ecdddf4ea6f3cd84e83720f3d852e6624a68 (Sep 21).
>
> ==================================================================
> BUG: KASAN: use-after-free in __run_timers+0xc0e/0xd40
> Write of size 8 at addr ffff880069f701b8 by task swapper/0/0
>
> CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.14.0-rc1-42311-g6e80ecdddf4e #234
> Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011

[...]

> Allocated by task 1845:
>  save_stack_trace+0x1b/0x20 arch/x86/kernel/stacktrace.c:59
>  save_stack+0x43/0xd0 mm/kasan/kasan.c:447
>  set_track mm/kasan/kasan.c:459
>  kasan_kmalloc+0xad/0xe0 mm/kasan/kasan.c:551
>  kmem_cache_alloc_trace+0x11e/0x2d0 mm/slub.c:2772
>  kmalloc ./include/linux/slab.h:493
>  kzalloc ./include/linux/slab.h:666
>  rsi_91x_init+0x98/0x510 drivers/net/wireless/rsi/rsi_91x_main.c:203
>  rsi_probe+0xb6/0x13b0 drivers/net/wireless/rsi/rsi_91x_usb.c:665
>  usb_probe_interface+0x35d/0x8e0 drivers/usb/core/driver.c:361

I'm curious about your setup. Apparently you are running syzkaller on
QEMU but what I don't understand is how the rsi device comes into the
picture. Did you have a rsi usb device connected to the virtual machine
or what? Or does syzkaller do some kind of magic here?

-- 
Kalle Valo

^ permalink raw reply

* Re: [PATCH] brcm80211: make const array ucode_ofdm_rates static, reduces object code size
From: Kalle Valo @ 2017-09-25  4:20 UTC (permalink / raw)
  To: Arend van Spriel
  Cc: Colin King, Franky Lin, Hante Meuleman, Chi-Hsien Lin,
	Wright Feng, linux-wireless, brcm80211-dev-list.pdl,
	brcm80211-dev-list, netdev, kernel-janitors, linux-kernel
In-Reply-To: <96caf646-a43c-9b78-a4a9-2becf7e74125@broadcom.com>

Arend van Spriel <arend.vanspriel@broadcom.com> writes:

> Please use 'brcmsmac:' as prefix instead of 'brcm80211:'.

I can fix that.

-- 
Kalle Valo

^ permalink raw reply

* [PATCH] PCI MSI: allow alignment restrictions on vector allocation
From: Daniel Drake @ 2017-09-25  4:11 UTC (permalink / raw)
  To: tglx, mingo, hpa; +Cc: linux-pci, x86, linux-wireless, ath9k-devel, linux

ath9k hardware claims to support up to 4 MSI vectors, and when run in
that configuration, it would be allowed to modify the lower bits of the
MSI Message Data when generating interrupts in order to signal which
of the 4 vectors the interrupt is being raised on.

Linux's PCI-MSI irqchip only supports a single MSI vector for each
device, and it tells the device this, but the device appears to assume
it is working with 4, as it will unset the lower 2 bits of Message Data
presumably to indicate that it is an IRQ for the first of 4 possible
vectors.

Linux will then receive an interrupt on the wrong vector, so the
ath9k interrupt handler will not be invoked.

To work around this, introduce a mechanism where the vector assignment
algorithm can be restricted to only a subset of available vector numbers
based on a bitmap.

As a user of this bitmap, introduce a pci_dev.align_msi_vector flag which
can be used to state that MSI vector numbers must be aligned to a specific
amount. If we 4-align the ath9k MSI vector then the lower bits will
already be 0 and hence the device will not modify the Message Data away
from its original value.

This is needed in order to support the wifi card in at least 8 new Acer
consumer laptop models which come with the Foxconn NFA335 WiFi module.
Legacy interrupts do not work on that module, so MSI support is required.

Signed-off-by: Daniel Drake <drake@endlessm.com>

https://phabricator.endlessm.com/T16988
---
 arch/x86/include/asm/hw_irq.h |  1 +
 arch/x86/kernel/apic/msi.c    | 15 +++++++++++++++
 arch/x86/kernel/apic/vector.c | 32 +++++++++++++++++++++++++-------
 include/linux/pci.h           |  2 ++
 4 files changed, 43 insertions(+), 7 deletions(-)

This solves the issue described here:
https://marc.info/?l=linux-pci&m=150238260826803&w=2

If this approach looks good I'll follow up with the ath9k patch
to enable MSI interrupts.

diff --git a/arch/x86/include/asm/hw_irq.h b/arch/x86/include/asm/hw_irq.h
index 6dfe366a8804..7f35178586a1 100644
--- a/arch/x86/include/asm/hw_irq.h
+++ b/arch/x86/include/asm/hw_irq.h
@@ -77,6 +77,7 @@ struct irq_alloc_info {
 		struct {
 			struct pci_dev	*msi_dev;
 			irq_hw_number_t	msi_hwirq;
+			DECLARE_BITMAP(allowed_vectors, NR_VECTORS);
 		};
 #endif
 #ifdef	CONFIG_X86_IO_APIC
diff --git a/arch/x86/kernel/apic/msi.c b/arch/x86/kernel/apic/msi.c
index 9b18be764422..80067873cfd5 100644
--- a/arch/x86/kernel/apic/msi.c
+++ b/arch/x86/kernel/apic/msi.c
@@ -111,6 +111,21 @@ int pci_msi_prepare(struct irq_domain *domain, struct device *dev, int nvec,
 		arg->flags |= X86_IRQ_ALLOC_CONTIGUOUS_VECTORS;
 	}
 
+	if (pdev->align_msi_vector) {
+		/* We have specific alignment requirements on the vector
+		 * number used by the device. Set up a bitmap that restricts
+		 * the vector selection accordingly.
+		 */
+		int i = pdev->align_msi_vector;
+
+		set_bit(0, arg->allowed_vectors);
+		for (; i < NR_VECTORS; i += pdev->align_msi_vector)
+			set_bit(i, arg->allowed_vectors);
+	} else {
+		/* No specific alignment requirements so allow all vectors. */
+		bitmap_fill(arg->allowed_vectors, NR_VECTORS);
+	}
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(pci_msi_prepare);
diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c
index 88c214e75a6b..64ddac198c25 100644
--- a/arch/x86/kernel/apic/vector.c
+++ b/arch/x86/kernel/apic/vector.c
@@ -104,7 +104,8 @@ static void free_apic_chip_data(struct apic_chip_data *data)
 
 static int __assign_irq_vector(int irq, struct apic_chip_data *d,
 			       const struct cpumask *mask,
-			       struct irq_data *irqdata)
+			       struct irq_data *irqdata,
+			       unsigned long *allowed_vectors)
 {
 	/*
 	 * NOTE! The local APIC isn't very good at handling
@@ -178,6 +179,9 @@ static int __assign_irq_vector(int irq, struct apic_chip_data *d,
 		if (test_bit(vector, used_vectors))
 			goto next;
 
+		if (allowed_vectors && !test_bit(vector, allowed_vectors))
+			goto next;
+
 		for_each_cpu(new_cpu, vector_searchmask) {
 			if (!IS_ERR_OR_NULL(per_cpu(vector_irq, new_cpu)[vector]))
 				goto next;
@@ -234,13 +238,14 @@ static int __assign_irq_vector(int irq, struct apic_chip_data *d,
 
 static int assign_irq_vector(int irq, struct apic_chip_data *data,
 			     const struct cpumask *mask,
-			     struct irq_data *irqdata)
+			     struct irq_data *irqdata,
+			     unsigned long *allowed_vectors)
 {
 	int err;
 	unsigned long flags;
 
 	raw_spin_lock_irqsave(&vector_lock, flags);
-	err = __assign_irq_vector(irq, data, mask, irqdata);
+	err = __assign_irq_vector(irq, data, mask, irqdata, allowed_vectors);
 	raw_spin_unlock_irqrestore(&vector_lock, flags);
 	return err;
 }
@@ -250,12 +255,25 @@ static int assign_irq_vector_policy(int irq, int node,
 				    struct irq_alloc_info *info,
 				    struct irq_data *irqdata)
 {
+	unsigned long *allowed_vectors = NULL;
+
+	/* Some MSI interrupts have restrictions on which vector numbers
+	 * can be used.
+	 */
+	if (info &&
+		(info->type == X86_IRQ_ALLOC_TYPE_MSI ||
+		 info->type == X86_IRQ_ALLOC_TYPE_MSIX))
+		allowed_vectors = info->allowed_vectors;
+
 	if (info && info->mask)
-		return assign_irq_vector(irq, data, info->mask, irqdata);
+		return assign_irq_vector(irq, data, info->mask, irqdata,
+					 allowed_vectors);
 	if (node != NUMA_NO_NODE &&
-	    assign_irq_vector(irq, data, cpumask_of_node(node), irqdata) == 0)
+	    assign_irq_vector(irq, data, cpumask_of_node(node), irqdata,
+			      allowed_vectors) == 0)
 		return 0;
-	return assign_irq_vector(irq, data, apic->target_cpus(), irqdata);
+	return assign_irq_vector(irq, data, apic->target_cpus(), irqdata,
+				 allowed_vectors);
 }
 
 static void clear_irq_vector(int irq, struct apic_chip_data *data)
@@ -549,7 +567,7 @@ static int apic_set_affinity(struct irq_data *irq_data,
 	if (!cpumask_intersects(dest, cpu_online_mask))
 		return -EINVAL;
 
-	err = assign_irq_vector(irq, data, dest, irq_data);
+	err = assign_irq_vector(irq, data, dest, irq_data, NULL);
 	return err ? err : IRQ_SET_MASK_OK;
 }
 
diff --git a/include/linux/pci.h b/include/linux/pci.h
index f68c58a93dd0..7755450be02d 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -419,6 +419,8 @@ struct pci_dev {
 #endif
 #ifdef CONFIG_PCI_MSI
 	const struct attribute_group **msi_irq_groups;
+	int align_msi_vector;	/* device requires MSI vector numbers aligned
+				 * by this amount */
 #endif
 	struct pci_vpd *vpd;
 #ifdef CONFIG_PCI_ATS
-- 
2.11.0

^ permalink raw reply related

* Re: [PATCH] mac80211: aead api to reduce redundancy
From: Xiang Gao @ 2017-09-24 18:39 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Herbert Xu, David S. Miller, linux-crypto, linux-kernel,
	linux-wireless, netdev
In-Reply-To: <1506274966.2909.7.camel@sipsolutions.net>

2017-09-24 13:42 GMT-04:00 Johannes Berg <johannes@sipsolutions.net>:
> On Sun, 2017-09-24 at 13:21 -0400, Xiang Gao wrote:
>>
>> Do you mean to put more characters each line in the description
>>
> Huh, sorry, no - my bad. I was thinking of the code, not the
> description at all.

Oh yes, these indentation do looks ugly. Thank you for figuring this
out. The tab
width of my editor was set to 4. It should be 8... I will fix these
problems and resend
the patch soon, maybe after receiving a bit more feedback.

>
> For example here:
>
>> -int ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
>> -                             u8 *data, size_t data_len, u8 *mic)
>> +int aead_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, size_t aad_len,
>> +                                u8 *data, size_t data_len, u8 *auth)
>>
>
> I think you should adjust the indentation to match - or did it just get
> mangled in my mail? It looks *further* indented now, when it should be
> less (to after the opening parenthesis). Similarly in various other
> places.
>
> And perhaps for long things like
>
>> +static inline struct crypto_aead *ieee80211_aes_key_setup_encrypt(
>> +                               const u8 key[], size_t key_len,
>> size_t mic_len)
>
>> +struct crypto_aead *aead_key_setup_encrypt(const char *alg,
>> +                       const u8 key[], size_t key_len, size_t authsize);
>
> it might be better to write
>
> static inline struct crypto_aead *
> ieee80211_aes_key_setup_encrypt(const u8 key[], ...)
>
> and
>
> struct crypto_aead *
> aead_key_setup_encrypt(const char *alg, ...)
>
>
> respectively, depending on how far you have to indent to break lines
> etc.
>
> Anyway, I'm nitpicking.
>
> Unrelated to this, I'm not sure whose tree this should go through -
> probably Herbert's (or DaveM's with his ACK? not sure if there's a
> crypto tree?) or so?

Yes, there is one at
https://git.kernel.org/pub/scm/linux/kernel/git/herbert/cryptodev-2.6.git/
I'm not sure which tree to go either. I'm also not sure about the
beginning of the patch title,
should it be "mac80211:" or "crypto:"?

Options are:
1. This whole patch goes to either mac80211 tree or crypto tree. I
don't know which is better.
2. Make the higher level api only for internal usage in mac80211, i.e.
move the aead_api.c and aead_api.h to net/mac80211, does not export
the symbol. And of course, this will go to the mac80211 tree. I
personally don't want this to be the final solution because I happen
to be writing a loadable kernel module that uses these higher level
api.
3. Maybe split this patch, one for changes in crypto, which will go to
crypto tree, and the other for mac80211 part, which goes to the
mac80211 tree?

>
> johannes

^ permalink raw reply

* Re: [PATCH] mac80211: aead api to reduce redundancy
From: Johannes Berg @ 2017-09-24 17:42 UTC (permalink / raw)
  To: Xiang Gao
  Cc: Herbert Xu, David S. Miller, linux-crypto, linux-kernel,
	linux-wireless, netdev
In-Reply-To: <CAMtaSwR4YTgh9N9x8a12R4dEZNuarjwvfOmnO6vnaDffVV-j3w@mail.gmail.com>

On Sun, 2017-09-24 at 13:21 -0400, Xiang Gao wrote:
> 
> Do you mean to put more characters each line in the description
> 
Huh, sorry, no - my bad. I was thinking of the code, not the
description at all.

For example here:

> -int ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
> -                             u8 *data, size_t data_len, u8 *mic)
> +int aead_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, size_t aad_len,
> +                                u8 *data, size_t data_len, u8 *auth)
> 

I think you should adjust the indentation to match - or did it just get
mangled in my mail? It looks *further* indented now, when it should be
less (to after the opening parenthesis). Similarly in various other
places.

And perhaps for long things like

> +static inline struct crypto_aead *ieee80211_aes_key_setup_encrypt(
> +                               const u8 key[], size_t key_len,
> size_t mic_len)

> +struct crypto_aead *aead_key_setup_encrypt(const char *alg,
> +                       const u8 key[], size_t key_len, size_t authsize);

it might be better to write

static inline struct crypto_aead *
ieee80211_aes_key_setup_encrypt(const u8 key[], ...)

and

struct crypto_aead *
aead_key_setup_encrypt(const char *alg, ...)


respectively, depending on how far you have to indent to break lines
etc.

Anyway, I'm nitpicking.

Unrelated to this, I'm not sure whose tree this should go through -
probably Herbert's (or DaveM's with his ACK? not sure if there's a
crypto tree?) or so?

johannes

^ permalink raw reply

* Re: [PATCH] mac80211: aead api to reduce redundancy
From: Xiang Gao @ 2017-09-24 17:21 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Herbert Xu, David S. Miller, linux-crypto, linux-kernel,
	linux-wireless, netdev
In-Reply-To: <1506265531.2909.5.camel@sipsolutions.net>

2017-09-24 11:05 GMT-04:00 Johannes Berg <johannes@sipsolutions.net>:
> On Sun, 2017-09-24 at 01:40 -0400, Xiang Gao wrote:
>> Currently, the aes_ccm.c and aes_gcm.c are almost line by line
>> copy of each other. This patch reduce code redundancy by moving
>> the code in these two files to crypto/aead_api.c to make it a
>> higher level aead api. The aes_ccm.c and aes_gcm.c are removed
>> and all the functions are now implemented in their headers using
>> the newly added aead api.
>>
> No objection from me, though I'd ask you to respin with the indentation
> fixed up a bit.

Hi Johannes,

Thank you for you time for the suggestion. I'm not sure if I correctly
understand you point.
Do you mean to put more characters each line in the description? Something like:

> Currently, the aes_ccm.c and aes_gcm.c are almost line by line copy of
> each other. This patch reduce code redundancy by moving the code in these
> two files to crypto/aead_api.c to make it a higher level aead api. The
> file aes_ccm.c and aes_gcm.c are removed and all the functions there are
> now implemented in their headers using the newly added aead api.

instead of

> Currently, the aes_ccm.c and aes_gcm.c are almost line by line
> copy of each other. This patch reduce code redundancy by moving
> the code in these two files to crypto/aead_api.c to make it a
> higher level aead api. The aes_ccm.c and aes_gcm.c are removed
> and all the functions are now implemented in their headers using
> the newly added aead api.

Xiang Gao

>
> johannes

^ permalink raw reply

* Re: [PATCH] mac80211: aead api to reduce redundancy
From: Johannes Berg @ 2017-09-24 15:05 UTC (permalink / raw)
  To: Xiang Gao, herbert, davem, linux-crypto, linux-kernel,
	linux-wireless, netdev
In-Reply-To: <20170924054015.8958-1-qasdfgtyuiop@gmail.com>

On Sun, 2017-09-24 at 01:40 -0400, Xiang Gao wrote:
> Currently, the aes_ccm.c and aes_gcm.c are almost line by line
> copy of each other. This patch reduce code redundancy by moving
> the code in these two files to crypto/aead_api.c to make it a
> higher level aead api. The aes_ccm.c and aes_gcm.c are removed
> and all the functions are now implemented in their headers using
> the newly added aead api.
> 
No objection from me, though I'd ask you to respin with the indentation
fixed up a bit.

johannes

^ permalink raw reply

* Re: [RESEND] Re: usb/net/p54: trying to register non-static key in p54_unregister_leds
From: Johannes Berg @ 2017-09-24 14:13 UTC (permalink / raw)
  To: Christian Lamparter, Andrey Konovalov
  Cc: Kalle Valo, linux-wireless, netdev, LKML, Dmitry Vyukov,
	Kostya Serebryany, syzkaller, Stephen Boyd, Tejun Heo, Yong Zhang
In-Reply-To: <2589427.Vd4nrgaY4N@debian64>

On Sat, 2017-09-23 at 21:37 +0200, Christian Lamparter wrote:

> But this also begs the question: Is this really working then?
> From what I can tell, if CONFIG_LOCKDEP is not set then there's no
> BUG no WARN, no other splat or any other odd system behaviour. Does
> [cancel | flush]_[delayed_]work[_sync] really "just work" by
> *accident*, as long the delayed_work | work_struct is zeroed out? 

It looks like it does, but I'm not sure it's not more or less by
accident. Look at get_work_pool() for example, it might actually return
non-NULL in this case, and then in start_flush_work() you'll probably
fall into one of the few "already_gone" cases.

> And should it work in the future as well?

I guess it's not really guaranteed, the API doesn't state anything to
that effect. Not that I'm looking forward to a new workqueue rewrite ;)

johannes

^ permalink raw reply

* [PATCH] mac80211: aead api to reduce redundancy
From: Xiang Gao @ 2017-09-24  5:40 UTC (permalink / raw)
  To: herbert, davem, johannes, linux-crypto, linux-kernel,
	linux-wireless, netdev
  Cc: qasdfgtyuiop

Currently, the aes_ccm.c and aes_gcm.c are almost line by line
copy of each other. This patch reduce code redundancy by moving
the code in these two files to crypto/aead_api.c to make it a
higher level aead api. The aes_ccm.c and aes_gcm.c are removed
and all the functions are now implemented in their headers using
the newly added aead api.

Signed-off-by: Xiang Gao <qasdfgtyuiop@gmail.com>
---
 crypto/Makefile                             |   2 +-
 net/mac80211/aes_gcm.c => crypto/aead_api.c |  53 +++++++------
 include/crypto/aead_api.h                   |  21 +++++
 net/mac80211/Makefile                       |   2 -
 net/mac80211/aes_ccm.c                      | 115 ----------------------------
 net/mac80211/aes_ccm.h                      |  42 +++++++---
 net/mac80211/aes_gcm.h                      |  40 ++++++++--
 net/mac80211/key.c                          |   1 +
 net/mac80211/wpa.c                          |  11 +--
 9 files changed, 118 insertions(+), 169 deletions(-)
 rename net/mac80211/aes_gcm.c => crypto/aead_api.c (54%)
 create mode 100644 include/crypto/aead_api.h
 delete mode 100644 net/mac80211/aes_ccm.c

diff --git a/crypto/Makefile b/crypto/Makefile
index d41f0331b085..541316db5841 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -14,7 +14,7 @@ crypto_algapi-$(CONFIG_PROC_FS) += proc.o
 crypto_algapi-y := algapi.o scatterwalk.o $(crypto_algapi-y)
 obj-$(CONFIG_CRYPTO_ALGAPI2) += crypto_algapi.o
 
-obj-$(CONFIG_CRYPTO_AEAD2) += aead.o
+obj-$(CONFIG_CRYPTO_AEAD2) += aead.o aead_api.o
 
 crypto_blkcipher-y := ablkcipher.o
 crypto_blkcipher-y += blkcipher.o
diff --git a/net/mac80211/aes_gcm.c b/crypto/aead_api.c
similarity index 54%
rename from net/mac80211/aes_gcm.c
rename to crypto/aead_api.c
index 8a4397cc1b08..9585ee400b2e 100644
--- a/net/mac80211/aes_gcm.c
+++ b/crypto/aead_api.c
@@ -1,7 +1,4 @@
-/*
- * Copyright 2014-2015, Qualcomm Atheros, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
+/* This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
@@ -9,43 +6,43 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/err.h>
-#include <crypto/aead.h>
+#include <linux/scatterlist.h>
 
-#include <net/mac80211.h>
-#include "key.h"
-#include "aes_gcm.h"
+#include <crypto/aead_api.h>
 
-int ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
-			      u8 *data, size_t data_len, u8 *mic)
+int aead_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, size_t aad_len,
+				 u8 *data, size_t data_len, u8 *auth)
 {
 	struct scatterlist sg[3];
 	struct aead_request *aead_req;
 	int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm);
 	u8 *__aad;
 
-	aead_req = kzalloc(reqsize + GCM_AAD_LEN, GFP_ATOMIC);
+	aead_req = kzalloc(reqsize + aad_len, GFP_ATOMIC);
 	if (!aead_req)
 		return -ENOMEM;
 
 	__aad = (u8 *)aead_req + reqsize;
-	memcpy(__aad, aad, GCM_AAD_LEN);
+	memcpy(__aad, aad, aad_len);
 
 	sg_init_table(sg, 3);
-	sg_set_buf(&sg[0], &__aad[2], be16_to_cpup((__be16 *)__aad));
+	sg_set_buf(&sg[0], __aad, aad_len);
 	sg_set_buf(&sg[1], data, data_len);
-	sg_set_buf(&sg[2], mic, IEEE80211_GCMP_MIC_LEN);
+	sg_set_buf(&sg[2], auth, tfm->authsize);
 
 	aead_request_set_tfm(aead_req, tfm);
-	aead_request_set_crypt(aead_req, sg, sg, data_len, j_0);
+	aead_request_set_crypt(aead_req, sg, sg, data_len, b_0);
 	aead_request_set_ad(aead_req, sg[0].length);
 
 	crypto_aead_encrypt(aead_req);
 	kzfree(aead_req);
+
 	return 0;
 }
+EXPORT_SYMBOL_GPL(aead_encrypt);
 
-int ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
-			      u8 *data, size_t data_len, u8 *mic)
+int aead_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, size_t aad_len,
+				 u8 *data, size_t data_len, u8 *auth)
 {
 	struct scatterlist sg[3];
 	struct aead_request *aead_req;
@@ -56,21 +53,20 @@ int ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
 	if (data_len == 0)
 		return -EINVAL;
 
-	aead_req = kzalloc(reqsize + GCM_AAD_LEN, GFP_ATOMIC);
+	aead_req = kzalloc(reqsize + aad_len, GFP_ATOMIC);
 	if (!aead_req)
 		return -ENOMEM;
 
 	__aad = (u8 *)aead_req + reqsize;
-	memcpy(__aad, aad, GCM_AAD_LEN);
+	memcpy(__aad, aad, aad_len);
 
 	sg_init_table(sg, 3);
 	sg_set_buf(&sg[0], &__aad[2], be16_to_cpup((__be16 *)__aad));
 	sg_set_buf(&sg[1], data, data_len);
-	sg_set_buf(&sg[2], mic, IEEE80211_GCMP_MIC_LEN);
+	sg_set_buf(&sg[2], auth, tfm->authsize);
 
 	aead_request_set_tfm(aead_req, tfm);
-	aead_request_set_crypt(aead_req, sg, sg,
-			       data_len + IEEE80211_GCMP_MIC_LEN, j_0);
+	aead_request_set_crypt(aead_req, sg, sg, data_len + tfm->authsize, b_0);
 	aead_request_set_ad(aead_req, sg[0].length);
 
 	err = crypto_aead_decrypt(aead_req);
@@ -78,21 +74,22 @@ int ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
 
 	return err;
 }
+EXPORT_SYMBOL_GPL(aead_decrypt);
 
-struct crypto_aead *ieee80211_aes_gcm_key_setup_encrypt(const u8 key[],
-							size_t key_len)
+struct crypto_aead *aead_key_setup_encrypt(const char *alg,
+				const u8 key[], size_t key_len, size_t authsize)
 {
 	struct crypto_aead *tfm;
 	int err;
 
-	tfm = crypto_alloc_aead("gcm(aes)", 0, CRYPTO_ALG_ASYNC);
+	tfm = crypto_alloc_aead(alg, 0, CRYPTO_ALG_ASYNC);
 	if (IS_ERR(tfm))
 		return tfm;
 
 	err = crypto_aead_setkey(tfm, key, key_len);
 	if (err)
 		goto free_aead;
-	err = crypto_aead_setauthsize(tfm, IEEE80211_GCMP_MIC_LEN);
+	err = crypto_aead_setauthsize(tfm, authsize);
 	if (err)
 		goto free_aead;
 
@@ -102,8 +99,10 @@ struct crypto_aead *ieee80211_aes_gcm_key_setup_encrypt(const u8 key[],
 	crypto_free_aead(tfm);
 	return ERR_PTR(err);
 }
+EXPORT_SYMBOL_GPL(aead_key_setup_encrypt);
 
-void ieee80211_aes_gcm_key_free(struct crypto_aead *tfm)
+void aead_key_free(struct crypto_aead *tfm)
 {
 	crypto_free_aead(tfm);
 }
+EXPORT_SYMBOL_GPL(aead_key_free);
diff --git a/include/crypto/aead_api.h b/include/crypto/aead_api.h
new file mode 100644
index 000000000000..45deda0d538f
--- /dev/null
+++ b/include/crypto/aead_api.h
@@ -0,0 +1,21 @@
+/* This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _AEAD_API_H
+#define _AEAD_API_H
+
+#include <crypto/aead.h>
+#include <linux/crypto.h>
+
+struct crypto_aead *aead_key_setup_encrypt(const char *alg,
+			const u8 key[], size_t key_len, size_t authsize);
+
+int aead_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
+			size_t aad_len, u8 *data, size_t data_len, u8 *auth);
+int aead_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
+			size_t aad_len, u8 *data, size_t data_len, u8 *auth);
+void aead_key_free(struct crypto_aead *tfm);
+
+#endif /* _AEAD_API_H */
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile
index 282912245938..f1efc8c81ce6 100644
--- a/net/mac80211/Makefile
+++ b/net/mac80211/Makefile
@@ -15,8 +15,6 @@ mac80211-y := \
 	rate.o \
 	michael.o \
 	tkip.o \
-	aes_ccm.o \
-	aes_gcm.o \
 	aes_cmac.o \
 	aes_gmac.o \
 	fils_aead.o \
diff --git a/net/mac80211/aes_ccm.c b/net/mac80211/aes_ccm.c
deleted file mode 100644
index a4e0d59a40dd..000000000000
--- a/net/mac80211/aes_ccm.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright 2003-2004, Instant802 Networks, Inc.
- * Copyright 2005-2006, Devicescape Software, Inc.
- *
- * Rewrite: Copyright (C) 2013 Linaro Ltd <ard.biesheuvel@linaro.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/err.h>
-#include <crypto/aead.h>
-
-#include <net/mac80211.h>
-#include "key.h"
-#include "aes_ccm.h"
-
-int ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
-			      u8 *data, size_t data_len, u8 *mic,
-			      size_t mic_len)
-{
-	struct scatterlist sg[3];
-	struct aead_request *aead_req;
-	int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm);
-	u8 *__aad;
-
-	aead_req = kzalloc(reqsize + CCM_AAD_LEN, GFP_ATOMIC);
-	if (!aead_req)
-		return -ENOMEM;
-
-	__aad = (u8 *)aead_req + reqsize;
-	memcpy(__aad, aad, CCM_AAD_LEN);
-
-	sg_init_table(sg, 3);
-	sg_set_buf(&sg[0], &__aad[2], be16_to_cpup((__be16 *)__aad));
-	sg_set_buf(&sg[1], data, data_len);
-	sg_set_buf(&sg[2], mic, mic_len);
-
-	aead_request_set_tfm(aead_req, tfm);
-	aead_request_set_crypt(aead_req, sg, sg, data_len, b_0);
-	aead_request_set_ad(aead_req, sg[0].length);
-
-	crypto_aead_encrypt(aead_req);
-	kzfree(aead_req);
-
-	return 0;
-}
-
-int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
-			      u8 *data, size_t data_len, u8 *mic,
-			      size_t mic_len)
-{
-	struct scatterlist sg[3];
-	struct aead_request *aead_req;
-	int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm);
-	u8 *__aad;
-	int err;
-
-	if (data_len == 0)
-		return -EINVAL;
-
-	aead_req = kzalloc(reqsize + CCM_AAD_LEN, GFP_ATOMIC);
-	if (!aead_req)
-		return -ENOMEM;
-
-	__aad = (u8 *)aead_req + reqsize;
-	memcpy(__aad, aad, CCM_AAD_LEN);
-
-	sg_init_table(sg, 3);
-	sg_set_buf(&sg[0], &__aad[2], be16_to_cpup((__be16 *)__aad));
-	sg_set_buf(&sg[1], data, data_len);
-	sg_set_buf(&sg[2], mic, mic_len);
-
-	aead_request_set_tfm(aead_req, tfm);
-	aead_request_set_crypt(aead_req, sg, sg, data_len + mic_len, b_0);
-	aead_request_set_ad(aead_req, sg[0].length);
-
-	err = crypto_aead_decrypt(aead_req);
-	kzfree(aead_req);
-
-	return err;
-}
-
-struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[],
-						    size_t key_len,
-						    size_t mic_len)
-{
-	struct crypto_aead *tfm;
-	int err;
-
-	tfm = crypto_alloc_aead("ccm(aes)", 0, CRYPTO_ALG_ASYNC);
-	if (IS_ERR(tfm))
-		return tfm;
-
-	err = crypto_aead_setkey(tfm, key, key_len);
-	if (err)
-		goto free_aead;
-	err = crypto_aead_setauthsize(tfm, mic_len);
-	if (err)
-		goto free_aead;
-
-	return tfm;
-
-free_aead:
-	crypto_free_aead(tfm);
-	return ERR_PTR(err);
-}
-
-void ieee80211_aes_key_free(struct crypto_aead *tfm)
-{
-	crypto_free_aead(tfm);
-}
diff --git a/net/mac80211/aes_ccm.h b/net/mac80211/aes_ccm.h
index fcd3254c5cf0..b51ef23201c1 100644
--- a/net/mac80211/aes_ccm.h
+++ b/net/mac80211/aes_ccm.h
@@ -10,19 +10,39 @@
 #ifndef AES_CCM_H
 #define AES_CCM_H
 
-#include <linux/crypto.h>
+#include <crypto/aead_api.h>
 
 #define CCM_AAD_LEN	32
 
-struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[],
-						    size_t key_len,
-						    size_t mic_len);
-int ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
-			      u8 *data, size_t data_len, u8 *mic,
-			      size_t mic_len);
-int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
-			      u8 *data, size_t data_len, u8 *mic,
-			      size_t mic_len);
-void ieee80211_aes_key_free(struct crypto_aead *tfm);
+static inline struct crypto_aead *ieee80211_aes_key_setup_encrypt(
+				const u8 key[], size_t key_len, size_t mic_len)
+{
+	return aead_key_setup_encrypt("ccm(aes)", key, key_len, mic_len);
+}
+
+static inline int ieee80211_aes_ccm_encrypt(
+		struct crypto_aead *tfm,
+		u8 *b_0, u8 *aad, u8 *data,
+		size_t data_len, u8 *mic)
+{
+	return aead_encrypt(tfm, b_0, aad + 2,
+						be16_to_cpup((__be16 *)aad),
+						data, data_len, mic);
+}
+
+static inline int ieee80211_aes_ccm_decrypt(
+		struct crypto_aead *tfm,
+		u8 *b_0, u8 *aad, u8 *data,
+		size_t data_len, u8 *mic)
+{
+	return aead_decrypt(tfm, b_0, aad + 2,
+						be16_to_cpup((__be16 *)aad),
+						data, data_len, mic);
+}
+
+static inline void ieee80211_aes_key_free(struct crypto_aead *tfm)
+{
+	return aead_key_free(tfm);
+}
 
 #endif /* AES_CCM_H */
diff --git a/net/mac80211/aes_gcm.h b/net/mac80211/aes_gcm.h
index 55aed5352494..f07359d5ebbd 100644
--- a/net/mac80211/aes_gcm.h
+++ b/net/mac80211/aes_gcm.h
@@ -9,16 +9,40 @@
 #ifndef AES_GCM_H
 #define AES_GCM_H
 
-#include <linux/crypto.h>
+#include <crypto/aead_api.h>
 
 #define GCM_AAD_LEN	32
 
-int ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
-			      u8 *data, size_t data_len, u8 *mic);
-int ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
-			      u8 *data, size_t data_len, u8 *mic);
-struct crypto_aead *ieee80211_aes_gcm_key_setup_encrypt(const u8 key[],
-							size_t key_len);
-void ieee80211_aes_gcm_key_free(struct crypto_aead *tfm);
+static inline int ieee80211_aes_gcm_encrypt(
+		struct crypto_aead *tfm,
+		u8 *j_0, u8 *aad,  u8 *data,
+		size_t data_len, u8 *mic)
+{
+	return aead_encrypt(tfm, j_0, aad + 2,
+						be16_to_cpup((__be16 *)aad),
+						data, data_len, mic);
+}
+
+static inline int ieee80211_aes_gcm_decrypt(
+		struct crypto_aead *tfm,
+		u8 *j_0, u8 *aad, u8 *data,
+		size_t data_len, u8 *mic)
+{
+	return aead_decrypt(tfm, j_0, aad + 2,
+						be16_to_cpup((__be16 *)aad),
+						data, data_len, mic);
+}
+
+static inline struct crypto_aead *ieee80211_aes_gcm_key_setup_encrypt(
+		const u8 key[], size_t key_len)
+{
+	return aead_key_setup_encrypt("gcm(aes)", key,
+				key_len, IEEE80211_GCMP_MIC_LEN);
+}
+
+static inline void ieee80211_aes_gcm_key_free(struct crypto_aead *tfm)
+{
+	return aead_key_free(tfm);
+}
 
 #endif /* AES_GCM_H */
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index a98fc2b5e0dc..a61cecd078bb 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -18,6 +18,7 @@
 #include <linux/rtnetlink.h>
 #include <linux/slab.h>
 #include <linux/export.h>
+#include <linux/crypto.h>
 #include <net/mac80211.h>
 #include <asm/unaligned.h>
 #include "ieee80211_i.h"
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
index 0d722ea98a1b..e30e09c1e149 100644
--- a/net/mac80211/wpa.c
+++ b/net/mac80211/wpa.c
@@ -464,7 +464,7 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb,
 	pos += IEEE80211_CCMP_HDR_LEN;
 	ccmp_special_blocks(skb, pn, b_0, aad);
 	return ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len,
-					 skb_put(skb, mic_len), mic_len);
+				skb_put(skb, key->u.ccmp.tfm->authsize));
 }
 
 
@@ -540,10 +540,11 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx,
 			ccmp_special_blocks(skb, pn, b_0, aad);
 
 			if (ieee80211_aes_ccm_decrypt(
-				    key->u.ccmp.tfm, b_0, aad,
-				    skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN,
-				    data_len,
-				    skb->data + skb->len - mic_len, mic_len))
+				key->u.ccmp.tfm, b_0, aad,
+				skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN,
+				data_len,
+				skb->data + skb->len - key->u.ccmp.tfm->authsize
+			))
 				return RX_DROP_UNUSABLE;
 		}
 
-- 
2.14.1

^ permalink raw reply related

* [RESEND] Re: usb/net/p54: trying to register non-static key in p54_unregister_leds
From: Christian Lamparter @ 2017-09-23 19:37 UTC (permalink / raw)
  To: Andrey Konovalov
  Cc: Johannes Berg, Kalle Valo, linux-wireless, netdev, LKML,
	Dmitry Vyukov, Kostya Serebryany, syzkaller, Stephen Boyd,
	Tejun Heo, Yong Zhang
In-Reply-To: <CAAeHK+wWRZuCDNhoZJ0ACDhiNQw8tVRp2HW0j1EDH0HOe523xA@mail.gmail.com>

This got rejected by gmail once. Let's see if it works now.

On Thursday, September 21, 2017 8:22:45 PM CEST Andrey Konovalov wrote:
> On Wed, Sep 20, 2017 at 9:55 PM, Johannes Berg
> <johannes@sipsolutions.net> wrote:
> > On Wed, 2017-09-20 at 21:27 +0200, Christian Lamparter wrote:
> >
> >> It seems this is caused as a result of:
> >>     -> lock_map_acquire(&work->lockdep_map);
> >>           lock_map_release(&work->lockdep_map);
> >>
> >>     in flush_work() [0]
> >
> > Agree.
> >
> >> This was added by:
> >>
> >>       commit 0976dfc1d0cd80a4e9dfaf87bd8744612bde475a
> >>       Author: Stephen Boyd <sboyd@codeaurora.org>
> >>       Date:   Fri Apr 20 17:28:50 2012 -0700
> >>
> >>       workqueue: Catch more locking problems with flush_work()
> >
> > Yes, but that doesn't matter.
> >
> >> Looking at the Stephen's patch, it's clear that it was made
> >> with "static DECLARE_WORK(work, my_work)" in mind. However
> >> p54's led_work is "per-device", hence it is stored in the
> >> devices context p54_common, which is dynamically allocated.
> >> So, maybe revert Stephen's patch?
> >
> > I disagree - as the lockdep warning says:
> >
> >> > INFO: trying to register non-static key.
> >> > the code is fine but needs lockdep annotation.
> >> > turning off the locking correctness validator.
> >
> > What it needs is to actually correctly go through initializing the work
> > at least once.
> >
> > Without more information, I can't really say what's going on, but I
> > assume that something is failing and p54_unregister_leds() is getting
> > invoked without p54_init_leds() having been invoked, so essentially
> > it's trying to flush a work that was never initialized?
> >
> > INIT_DELAYED_WORK() does, after all, initialize the lockdep map
> > properly via __INIT_WORK().

Ok, thanks. This does indeed explain it.

But this also begs the question: Is this really working then?
>From what I can tell, if CONFIG_LOCKDEP is not set then there's no BUG
no WARN, no other splat or any other odd system behaviour. Does
[cancel | flush]_[delayed_]work[_sync] really "just work" by *accident*,
as long the delayed_work | work_struct is zeroed out? 
And should it work in the future as well?

> Since I'm able to reproduce this, please let me know if you need me to
> collect some debug traces to help with the triage.

Do you want to take a shot at making a patch too? At a quick glance, it
should be enough to move the [#ifdef CONFIG_P54_LEDS ... #endif] block
in p54_unregister_common() into the if (priv->registered) { block
(preferably before the ieee80211_unregister_hw(dev).

Regards,
Christian

^ permalink raw reply

* [PATCH] wireless: iwlwifi: fix minor code style issues
From: Christoph Böhmwalder @ 2017-09-23 10:31 UTC (permalink / raw)
  To: johannes.berg
  Cc: emmanuel.grumbach, luciano.coelho, kvalo, linux-wireless, netdev,
	linux-kernel, Christoph Böhmwalder

Fixes three trivial issues as reported by checkpatch.pl, namely two
switch/case indentation issues and one alignment issue in a multiline comment.

Signed-off-by: Christoph Böhmwalder <christoph@boehmwalder.at>
---
 drivers/net/wireless/intel/iwlwifi/iwl-drv.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
index 99676d6c4713..ccdb247d68c5 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
@@ -832,7 +832,7 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
 			capa->standard_phy_calibration_size =
 					le32_to_cpup((__le32 *)tlv_data);
 			break;
-		 case IWL_UCODE_TLV_SEC_RT:
+		case IWL_UCODE_TLV_SEC_RT:
 			iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_REGULAR,
 					    tlv_len);
 			drv->fw.type = IWL_FW_MVM;
@@ -864,7 +864,7 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
 						FW_PHY_CFG_RX_CHAIN) >>
 						FW_PHY_CFG_RX_CHAIN_POS;
 			break;
-		 case IWL_UCODE_TLV_SECURE_SEC_RT:
+		case IWL_UCODE_TLV_SECURE_SEC_RT:
 			iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_REGULAR,
 					    tlv_len);
 			drv->fw.type = IWL_FW_MVM;
@@ -1335,7 +1335,8 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
 
 	/* Runtime instructions and 2 copies of data:
 	 * 1) unmodified from disk
-	 * 2) backup cache for save/restore during power-downs */
+	 * 2) backup cache for save/restore during power-downs
+	 */
 	for (i = 0; i < IWL_UCODE_TYPE_MAX; i++)
 		if (iwl_alloc_ucode(drv, pieces, i))
 			goto out_free_fw;
-- 
2.13.5

^ permalink raw reply related

* Re: [PATCH] mwifiex: add device specific ioctl handler
From: kbuild test robot @ 2017-09-23  3:01 UTC (permalink / raw)
  To: Xinming Hu
  Cc: kbuild-all, Linux Wireless, Kalle Valo, Brian Norris,
	Dmitry Torokhov, rajatja, Zhiyuan Yang, Tim Song, Cathy Luo,
	Ganapathi Bhat, Xinming Hu
In-Reply-To: <1505889853-20493-1-git-send-email-huxinming820@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 2377 bytes --]

Hi Xinming,

[auto build test ERROR on wireless-drivers-next/master]
[also build test ERROR on v4.14-rc1 next-20170922]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Xinming-Hu/mwifiex-add-device-specific-ioctl-handler/20170923-094243
base:   https://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next.git master
config: tile-allyesconfig (attached as .config)
compiler: tilegx-linux-gcc (GCC) 4.6.2
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=tile 

All errors (new ones prefixed by >>):

   drivers/net//wireless/marvell/mwifiex/main.c: In function 'mwifiex_do_ioctl':
   drivers/net//wireless/marvell/mwifiex/main.c:1276:1: error: pasting "MWIFIEX_DBG_" and ""ioctl cmd = 0x%x\n"" does not give a valid preprocessing token
>> drivers/net//wireless/marvell/mwifiex/main.c:1276:1: error: 'MWIFIEX_DBG_' undeclared (first use in this function)
   drivers/net//wireless/marvell/mwifiex/main.c:1276:1: note: each undeclared identifier is reported only once for each function it appears in
   drivers/net//wireless/marvell/mwifiex/main.c:1276:2: error: expected ')' before string constant
>> drivers/net//wireless/marvell/mwifiex/main.c:1276:2: error: too few arguments to function '_mwifiex_dbg'
   drivers/net//wireless/marvell/mwifiex/main.h:206:6: note: declared here

vim +1276 drivers/net//wireless/marvell/mwifiex/main.c

  1267	
  1268	static int mwifiex_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
  1269	{
  1270		struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
  1271		int ret;
  1272	
  1273		if (!priv->adapter->mfg_mode)
  1274			return -EINVAL;
  1275	
> 1276		mwifiex_dbg(priv->adapter, "ioctl cmd = 0x%x\n", cmd);
  1277	
  1278		switch (cmd) {
  1279		case MWIFIEX_HOSTCMD_IOCTL:
  1280			ret = mwifiex_process_host_command(priv, req);
  1281			break;
  1282		default:
  1283			ret = -EINVAL;
  1284			break;
  1285		}
  1286	
  1287		return ret;
  1288	}
  1289	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 50505 bytes --]

^ permalink raw reply

* Re: [PATCH] mwifiex: add device specific ioctl handler
From: kbuild test robot @ 2017-09-23  2:29 UTC (permalink / raw)
  To: Xinming Hu
  Cc: kbuild-all, Linux Wireless, Kalle Valo, Brian Norris,
	Dmitry Torokhov, rajatja, Zhiyuan Yang, Tim Song, Cathy Luo,
	Ganapathi Bhat, Xinming Hu
In-Reply-To: <1505889853-20493-1-git-send-email-huxinming820@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 4621 bytes --]

Hi Xinming,

[auto build test ERROR on wireless-drivers-next/master]
[also build test ERROR on v4.14-rc1 next-20170922]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Xinming-Hu/mwifiex-add-device-specific-ioctl-handler/20170923-094243
base:   https://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next.git master
config: x86_64-randconfig-x000-201738 (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All error/warnings (new ones prefixed by >>):

   In file included from drivers/net/wireless/marvell/mwifiex/main.c:22:0:
   drivers/net/wireless/marvell/mwifiex/main.c: In function 'mwifiex_do_ioctl':
   drivers/net/wireless/marvell/mwifiex/main.h:209:24: error: pasting "MWIFIEX_DBG_" and ""ioctl cmd = 0x%x\n"" does not give a valid preprocessing token
     _mwifiex_dbg(adapter, MWIFIEX_DBG_##mask, fmt, ##__VA_ARGS__)
                           ^
>> drivers/net/wireless/marvell/mwifiex/main.c:1276:2: note: in expansion of macro 'mwifiex_dbg'
     mwifiex_dbg(priv->adapter, "ioctl cmd = 0x%x\n", cmd);
     ^~~~~~~~~~~
>> drivers/net/wireless/marvell/mwifiex/main.h:209:24: error: 'MWIFIEX_DBG_' undeclared (first use in this function)
     _mwifiex_dbg(adapter, MWIFIEX_DBG_##mask, fmt, ##__VA_ARGS__)
                           ^
>> drivers/net/wireless/marvell/mwifiex/main.c:1276:2: note: in expansion of macro 'mwifiex_dbg'
     mwifiex_dbg(priv->adapter, "ioctl cmd = 0x%x\n", cmd);
     ^~~~~~~~~~~
   drivers/net/wireless/marvell/mwifiex/main.h:209:24: note: each undeclared identifier is reported only once for each function it appears in
     _mwifiex_dbg(adapter, MWIFIEX_DBG_##mask, fmt, ##__VA_ARGS__)
                           ^
>> drivers/net/wireless/marvell/mwifiex/main.c:1276:2: note: in expansion of macro 'mwifiex_dbg'
     mwifiex_dbg(priv->adapter, "ioctl cmd = 0x%x\n", cmd);
     ^~~~~~~~~~~
>> drivers/net/wireless/marvell/mwifiex/main.c:1276:29: error: expected ')' before string constant
     mwifiex_dbg(priv->adapter, "ioctl cmd = 0x%x\n", cmd);
                                ^
   drivers/net/wireless/marvell/mwifiex/main.h:209:38: note: in definition of macro 'mwifiex_dbg'
     _mwifiex_dbg(adapter, MWIFIEX_DBG_##mask, fmt, ##__VA_ARGS__)
                                         ^~~~
>> drivers/net/wireless/marvell/mwifiex/main.h:209:2: error: too few arguments to function '_mwifiex_dbg'
     _mwifiex_dbg(adapter, MWIFIEX_DBG_##mask, fmt, ##__VA_ARGS__)
     ^
>> drivers/net/wireless/marvell/mwifiex/main.c:1276:2: note: in expansion of macro 'mwifiex_dbg'
     mwifiex_dbg(priv->adapter, "ioctl cmd = 0x%x\n", cmd);
     ^~~~~~~~~~~
   drivers/net/wireless/marvell/mwifiex/main.h:206:6: note: declared here
    void _mwifiex_dbg(const struct mwifiex_adapter *adapter, int mask,
         ^~~~~~~~~~~~

vim +209 drivers/net/wireless/marvell/mwifiex/main.h

c687a0077 drivers/net/wireless/mwifiex/main.h Zhaoyang Liu 2015-05-12  200  
c687a0077 drivers/net/wireless/mwifiex/main.h Zhaoyang Liu 2015-05-12  201  #define MWIFIEX_DEFAULT_DEBUG_MASK	(MWIFIEX_DBG_MSG | \
c687a0077 drivers/net/wireless/mwifiex/main.h Zhaoyang Liu 2015-05-12  202  					MWIFIEX_DBG_FATAL | \
c687a0077 drivers/net/wireless/mwifiex/main.h Zhaoyang Liu 2015-05-12  203  					MWIFIEX_DBG_ERROR)
c687a0077 drivers/net/wireless/mwifiex/main.h Zhaoyang Liu 2015-05-12  204  
36925e52c drivers/net/wireless/mwifiex/main.h Joe Perches  2015-08-31  205  __printf(3, 4)
36925e52c drivers/net/wireless/mwifiex/main.h Joe Perches  2015-08-31  206  void _mwifiex_dbg(const struct mwifiex_adapter *adapter, int mask,
36925e52c drivers/net/wireless/mwifiex/main.h Joe Perches  2015-08-31  207  		  const char *fmt, ...);
36925e52c drivers/net/wireless/mwifiex/main.h Joe Perches  2015-08-31  208  #define mwifiex_dbg(adapter, mask, fmt, ...)				\
36925e52c drivers/net/wireless/mwifiex/main.h Joe Perches  2015-08-31 @209  	_mwifiex_dbg(adapter, MWIFIEX_DBG_##mask, fmt, ##__VA_ARGS__)
c687a0077 drivers/net/wireless/mwifiex/main.h Zhaoyang Liu 2015-05-12  210  

:::::: The code at line 209 was first introduced by commit
:::::: 36925e52c5ac9d10a553d1339e13a61bfbdd4ba4 mwifiex: Make mwifiex_dbg a function, reduce object size

:::::: TO: Joe Perches <joe@perches.com>
:::::: CC: Kalle Valo <kvalo@codeaurora.org>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 28706 bytes --]

^ permalink raw reply

* [PATCH v4 9/9] kasan: rework Kconfig settings
From: Arnd Bergmann @ 2017-09-22 21:29 UTC (permalink / raw)
  To: Andrey Ryabinin, Masahiro Yamada, Michal Marek, Andrew Morton
  Cc: Arnd Bergmann, Mauro Carvalho Chehab, Jiri Pirko,
	Arend van Spriel, Kalle Valo, David S. Miller,
	Alexander Potapenko, Dmitry Vyukov, Kees Cook, Geert Uytterhoeven,
	Greg Kroah-Hartman, linux-media, linux-kernel, netdev,
	linux-wireless, brcm80211-dev-list.pdl, brcm80211-dev-list,
	kasan-dev, linux-kbuild, Jakub Jelinek, Martin Liška
In-Reply-To: <20170922212930.620249-1-arnd@arndb.de>

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/gpu/drm/i915/gvt/handlers.c:2407:1: error: the frame size of 31216 bytes is larger than 2048 bytes
drivers/net/wireless/ralink/rt2x00/rt2800lib.c:5650:1: error: the frame size of 23632 bytes is larger than 2048 bytes
drivers/scsi/fnic/fnic_trace.c:451:1: error: the frame size of 5152 bytes is larger than 2048 bytes
fs/btrfs/relocation.c:1202:1: error: the frame size of 4256 bytes is larger than 2048 bytes
fs/fscache/stats.c:287:1: error: the frame size of 6552 bytes is larger than 2048 bytes
lib/atomic64_test.c:250:1: error: the frame size of 12616 bytes is larger than 2048 bytes
mm/vmscan.c:1367:1: error: the frame size of 5080 bytes is larger than 2048 bytes
net/wireless/nl80211.c:1905:1: error: the frame size of 4232 bytes is larger than 2048 bytes

To reduce this risk, -fsanitize-address-use-after-scope is now split
out into a separate CONFIG_KASAN_EXTRA Kconfig option, 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
and make KASAN and KMEMCHECK mutually exclusive.

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.
I arbitrarily raise the warning limit for KASAN_EXTRA to 3072 to reduce
the noise, but an allmodconfig kernel still has around 50 warnings
on gcc-7.

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 (without CONFIG_KASAN).

With earlier versions of this patch series, I also had patches to
address the warnings we get with KASAN and/or KASAN_EXTRA, using a
"noinline_if_stackbloat" annotation. That annotation now got replaced with
a gcc-8 bugfix (see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81715)
and a workaround for older compilers, which means that KASAN_EXTRA is
now just as bad as before and will lead to an instant stack overflow in
a few extreme cases.

This reverts parts of commit commit 3f181b4 ("lib/Kconfig.debug: disable
-Wframe-larger-than warnings with KASAN=y").

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 lib/Kconfig.debug      |  4 ++--
 lib/Kconfig.kasan      | 13 ++++++++++++-
 lib/Kconfig.kmemcheck  |  1 +
 scripts/Makefile.kasan |  3 +++
 4 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index b19c491cbc4e..5755875d4a80 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
@@ -503,7 +503,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..db799e6e9dba 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,17 @@ 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 && DEBUG_KERNEL && !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.
+	  https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 has more
+
+
 choice
 	prompt "Instrumentation type"
 	depends on KASAN
diff --git a/lib/Kconfig.kmemcheck b/lib/Kconfig.kmemcheck
index 846e039a86b4..1a534e638635 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
 	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

^ permalink raw reply related

* [PATCH v4 7/9] rocker: fix rocker_tlv_put_* functions for KASAN
From: Arnd Bergmann @ 2017-09-22 21:29 UTC (permalink / raw)
  To: Jiri Pirko
  Cc: Arnd Bergmann, Mauro Carvalho Chehab, Arend van Spriel,
	Kalle Valo, David S. Miller, Andrey Ryabinin, Alexander Potapenko,
	Dmitry Vyukov, Masahiro Yamada, Michal Marek, Andrew Morton,
	Kees Cook, Geert Uytterhoeven, Greg Kroah-Hartman, linux-media,
	linux-kernel, netdev, linux-wireless, brcm80211-dev-list.pdl,
	brcm80211-dev-list, kasan-dev, linux-kbuild, Jakub Jelinek,
	Martin Liška, stable
In-Reply-To: <20170922212930.620249-1-arnd@arndb.de>

Inlining these functions creates lots of stack variables that each take
64 bytes 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=]

gcc-8 can now consolidate the stack slots itself, but on older versions
we get the same behavior by using a temporary variable that holds a
copy of the inline function argument.

Cc: stable@vger.kernel.org
Link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81715
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 drivers/net/ethernet/rocker/rocker_tlv.h | 48 ++++++++++++++++++++------------
 1 file changed, 30 insertions(+), 18 deletions(-)

diff --git a/drivers/net/ethernet/rocker/rocker_tlv.h b/drivers/net/ethernet/rocker/rocker_tlv.h
index a63ef82e7c72..dfae3c9d57c6 100644
--- a/drivers/net/ethernet/rocker/rocker_tlv.h
+++ b/drivers/net/ethernet/rocker/rocker_tlv.h
@@ -139,40 +139,52 @@ 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 inline 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);
+	u8 tmp = value; /* work around GCC PR81715 */
+
+	return rocker_tlv_put(desc_info, attrtype, sizeof(u8), &tmp);
 }
 
-static inline int rocker_tlv_put_u16(struct rocker_desc_info *desc_info,
-				     int attrtype, u16 value)
+static inline 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);
+	u16 tmp = value;
+
+	return rocker_tlv_put(desc_info, attrtype, sizeof(u16), &tmp);
 }
 
-static inline int rocker_tlv_put_be16(struct rocker_desc_info *desc_info,
-				      int attrtype, __be16 value)
+static inline 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);
+	__be16 tmp = value;
+
+	return rocker_tlv_put(desc_info, attrtype, sizeof(__be16), &tmp);
 }
 
-static inline int rocker_tlv_put_u32(struct rocker_desc_info *desc_info,
-				     int attrtype, u32 value)
+static inline 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);
+	u32 tmp = value;
+
+	return rocker_tlv_put(desc_info, attrtype, sizeof(u32), &tmp);
 }
 
-static inline int rocker_tlv_put_be32(struct rocker_desc_info *desc_info,
-				      int attrtype, __be32 value)
+static inline 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);
+	__be32 tmp = value;
+
+	return rocker_tlv_put(desc_info, attrtype, sizeof(__be32), &tmp);
 }
 
-static inline int rocker_tlv_put_u64(struct rocker_desc_info *desc_info,
-				     int attrtype, u64 value)
+static inline 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);
+	u64 tmp = value;
+
+	return rocker_tlv_put(desc_info, attrtype, sizeof(u64), &tmp);
 }
 
 static inline struct rocker_tlv *
-- 
2.9.0

^ permalink raw reply related

* [PATCH v4 8/9] netlink: fix nla_put_{u8,u16,u32} for KASAN
From: Arnd Bergmann @ 2017-09-22 21:29 UTC (permalink / raw)
  To: David S. Miller
  Cc: Arnd Bergmann, Mauro Carvalho Chehab, Jiri Pirko,
	Arend van Spriel, Kalle Valo, Andrey Ryabinin,
	Alexander Potapenko, Dmitry Vyukov, Masahiro Yamada, Michal Marek,
	Andrew Morton, Kees Cook, Geert Uytterhoeven, Greg Kroah-Hartman,
	linux-media, linux-kernel, netdev, linux-wireless,
	brcm80211-dev-list.pdl, brcm80211-dev-list, kasan-dev,
	linux-kbuild, Jakub Jelinek, Martin Liška, stable
In-Reply-To: <20170922212930.620249-1-arnd@arndb.de>

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=]

Most of this problem is now solved in gcc-8, which can consolidate
the stack slots for the inline function arguments. On older compilers
we can add a workaround by declaring a local variable in each function
to pass the inline function argument.

Cc: stable@vger.kernel.org
Link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81715
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 include/net/netlink.h | 73 ++++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 55 insertions(+), 18 deletions(-)

diff --git a/include/net/netlink.h b/include/net/netlink.h
index e51cf5f81597..14c289393071 100644
--- a/include/net/netlink.h
+++ b/include/net/netlink.h
@@ -773,7 +773,10 @@ static inline int nla_parse_nested(struct nlattr *tb[], int maxtype,
  */
 static inline int nla_put_u8(struct sk_buff *skb, int attrtype, u8 value)
 {
-	return nla_put(skb, attrtype, sizeof(u8), &value);
+	/* temporary variables to work around GCC PR81715 with asan-stack=1 */
+	u8 tmp = value;
+
+	return nla_put(skb, attrtype, sizeof(u8), &tmp);
 }
 
 /**
@@ -784,7 +787,9 @@ static inline int nla_put_u8(struct sk_buff *skb, int attrtype, u8 value)
  */
 static inline int nla_put_u16(struct sk_buff *skb, int attrtype, u16 value)
 {
-	return nla_put(skb, attrtype, sizeof(u16), &value);
+	u16 tmp = value;
+
+	return nla_put(skb, attrtype, sizeof(u16), &tmp);
 }
 
 /**
@@ -795,7 +800,9 @@ static inline int nla_put_u16(struct sk_buff *skb, int attrtype, u16 value)
  */
 static inline int nla_put_be16(struct sk_buff *skb, int attrtype, __be16 value)
 {
-	return nla_put(skb, attrtype, sizeof(__be16), &value);
+	__be16 tmp = value;
+
+	return nla_put(skb, attrtype, sizeof(__be16), &tmp);
 }
 
 /**
@@ -806,7 +813,9 @@ static inline int nla_put_be16(struct sk_buff *skb, int attrtype, __be16 value)
  */
 static inline int nla_put_net16(struct sk_buff *skb, int attrtype, __be16 value)
 {
-	return nla_put_be16(skb, attrtype | NLA_F_NET_BYTEORDER, value);
+	__be16 tmp = value;
+
+	return nla_put_be16(skb, attrtype | NLA_F_NET_BYTEORDER, tmp);
 }
 
 /**
@@ -817,7 +826,9 @@ static inline int nla_put_net16(struct sk_buff *skb, int attrtype, __be16 value)
  */
 static inline int nla_put_le16(struct sk_buff *skb, int attrtype, __le16 value)
 {
-	return nla_put(skb, attrtype, sizeof(__le16), &value);
+	__le16 tmp = value;
+
+	return nla_put(skb, attrtype, sizeof(__le16), &tmp);
 }
 
 /**
@@ -828,7 +839,9 @@ static inline int nla_put_le16(struct sk_buff *skb, int attrtype, __le16 value)
  */
 static inline int nla_put_u32(struct sk_buff *skb, int attrtype, u32 value)
 {
-	return nla_put(skb, attrtype, sizeof(u32), &value);
+	u32 tmp = value;
+
+	return nla_put(skb, attrtype, sizeof(u32), &tmp);
 }
 
 /**
@@ -839,7 +852,9 @@ static inline int nla_put_u32(struct sk_buff *skb, int attrtype, u32 value)
  */
 static inline int nla_put_be32(struct sk_buff *skb, int attrtype, __be32 value)
 {
-	return nla_put(skb, attrtype, sizeof(__be32), &value);
+	__be32 tmp = value;
+
+	return nla_put(skb, attrtype, sizeof(__be32), &tmp);
 }
 
 /**
@@ -850,7 +865,9 @@ static inline int nla_put_be32(struct sk_buff *skb, int attrtype, __be32 value)
  */
 static inline int nla_put_net32(struct sk_buff *skb, int attrtype, __be32 value)
 {
-	return nla_put_be32(skb, attrtype | NLA_F_NET_BYTEORDER, value);
+	__be32 tmp = value;
+
+	return nla_put_be32(skb, attrtype | NLA_F_NET_BYTEORDER, tmp);
 }
 
 /**
@@ -861,7 +878,9 @@ static inline int nla_put_net32(struct sk_buff *skb, int attrtype, __be32 value)
  */
 static inline int nla_put_le32(struct sk_buff *skb, int attrtype, __le32 value)
 {
-	return nla_put(skb, attrtype, sizeof(__le32), &value);
+	__le32 tmp = value;
+
+	return nla_put(skb, attrtype, sizeof(__le32), &tmp);
 }
 
 /**
@@ -874,7 +893,9 @@ static inline int nla_put_le32(struct sk_buff *skb, int attrtype, __le32 value)
 static inline 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);
+	u64 tmp = value;
+
+	return nla_put_64bit(skb, attrtype, sizeof(u64), &tmp, padattr);
 }
 
 /**
@@ -887,7 +908,9 @@ static inline int nla_put_u64_64bit(struct sk_buff *skb, int attrtype,
 static inline int nla_put_be64(struct sk_buff *skb, int attrtype, __be64 value,
 			       int padattr)
 {
-	return nla_put_64bit(skb, attrtype, sizeof(__be64), &value, padattr);
+	__be64 tmp = value;
+
+	return nla_put_64bit(skb, attrtype, sizeof(__be64), &tmp, padattr);
 }
 
 /**
@@ -900,7 +923,9 @@ static inline int nla_put_be64(struct sk_buff *skb, int attrtype, __be64 value,
 static inline 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,
+	__be64 tmp = value;
+
+	return nla_put_be64(skb, attrtype | NLA_F_NET_BYTEORDER, tmp,
 			    padattr);
 }
 
@@ -914,7 +939,9 @@ static inline int nla_put_net64(struct sk_buff *skb, int attrtype, __be64 value,
 static inline int nla_put_le64(struct sk_buff *skb, int attrtype, __le64 value,
 			       int padattr)
 {
-	return nla_put_64bit(skb, attrtype, sizeof(__le64), &value, padattr);
+	__le64 tmp = value;
+
+	return nla_put_64bit(skb, attrtype, sizeof(__le64), &tmp, padattr);
 }
 
 /**
@@ -925,7 +952,9 @@ static inline int nla_put_le64(struct sk_buff *skb, int attrtype, __le64 value,
  */
 static inline int nla_put_s8(struct sk_buff *skb, int attrtype, s8 value)
 {
-	return nla_put(skb, attrtype, sizeof(s8), &value);
+	s8 tmp = value;
+
+	return nla_put(skb, attrtype, sizeof(s8), &tmp);
 }
 
 /**
@@ -936,7 +965,9 @@ static inline int nla_put_s8(struct sk_buff *skb, int attrtype, s8 value)
  */
 static inline int nla_put_s16(struct sk_buff *skb, int attrtype, s16 value)
 {
-	return nla_put(skb, attrtype, sizeof(s16), &value);
+	s16 tmp = value;
+
+	return nla_put(skb, attrtype, sizeof(s16), &tmp);
 }
 
 /**
@@ -947,7 +978,9 @@ static inline int nla_put_s16(struct sk_buff *skb, int attrtype, s16 value)
  */
 static inline int nla_put_s32(struct sk_buff *skb, int attrtype, s32 value)
 {
-	return nla_put(skb, attrtype, sizeof(s32), &value);
+	s32 tmp = value;
+
+	return nla_put(skb, attrtype, sizeof(s32), &tmp);
 }
 
 /**
@@ -960,7 +993,9 @@ static inline int nla_put_s32(struct sk_buff *skb, int attrtype, s32 value)
 static inline int nla_put_s64(struct sk_buff *skb, int attrtype, s64 value,
 			      int padattr)
 {
-	return nla_put_64bit(skb, attrtype, sizeof(s64), &value, padattr);
+	s64 tmp = value;
+
+	return nla_put_64bit(skb, attrtype, sizeof(s64), &tmp, padattr);
 }
 
 /**
@@ -1010,7 +1045,9 @@ static inline int nla_put_msecs(struct sk_buff *skb, int attrtype,
 static inline int nla_put_in_addr(struct sk_buff *skb, int attrtype,
 				  __be32 addr)
 {
-	return nla_put_be32(skb, attrtype, addr);
+	__be32 tmp = addr;
+
+	return nla_put_be32(skb, attrtype, tmp);
 }
 
 /**
-- 
2.9.0

^ permalink raw reply related

* [PATCH v4 4/9] em28xx: fix em28xx_dvb_init for KASAN
From: Arnd Bergmann @ 2017-09-22 21:29 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Arnd Bergmann, Jiri Pirko, Arend van Spriel, Kalle Valo,
	David S. Miller, Andrey Ryabinin, Alexander Potapenko,
	Dmitry Vyukov, Masahiro Yamada, Michal Marek, Andrew Morton,
	Kees Cook, Geert Uytterhoeven, Greg Kroah-Hartman, linux-media,
	linux-kernel, netdev, linux-wireless, brcm80211-dev-list.pdl,
	brcm80211-dev-list, kasan-dev, linux-kbuild, Jakub Jelinek,
	Martin Liška, stable
In-Reply-To: <20170922212930.620249-1-arnd@arndb.de>

With CONFIG_KASAN, the init function uses a large amount of kernel stack:

drivers/media/usb/em28xx/em28xx-dvb.c: In function 'em28xx_dvb_init.part.4':
drivers/media/usb/em28xx/em28xx-dvb.c:2061:1: error: the frame size of 3232 bytes is larger than 2048 bytes [-Werror=frame-larger-than=]

It seems that this is triggered in part by using strlcpy(), which the
compiler doesn't recognize as copying at most 'len' bytes, since strlcpy
is not part of the C standard.

It does however recognize the standard strncpy() and optimizes away
the extra checks for that, using only 1688 bytes in the end.
I have another larger patch that we could use in addition to this one,
in order to shrink the stack for -fsanitize-address-use-after-scope
(with gcc-7.1.1) as well, but that would not be appropriate for
stable backports, so let's focus on this one first.

Cc: stable@vger.kernel.org
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 drivers/media/usb/em28xx/em28xx-dvb.c | 30 +++++++++++++++---------------
 1 file changed, 15 insertions(+), 15 deletions(-)

diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c
index 4a7db623fe29..06c363dc55ed 100644
--- a/drivers/media/usb/em28xx/em28xx-dvb.c
+++ b/drivers/media/usb/em28xx/em28xx-dvb.c
@@ -1440,7 +1440,7 @@ static int em28xx_dvb_init(struct em28xx *dev)
 		tda10071_pdata.pll_multiplier = 20,
 		tda10071_pdata.tuner_i2c_addr = 0x14,
 		memset(&board_info, 0, sizeof(board_info));
-		strlcpy(board_info.type, "tda10071_cx24118", I2C_NAME_SIZE);
+		strncpy(board_info.type, "tda10071_cx24118", I2C_NAME_SIZE - 1);
 		board_info.addr = 0x55;
 		board_info.platform_data = &tda10071_pdata;
 		request_module("tda10071");
@@ -1460,7 +1460,7 @@ static int em28xx_dvb_init(struct em28xx *dev)
 		/* attach SEC */
 		a8293_pdata.dvb_frontend = dvb->fe[0];
 		memset(&board_info, 0, sizeof(board_info));
-		strlcpy(board_info.type, "a8293", I2C_NAME_SIZE);
+		strncpy(board_info.type, "a8293", I2C_NAME_SIZE - 1);
 		board_info.addr = 0x08;
 		board_info.platform_data = &a8293_pdata;
 		request_module("a8293");
@@ -1643,7 +1643,7 @@ static int em28xx_dvb_init(struct em28xx *dev)
 		m88ds3103_pdata.ts_clk_pol = 1;
 		m88ds3103_pdata.agc = 0x99;
 		memset(&board_info, 0, sizeof(board_info));
-		strlcpy(board_info.type, "m88ds3103", I2C_NAME_SIZE);
+		strncpy(board_info.type, "m88ds3103", I2C_NAME_SIZE - 1);
 		board_info.addr = 0x68;
 		board_info.platform_data = &m88ds3103_pdata;
 		request_module("m88ds3103");
@@ -1664,7 +1664,7 @@ static int em28xx_dvb_init(struct em28xx *dev)
 		/* attach tuner */
 		ts2020_config.fe = dvb->fe[0];
 		memset(&board_info, 0, sizeof(board_info));
-		strlcpy(board_info.type, "ts2022", I2C_NAME_SIZE);
+		strncpy(board_info.type, "ts2022", I2C_NAME_SIZE - 1);
 		board_info.addr = 0x60;
 		board_info.platform_data = &ts2020_config;
 		request_module("ts2020");
@@ -1690,7 +1690,7 @@ static int em28xx_dvb_init(struct em28xx *dev)
 		/* attach SEC */
 		a8293_pdata.dvb_frontend = dvb->fe[0];
 		memset(&board_info, 0, sizeof(board_info));
-		strlcpy(board_info.type, "a8293", I2C_NAME_SIZE);
+		strncpy(board_info.type, "a8293", I2C_NAME_SIZE - 1);
 		board_info.addr = 0x08;
 		board_info.platform_data = &a8293_pdata;
 		request_module("a8293");
@@ -1729,7 +1729,7 @@ static int em28xx_dvb_init(struct em28xx *dev)
 			si2168_config.fe = &dvb->fe[0];
 			si2168_config.ts_mode = SI2168_TS_PARALLEL;
 			memset(&info, 0, sizeof(struct i2c_board_info));
-			strlcpy(info.type, "si2168", I2C_NAME_SIZE);
+			strncpy(info.type, "si2168", I2C_NAME_SIZE - 1);
 			info.addr = 0x64;
 			info.platform_data = &si2168_config;
 			request_module(info.type);
@@ -1755,7 +1755,7 @@ static int em28xx_dvb_init(struct em28xx *dev)
 			si2157_config.mdev = dev->media_dev;
 #endif
 			memset(&info, 0, sizeof(struct i2c_board_info));
-			strlcpy(info.type, "si2157", I2C_NAME_SIZE);
+			strncpy(info.type, "si2157", I2C_NAME_SIZE - 1);
 			info.addr = 0x60;
 			info.platform_data = &si2157_config;
 			request_module(info.type);
@@ -1793,7 +1793,7 @@ static int em28xx_dvb_init(struct em28xx *dev)
 			si2168_config.fe = &dvb->fe[0];
 			si2168_config.ts_mode = SI2168_TS_PARALLEL;
 			memset(&info, 0, sizeof(struct i2c_board_info));
-			strlcpy(info.type, "si2168", I2C_NAME_SIZE);
+			strncpy(info.type, "si2168", I2C_NAME_SIZE - 1);
 			info.addr = 0x64;
 			info.platform_data = &si2168_config;
 			request_module(info.type);
@@ -1819,7 +1819,7 @@ static int em28xx_dvb_init(struct em28xx *dev)
 			si2157_config.mdev = dev->media_dev;
 #endif
 			memset(&info, 0, sizeof(struct i2c_board_info));
-			strlcpy(info.type, "si2146", I2C_NAME_SIZE);
+			strncpy(info.type, "si2146", I2C_NAME_SIZE - 1);
 			info.addr = 0x60;
 			info.platform_data = &si2157_config;
 			request_module("si2157");
@@ -1853,7 +1853,7 @@ static int em28xx_dvb_init(struct em28xx *dev)
 			/* attach demod */
 			memset(&tc90522_config, 0, sizeof(tc90522_config));
 			memset(&info, 0, sizeof(struct i2c_board_info));
-			strlcpy(info.type, "tc90522sat", I2C_NAME_SIZE);
+			strncpy(info.type, "tc90522sat", I2C_NAME_SIZE - 1);
 			info.addr = 0x15;
 			info.platform_data = &tc90522_config;
 			request_module("tc90522");
@@ -1875,7 +1875,7 @@ static int em28xx_dvb_init(struct em28xx *dev)
 			qm1d1c0042_config.fe = tc90522_config.fe;
 			qm1d1c0042_config.lpf = 1;
 			memset(&info, 0, sizeof(struct i2c_board_info));
-			strlcpy(info.type, "qm1d1c0042", I2C_NAME_SIZE);
+			strncpy(info.type, "qm1d1c0042", I2C_NAME_SIZE - 1);
 			info.addr = 0x61;
 			info.platform_data = &qm1d1c0042_config;
 			request_module(info.type);
@@ -1913,7 +1913,7 @@ static int em28xx_dvb_init(struct em28xx *dev)
 			si2168_config.fe = &dvb->fe[0];
 			si2168_config.ts_mode = SI2168_TS_SERIAL;
 			memset(&info, 0, sizeof(struct i2c_board_info));
-			strlcpy(info.type, "si2168", I2C_NAME_SIZE);
+			strncpy(info.type, "si2168", I2C_NAME_SIZE - 1);
 			info.addr = 0x64;
 			info.platform_data = &si2168_config;
 			request_module(info.type);
@@ -1939,7 +1939,7 @@ static int em28xx_dvb_init(struct em28xx *dev)
 			si2157_config.mdev = dev->media_dev;
 #endif
 			memset(&info, 0, sizeof(struct i2c_board_info));
-			strlcpy(info.type, "si2157", I2C_NAME_SIZE);
+			strncpy(info.type, "si2157", I2C_NAME_SIZE - 1);
 			info.addr = 0x60;
 			info.platform_data = &si2157_config;
 			request_module(info.type);
@@ -1975,7 +1975,7 @@ static int em28xx_dvb_init(struct em28xx *dev)
 			lgdt3306a_config = hauppauge_01595_lgdt3306a_config;
 			lgdt3306a_config.fe = &dvb->fe[0];
 			lgdt3306a_config.i2c_adapter = &adapter;
-			strlcpy(info.type, "lgdt3306a", sizeof(info.type));
+			strncpy(info.type, "lgdt3306a", sizeof(info.type) - 1);
 			info.addr = 0x59;
 			info.platform_data = &lgdt3306a_config;
 			request_module(info.type);
@@ -2002,7 +2002,7 @@ static int em28xx_dvb_init(struct em28xx *dev)
 			si2157_config.mdev = dev->media_dev;
 #endif
 			memset(&info, 0, sizeof(struct i2c_board_info));
-			strlcpy(info.type, "si2157", sizeof(info.type));
+			strncpy(info.type, "si2157", sizeof(info.type) - 1);
 			info.addr = 0x60;
 			info.platform_data = &si2157_config;
 			request_module(info.type);
-- 
2.9.0

^ permalink raw reply related

* [PATCH v4 6/9] dvb-frontends: fix i2c access helpers for KASAN
From: Arnd Bergmann @ 2017-09-22 21:29 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Arnd Bergmann, Jiri Pirko, Arend van Spriel, Kalle Valo,
	David S. Miller, Andrey Ryabinin, Alexander Potapenko,
	Dmitry Vyukov, Masahiro Yamada, Michal Marek, Andrew Morton,
	Kees Cook, Geert Uytterhoeven, Greg Kroah-Hartman, linux-media,
	linux-kernel, netdev, linux-wireless, brcm80211-dev-list.pdl,
	brcm80211-dev-list, kasan-dev, linux-kbuild, Jakub Jelinek,
	Martin Liška, stable
In-Reply-To: <20170922212930.620249-1-arnd@arndb.de>

A typical code fragment was copied across many dvb-frontend drivers and
causes large stack frames when built with with CONFIG_KASAN on gcc-5/6/7:

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=]

gcc-8 now solves this by consolidating the stack slots for the argument
variables, but on older compilers we can get the same behavior by taking
the pointer of a local variable rather than the inline function argument.

Cc: stable@vger.kernel.org
Link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81715
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
I'm undecided here whether there should be a comment pointing
to PR81715 for each file that the bogus local variable workaround
to prevent it from being cleaned up again. It's probably not
necessary since anything that causes actual problems would also
trigger a build warning.
---
 drivers/media/dvb-frontends/ascot2e.c     | 4 +++-
 drivers/media/dvb-frontends/cxd2841er.c   | 4 +++-
 drivers/media/dvb-frontends/helene.c      | 4 +++-
 drivers/media/dvb-frontends/horus3a.c     | 4 +++-
 drivers/media/dvb-frontends/itd1000.c     | 5 +++--
 drivers/media/dvb-frontends/mt312.c       | 4 +++-
 drivers/media/dvb-frontends/stb0899_drv.c | 3 ++-
 drivers/media/dvb-frontends/stb6100.c     | 6 ++++--
 drivers/media/dvb-frontends/stv0367.c     | 4 +++-
 drivers/media/dvb-frontends/stv090x.c     | 4 +++-
 drivers/media/dvb-frontends/stv6110x.c    | 4 +++-
 drivers/media/dvb-frontends/zl10039.c     | 4 +++-
 12 files changed, 36 insertions(+), 14 deletions(-)

diff --git a/drivers/media/dvb-frontends/ascot2e.c b/drivers/media/dvb-frontends/ascot2e.c
index 0ee0df53b91b..1219272ca3f0 100644
--- a/drivers/media/dvb-frontends/ascot2e.c
+++ b/drivers/media/dvb-frontends/ascot2e.c
@@ -155,7 +155,9 @@ static int ascot2e_write_regs(struct ascot2e_priv *priv,
 
 static int ascot2e_write_reg(struct ascot2e_priv *priv, u8 reg, u8 val)
 {
-	return ascot2e_write_regs(priv, reg, &val, 1);
+	u8 tmp = val;
+
+	return ascot2e_write_regs(priv, reg, &tmp, 1);
 }
 
 static int ascot2e_read_regs(struct ascot2e_priv *priv,
diff --git a/drivers/media/dvb-frontends/cxd2841er.c b/drivers/media/dvb-frontends/cxd2841er.c
index 48ee9bc00c06..b7574deff5c6 100644
--- a/drivers/media/dvb-frontends/cxd2841er.c
+++ b/drivers/media/dvb-frontends/cxd2841er.c
@@ -257,7 +257,9 @@ static int cxd2841er_write_regs(struct cxd2841er_priv *priv,
 static int cxd2841er_write_reg(struct cxd2841er_priv *priv,
 			       u8 addr, u8 reg, u8 val)
 {
-	return cxd2841er_write_regs(priv, addr, reg, &val, 1);
+	u8 tmp = val;
+
+	return cxd2841er_write_regs(priv, addr, reg, &tmp, 1);
 }
 
 static int cxd2841er_read_regs(struct cxd2841er_priv *priv,
diff --git a/drivers/media/dvb-frontends/helene.c b/drivers/media/dvb-frontends/helene.c
index 4bf5a551ba40..6e93f2d1575b 100644
--- a/drivers/media/dvb-frontends/helene.c
+++ b/drivers/media/dvb-frontends/helene.c
@@ -331,7 +331,9 @@ static int helene_write_regs(struct helene_priv *priv,
 
 static int helene_write_reg(struct helene_priv *priv, u8 reg, u8 val)
 {
-	return helene_write_regs(priv, reg, &val, 1);
+	u8 tmp = val;
+
+	return helene_write_regs(priv, reg, &tmp, 1);
 }
 
 static int helene_read_regs(struct helene_priv *priv,
diff --git a/drivers/media/dvb-frontends/horus3a.c b/drivers/media/dvb-frontends/horus3a.c
index 68d759c4c52e..fa9e2d373073 100644
--- a/drivers/media/dvb-frontends/horus3a.c
+++ b/drivers/media/dvb-frontends/horus3a.c
@@ -89,7 +89,9 @@ static int horus3a_write_regs(struct horus3a_priv *priv,
 
 static int horus3a_write_reg(struct horus3a_priv *priv, u8 reg, u8 val)
 {
-	return horus3a_write_regs(priv, reg, &val, 1);
+	u8 tmp = val;
+
+	return horus3a_write_regs(priv, reg, &tmp, 1);
 }
 
 static int horus3a_enter_power_save(struct horus3a_priv *priv)
diff --git a/drivers/media/dvb-frontends/itd1000.c b/drivers/media/dvb-frontends/itd1000.c
index 5bb1e73a10b4..1ac5177162f6 100644
--- a/drivers/media/dvb-frontends/itd1000.c
+++ b/drivers/media/dvb-frontends/itd1000.c
@@ -95,8 +95,9 @@ static int itd1000_read_reg(struct itd1000_state *state, u8 reg)
 
 static inline 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;
+	u8 tmp = v;
+	int ret = itd1000_write_regs(state, r, &tmp, 1);
+	state->shadow[r] = tmp;
 	return ret;
 }
 
diff --git a/drivers/media/dvb-frontends/mt312.c b/drivers/media/dvb-frontends/mt312.c
index 961b9a2508e0..12c32c024252 100644
--- a/drivers/media/dvb-frontends/mt312.c
+++ b/drivers/media/dvb-frontends/mt312.c
@@ -142,7 +142,9 @@ static inline int mt312_readreg(struct mt312_state *state,
 static inline int mt312_writereg(struct mt312_state *state,
 				 const enum mt312_reg_addr reg, const u8 val)
 {
-	return mt312_write(state, reg, &val, 1);
+	u8 tmp = val;
+
+	return mt312_write(state, reg, &tmp, 1);
 }
 
 static inline u32 mt312_div(u32 a, u32 b)
diff --git a/drivers/media/dvb-frontends/stb0899_drv.c b/drivers/media/dvb-frontends/stb0899_drv.c
index 02347598277a..db5dde3215f0 100644
--- a/drivers/media/dvb-frontends/stb0899_drv.c
+++ b/drivers/media/dvb-frontends/stb0899_drv.c
@@ -539,7 +539,8 @@ int stb0899_write_regs(struct stb0899_state *state, unsigned int reg, u8 *data,
 
 int stb0899_write_reg(struct stb0899_state *state, unsigned int reg, u8 data)
 {
-	return stb0899_write_regs(state, reg, &data, 1);
+	u8 tmp = data;
+	return stb0899_write_regs(state, reg, &tmp, 1);
 }
 
 /*
diff --git a/drivers/media/dvb-frontends/stb6100.c b/drivers/media/dvb-frontends/stb6100.c
index 17a955d0031b..0167a3e1ecc5 100644
--- a/drivers/media/dvb-frontends/stb6100.c
+++ b/drivers/media/dvb-frontends/stb6100.c
@@ -226,12 +226,14 @@ static int stb6100_write_reg_range(struct stb6100_state *state, u8 buf[], int st
 
 static int stb6100_write_reg(struct stb6100_state *state, u8 reg, u8 data)
 {
+	u8 tmp = data;
+
 	if (unlikely(reg >= STB6100_NUMREGS)) {
 		dprintk(verbose, FE_ERROR, 1, "Invalid register offset 0x%x", reg);
 		return -EREMOTEIO;
 	}
-	data = (data & stb6100_template[reg].mask) | stb6100_template[reg].set;
-	return stb6100_write_reg_range(state, &data, reg, 1);
+	tmp = (tmp & stb6100_template[reg].mask) | stb6100_template[reg].set;
+	return stb6100_write_reg_range(state, &tmp, reg, 1);
 }
 
 
diff --git a/drivers/media/dvb-frontends/stv0367.c b/drivers/media/dvb-frontends/stv0367.c
index f3529df8211d..1964cb7d58b7 100644
--- a/drivers/media/dvb-frontends/stv0367.c
+++ b/drivers/media/dvb-frontends/stv0367.c
@@ -166,7 +166,9 @@ int stv0367_writeregs(struct stv0367_state *state, u16 reg, u8 *data, int len)
 
 static int stv0367_writereg(struct stv0367_state *state, u16 reg, u8 data)
 {
-	return stv0367_writeregs(state, reg, &data, 1);
+	u8 tmp = data;
+
+	return stv0367_writeregs(state, reg, &tmp, 1);
 }
 
 static u8 stv0367_readreg(struct stv0367_state *state, u16 reg)
diff --git a/drivers/media/dvb-frontends/stv090x.c b/drivers/media/dvb-frontends/stv090x.c
index 7ef469c0c866..85ec19305483 100644
--- a/drivers/media/dvb-frontends/stv090x.c
+++ b/drivers/media/dvb-frontends/stv090x.c
@@ -755,7 +755,9 @@ static int stv090x_write_regs(struct stv090x_state *state, unsigned int reg, u8
 
 static int stv090x_write_reg(struct stv090x_state *state, unsigned int reg, u8 data)
 {
-	return stv090x_write_regs(state, reg, &data, 1);
+	u8 tmp = data;
+
+	return stv090x_write_regs(state, reg, &tmp, 1);
 }
 
 static int stv090x_i2c_gate_ctrl(struct stv090x_state *state, int enable)
diff --git a/drivers/media/dvb-frontends/stv6110x.c b/drivers/media/dvb-frontends/stv6110x.c
index 66eba38f1014..f0fd9605aa77 100644
--- a/drivers/media/dvb-frontends/stv6110x.c
+++ b/drivers/media/dvb-frontends/stv6110x.c
@@ -97,7 +97,9 @@ static int stv6110x_write_regs(struct stv6110x_state *stv6110x, int start, u8 da
 
 static int stv6110x_write_reg(struct stv6110x_state *stv6110x, u8 reg, u8 data)
 {
-	return stv6110x_write_regs(stv6110x, reg, &data, 1);
+	u8 tmp = data;
+
+	return stv6110x_write_regs(stv6110x, reg, &tmp, 1);
 }
 
 static int stv6110x_init(struct dvb_frontend *fe)
diff --git a/drivers/media/dvb-frontends/zl10039.c b/drivers/media/dvb-frontends/zl10039.c
index 623355fc2666..4ec9a8fb8c12 100644
--- a/drivers/media/dvb-frontends/zl10039.c
+++ b/drivers/media/dvb-frontends/zl10039.c
@@ -134,7 +134,9 @@ static inline int zl10039_writereg(struct zl10039_state *state,
 				const enum zl10039_reg_addr reg,
 				const u8 val)
 {
-	return zl10039_write(state, reg, &val, 1);
+	const u8 tmp = val;
+
+	return zl10039_write(state, reg, &tmp, 1);
 }
 
 static int zl10039_init(struct dvb_frontend *fe)
-- 
2.9.0

^ permalink raw reply related

* [PATCH v4 5/9] r820t: fix r820t_write_reg for KASAN
From: Arnd Bergmann @ 2017-09-22 21:29 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Arnd Bergmann, Jiri Pirko, Arend van Spriel, Kalle Valo,
	David S. Miller, Andrey Ryabinin, Alexander Potapenko,
	Dmitry Vyukov, Masahiro Yamada, Michal Marek, Andrew Morton,
	Kees Cook, Geert Uytterhoeven, Greg Kroah-Hartman, linux-media,
	linux-kernel, netdev, linux-wireless, brcm80211-dev-list.pdl,
	brcm80211-dev-list, kasan-dev, linux-kbuild, Jakub Jelinek,
	Martin Liška
In-Reply-To: <20170922212930.620249-1-arnd@arndb.de>

With CONFIG_KASAN, we get an overly long stack frame due to inlining
the register access functions:

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=]

This is caused by a gcc bug that has now been fixed in gcc-8.
To work around the problem, we can pass the register data
through a local variable that older gcc versions can optimize
out as well.

Link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81715
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 drivers/media/tuners/r820t.c | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/drivers/media/tuners/r820t.c b/drivers/media/tuners/r820t.c
index ba80376a3b86..d097eb04a0e9 100644
--- a/drivers/media/tuners/r820t.c
+++ b/drivers/media/tuners/r820t.c
@@ -396,9 +396,11 @@ 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 inline int r820t_write_reg(struct r820t_priv *priv, u8 reg, u8 val)
 {
-	return r820t_write(priv, reg, &val, 1);
+	u8 tmp = val; /* work around GCC PR81715 with asan-stack=1 */
+
+	return r820t_write(priv, reg, &tmp, 1);
 }
 
 static int r820t_read_cache_reg(struct r820t_priv *priv, int reg)
@@ -411,17 +413,18 @@ 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 inline int r820t_write_reg_mask(struct r820t_priv *priv, u8 reg, u8 val,
 				u8 bit_mask)
 {
+	u8 tmp = val;
 	int rc = r820t_read_cache_reg(priv, reg);
 
 	if (rc < 0)
 		return rc;
 
-	val = (rc & ~bit_mask) | (val & bit_mask);
+	tmp = (rc & ~bit_mask) | (tmp & bit_mask);
 
-	return r820t_write(priv, reg, &val, 1);
+	return r820t_write(priv, reg, &tmp, 1);
 }
 
 static int r820t_read(struct r820t_priv *priv, u8 reg, u8 *val, int len)
-- 
2.9.0

^ permalink raw reply related

* [PATCH v4 3/9] brcmsmac: reindent split functions
From: Arnd Bergmann @ 2017-09-22 21:29 UTC (permalink / raw)
  To: Arend van Spriel, Franky Lin, Hante Meuleman, Chi-Hsien Lin,
	Wright Feng, Kalle Valo
  Cc: Arnd Bergmann, Mauro Carvalho Chehab, Jiri Pirko, David S. Miller,
	Andrey Ryabinin, Alexander Potapenko, Dmitry Vyukov,
	Masahiro Yamada, Michal Marek, Andrew Morton, Kees Cook,
	Geert Uytterhoeven, Greg Kroah-Hartman, linux-media, linux-kernel,
	netdev, linux-wireless, brcm80211-dev-list.pdl,
	brcm80211-dev-list, kasan-dev, linux-kbuild, Jakub Jelinek,
	Martin Liška
In-Reply-To: <20170922212930.620249-1-arnd@arndb.de>

In the previous commit I left the indentation alone to help reviewing
the patch, this one now runs the three new functions through 'indent -kr -8'
with some manual fixups to avoid silliness.

No changes other than whitespace are intended here.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
---
 .../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

^ permalink raw reply related

* [PATCH v4 2/9] brcmsmac: split up wlc_phy_workarounds_nphy
From: Arnd Bergmann @ 2017-09-22 21:29 UTC (permalink / raw)
  To: Arend van Spriel, Franky Lin, Hante Meuleman, Chi-Hsien Lin,
	Wright Feng, Kalle Valo
  Cc: Arnd Bergmann, Mauro Carvalho Chehab, Jiri Pirko, David S. Miller,
	Andrey Ryabinin, Alexander Potapenko, Dmitry Vyukov,
	Masahiro Yamada, Michal Marek, Andrew Morton, Kees Cook,
	Geert Uytterhoeven, Greg Kroah-Hartman, linux-media, linux-kernel,
	netdev, linux-wireless, brcm80211-dev-list.pdl,
	brcm80211-dev-list, kasan-dev, linux-kbuild, Jakub Jelinek,
	Martin Liška
In-Reply-To: <20170922212930.620249-1-arnd@arndb.de>

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 <arend.vanspriel@broadcom.com>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 .../broadcom/brcm80211/brcmsmac/phy/phy_n.c        | 178 ++++++++++++---------
 1 file changed, 104 insertions(+), 74 deletions(-)

This one and the following patch could be merged for either v4.14 or
v4.15 at this point, whichever the maintainers prefer. No need to
backport them to stable kernels.

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

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox