Linux wireless drivers development
 help / color / mirror / Atom feed
* Minimal cross-compilation fix for CRDA
From: Philip A. Prindeville @ 2009-08-13  1:45 UTC (permalink / raw)
  To: wireless

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

Reposting.

I think I've addresses all of the comments, and this fix is as short as
possible.

I considered passing in all of the variables from outside, but (a) this
doesn't scale well, and (b) things like $(NLLIBNAME) are "scratch"
variables used by the make process when doing discovery about the host
it's running on... they shouldn't be externally visible, much less
overridden by some encompassing make.

Putting the auto-discovery into its own path with a gating variable
seems like the cleanest, most robust, most maintainable approach.



[-- Attachment #2: crda-cross-compile.patch --]
[-- Type: text/plain, Size: 1543 bytes --]

Changes:

1. Move invariant definitions to before any cross-compilation conditional sections for clarity (and to avoid having to duplicate them).

2. Bracket any host (native) compilation sections with conditional based on $(CROSS_COMPILE) being empty.

4. Add 'else' section for cross-compilation using openssl and libnl-1 (or libnl-2 if explicitly selected).


--- crda-1.1.0/Makefile	2009-08-10 13:37:36.000000000 -0700
+++ crda-1.1.0/Makefile.new	2009-08-10 17:29:22.000000000 -0700
@@ -22,12 +22,17 @@
 # with make PUBKEY_DIR=/usr/lib/crda/pubkeys
 PUBKEY_DIR?=pubkeys
 
+MKDIR ?= mkdir -p
+INSTALL ?= install
+
 CFLAGS += -Wall -g
 
 all: all_noverify verify
 
 all_noverify: crda intersect regdbdump
 
+ifeq ($(CROSS_COMPILE),)
+
 ifeq ($(USE_OPENSSL),1)
 CFLAGS += -DUSE_OPENSSL `pkg-config --cflags openssl`
 LDLIBS += `pkg-config --libs openssl`
@@ -41,8 +46,6 @@
 reglib.o: keys-gcrypt.c
 
 endif
-MKDIR ?= mkdir -p
-INSTALL ?= install
 
 NL1FOUND := $(shell pkg-config --atleast-version=1 libnl-1 && echo Y)
 NL2FOUND := $(shell pkg-config --atleast-version=2 libnl-2.0 && echo Y)
@@ -64,6 +67,31 @@
 NLLIBS += `pkg-config --libs $(NLLIBNAME)`
 CFLAGS += `pkg-config --cflags $(NLLIBNAME)`
 
+else
+
+ifeq ($(USE_OPENSSL),1)
+CFLAGS += -DUSE_OPENSSL
+LDLIBS += -lssl
+
+reglib.o: keys-ssl.c
+
+else
+CFLAGS += -DUSE_GCRYPT
+LDLIBS += -lgcrypt
+
+reglib.o: keys-gcrypt.c
+
+endif
+
+ifeq ($(USE_LIBNL20),1)
+CFLAGS += -DCONFIG_LIBNL20
+NLLIBS = -lnl-genl -lnl-2.0
+else
+NLLIBS = -lnl
+endif
+
+endif
+
 ifeq ($(V),1)
 Q=
 NQ=@true

^ permalink raw reply

* Re: pull request: wireless-2.6 2009-08-11
From: David Miller @ 2009-08-13  0:38 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, netdev, linux-kernel
In-Reply-To: <20090812182403.GF2657@tuxdriver.com>

From: "John W. Linville" <linville@tuxdriver.com>
Date: Wed, 12 Aug 2009 14:24:03 -0400

> When you pull this, could you also revert 57921c31 ("libertas: Read
> buffer overflow").  It has been shown to create a new problem.  There
> is work towards a solution to that one, but it isn't a simple clean-up.

Done.

^ permalink raw reply

* Re: pull request: wireless-2.6 2009-08-11
From: David Miller @ 2009-08-13  0:37 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, netdev, linux-kernel
In-Reply-To: <20090811183605.GG2634@tuxdriver.com>

From: "John W. Linville" <linville@tuxdriver.com>
Date: Tue, 11 Aug 2009 14:36:06 -0400

> Here are a couple more minor fixes intended for 2.6.31.  Hopefully we
> are winding-down!

Pulled, thanks John.

^ permalink raw reply

* Re: [PATCH 16/16] iwlwifi: disable powersave mode
From: reinette chatre @ 2009-08-12 21:53 UTC (permalink / raw)
  To: Kalle Valo
  Cc: linville@tuxdriver.com, linux-wireless@vger.kernel.org,
	ipw3945-devel@lists.sourceforge.net, Guy, Wey-Yi W
In-Reply-To: <87k518kgmm.fsf@litku.valot.fi>

On Wed, 2009-08-12 at 11:54 -0700, Kalle Valo wrote:
> reinette chatre <reinette.chatre@intel.com> writes:

> >> You are again creating driver specific parameters. But we should be
> >> moving away from this and instead use just generic interfaces. Please,
> >> think three times (or even more) whenever creating new driver specific
> >> interfaces, be it module parameters, sysfs files etc.. It's a
> >> maintenance nightmare and also very confusing for the users. We need to
> >> focus on nl80211 and make it work properly with all drivers.
> >
> > What we have done here is not intended to be maintained at all - this is
> > why the module parameter description reads "power save support
> > (deprecated) (default disabled)" - it is deprecated from the beginning.
> 
> Yes, I understand this. But creating a new module parameters should be
> added carefully only when really needed, just to avoid confusion within
> users. And it sounds wrong to create a new variable which is deprecated
> from the beginning. If it needs to be deprecated, don't create it at
> all. Simple as that.
> 
> What I'm worried is the complexity of the driver interfaces and
> configuration methods. For iwlwifi power save, after this patch, we have
> now:
> 
> o Wireless Extensions
> o sysfs
> o CONFIG_CFG80211_DEFAULT_PS Kconfig parameter

We could not see how any of the current measures can be used to
accomplish out goal. Fortunately Johannes implemented something that now
can be used to accomplish this.

John, could you please revert this patch? Johannes's new "cfg80211:
allow driver to override PS default" makes it possible for us to have
power save support disabled.

Thank you very much

Reinette



^ permalink raw reply

* Re: pull request: wireless-2.6 2009-08-11
From: David Miller @ 2009-08-12 21:52 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, netdev, linux-kernel
In-Reply-To: <20090812182403.GF2657@tuxdriver.com>

From: "John W. Linville" <linville@tuxdriver.com>
Date: Wed, 12 Aug 2009 14:24:03 -0400

> When you pull this, could you also revert 57921c31 ("libertas: Read
> buffer overflow").  It has been shown to create a new problem.  There
> is work towards a solution to that one, but it isn't a simple clean-up.

Ok, I'll take care of that.

^ permalink raw reply

* [PATCH] ath9k: update kconfig to indicate support for AR9002 family
From: Luis R. Rodriguez @ 2009-08-12 21:45 UTC (permalink / raw)
  To: linville
  Cc: linux-wireless, ath9k-devel, ath5k-devel, Luis R. Rodriguez,
	Dakota Lee

ath9k supports the AR9002 family of chipsets. This includes
the AR9285 and the miniPCI AR9223 and AR9220 (which themselves
have AR9280+AR5133).

We now refer people to the wiki page as it seems this is not
as popular as we would have hoped.

Reported-by: JD <jd1008@gmail.com>
Cc: Dakota Lee <Dakota.Lee@Atheros.com>
Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
---
 drivers/net/wireless/ath/ath9k/Kconfig |    8 +++++++-
 1 files changed, 7 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig
index 2cb72f8..ef5f59c 100644
--- a/drivers/net/wireless/ath/ath9k/Kconfig
+++ b/drivers/net/wireless/ath/ath9k/Kconfig
@@ -6,7 +6,13 @@ config ATH9K
 	select NEW_LEDS
 	---help---
 	  This module adds support for wireless adapters based on
-	  Atheros IEEE 802.11n AR5008 and AR9001 family of chipsets.
+	  Atheros IEEE 802.11n AR5008, AR9001 and AR9002 family
+	  of chipsets. For a specific list of supported external
+	  cards, laptops that already ship with these cards and
+	  APs that come with these cards refer to to ath9k wiki
+	  products page:
+
+	  http://wireless.kernel.org/en/users/Drivers/ath9k/products
 
 	  If you choose to build a module, it'll be called ath9k.
 
-- 
1.6.3.3


^ permalink raw reply related

* [PATCH] cfg80211: allow driver to override PS default
From: Johannes Berg @ 2009-08-12 21:33 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless

Sometimes drivers might have a good reason to override
the PS default, like iwlwifi right now where it affects
RX performance significantly at this point. This will
allow them to override the default, if desired, in a
way that users can still change it according to their
trade-off choices, not the driver's, like would happen
if the driver just disabled PS completely then.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
 include/net/cfg80211.h |    4 ++++
 net/wireless/core.c    |    4 +++-
 2 files changed, 7 insertions(+), 1 deletion(-)

--- wireless-testing.orig/include/net/cfg80211.h	2009-08-12 23:17:58.000000000 +0200
+++ wireless-testing/include/net/cfg80211.h	2009-08-12 23:19:13.000000000 +0200
@@ -1108,6 +1108,9 @@ struct cfg80211_ops {
  * @net: the network namespace this wiphy currently lives in
  * @netnsok: if set to false, do not allow changing the netns of this
  *	wiphy at all
+ * @ps_default: default for powersave, will be set depending on the
+ *	kernel's default on wiphy_new(), but can be changed by the
+ *	driver if it has a good reason to override the default
  */
 struct wiphy {
 	/* assign these fields before you register the wiphy */
@@ -1123,6 +1126,7 @@ struct wiphy {
 	bool disable_beacon_hints;
 
 	bool netnsok;
+	bool ps_default;
 
 	enum cfg80211_signal_type signal_type;
 
--- wireless-testing.orig/net/wireless/core.c	2009-08-12 23:19:17.000000000 +0200
+++ wireless-testing/net/wireless/core.c	2009-08-12 23:19:56.000000000 +0200
@@ -412,6 +412,8 @@ struct wiphy *wiphy_new(const struct cfg
 	rdev->wiphy.dev.class = &ieee80211_class;
 	rdev->wiphy.dev.platform_data = rdev;
 
+	rdev->wiphy.ps_default = CONFIG_CFG80211_DEFAULT_PS_VALUE;
+
 	wiphy_net_set(&rdev->wiphy, &init_net);
 
 	rdev->rfkill_ops.set_block = cfg80211_rfkill_set_block;
@@ -674,7 +676,7 @@ static int cfg80211_netdev_notifier_call
 		wdev->wext.default_key = -1;
 		wdev->wext.default_mgmt_key = -1;
 		wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
-		wdev->wext.ps = CONFIG_CFG80211_DEFAULT_PS_VALUE;
+		wdev->wext.ps = wdev->wiphy->ps_default;
 		wdev->wext.ps_timeout = 100;
 		if (rdev->ops->set_power_mgmt)
 			if (rdev->ops->set_power_mgmt(wdev->wiphy, dev,



^ permalink raw reply

* Re: [ath9k-devel] [PATCH] ath5k: fix requested allocated RX skb size for DMA
From: Bob Copeland @ 2009-08-12 21:08 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: Jiri Slaby, linux-wireless, ath5k-devel, linville, ath9k-devel,
	Nick Kossifidis
In-Reply-To: <43e72e890908121148l2cde20a9xb2c045e03574ffaa@mail.gmail.com>

On Wed, Aug 12, 2009 at 2:48 PM, Luis R.
Rodriguez<lrodriguez@atheros.com> wrote:
> On Wed, Aug 12, 2009 at 11:13 AM, Jiri Slaby<jirislaby@gmail.com> wrote:
>> What was the exact purpose of this? My guess is that we should map
>> starting at a next cache line boundary and put this aligned address to
>> the device instead?
>
> I've heard two theories:
>
> 1) AR5210 *required* it otherwise bad we would get bad data
> 2) Performance considerations

>From what I can tell Jiri has the right guess:

  // ?? nice pointer arithmetic... should use PTR_ALIGN here?
  off = ((unsigned long) skb->data) % sc->cachelsz;
  if (off != 0)
      skb_reserve(skb, sc->cachelsz);

in other words, when we allocate, round up to the next cache line
greater than IEEE80211_MAX_LEN, then add an extra cache_line-1
bytes so we can map starting from it.

dev_alloc_skb already does some padding and alignment, and it's
configurable on a per-arch basis (though looks like only powerpc
sets it to L1 cache size, everywhere else it's 32 bytes.)

I guess if someone is bored some benchmarking would be useful.

-- 
Bob Copeland %% www.bobcopeland.com

^ permalink raw reply

* Re: [PATCH 1/2] mac802154: add a software MAC 802.15.4 implementation
From: Dmitry Eremin-Solenikov @ 2009-08-12 20:46 UTC (permalink / raw)
  To: Johannes Berg; +Cc: netdev, linux-wireless, Sergey Lapin
In-Reply-To: <1250082837.8784.21.camel@johannes.local>

On Wed, Aug 12, 2009 at 03:13:57PM +0200, Johannes Berg wrote:
> On Wed, 2009-08-12 at 17:06 +0400, Dmitry Eremin-Solenikov wrote:
> 
> > > In addition to that, you can't put anything into skb->cb, then push the
> > > frame to the master netdev, and expect things in skb->cb to still be
> > > there when the frame arrives at the master netdev. Not sure you do that
> > > (I hope not because that would be very buggy), but eventually you'll
> > > probably find that you do want that, etc.
> > 
> > Hmm. It works for us. Could you please tell me more about the problems
> > with skb->cb ?
> 
> Uh, well, you don't own the skb->cb between dev_queue_xmit() and
> ndo_start_xmit(). In fact, your phy_cb data will be overwritten by the
> qdisc.

Hmmm. Really weird. Then, if we want to pass data from socket layer to
MAC layer, we should place data in skb->data and not in skb->cb (like
radiotap header)?

> Also, looking into this a bit more, I see no reason to allocate a work
> struct every time you get a frame -- better just queue them up and stick
> everything else into skb->cb. In fact, you don't need a master netdev
> here anyway, just move all code from ieee802154_master_hard_start_xmit()
> into ieee802154_net_xmit().
> 

Nice idea. Thanks a lot!

-- 
With best wishes
Dmitry


^ permalink raw reply

* [PATCH] b43: LP-PHY: Initialize TX power control
From: Gábor Stefanik @ 2009-08-12 20:42 UTC (permalink / raw)
  To: John Linville, Michael Buesch, Larry Finger
  Cc: Broadcom Wireless, linux-wireless

The HW TX power control init still needs work.
The SW init is complete according to the specs.

Signed-off-by: Gábor Stefanik <netrolller.3d@gmail.com>
---
This depends on both the rev0/1 RC calibration patch and the
V4 dummy transmission patch I submitted earlier.

Larry, please check the SPEC TODO/SPEC FIXME comments.

 drivers/net/wireless/b43/phy_lp.c |  104 ++++++++++++++++++++++++++++++++++---
 drivers/net/wireless/b43/phy_lp.h |    5 ++
 2 files changed, 102 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c
index e05981b..6ebaeb2 100644
--- a/drivers/net/wireless/b43/phy_lp.c
+++ b/drivers/net/wireless/b43/phy_lp.c
@@ -1258,18 +1258,108 @@ static void lpphy_calibration(struct b43_wldev *dev)
 	b43_mac_enable(dev);
 }
 
+static void lpphy_set_tssi_mux(struct b43_wldev *dev, enum tssi_mux_mode mode)
+{
+	if (mode != TSSI_MUX_EXT) {
+		b43_radio_set(dev, B2063_PA_SP1, 0x2);
+		b43_phy_set(dev, B43_PHY_OFDM(0xF3), 0x1000);
+		b43_radio_write(dev, B2063_PA_CTL10, 0x51);
+		if (mode == TSSI_MUX_POSTPA) {
+			b43_radio_mask(dev, B2063_PA_SP1, 0xFFFE);
+			b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVRVAL, 0xFFC7);
+		} else {
+			b43_radio_maskset(dev, B2063_PA_SP1, 0xFFFE, 0x1);
+			b43_phy_maskset(dev, B43_LPPHY_AFE_CTL_OVRVAL,
+					0xFFC7, 0x20);
+		}
+	} else {
+		//SPEC TODO
+	}
+}
+
+static void lpphy_tx_pctl_init_hw(struct b43_wldev *dev)
+{
+	u16 tmp;
+	int i;
+
+	//SPEC TODO Call LP PHY Clear TX Power offsets
+	for (i = 0; i < 64; i++) {
+		if (dev->phy.rev >= 2)
+			b43_lptab_write(dev, B43_LPTAB32(7, i+1), i);
+		else
+			b43_lptab_write(dev, B43_LPTAB32(10, i+1), i);
+	}
+
+	b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_NNUM, 0xFF00, 0xFF);
+	b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_NNUM, 0x8FFF, 0x5000);
+	b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_IDLETSSI, 0xFFC0, 0x1F);
+	if (dev->phy.rev < 2) {
+		b43_phy_mask(dev, B43_LPPHY_LP_PHY_CTL, 0xEFFF);
+		b43_phy_maskset(dev, B43_LPPHY_LP_PHY_CTL, 0xDFFF, 0x2000);
+	} else {
+		b43_phy_mask(dev, B43_PHY_OFDM(0x103), 0xFFFE);
+		b43_phy_maskset(dev, B43_PHY_OFDM(0x103), 0xFFFB, 0x4);
+		b43_phy_maskset(dev, B43_PHY_OFDM(0x103), 0xFFEF, 0x10);
+		b43_radio_maskset(dev, B2063_IQ_CALIB_CTL2, 0xF3, 0x1);
+		lpphy_set_tssi_mux(dev, TSSI_MUX_POSTPA);
+	}
+	b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_IDLETSSI, 0x7FFF, 0x8000);
+	b43_phy_mask(dev, B43_LPPHY_TX_PWR_CTL_DELTAPWR_LIMIT, 0xFF);
+	b43_phy_write(dev, B43_LPPHY_TX_PWR_CTL_DELTAPWR_LIMIT, 0xA);
+	b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_CMD,
+			(u16)~B43_LPPHY_TX_PWR_CTL_CMD_MODE,
+			B43_LPPHY_TX_PWR_CTL_CMD_MODE_OFF);
+	b43_phy_mask(dev, B43_LPPHY_TX_PWR_CTL_NNUM, 0xF8FF);
+	b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_CMD,
+			(u16)~B43_LPPHY_TX_PWR_CTL_CMD_MODE,
+			B43_LPPHY_TX_PWR_CTL_CMD_MODE_SW);
+
+	if (dev->phy.rev < 2) {
+		b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_0, 0xEFFF, 0x1000);
+		b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xEFFF);
+	} else {
+		lpphy_set_tx_power_by_index(dev, 0x7F);
+	}
+
+	b43_dummy_transmission_v4(dev, true, true);
+
+	tmp = b43_phy_read(dev, B43_LPPHY_TX_PWR_CTL_STAT);
+	if (tmp & 0x8000)
+		b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_IDLETSSI,
+				0xFFC0, (tmp & 0xFF) - 32);
+
+	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xEFFF);
+
+	// (SPEC?) TODO Set "Target TX frequency" variable to 0
+	// SPEC FIXME "Set BB Multiplier to 0xE000" impossible - bb_mult is u8!
+}
+
+static void lpphy_tx_pctl_init_sw(struct b43_wldev *dev)
+{
+	struct lpphy_tx_gains gains;
+
+	if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
+		gains.gm = 4;
+		gains.pad = 12;
+		gains.pga = 12;
+		gains.dac = 0;
+	} else {
+		gains.gm = 7;
+		gains.pad = 14;
+		gains.pga = 15;
+		gains.dac = 0;
+	}
+	lpphy_set_tx_gains(dev, gains);
+	lpphy_set_bb_mult(dev, 150);
+}
+
 /* Initialize TX power control */
 static void lpphy_tx_pctl_init(struct b43_wldev *dev)
 {
 	if (0/*FIXME HWPCTL capable */) {
-		//TODO
+		lpphy_tx_pctl_init_hw(dev);
 	} else { /* This device is only software TX power control capable. */
-		if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
-			//TODO
-		} else {
-			//TODO
-		}
-		//TODO set BB multiplier to 0x0096
+		lpphy_tx_pctl_init_sw(dev);
 	}
 }
 
diff --git a/drivers/net/wireless/b43/phy_lp.h b/drivers/net/wireless/b43/phy_lp.h
index 0461d5b..4eab760 100644
--- a/drivers/net/wireless/b43/phy_lp.h
+++ b/drivers/net/wireless/b43/phy_lp.h
@@ -886,6 +886,11 @@ struct b43_phy_lp {
 	u16 dig_flt_state[9];
 };
 
+enum tssi_mux_mode {
+	TSSI_MUX_PREPA,
+	TSSI_MUX_POSTPA,
+	TSSI_MUX_EXT,
+};
 
 struct b43_phy_operations;
 extern const struct b43_phy_operations b43_phyops_lp;
-- 
1.6.2.4




^ permalink raw reply related

* [PATCH] b43: Update dummy transmission to match V4 specs
From: Gábor Stefanik @ 2009-08-12 20:39 UTC (permalink / raw)
  To: John Linville, Michael Buesch
  Cc: Larry Finger, Broadcom Wireless, linux-wireless

The V4 dummy transmission function has two extra bools in its
prototype, so add a wrapper function for callers that expect the
V3 version.

Signed-off-by: Gábor Stefanik <netrolller.3d@gmail.com>
---
 drivers/net/wireless/b43/main.c |   60 ++++++++++++++++++++++++++++-----------
 drivers/net/wireless/b43/main.h |    1 +
 2 files changed, 44 insertions(+), 17 deletions(-)

diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index cb4a871..80bc962 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -683,11 +683,29 @@ static void b43_synchronize_irq(struct b43_wldev *dev)
 	tasklet_kill(&dev->isr_tasklet);
 }
 
-/* DummyTransmission function, as documented on
- * http://bcm-specs.sipsolutions.net/DummyTransmission
+/* Wrapper for callers of the old V3 dummy transmission function
+ * Please don't use this in new code, call the v4 routine directly instead.
  */
 void b43_dummy_transmission(struct b43_wldev *dev)
 {
+	switch (dev->phy.type) {
+	case B43_PHYTYPE_A:
+		b43_dummy_transmission_v4(dev, true, true);
+		break;
+	case B43_PHYTYPE_B:
+	case B43_PHYTYPE_G:
+		b43_dummy_transmission_v4(dev, false, true);
+		break;
+	default:
+		B43_WARN_ON(1);
+	}
+}
+
+/* DummyTransmission function, as documented on
+ * http://bcm-v4.sipsolutions.net/802.11/DummyTransmission
+ */
+void b43_dummy_transmission_v4(struct b43_wldev *dev, bool ofdm, bool pa_on)
+{
 	struct b43_wl *wl = dev->wl;
 	struct b43_phy *phy = &dev->phy;
 	unsigned int i, max_loop;
@@ -700,19 +718,12 @@ void b43_dummy_transmission(struct b43_wldev *dev)
 		0x00000000,
 	};
 
-	switch (phy->type) {
-	case B43_PHYTYPE_A:
+	if (ofdm) {
 		max_loop = 0x1E;
 		buffer[0] = 0x000201CC;
-		break;
-	case B43_PHYTYPE_B:
-	case B43_PHYTYPE_G:
+	} else {
 		max_loop = 0xFA;
 		buffer[0] = 0x000B846E;
-		break;
-	default:
-		B43_WARN_ON(1);
-		return;
 	}
 
 	spin_lock_irq(&wl->irq_lock);
@@ -721,20 +732,35 @@ void b43_dummy_transmission(struct b43_wldev *dev)
 	for (i = 0; i < 5; i++)
 		b43_ram_write(dev, i * 4, buffer[i]);
 
-	/* Commit writes */
-	b43_read32(dev, B43_MMIO_MACCTL);
-
 	b43_write16(dev, 0x0568, 0x0000);
-	b43_write16(dev, 0x07C0, 0x0000);
-	value = ((phy->type == B43_PHYTYPE_A) ? 1 : 0);
+	if (dev->dev->id.revision < 11)
+		b43_write16(dev, 0x07C0, 0x0000);
+	else
+		b43_write16(dev, 0x07C0, 0x0100);
+	value = (ofdm ? 0x41 : 0x40);
 	b43_write16(dev, 0x050C, value);
+	if ((phy->type == B43_PHYTYPE_N) || (phy->type == B43_PHYTYPE_LP))
+		b43_write16(dev, 0x0514, 0x1A02);
 	b43_write16(dev, 0x0508, 0x0000);
 	b43_write16(dev, 0x050A, 0x0000);
 	b43_write16(dev, 0x054C, 0x0000);
 	b43_write16(dev, 0x056A, 0x0014);
 	b43_write16(dev, 0x0568, 0x0826);
 	b43_write16(dev, 0x0500, 0x0000);
-	b43_write16(dev, 0x0502, 0x0030);
+	if (!pa_on && (phy->type == B43_PHYTYPE_N)) {
+		//SPEC TODO
+	}
+
+	switch (phy->type) {
+	case B43_PHYTYPE_N:
+		b43_write16(dev, 0x0502, 0x00D0);
+		break;
+	case B43_PHYTYPE_LP:
+		b43_write16(dev, 0x0502, 0x0050);
+		break;
+	default:
+		b43_write16(dev, 0x0502, 0x0030);
+	}
 
 	if (phy->radio_ver == 0x2050 && phy->radio_rev <= 0x5)
 		b43_radio_write16(dev, 0x0051, 0x0017);
diff --git a/drivers/net/wireless/b43/main.h b/drivers/net/wireless/b43/main.h
index 40abcf5..7f26fd9 100644
--- a/drivers/net/wireless/b43/main.h
+++ b/drivers/net/wireless/b43/main.h
@@ -125,6 +125,7 @@ u64 b43_hf_read(struct b43_wldev *dev);
 void b43_hf_write(struct b43_wldev *dev, u64 value);
 
 void b43_dummy_transmission(struct b43_wldev *dev);
+void b43_dummy_transmission_v4(struct b43_wldev *dev, bool ofdm, bool pa_on);
 
 void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags);
 
-- 
1.6.2.4




^ permalink raw reply related

* [PATCH] cfg80211: check for and abort dangling scan requests
From: Johannes Berg @ 2009-08-12 20:21 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless, Wey-Yi W Guy

If you trigger a scan request on an interface and then
take it down, or rmmod the module or unplug the device
the driver might "forget" to cancel the scan request.
That is a bug in the driver, but the current behaviour
is that we just hang endlessly waiting for the netdev
refcount to become 0 which it never will. To improve
robustness, check for this situation in cfg80211, warn
about it and clean up behind the driver. I don't just
clean up silently because it's likely that the driver
also has some internal state it has now leaked.

Additionally, this fixes a locking bug, clearing the
scan_req pointer should be done under the rdev lock.

Finally, we also need to _wait_ for the scan work and
not just abort it since it might be pending and wanting
to do a cleanup.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
This currently triggers if you rmmod iwlwifi while scanning, which is
how we found it. I'll look at iwlwifi next to see why it's doing this.

 net/wireless/core.c |   10 +++++++++-
 net/wireless/core.h |    1 +
 net/wireless/scan.c |   26 ++++++++++++++++----------
 3 files changed, 26 insertions(+), 11 deletions(-)

--- wireless-testing.orig/net/wireless/core.c	2009-08-12 21:56:24.000000000 +0200
+++ wireless-testing/net/wireless/core.c	2009-08-12 22:19:52.000000000 +0200
@@ -601,8 +601,8 @@ void wiphy_unregister(struct wiphy *wiph
 
 	mutex_unlock(&cfg80211_mutex);
 
+	flush_work(&rdev->scan_done_wk);
 	cancel_work_sync(&rdev->conn_work);
-	cancel_work_sync(&rdev->scan_done_wk);
 	kfree(rdev->scan_req);
 	flush_work(&rdev->event_work);
 }
@@ -728,6 +728,13 @@ static int cfg80211_netdev_notifier_call
 #endif
 		break;
 	case NETDEV_UNREGISTER:
+		cfg80211_lock_rdev(rdev);
+
+		if (WARN_ON(rdev->scan_req && rdev->scan_req->dev == dev)) {
+			rdev->scan_req->aborted = true;
+			___cfg80211_scan_done(rdev);
+		}
+
 		mutex_lock(&rdev->devlist_mtx);
 		/*
 		 * It is possible to get NETDEV_UNREGISTER
@@ -746,6 +753,7 @@ static int cfg80211_netdev_notifier_call
 #endif
 		}
 		mutex_unlock(&rdev->devlist_mtx);
+		cfg80211_unlock_rdev(rdev);
 		break;
 	case NETDEV_PRE_UP:
 		if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype)))
--- wireless-testing.orig/net/wireless/scan.c	2009-08-12 21:55:09.000000000 +0200
+++ wireless-testing/net/wireless/scan.c	2009-08-12 22:08:48.000000000 +0200
@@ -18,19 +18,14 @@
 
 #define IEEE80211_SCAN_RESULT_EXPIRE	(15 * HZ)
 
-void __cfg80211_scan_done(struct work_struct *wk)
+void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev)
 {
-	struct cfg80211_registered_device *rdev;
 	struct cfg80211_scan_request *request;
 	struct net_device *dev;
 #ifdef CONFIG_WIRELESS_EXT
 	union iwreq_data wrqu;
 #endif
 
-	rdev = container_of(wk, struct cfg80211_registered_device,
-			    scan_done_wk);
-
-	mutex_lock(&rdev->mtx);
 	request = rdev->scan_req;
 
 	dev = request->dev;
@@ -43,9 +38,9 @@ void __cfg80211_scan_done(struct work_st
 	cfg80211_sme_scan_done(dev);
 
 	if (request->aborted)
-		nl80211_send_scan_aborted(wiphy_to_dev(request->wiphy), dev);
+		nl80211_send_scan_aborted(rdev, dev);
 	else
-		nl80211_send_scan_done(wiphy_to_dev(request->wiphy), dev);
+		nl80211_send_scan_done(rdev, dev);
 
 #ifdef CONFIG_WIRELESS_EXT
 	if (!request->aborted) {
@@ -57,11 +52,22 @@ void __cfg80211_scan_done(struct work_st
 
 	dev_put(dev);
 
-	cfg80211_unlock_rdev(rdev);
-	wiphy_to_dev(request->wiphy)->scan_req = NULL;
+	rdev->scan_req = NULL;
 	kfree(request);
 }
 
+void __cfg80211_scan_done(struct work_struct *wk)
+{
+	struct cfg80211_registered_device *rdev;
+
+	rdev = container_of(wk, struct cfg80211_registered_device,
+			    scan_done_wk);
+
+	cfg80211_lock_rdev(rdev);
+	___cfg80211_scan_done(rdev);
+	cfg80211_unlock_rdev(rdev);
+}
+
 void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)
 {
 	WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req);
--- wireless-testing.orig/net/wireless/core.h	2009-08-12 22:00:57.000000000 +0200
+++ wireless-testing/net/wireless/core.h	2009-08-12 22:01:19.000000000 +0200
@@ -368,6 +368,7 @@ void cfg80211_sme_scan_done(struct net_d
 void cfg80211_sme_rx_auth(struct net_device *dev, const u8 *buf, size_t len);
 void cfg80211_sme_disassoc(struct net_device *dev, int idx);
 void __cfg80211_scan_done(struct work_struct *wk);
+void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev);
 void cfg80211_upload_connect_keys(struct wireless_dev *wdev);
 
 struct ieee80211_channel *



^ permalink raw reply

* Re: Multiple SSID
From: Stephen Hemminger @ 2009-08-12 19:41 UTC (permalink / raw)
  To: Luis R. Rodriguez; +Cc: John W. Linville, Johannes Berg, linux-wireless
In-Reply-To: <43e72e890908121025p75b141b6o86c30518bf9de7ea@mail.gmail.com>

On Wed, 12 Aug 2009 10:25:34 -0700
"Luis R. Rodriguez" <mcgrof@gmail.com> wrote:

> On Wed, Aug 12, 2009 at 10:04 AM, Stephen
> Hemminger<shemminger@vyatta.com> wrote:
> > I have a dumb questions. How does one setup multiple SSID's with
> > current (ie not madwifi) wireless API?
> >
> > 1. I assume need to run multiple instances of hostapd with different
> >   config. Will that work?
> 
> Yes. But the next question is how to create new wlan%d AP interfaces.
> That is answered below.
> 
> > 2. Since IP address is attached to device (wlan0), how can each SSID
> >   have different IP address? Use vlan's?
> 
> The new 'iw' [2] utility could be used to create monitor interfaces or
> ad-hoc interfaces for example. We decided to only allow you to create
> an "AP" type of interface with a utility that handles the MLME in
> userspace, such a utility is hostapd. You will need to use the nl80211
> driver with hosatpd [2]. We have documented the supported wireless
> modes in our wiki [3], I suppose that could use some updating.
> 
> Anyway I believe AP-enabled devices right now only support creating 1
> AP interfface. I believe the exception to this right now is ath9k
> through the private virtual interface stuff Jouni created, but to be
> honest I have to go and review that to make sure you can create 2 APs.
> 
> Typically drivers (MadWifi) which supported multiple BSSs (therefore
> with two SSIDs) would allow you to do this by creating BSSes on the
> same channel. The ath9k virtual interface thing allows you to create
> interfaces on *separate* channels, and provides its own scheduler,
> which you can tune, for switching back and forth.
> 
> [1] http://wireless.kernel.org/en/users/Documentation/iw
> [2] http://wireless.kernel.org/en/users/Documentation/hostapd
> [3] http://wireless.kernel.org/en/users/Documentation/modes

The existing API creates another entity 'phy0' which lives in
yet another namespace, it is not a filesystem or a network device.
The only way to enumerate these is the 'iw phy' which is okay,
but does this work with hotplug (it doesn't go through udev?)
and what about network namespaces?

^ permalink raw reply

* Re: [PATCH 2/3] mac80211: fix dynamic power save for devices which have nullfunc support
From: Kalle Valo @ 2009-08-12 18:57 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linville, linux-wireless
In-Reply-To: <1250089389.26464.1.camel@johannes.local>

Johannes Berg <johannes@sipsolutions.net> writes:

> On Wed, 2009-08-12 at 17:52 +0300, Kalle Valo wrote:
>
>>  static bool is_dynamic_ps_enabled(struct ieee80211_local *local)
>>  {
>> -	if (!(local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK))
>> +
>> +	if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS))
>>  		/* driver doesn't support power save */
>>  		return false;
>
> Why the blank line?

A mistake, will remove.

>> +	if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)
>> +		/* hardware does dynamic power save */
>> +		return false;
>
> FWIW, also applies to patch 1, I think I prefer
>
> 	/* check if hardware does dynamic power save */
> 	if (local->hw.flags & ...)
> 		return false;
>
> (wrt. comment location)

I'll change that.

> and you should probably rename the function to do_software_dynamic_ps()
> or something like that?

I had problems coming up with a good name. "do" in a sense is confusing
because the function only checks the state, it doesn't have any code to
change the timer or anything like that. I'll think of this a bit more.
Suggestions are welcome.

I'll send v2 later this week. John, please drop these three patches.

-- 
Kalle Valo

^ permalink raw reply

* Re: [PATCH 16/16] iwlwifi: disable powersave mode
From: Kalle Valo @ 2009-08-12 18:54 UTC (permalink / raw)
  To: reinette chatre
  Cc: linville@tuxdriver.com, linux-wireless@vger.kernel.org,
	ipw3945-devel@lists.sourceforge.net, Guy, Wey-Yi W
In-Reply-To: <1249760168.30019.5588.camel@rc-desk>

reinette chatre <reinette.chatre@intel.com> writes:

> Hi Kalle,

Hello,

> Thank you for looking at our patches. You have great feedback.

Thank you for listening :)

>> You are again creating driver specific parameters. But we should be
>> moving away from this and instead use just generic interfaces. Please,
>> think three times (or even more) whenever creating new driver specific
>> interfaces, be it module parameters, sysfs files etc.. It's a
>> maintenance nightmare and also very confusing for the users. We need to
>> focus on nl80211 and make it work properly with all drivers.
>
> What we have done here is not intended to be maintained at all - this is
> why the module parameter description reads "power save support
> (deprecated) (default disabled)" - it is deprecated from the beginning.

Yes, I understand this. But creating a new module parameters should be
added carefully only when really needed, just to avoid confusion within
users. And it sounds wrong to create a new variable which is deprecated
from the beginning. If it needs to be deprecated, don't create it at
all. Simple as that.

What I'm worried is the complexity of the driver interfaces and
configuration methods. For iwlwifi power save, after this patch, we have
now:

o Wireless Extensions
o sysfs
o CONFIG_CFG80211_DEFAULT_PS Kconfig parameter
o module parameter

Just think how confused an average Linux user will be? Instead of adding
more, we should instead decrease the ways to configure power save. sysfs
and the module parameter are high on my list for removal.

>> For the problem at hand, I see two options:
>> 
>> 1. Users seeing the problem disable power save either via wext or with
>>    CONFIG_CFG80211_DEFAULT_PS and everyone else still can use power
>>    save. The issue will be investigated and fixed. If the AP is buggy,
>>    there isn't much we can do.
>
> Please take a look at those bug reports. What we are seeing is huge ping
> delays ( > 1000ms rtt), dropped frames which is stalling connections,
> and throughput dropping in half. This is too severe to have powersave
> enabled at this time.

Yes, that makes sense. Then disable power save from iwlwifi until the
problem is solved (or analysed that it's a problem on AP), but don't
create a new module parameter.

>> 2. If you think the problem is widespread, remove
>>    IEEE80211_HW_SUPPORTS_PS from the driver, fix the issues and renable
>>    power save support.
>
> Yes - this is the goal of this patch. At the same time we would also
> like to make it easier for the people who are testing this issue right
> now and having the module parameter makes their life easier.

The very few users who want to test this can apply a patch or edit the
source code. It's a oneliner anyway.

> This module parameter is a temporary measure used to help us fix the
> power save issues. When the issues have been resolved we will enable
> power save support by default and remove the module parameter.

I'm not going to fight about this, for now, but in the future I hope
that people would consider carefully before adding hacks like this. If
all drivers create their own configuration parameters all the time, in
the end it will become a maintenance nightmare.

-- 
Kalle Valo

^ permalink raw reply

* Re: [ath9k-devel] [PATCH] ath5k: fix requested allocated RX skb size for DMA
From: Luis R. Rodriguez @ 2009-08-12 18:48 UTC (permalink / raw)
  To: Jiri Slaby
  Cc: linux-wireless, ath5k-devel, Bob Copeland, linville, ath9k-devel,
	Nick Kossifidis
In-Reply-To: <4A83064A.2080609@gmail.com>

On Wed, Aug 12, 2009 at 11:13 AM, Jiri Slaby<jirislaby@gmail.com> wrote:
> On 08/12/2009 06:58 PM, Luis R. Rodriguez wrote:
>> --- a/drivers/net/wireless/ath/ath5k/base.c
>> +++ b/drivers/net/wireless/ath/ath5k/base.c
>> @@ -1157,17 +1157,18 @@ struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_softc *sc, dma_addr_t *skb_addr)
>>        * fake physical layer header at the start.
>>        */
>>       skb = ath_rxbuf_alloc(&sc->common,
>> -                           sc->rxbufsize + sc->common.cachelsz - 1,
>
> What was the exact purpose of this? My guess is that we should map
> starting at a next cache line boundary and put this aligned address to
> the device instead?

I've heard two theories:

1) AR5210 *required* it otherwise bad we would get bad data
2) Performance considerations

I've tried checking internally but haven't found out yet the exact
answer and this seems purely historical. I poked Sam Leffler to see if
he recalls. But as we the 0x41 reset which I removed it seems to be
best to leave unless we can be 100% sure we can remove this.

  Luis

^ permalink raw reply

* [PATCH v2] b43: Implement RC calibration for rev.0/1 LP-PHYs
From: Gábor Stefanik @ 2009-08-12 18:41 UTC (permalink / raw)
  To: John Linville, Michael Buesch, Larry Finger
  Cc: Broadcom Wireless, linux-wireless

Also implement get/set BB mult, get/set TX gain, set RX gain,
disable/restore CRS, run/stop DDFS, RX IQ est and QDIV roundup
in the process.

Signed-off-by: Gábor Stefanik <netrolller.3d@gmail.com>
---
Changes from v1->v2:
-Coding style fixes as suggested by Michael.
-Added missing static to lpphy_qdiv_roundup.
-Moved set_tx_power_control & related functions before rev0/1 RC calibration,
 and removed forward declaration
-Reordered variable declarations at the start of rev0_1_rc_calib.
-The ideal power table is now static const.

Interdiff v1->v2 available @ http://b43.pastebin.com/f5fe6ba3c for easier review.

 drivers/net/wireless/b43/phy_lp.c |  508 +++++++++++++++++++++++++++++++++----
 1 files changed, 461 insertions(+), 47 deletions(-)

diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c
index 689c932..e05981b 100644
--- a/drivers/net/wireless/b43/phy_lp.c
+++ b/drivers/net/wireless/b43/phy_lp.c
@@ -605,6 +605,8 @@ static void lpphy_radio_init(struct b43_wldev *dev)
 	}
 }
 
+struct lpphy_iq_est { u32 iq_prod, i_pwr, q_pwr; };
+
 static void lpphy_set_rc_cap(struct b43_wldev *dev)
 {
 	u8 rc_cap = dev->phy.lp->rc_cap;
@@ -614,79 +616,327 @@ static void lpphy_set_rc_cap(struct b43_wldev *dev)
 	b43_radio_write(dev, B2062_S_RXG_CNT16, ((rc_cap & 0x1F) >> 2) | 0x80);
 }
 
-static void lpphy_rev0_1_rc_calib(struct b43_wldev *dev)
+static u8 lpphy_get_bb_mult(struct b43_wldev *dev)
 {
-	//TODO and SPEC FIXME
+	return (b43_lptab_read(dev, B43_LPTAB16(0, 87)) & 0xFF00) >> 8;
 }
 
-static void lpphy_rev2plus_rc_calib(struct b43_wldev *dev)
+static void lpphy_set_bb_mult(struct b43_wldev *dev, u8 bb_mult)
 {
-	struct ssb_bus *bus = dev->dev->bus;
-	u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000;
-	u8 tmp = b43_radio_read(dev, B2063_RX_BB_SP8) & 0xFF;
-	int i;
+	b43_lptab_write(dev, B43_LPTAB16(0, 87), (u16)bb_mult << 8);
+}
 
-	b43_radio_write(dev, B2063_RX_BB_SP8, 0x0);
-	b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7E);
-	b43_radio_mask(dev, B2063_PLL_SP1, 0xF7);
-	b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7C);
-	b43_radio_write(dev, B2063_RC_CALIB_CTL2, 0x15);
-	b43_radio_write(dev, B2063_RC_CALIB_CTL3, 0x70);
-	b43_radio_write(dev, B2063_RC_CALIB_CTL4, 0x52);
-	b43_radio_write(dev, B2063_RC_CALIB_CTL5, 0x1);
-	b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7D);
+static void lpphy_disable_crs(struct b43_wldev *dev)
+{
+	b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFF1F, 0x80);
+	b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFC, 0x1);
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x3);
+	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFB);
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x4);
+	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFF7);
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x8);
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x10);
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x10);
+	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFDF);
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x20);
+	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFBF);
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x40);
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0x7);
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0x38);
+	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFF3F);
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0x100);
+	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFDFF);
+	b43_phy_write(dev, B43_LPPHY_PS_CTL_OVERRIDE_VAL0, 0);
+	b43_phy_write(dev, B43_LPPHY_PS_CTL_OVERRIDE_VAL1, 1);
+	b43_phy_write(dev, B43_LPPHY_PS_CTL_OVERRIDE_VAL2, 0x20);
+	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFBFF);
+	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xF7FF);
+	b43_phy_write(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL, 0);
+	b43_phy_write(dev, B43_LPPHY_RX_GAIN_CTL_OVERRIDE_VAL, 0x45AF);
+	b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_2, 0x3FF);
+}
 
-	for (i = 0; i < 10000; i++) {
-		if (b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2)
-			break;
-		msleep(1);
+static void lpphy_restore_crs(struct b43_wldev *dev)
+{
+	if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
+		b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFF1F, 0x60);
+	else
+		b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFF1F, 0x20);
+	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFF80);
+	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFC00);
+}
+
+struct lpphy_tx_gains { u16 gm, pga, pad, dac; };
+
+static struct lpphy_tx_gains lpphy_get_tx_gains(struct b43_wldev *dev)
+{
+	struct lpphy_tx_gains gains;
+	u16 tmp;
+
+	gains.dac = (b43_phy_read(dev, B43_LPPHY_AFE_DAC_CTL) & 0x380) >> 7;
+	if (dev->phy.rev < 2) {
+		tmp = b43_phy_read(dev,
+				   B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL) & 0x7FF;
+		gains.gm = tmp & 0x0007;
+		gains.pga = (tmp & 0x0078) >> 3;
+		gains.pad = (tmp & 0x780) >> 7;
+	} else {
+		tmp = b43_phy_read(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL);
+		gains.pad = b43_phy_read(dev, B43_PHY_OFDM(0xFB)) & 0xFF;
+		gains.gm = tmp & 0xFF;
+		gains.pga = (tmp >> 8) & 0xFF;
 	}
 
-	if (!(b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2))
-		b43_radio_write(dev, B2063_RX_BB_SP8, tmp);
+	return gains;
+}
 
-	tmp = b43_radio_read(dev, B2063_TX_BB_SP3) & 0xFF;
+static void lpphy_set_dac_gain(struct b43_wldev *dev, u16 dac)
+{
+	u16 ctl = b43_phy_read(dev, B43_LPPHY_AFE_DAC_CTL) & 0xC7F;
+	ctl |= dac << 7;
+	b43_phy_maskset(dev, B43_LPPHY_AFE_DAC_CTL, 0xF000, ctl);
+}
 
-	b43_radio_write(dev, B2063_TX_BB_SP3, 0x0);
-	b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7E);
-	b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7C);
-	b43_radio_write(dev, B2063_RC_CALIB_CTL2, 0x55);
-	b43_radio_write(dev, B2063_RC_CALIB_CTL3, 0x76);
+static void lpphy_set_tx_gains(struct b43_wldev *dev,
+			       struct lpphy_tx_gains gains)
+{
+	u16 rf_gain, pa_gain;
 
-	if (crystal_freq == 24000000) {
-		b43_radio_write(dev, B2063_RC_CALIB_CTL4, 0xFC);
-		b43_radio_write(dev, B2063_RC_CALIB_CTL5, 0x0);
+	if (dev->phy.rev < 2) {
+		rf_gain = (gains.pad << 7) | (gains.pga << 3) | gains.gm;
+		b43_phy_maskset(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL,
+				0xF800, rf_gain);
 	} else {
-		b43_radio_write(dev, B2063_RC_CALIB_CTL4, 0x13);
-		b43_radio_write(dev, B2063_RC_CALIB_CTL5, 0x1);
+		pa_gain = b43_phy_read(dev, B43_PHY_OFDM(0xFB)) & 0x7F00;
+		b43_phy_write(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL,
+			      (gains.pga << 8) | gains.gm);
+		b43_phy_maskset(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL,
+				0x8000, gains.pad | pa_gain);
+		b43_phy_write(dev, B43_PHY_OFDM(0xFC),
+			      (gains.pga << 8) | gains.gm);
+		b43_phy_maskset(dev, B43_PHY_OFDM(0xFD),
+				0x8000, gains.pad | pa_gain);
+	}
+	lpphy_set_dac_gain(dev, gains.dac);
+	if (dev->phy.rev < 2) {
+		b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFEFF, 1 << 8);
+	} else {
+		b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFF7F, 1 << 7);
+		b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xBFFF, 1 << 14);
 	}
+	b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFFBF, 1 << 4);
+}
 
-	b43_radio_write(dev, B2063_PA_SP7, 0x7D);
+static void lpphy_rev0_1_set_rx_gain(struct b43_wldev *dev, u32 gain)
+{
+	u16 trsw = gain & 0x1;
+	u16 lna = (gain & 0xFFFC) | ((gain & 0xC) >> 2);
+	u16 ext_lna = (gain & 2) >> 1;
+
+	b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFE, trsw);
+	b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL,
+			0xFBFF, ext_lna << 10);
+	b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL,
+			0xF7FF, ext_lna << 11);
+	b43_phy_write(dev, B43_LPPHY_RX_GAIN_CTL_OVERRIDE_VAL, lna);
+}
 
-	for (i = 0; i < 10000; i++) {
-		if (b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2)
+static void lpphy_rev2plus_set_rx_gain(struct b43_wldev *dev, u32 gain)
+{
+	u16 low_gain = gain & 0xFFFF;
+	u16 high_gain = (gain >> 16) & 0xF;
+	u16 ext_lna = (gain >> 21) & 0x1;
+	u16 trsw = ~(gain >> 21) & 0x1;
+	u16 tmp;
+	//SPEC FIXME is trsw really just ~(bool)ext_lna for rev2+?
+
+	b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFE, trsw);
+	b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL,
+			0xFDFF, ext_lna << 9);
+	b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 
+			0xFBFF, ext_lna << 10);
+	b43_phy_write(dev, B43_LPPHY_RX_GAIN_CTL_OVERRIDE_VAL, low_gain);
+	b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS, 0xFFF0, high_gain);
+	if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
+		tmp = (gain >> 2) & 0x3;
+		b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL,
+				0xE7FF, tmp<<11);
+		b43_phy_maskset(dev, B43_PHY_OFDM(0xE6), 0xFFE7, tmp << 3);
+	}
+}
+
+static void lpphy_enable_rx_gain_override(struct b43_wldev *dev)
+{
+	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFFE);
+	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFEF);
+	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFBF);
+	if (dev->phy.rev >= 2) {
+		b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFEFF);
+		if (b43_current_band(dev->wl) != IEEE80211_BAND_2GHZ)
+			return;
+		b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFBFF);
+		b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFFF7);
+	} else {
+		b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFDFF);
+	}
+}
+
+static void lpphy_disable_rx_gain_override(struct b43_wldev *dev)
+{
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x1);
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x10);
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x40);
+	if (dev->phy.rev >= 2) {
+		b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x100);
+		if (b43_current_band(dev->wl) != IEEE80211_BAND_2GHZ)
+			return;
+		b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x400);
+		b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x8);
+	} else {
+		b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x200);
+	}
+}
+
+static void lpphy_set_rx_gain(struct b43_wldev *dev, u32 gain)
+{
+	if (dev->phy.rev < 2)
+		lpphy_rev0_1_set_rx_gain(dev, gain);
+	else
+		lpphy_rev2plus_set_rx_gain(dev, gain);
+	lpphy_enable_rx_gain_override(dev);
+}
+
+static void lpphy_set_rx_gain_by_index(struct b43_wldev *dev, u16 idx)
+{
+	u32 gain = b43_lptab_read(dev, B43_LPTAB16(12, idx));
+	lpphy_set_rx_gain(dev, gain);
+}
+
+static void lpphy_stop_ddfs(struct b43_wldev *dev)
+{
+	b43_phy_mask(dev, B43_LPPHY_AFE_DDFS, 0xFFFD);
+	b43_phy_mask(dev, B43_LPPHY_LP_PHY_CTL, 0xFFDF);
+}
+
+static void lpphy_run_ddfs(struct b43_wldev *dev, int i_on, int q_on,
+			   int incr1, int incr2, int scale_idx)
+{
+	lpphy_stop_ddfs(dev);
+	b43_phy_mask(dev, B43_LPPHY_AFE_DDFS_POINTER_INIT, 0xFF80);
+	b43_phy_mask(dev, B43_LPPHY_AFE_DDFS_POINTER_INIT, 0x80FF);
+	b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS_INCR_INIT, 0xFF80, incr1);
+	b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS_INCR_INIT, 0x80FF, incr2 << 3);
+	b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS, 0xFFF7, i_on << 3);
+	b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS, 0xFFEF, q_on << 4);
+	b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS, 0xFF9F, scale_idx << 5);
+	b43_phy_mask(dev, B43_LPPHY_AFE_DDFS, 0xFFFB);
+	b43_phy_set(dev, B43_LPPHY_AFE_DDFS, 0x2);
+	b43_phy_set(dev, B43_LPPHY_AFE_DDFS, 0x20);
+}
+
+static bool lpphy_rx_iq_est(struct b43_wldev *dev, u16 samples, u8 time,
+			   struct lpphy_iq_est *iq_est)
+{
+	int i;
+
+	b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, 0xFFF7);
+	b43_phy_write(dev, B43_LPPHY_IQ_NUM_SMPLS_ADDR, samples);
+	b43_phy_maskset(dev, B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xFF00, time);
+	b43_phy_mask(dev, B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xFEFF);
+	b43_phy_set(dev, B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xFDFF);
+
+	for (i = 0; i < 500; i++) {
+		if (!(b43_phy_read(dev,
+				B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200))
 			break;
 		msleep(1);
 	}
 
-	if (!(b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2))
-		b43_radio_write(dev, B2063_TX_BB_SP3, tmp);
+	if ((b43_phy_read(dev, B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200)) {
+		b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x8);
+		return false;
+	}
 
-	b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7E);
+	iq_est->iq_prod = b43_phy_read(dev, B43_LPPHY_IQ_ACC_HI_ADDR);
+	iq_est->iq_prod <<= 16;
+	iq_est->iq_prod |= b43_phy_read(dev, B43_LPPHY_IQ_ACC_LO_ADDR);
+
+	iq_est->i_pwr = b43_phy_read(dev, B43_LPPHY_IQ_I_PWR_ACC_HI_ADDR);
+	iq_est->i_pwr <<= 16;
+	iq_est->i_pwr |= b43_phy_read(dev, B43_LPPHY_IQ_I_PWR_ACC_LO_ADDR);
+
+	iq_est->q_pwr = b43_phy_read(dev, B43_LPPHY_IQ_Q_PWR_ACC_HI_ADDR);
+	iq_est->q_pwr <<= 16;
+	iq_est->q_pwr |= b43_phy_read(dev, B43_LPPHY_IQ_Q_PWR_ACC_LO_ADDR);
+
+	b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x8);
+	return true;
 }
 
-static void lpphy_calibrate_rc(struct b43_wldev *dev)
+static int lpphy_loopback(struct b43_wldev *dev)
 {
-	struct b43_phy_lp *lpphy = dev->phy.lp;
+	struct lpphy_iq_est iq_est;
+	int i, index = -1;
+	u32 tmp;
+
+	memset(&iq_est, 0, sizeof(iq_est));
+
+	b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFC, 0x3);
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x3);
+	b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVRVAL, 0xFFFE);
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x800);
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x800);
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x8);
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x8);
+	b43_radio_write(dev, B2062_N_TX_CTL_A, 0x80);
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x80);
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x80);
+	for (i = 0; i < 32; i++) {
+		lpphy_set_rx_gain_by_index(dev, i);
+		lpphy_run_ddfs(dev, 1, 1, 5, 5, 0);
+		if (!(lpphy_rx_iq_est(dev, 1000, 32, &iq_est)))
+			continue;
+		tmp = (iq_est.i_pwr + iq_est.q_pwr) / 1000;
+		if ((tmp > 4000) && (tmp < 10000)) {
+			index = i;
+			break;
+		}
+	}
+	lpphy_stop_ddfs(dev);
+	return index;
+}
 
-	if (dev->phy.rev >= 2) {
-		lpphy_rev2plus_rc_calib(dev);
-	} else if (!lpphy->rc_cap) {
-		if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
-			lpphy_rev0_1_rc_calib(dev);
+static u32 lpphy_qdiv_roundup(u32 dividend, u32 divisor, u8 precision)
+{
+	u32 quotient, remainder, rbit, roundup, tmp;
+
+	if (divisor == 0) {
+		quotient = 0;
+		remainder = 0;
 	} else {
-		lpphy_set_rc_cap(dev);
+		quotient = dividend / divisor;
+		remainder = dividend % divisor;
 	}
+
+	rbit = divisor & 0x1;
+	roundup = (divisor >> 1) + rbit;
+	precision--;
+
+	while (precision != 0xFF) {
+		tmp = remainder - roundup;
+		quotient <<= 1;
+		remainder <<= 1;
+		if (remainder >= roundup) {
+			remainder = (tmp << 1) + rbit;
+			quotient--;
+		}
+		precision--;
+	}
+
+	if (remainder >= roundup)
+		quotient++;
+
+	return quotient;
 }
 
 /* Read the TX power control mode from hardware. */
@@ -773,6 +1023,170 @@ static void lpphy_set_tx_power_control(struct b43_wldev *dev,
 	lpphy_write_tx_pctl_mode_to_hardware(dev);
 }
 
+static void lpphy_rev0_1_rc_calib(struct b43_wldev *dev)
+{
+	struct b43_phy_lp *lpphy = dev->phy.lp;
+	struct lpphy_iq_est iq_est;
+	struct lpphy_tx_gains tx_gains;
+	static const u32 ideal_pwr_table[22] = {
+		0x10000, 0x10557, 0x10e2d, 0x113e0, 0x10f22, 0x0ff64,
+		0x0eda2, 0x0e5d4, 0x0efd1, 0x0fbe8, 0x0b7b8, 0x04b35,
+		0x01a5e, 0x00a0b, 0x00444, 0x001fd, 0x000ff, 0x00088,
+		0x0004c, 0x0002c, 0x0001a, 0xc0006,
+	};
+	bool old_txg_ovr;
+	u8 old_bbmult;
+	u16 old_rf_ovr, old_rf_ovrval, old_afe_ovr, old_afe_ovrval,
+	    old_rf2_ovr, old_rf2_ovrval, old_phy_ctl, old_txpctl;
+	u32 normal_pwr, ideal_pwr, mean_sq_pwr, tmp = 0, mean_sq_pwr_min = 0;
+	int loopback, i, j, inner_sum;
+
+	memset(&iq_est, 0, sizeof(iq_est));
+
+	b43_switch_channel(dev, 7);
+	old_txg_ovr = (b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVR) >> 6) & 1;
+	old_bbmult = lpphy_get_bb_mult(dev);
+	if (old_txg_ovr)
+		tx_gains = lpphy_get_tx_gains(dev);
+	old_rf_ovr = b43_phy_read(dev, B43_LPPHY_RF_OVERRIDE_0);
+	old_rf_ovrval = b43_phy_read(dev, B43_LPPHY_RF_OVERRIDE_VAL_0);
+	old_afe_ovr = b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVR);
+	old_afe_ovrval = b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVRVAL);
+	old_rf2_ovr = b43_phy_read(dev, B43_LPPHY_RF_OVERRIDE_2);
+	old_rf2_ovrval = b43_phy_read(dev, B43_LPPHY_RF_OVERRIDE_2_VAL);
+	old_phy_ctl = b43_phy_read(dev, B43_LPPHY_LP_PHY_CTL);
+	old_txpctl = b43_phy_read(dev, B43_LPPHY_TX_PWR_CTL_CMD) &
+					B43_LPPHY_TX_PWR_CTL_CMD_MODE;
+ 
+ 	lpphy_set_tx_power_control(dev, B43_LPPHY_TX_PWR_CTL_CMD_MODE_OFF);
+	lpphy_disable_crs(dev);
+	loopback = lpphy_loopback(dev);
+	if (loopback == -1)
+		goto finish;
+	lpphy_set_rx_gain_by_index(dev, loopback);
+	b43_phy_maskset(dev, B43_LPPHY_LP_PHY_CTL, 0xFFBF, 0x40);
+	b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFFF8, 0x1);
+	b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFFC7, 0x8);
+	b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFF3F, 0xC0);
+	for (i = 128; i <= 159; i++) {
+		b43_radio_write(dev, B2062_N_RXBB_CALIB2, i);
+  		inner_sum = 0;
+		for (j = 5; j <= 25; j++) {
+			lpphy_run_ddfs(dev, 1, 1, j, j, 0);
+			if (!(lpphy_rx_iq_est(dev, 1000, 32, &iq_est)))
+				goto finish;
+			mean_sq_pwr = iq_est.i_pwr + iq_est.q_pwr;
+			if (j == 5)
+				tmp = mean_sq_pwr;
+			ideal_pwr = ((ideal_pwr_table[j-5] >> 3) + 1) >> 1;
+			normal_pwr = lpphy_qdiv_roundup(mean_sq_pwr, tmp, 12);
+			mean_sq_pwr = ideal_pwr - normal_pwr;
+			mean_sq_pwr *= mean_sq_pwr;
+			inner_sum += mean_sq_pwr;
+			if ((i = 128) || (inner_sum < mean_sq_pwr_min)) {
+				lpphy->rc_cap = i;
+				mean_sq_pwr_min = inner_sum;
+			}
+		}
+	}
+	lpphy_stop_ddfs(dev);
+
+finish:
+	lpphy_restore_crs(dev);
+	b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, old_rf_ovrval);
+	b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_0, old_rf_ovr);
+	b43_phy_write(dev, B43_LPPHY_AFE_CTL_OVRVAL, old_afe_ovrval);
+	b43_phy_write(dev, B43_LPPHY_AFE_CTL_OVR, old_afe_ovr);
+	b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, old_rf2_ovrval);
+	b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_2, old_rf2_ovr);
+	b43_phy_write(dev, B43_LPPHY_LP_PHY_CTL, old_phy_ctl);
+
+	lpphy_set_bb_mult(dev, old_bbmult);
+	if (old_txg_ovr) {
+		/*
+		 * SPEC FIXME: The specs say "get_tx_gains" here, which is
+		 * illogical. According to lwfinger, vendor driver v4.150.10.5
+		 * has a Set here, while v4.174.64.19 has a Get - regression in
+		 * the vendor driver? This should be tested this once the code
+		 * is testable.
+		 */
+		lpphy_set_tx_gains(dev, tx_gains);
+	}
+	lpphy_set_tx_power_control(dev, old_txpctl);
+	if (lpphy->rc_cap)
+		lpphy_set_rc_cap(dev);
+}
+
+static void lpphy_rev2plus_rc_calib(struct b43_wldev *dev)
+{
+	struct ssb_bus *bus = dev->dev->bus;
+	u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000;
+	u8 tmp = b43_radio_read(dev, B2063_RX_BB_SP8) & 0xFF;
+	int i;
+
+	b43_radio_write(dev, B2063_RX_BB_SP8, 0x0);
+	b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7E);
+	b43_radio_mask(dev, B2063_PLL_SP1, 0xF7);
+	b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7C);
+	b43_radio_write(dev, B2063_RC_CALIB_CTL2, 0x15);
+	b43_radio_write(dev, B2063_RC_CALIB_CTL3, 0x70);
+	b43_radio_write(dev, B2063_RC_CALIB_CTL4, 0x52);
+	b43_radio_write(dev, B2063_RC_CALIB_CTL5, 0x1);
+	b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7D);
+
+	for (i = 0; i < 10000; i++) {
+		if (b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2)
+			break;
+		msleep(1);
+	}
+
+	if (!(b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2))
+		b43_radio_write(dev, B2063_RX_BB_SP8, tmp);
+
+	tmp = b43_radio_read(dev, B2063_TX_BB_SP3) & 0xFF;
+
+	b43_radio_write(dev, B2063_TX_BB_SP3, 0x0);
+	b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7E);
+	b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7C);
+	b43_radio_write(dev, B2063_RC_CALIB_CTL2, 0x55);
+	b43_radio_write(dev, B2063_RC_CALIB_CTL3, 0x76);
+
+	if (crystal_freq == 24000000) {
+		b43_radio_write(dev, B2063_RC_CALIB_CTL4, 0xFC);
+		b43_radio_write(dev, B2063_RC_CALIB_CTL5, 0x0);
+	} else {
+		b43_radio_write(dev, B2063_RC_CALIB_CTL4, 0x13);
+		b43_radio_write(dev, B2063_RC_CALIB_CTL5, 0x1);
+	}
+
+	b43_radio_write(dev, B2063_PA_SP7, 0x7D);
+
+	for (i = 0; i < 10000; i++) {
+		if (b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2)
+			break;
+		msleep(1);
+	}
+
+	if (!(b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2))
+		b43_radio_write(dev, B2063_TX_BB_SP3, tmp);
+
+	b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7E);
+}
+
+static void lpphy_calibrate_rc(struct b43_wldev *dev)
+{
+	struct b43_phy_lp *lpphy = dev->phy.lp;
+
+	if (dev->phy.rev >= 2) {
+		lpphy_rev2plus_rc_calib(dev);
+	} else if (!lpphy->rc_cap) {
+		if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
+			lpphy_rev0_1_rc_calib(dev);
+	} else {
+		lpphy_set_rc_cap(dev);
+	}
+}
+
 static void lpphy_set_tx_power_by_index(struct b43_wldev *dev, u8 index)
 {
 	struct b43_phy_lp *lpphy = dev->phy.lp;
-- 
1.6.2.4




^ permalink raw reply related

* Re: pull request: wireless-2.6 2009-08-11
From: John W. Linville @ 2009-08-12 18:24 UTC (permalink / raw)
  To: davem; +Cc: linux-wireless, netdev, linux-kernel
In-Reply-To: <20090811183605.GG2634@tuxdriver.com>

Dave,

When you pull this, could you also revert 57921c31 ("libertas: Read
buffer overflow").  It has been shown to create a new problem.  There
is work towards a solution to that one, but it isn't a simple clean-up.

If you would prefer, I can include the revert with another pull
request or even regenerate this one.  Just let me know if that is
what you prefer.

Thanks,

John

On Tue, Aug 11, 2009 at 02:36:06PM -0400, John W. Linville wrote:
> Dave,
> 
> Here are a couple more minor fixes intended for 2.6.31.  Hopefully we
> are winding-down!
> 
> Please let me know if there are problems!
> 
> John
> 
> ---
> 
> Individual patches are available here:
> 
> 	http://www.kernel.org/pub/linux/kernel/people/linville/wireless-2.6/
> 
> ---
> 
> The following changes since commit 973507cb8610d4c84f090d5f1f0ca54fa0559d27:
>   roel kluin (1):
>         mlx4_en: Fix read buffer overflow in mlx4_en_complete_rx_desc()
> 
> are available in the git repository at:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git master
> 
> Christian Lamparter (1):
>       ar9170usb: fix spurious firmware related message
> 
> Dan Carpenter (1):
>       ar9170: fix read & write outside array bounds
> 
>  drivers/net/wireless/ath/ar9170/main.c |    5 +++--
>  drivers/net/wireless/ath/ar9170/usb.c  |    6 +++++-
>  2 files changed, 8 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c
> index 9d38cf6..88c3d85 100644
> --- a/drivers/net/wireless/ath/ar9170/main.c
> +++ b/drivers/net/wireless/ath/ar9170/main.c
> @@ -1967,13 +1967,14 @@ static int ar9170_conf_tx(struct ieee80211_hw *hw, u16 queue,
>  	int ret;
>  
>  	mutex_lock(&ar->mutex);
> -	if ((param) && !(queue > __AR9170_NUM_TXQ)) {
> +	if (queue < __AR9170_NUM_TXQ) {
>  		memcpy(&ar->edcf[ar9170_qos_hwmap[queue]],
>  		       param, sizeof(*param));
>  
>  		ret = ar9170_set_qos(ar);
> -	} else
> +	} else {
>  		ret = -EINVAL;
> +	}
>  
>  	mutex_unlock(&ar->mutex);
>  	return ret;
> diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c
> index 754b1f8..007eb85 100644
> --- a/drivers/net/wireless/ath/ar9170/usb.c
> +++ b/drivers/net/wireless/ath/ar9170/usb.c
> @@ -598,11 +598,15 @@ static int ar9170_usb_request_firmware(struct ar9170_usb *aru)
>  
>  	err = request_firmware(&aru->init_values, "ar9170-1.fw",
>  			       &aru->udev->dev);
> +	if (err) {
> +		dev_err(&aru->udev->dev, "file with init values not found.\n");
> +		return err;
> +	}
>  
>  	err = request_firmware(&aru->firmware, "ar9170-2.fw", &aru->udev->dev);
>  	if (err) {
>  		release_firmware(aru->init_values);
> -		dev_err(&aru->udev->dev, "file with init values not found.\n");
> +		dev_err(&aru->udev->dev, "firmware file not found.\n");
>  		return err;
>  	}
>  
> -- 
> John W. Linville		Someday the world will need a hero, and you
> linville@tuxdriver.com			might be all we have.  Be ready.
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

-- 
John W. Linville		Someday the world will need a hero, and you
linville@tuxdriver.com			might be all we have.  Be ready.

^ permalink raw reply

* Re: [PATCH] iwl3945: fix compilation error in iwl3945_pass_packet_to_mac80211()
From: Kalle Valo @ 2009-08-12 18:27 UTC (permalink / raw)
  To: reinette chatre; +Cc: linville@tuxdriver.com, linux-wireless@vger.kernel.org
In-Reply-To: <1250091440.30019.5928.camel@rc-desk>

reinette chatre <reinette.chatre@intel.com> writes:

> On Wed, 2009-08-12 at 04:07 -0700, Kalle Valo wrote:
>> Commit "iwlwifi: Traffic type and counter for debugFs" broke iwl3945 in
>> a case when CONFIG_IWLWIFI_LEDS is disabled:
>> 
>> drivers/net/wireless/iwlwifi/iwl-3945.c:580: error: 'hdr' undeclared (first use in this function)
>> 
>> Fix it by removing the ifdef check for hdr variable.

[...]

> We have an identical patch pending. I assumed most people compile with
> led support and thus did not rush to get it in.

I don't remember why I have leds disabled. Most probably some problem a
long time ago and I never bothered to turn it back on.

> Now that it is a problem for more people I think this one should go
> in.

I agree that this should go in. Compilation errors are always annoying.

-- 
Kalle Valo

^ permalink raw reply

* [PATCH 2/2] mac80211: Fix invalid length passed to IE parser for PLINK CONFIRM frames
From: Javier Cardona @ 2009-08-12 18:03 UTC (permalink / raw)
  To: linux-wireless
  Cc: David Woo, Javier Cardona, andrey, johannes, linville, devel
In-Reply-To: <1250100224-23832-2-git-send-email-javier@cozybit.com>

From: David Woo <xinhua_wu@realsil.com.cn>

The length of the fixed portion of plink confirm frames is 4 bytes longer than
the other plink_action frames.  This path corrects an error in the length
adjustment done for these type of frames.

Signed-off-by: Javier Cardona <javier@cozybit.com>
---
 net/mac80211/mesh_plink.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index 7c49c95..3575fe3 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -415,7 +415,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
 	baselen = (u8 *) mgmt->u.action.u.plink_action.variable - (u8 *) mgmt;
 	if (mgmt->u.action.u.plink_action.action_code == PLINK_CONFIRM) {
 		baseaddr += 4;
-		baselen -= 4;
+		baselen += 4;
 	}
 	ieee802_11_parse_elems(baseaddr, len - baselen, &elems);
 	if (!elems.peer_link) {
-- 
1.5.4.3


^ permalink raw reply related

* [PATCH 1/2] mac80211: Mark a destination sequence number as valid when a PREQ is received.
From: Javier Cardona @ 2009-08-12 18:03 UTC (permalink / raw)
  To: linux-wireless
  Cc: David Woo, Javier Cardona, andrey, johannes, linville, devel
In-Reply-To: <1250100224-23832-1-git-send-email-javier@cozybit.com>

From: David Woo <xinhua_wu@realsil.com.cn>

If a PREQ frame is received giving us a fresher DSN than what we have, record
the new dsn and mark it as valid.  This patch fixes a bug in the setting of the
MESH_PATH_DSN_VALID flag.

Also, minor fix to coding style on that file.

Signed-off-by: Javier Cardona <javier@cozybit.com>
---
 net/mac80211/mesh_hwmp.c |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index 1cd1e72..ef1efd3 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -397,7 +397,8 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,
 
 static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
 				    struct ieee80211_mgmt *mgmt,
-				    u8 *preq_elem, u32 metric) {
+				    u8 *preq_elem, u32 metric)
+{
 	struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
 	struct mesh_path *mpath;
 	u8 *dst_addr, *orig_addr;
@@ -430,7 +431,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
 			if ((!(mpath->flags & MESH_PATH_DSN_VALID)) ||
 					DSN_LT(mpath->dsn, dst_dsn)) {
 				mpath->dsn = dst_dsn;
-				mpath->flags &= MESH_PATH_DSN_VALID;
+				mpath->flags |= MESH_PATH_DSN_VALID;
 			} else if ((!(dst_flags & MP_F_DO)) &&
 					(mpath->flags & MESH_PATH_ACTIVE)) {
 				reply = true;
-- 
1.5.4.3


^ permalink raw reply related

* Fix preq frame process and peer link frame baselen.
From: Javier Cardona @ 2009-08-12 18:03 UTC (permalink / raw)
  To: linux-wireless; +Cc: andrey, johannes, linville, devel, xinhua_wu
In-Reply-To: <4A82639F.6000908@realsil.com.cn>

> Yes, I agree with you, and this patch is just to check whether this PREQ is valid with
> the ttl it contains instead of local TTL, and the local TTL has also been provided for
> PREP further process.

I'm still unconvinced with that change.  The ttl check you refer to is done on
transmission: PREQs with ttl of zero are never transmitted.  See further down in
that same function:

	ttl = PREQ_IE_TTL(preq_elem);
	lifetime = PREQ_IE_LIFETIME(preq_elem);
	if (ttl <= 1) {
		/* supress frame */

Furthermore, with the change you propose, you open the possibility for PREPs to
be transmitted with ttl=0 (if ifmsh->mshcfg.dot11MeshTTL was set to zero).

Regarding your baselen explanation, I now understand it and agree to the
suggested change.  Your initial patch submission was reversed and I got confused
looking at two version of the same.

I've created a new series with the parts of your patch that I agree with.  They
follow this e-mail.

Thanks!

Javier

^ permalink raw reply

* Re: [PATCH] ath5k: fix requested allocated RX skb size for DMA
From: Jiri Slaby @ 2009-08-12 18:13 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: linville, linux-wireless, ath9k-devel, ath5k-devel,
	Nick Kossifidis, Bob Copeland
In-Reply-To: <1250096290-11058-1-git-send-email-lrodriguez@atheros.com>

On 08/12/2009 06:58 PM, Luis R. Rodriguez wrote:
> --- a/drivers/net/wireless/ath/ath5k/base.c
> +++ b/drivers/net/wireless/ath/ath5k/base.c
> @@ -1157,17 +1157,18 @@ struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_softc *sc, dma_addr_t *skb_addr)
>  	 * fake physical layer header at the start.
>  	 */
>  	skb = ath_rxbuf_alloc(&sc->common,
> -			      sc->rxbufsize + sc->common.cachelsz - 1,

What was the exact purpose of this? My guess is that we should map
starting at a next cache line boundary and put this aligned address to
the device instead?

^ permalink raw reply

* Re: [PATCH] b43: Implement RC calibration for rev.0/1 LP-PHYs
From: Michael Buesch @ 2009-08-12 18:08 UTC (permalink / raw)
  To: bcm43xx-dev
  Cc: Gábor Stefanik, John Linville, Larry Finger, linux-wireless
In-Reply-To: <4A830249.1010005@gmail.com>

On Wednesday 12 August 2009 19:56:25 Gábor Stefanik wrote:
> +		b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFEFF, 1<<8);

> +	b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS_INCR_INIT, 0x80FF, incr2 << 3);

Can you try to stick to one style? a << b is our coding style.

> +static void lpphy_run_ddfs(struct b43_wldev *dev, int i_on, int q_on,
> +                          int incr1, int incr2, int scale_idx)
> +{
> +       lpphy_stop_ddfs(dev);
> +       b43_phy_mask(dev, B43_LPPHY_AFE_DDFS_POINTER_INIT, 0xFF80);
> +       b43_phy_mask(dev, B43_LPPHY_AFE_DDFS_POINTER_INIT, 0x80FF);
> +       b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS_INCR_INIT, 0xFF80, incr1);
> +       b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS_INCR_INIT, 0x80FF, incr2 << 3);

3bit shift smells fishy. Did you want 8?

> +u32 lpphy_qdiv_roundup(u32 dividend, u32 divisor, u8 precision)

static?

> +static void lpphy_set_tx_power_control(struct b43_wldev *dev,
> +				       enum b43_lpphy_txpctl_mode mode);

Can you reorder the code to avoid the forward declaration?

> +	for (i = 128; i <= 159; i++) {
> +		b43_radio_write(dev, B2062_N_RXBB_CALIB2, i);
> +  		inner_sum = 0;
> +		for (j = 5; j <= 25; j++) {
> +			lpphy_run_ddfs(dev, 1, 1, j, j, 0);

(Just by guess) Did you really want j,j instead of i,j or something like that?

> +			if (!(lpphy_rx_iq_est(dev, 1000, 32, &iq_est)))
> +				goto finish;
> +			mean_sq_pwr = iq_est.i_pwr + iq_est.q_pwr;
> +			if (j == 5)
> +				tmp = mean_sq_pwr;
> +			ideal_pwr = ((ideal_pwr_table[j-5] >> 3) + 1) >> 1;
> +			normal_pwr = lpphy_qdiv_roundup(mean_sq_pwr, tmp, 12);
> +			mean_sq_pwr = ideal_pwr - normal_pwr;
> +			mean_sq_pwr *= mean_sq_pwr;
> +			inner_sum += mean_sq_pwr;
> +			if ((i = 128) || (inner_sum < mean_sq_pwr_min)) {
> +				lpphy->rc_cap = i;
> +				mean_sq_pwr_min = inner_sum;
> +			}
> +		}
> +	}
> +	lpphy_stop_ddfs(dev);
> +

> +	if (old_txg_ovr)
> +		/*
> +		 * SPEC FIXME: The specs say "get_tx_gains" here, which is
> +		 * illogical. According to lwfinger, vendor driver v4.150.10.5
> +		 * has a Set here, while v4.174.64.19 has a Get - regression in
> +		 * the vendor driver? This should be tested this once the code
> +		 * is testable.
> +		 */
> +		lpphy_set_tx_gains(dev, tx_gains);

Use curly brackets for multiline indents.

> +	lpphy_set_tx_power_control(dev, old_txpctl);
> +	if (lpphy->rc_cap)
> +		lpphy_set_rc_cap(dev);
>  }
>  
>  static void lpphy_rev2plus_rc_calib(struct b43_wldev *dev)



-- 
Greetings, Michael.

^ permalink raw reply

* Re: Multiple SSID
From: Ben Greear @ 2009-08-12 17:59 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: Stephen Hemminger, John W. Linville, Johannes Berg,
	linux-wireless
In-Reply-To: <43e72e890908121025p75b141b6o86c30518bf9de7ea@mail.gmail.com>

On 08/12/2009 10:25 AM, Luis R. Rodriguez wrote:
> On Wed, Aug 12, 2009 at 10:04 AM, Stephen
> Hemminger<shemminger@vyatta.com>  wrote:
>> I have a dumb questions. How does one setup multiple SSID's with
>> current (ie not madwifi) wireless API?

> Anyway I believe AP-enabled devices right now only support creating 1
> AP interfface. I believe the exception to this right now is ath9k
> through the private virtual interface stuff Jouni created, but to be
> honest I have to go and review that to make sure you can create 2 APs.

We're *still* working on virtualizing ath5k.  Over the last few days,
we have gotten this working pretty well, including virtual APs, virtual STAs with
WPA &  no security.  I haven't tested WEP lately.

We are chasing a few remaining buglets and optimizations currently.

I have a page up here to help get started using this:
http://www.candelatech.com/oss/vsta.html

NOTE:  The .31 tree mentioned there has a bunch of other patches in it
that we use for various purposes.  There is no clean way to get *just*
our wifi changes at this point.

We plan to submit the patches upstream, but there is a lot of churn in wifi code
so it will be a bit longer before we can get the patches tested on stable
code and then ported to the development branches.

I haven't tried out ath9k yet, but look forward to it once we get
ath5k nailed down.

Thanks,
Ben

-- 
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc  http://www.candelatech.com


^ permalink raw reply


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