Linux wireless drivers development
 help / color / mirror / Atom feed
* [PATCH 1/2] rtl8187: fix circular locking (rtl8187_stop/rtl8187_work)
From: Herton Ronaldo Krzesinski @ 2009-08-26 16:54 UTC (permalink / raw)
  To: linux-wireless
  Cc: John W Linville, Larry Finger, Hin-Tak Leung,
	Herton Ronaldo Krzesinski

Larry Finger reports following lockdep warning:

[ INFO: possible circular locking dependency detected ]
2.6.31-rc6-wl #201
-------------------------------------------------------
rfkill/30578 is trying to acquire lock:
 (&(&priv->work)->work#2){+.+...}, at: [<ffffffff81051215>]
__cancel_work_timer+0xd9/0x222

but task is already holding lock:
 (&priv->conf_mutex#2){+.+.+.}, at: [<ffffffffa064a024>]
rtl8187_stop+0x31/0x364 [rtl8187]

which lock already depends on the new lock.

the existing dependency chain (in reverse order) is:

-> #1 (&priv->conf_mutex#2){+.+.+.}:
       [<ffffffff81065957>] __lock_acquire+0x12d0/0x1614
       [<ffffffff81065d54>] lock_acquire+0xb9/0xdd
       [<ffffffff8127c32f>] mutex_lock_nested+0x56/0x2a8
       [<ffffffffa064a392>] rtl8187_work+0x3b/0xf2 [rtl8187]
       [<ffffffff81050758>] worker_thread+0x1fa/0x30a
       [<ffffffff81054ca5>] kthread+0x8f/0x97
       [<ffffffff8100cb7a>] child_rip+0xa/0x20
       [<ffffffffffffffff>] 0xffffffffffffffff

-> #0 (&(&priv->work)->work#2){+.+...}:
       [<ffffffff8106568c>] __lock_acquire+0x1005/0x1614
       [<ffffffff81065d54>] lock_acquire+0xb9/0xdd
       [<ffffffff8105124e>] __cancel_work_timer+0x112/0x222
       [<ffffffff8105136b>] cancel_delayed_work_sync+0xd/0xf
       [<ffffffffa064a33f>] rtl8187_stop+0x34c/0x364 [rtl8187]
       [<ffffffffa0242866>] ieee80211_stop_device+0x29/0x61 [mac80211]
       [<ffffffffa0239194>] ieee80211_stop+0x476/0x530 [mac80211]
       [<ffffffff8120ce15>] dev_close+0x8a/0xac
       [<ffffffffa01d9fa7>] cfg80211_rfkill_set_block+0x4a/0x7a [cfg80211]
       [<ffffffffa01bf4f0>] rfkill_set_block+0x84/0xd9 [rfkill]
       [<ffffffffa01bfc31>] rfkill_fop_write+0xda/0x124 [rfkill]
       [<ffffffff810cf286>] vfs_write+0xae/0x14a
       [<ffffffff810cf3e6>] sys_write+0x47/0x6e
       [<ffffffff8100ba6b>] system_call_fastpath+0x16/0x1b
       [<ffffffffffffffff>] 0xffffffffffffffff

The problem here is that rtl8187_stop, while helding priv->conf_mutex,
runs cancel_delayed_work_sync on an workqueue that runs rtl8187_work,
which also takes priv->conf_mutex lock. Move cancel_delayed_work_sync
out of rtl8187_stop priv->conf_mutex locking region.

Reported-by: Larry Finger <Larry.Finger@lwfinger.net>
Tested-by: Larry Finger <Larry.Finger@lwfinger.net>
Signed-off-by: Herton Ronaldo Krzesinski <herton@mandriva.com.br>
---
 drivers/net/wireless/rtl818x/rtl8187_dev.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c
index 5830f6c..75b63ac 100644
--- a/drivers/net/wireless/rtl818x/rtl8187_dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c
@@ -1017,9 +1017,10 @@ static void rtl8187_stop(struct ieee80211_hw *dev)
 		dev_kfree_skb_any(skb);
 
 	usb_kill_anchored_urbs(&priv->anchored);
+	mutex_unlock(&priv->conf_mutex);
+
 	if (!priv->is_rtl8187b)
 		cancel_delayed_work_sync(&priv->work);
-	mutex_unlock(&priv->conf_mutex);
 }
 
 static int rtl8187_add_interface(struct ieee80211_hw *dev,
-- 
1.6.4.1


^ permalink raw reply related

* [PATCH 2/2] rtl8187: Implement rfkill support
From: Herton Ronaldo Krzesinski @ 2009-08-26 16:54 UTC (permalink / raw)
  To: linux-wireless
  Cc: John W Linville, Larry Finger, Hin-Tak Leung,
	Herton Ronaldo Krzesinski
In-Reply-To: <1251305649-12508-1-git-send-email-herton@mandriva.com.br>

This change implements rfkill support for RTL8187B and RTL8187L devices,
using new cfg80211 rfkill API.

Acked-by: Larry Finger <Larry.Finger@lwfinger.net>
Tested-by: Hin-Tak Leung <htl10@users.sourceforge.net>
Signed-off-by: Herton Ronaldo Krzesinski <herton@mandriva.com.br>
---
 drivers/net/wireless/rtl818x/Makefile         |    2 +-
 drivers/net/wireless/rtl818x/rtl8187.h        |    1 +
 drivers/net/wireless/rtl818x/rtl8187_dev.c    |   28 ++++++-----
 drivers/net/wireless/rtl818x/rtl8187_leds.c   |    4 +-
 drivers/net/wireless/rtl818x/rtl8187_rfkill.c |   63 +++++++++++++++++++++++++
 drivers/net/wireless/rtl818x/rtl8187_rfkill.h |    8 +++
 drivers/net/wireless/rtl818x/rtl818x.h        |    5 +-
 7 files changed, 94 insertions(+), 17 deletions(-)
 create mode 100644 drivers/net/wireless/rtl818x/rtl8187_rfkill.c
 create mode 100644 drivers/net/wireless/rtl818x/rtl8187_rfkill.h

diff --git a/drivers/net/wireless/rtl818x/Makefile b/drivers/net/wireless/rtl818x/Makefile
index 37e3d4d..93cbfbe 100644
--- a/drivers/net/wireless/rtl818x/Makefile
+++ b/drivers/net/wireless/rtl818x/Makefile
@@ -1,5 +1,5 @@
 rtl8180-objs		:= rtl8180_dev.o rtl8180_rtl8225.o rtl8180_sa2400.o rtl8180_max2820.o rtl8180_grf5101.o
-rtl8187-objs		:= rtl8187_dev.o rtl8187_rtl8225.o rtl8187_leds.o
+rtl8187-objs		:= rtl8187_dev.o rtl8187_rtl8225.o rtl8187_leds.o rtl8187_rfkill.o
 
 obj-$(CONFIG_RTL8180)	+= rtl8180.o
 obj-$(CONFIG_RTL8187)	+= rtl8187.o
diff --git a/drivers/net/wireless/rtl818x/rtl8187.h b/drivers/net/wireless/rtl818x/rtl8187.h
index c09bfef..bf9175a 100644
--- a/drivers/net/wireless/rtl818x/rtl8187.h
+++ b/drivers/net/wireless/rtl818x/rtl8187.h
@@ -133,6 +133,7 @@ struct rtl8187_priv {
 		__le16 bits16;
 		__le32 bits32;
 	} *io_dmabuf;
+	bool rfkill_off;
 };
 
 void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data);
diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c
index 75b63ac..2017ccc 100644
--- a/drivers/net/wireless/rtl818x/rtl8187_dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c
@@ -32,6 +32,7 @@
 #ifdef CONFIG_RTL8187_LEDS
 #include "rtl8187_leds.h"
 #endif
+#include "rtl8187_rfkill.h"
 
 MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>");
 MODULE_AUTHOR("Andrea Merello <andreamrl@tiscali.it>");
@@ -648,10 +649,10 @@ static int rtl8187_init_hw(struct ieee80211_hw *dev)
 
 	/* setup card */
 	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0);
-	rtl818x_iowrite8(priv, &priv->map->GPIO, 0);
+	rtl818x_iowrite8(priv, &priv->map->GPIO0, 0);
 
 	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, (4 << 8));
-	rtl818x_iowrite8(priv, &priv->map->GPIO, 1);
+	rtl818x_iowrite8(priv, &priv->map->GPIO0, 1);
 	rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0);
 
 	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
@@ -674,11 +675,11 @@ static int rtl8187_init_hw(struct ieee80211_hw *dev)
 
 	/* host_usb_init */
 	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0);
-	rtl818x_iowrite8(priv, &priv->map->GPIO, 0);
+	rtl818x_iowrite8(priv, &priv->map->GPIO0, 0);
 	reg = rtl818x_ioread8(priv, (u8 *)0xFE53);
 	rtl818x_iowrite8(priv, (u8 *)0xFE53, reg | (1 << 7));
 	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, (4 << 8));
-	rtl818x_iowrite8(priv, &priv->map->GPIO, 0x20);
+	rtl818x_iowrite8(priv, &priv->map->GPIO0, 0x20);
 	rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0);
 	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x80);
 	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x80);
@@ -910,12 +911,12 @@ static int rtl8187_start(struct ieee80211_hw *dev)
 	u32 reg;
 	int ret;
 
+	mutex_lock(&priv->conf_mutex);
+
 	ret = (!priv->is_rtl8187b) ? rtl8187_init_hw(dev) :
 				     rtl8187b_init_hw(dev);
 	if (ret)
-		return ret;
-
-	mutex_lock(&priv->conf_mutex);
+		goto rtl8187_start_exit;
 
 	init_usb_anchor(&priv->anchored);
 	priv->dev = dev;
@@ -942,8 +943,7 @@ static int rtl8187_start(struct ieee80211_hw *dev)
 				  (7 << 21 /* MAX TX DMA */));
 		rtl8187_init_urbs(dev);
 		rtl8187b_init_status_urb(dev);
-		mutex_unlock(&priv->conf_mutex);
-		return 0;
+		goto rtl8187_start_exit;
 	}
 
 	rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0xFFFF);
@@ -987,9 +987,10 @@ static int rtl8187_start(struct ieee80211_hw *dev)
 	reg |= RTL818X_CMD_RX_ENABLE;
 	rtl818x_iowrite8(priv, &priv->map->CMD, reg);
 	INIT_DELAYED_WORK(&priv->work, rtl8187_work);
-	mutex_unlock(&priv->conf_mutex);
 
-	return 0;
+rtl8187_start_exit:
+	mutex_unlock(&priv->conf_mutex);
+	return ret;
 }
 
 static void rtl8187_stop(struct ieee80211_hw *dev)
@@ -1283,7 +1284,8 @@ static const struct ieee80211_ops rtl8187_ops = {
 	.bss_info_changed	= rtl8187_bss_info_changed,
 	.prepare_multicast	= rtl8187_prepare_multicast,
 	.configure_filter	= rtl8187_configure_filter,
-	.conf_tx		= rtl8187_conf_tx
+	.conf_tx		= rtl8187_conf_tx,
+	.rfkill_poll		= rtl8187_rfkill_poll
 };
 
 static void rtl8187_eeprom_register_read(struct eeprom_93cx6 *eeprom)
@@ -1523,6 +1525,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
 	reg &= 0xFF;
 	rtl8187_leds_init(dev, reg);
 #endif
+	rtl8187_rfkill_init(dev);
 
 	return 0;
 
@@ -1546,6 +1549,7 @@ static void __devexit rtl8187_disconnect(struct usb_interface *intf)
 #ifdef CONFIG_RTL8187_LEDS
 	rtl8187_leds_exit(dev);
 #endif
+	rtl8187_rfkill_exit(dev);
 	ieee80211_unregister_hw(dev);
 
 	priv = dev->priv;
diff --git a/drivers/net/wireless/rtl818x/rtl8187_leds.c b/drivers/net/wireless/rtl818x/rtl8187_leds.c
index a6cfb7e..a1c670f 100644
--- a/drivers/net/wireless/rtl818x/rtl8187_leds.c
+++ b/drivers/net/wireless/rtl818x/rtl8187_leds.c
@@ -42,7 +42,7 @@ static void led_turn_on(struct work_struct *work)
 	mutex_lock(&priv->conf_mutex);
 	switch (led->ledpin) {
 	case LED_PIN_GPIO0:
-		rtl818x_iowrite8(priv, &priv->map->GPIO, 0x01);
+		rtl818x_iowrite8(priv, &priv->map->GPIO0, 0x01);
 		rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0x00);
 		break;
 	case LED_PIN_LED0:
@@ -80,7 +80,7 @@ static void led_turn_off(struct work_struct *work)
 	mutex_lock(&priv->conf_mutex);
 	switch (led->ledpin) {
 	case LED_PIN_GPIO0:
-		rtl818x_iowrite8(priv, &priv->map->GPIO, 0x01);
+		rtl818x_iowrite8(priv, &priv->map->GPIO0, 0x01);
 		rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0x01);
 		break;
 	case LED_PIN_LED0:
diff --git a/drivers/net/wireless/rtl818x/rtl8187_rfkill.c b/drivers/net/wireless/rtl818x/rtl8187_rfkill.c
new file mode 100644
index 0000000..9fab13e
--- /dev/null
+++ b/drivers/net/wireless/rtl818x/rtl8187_rfkill.c
@@ -0,0 +1,63 @@
+/*
+ * Linux RFKILL support for RTL8187
+ *
+ * Copyright (c) 2009 Herton Ronaldo Krzesinski <herton@mandriva.com.br>
+ *
+ * Based on the RFKILL handling in the r8187 driver, which is:
+ * Copyright (c) Realtek Semiconductor Corp. All rights reserved.
+ *
+ * Thanks to Realtek for their support!
+ *
+ * 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/types.h>
+#include <linux/usb.h>
+#include <net/mac80211.h>
+
+#include "rtl8187.h"
+
+static bool rtl8187_is_radio_enabled(struct rtl8187_priv *priv)
+{
+	u8 gpio;
+
+	gpio = rtl818x_ioread8(priv, &priv->map->GPIO0);
+	rtl818x_iowrite8(priv, &priv->map->GPIO0, gpio & ~0x02);
+	gpio = rtl818x_ioread8(priv, &priv->map->GPIO1);
+
+	return gpio & 0x02;
+}
+
+void rtl8187_rfkill_init(struct ieee80211_hw *hw)
+{
+	struct rtl8187_priv *priv = hw->priv;
+
+	priv->rfkill_off = rtl8187_is_radio_enabled(priv);
+	printk(KERN_INFO "rtl8187: wireless switch is %s\n",
+	       priv->rfkill_off ? "on" : "off");
+	wiphy_rfkill_set_hw_state(hw->wiphy, !priv->rfkill_off);
+	wiphy_rfkill_start_polling(hw->wiphy);
+}
+
+void rtl8187_rfkill_poll(struct ieee80211_hw *hw)
+{
+	bool enabled;
+	struct rtl8187_priv *priv = hw->priv;
+
+	mutex_lock(&priv->conf_mutex);
+	enabled = rtl8187_is_radio_enabled(priv);
+	if (unlikely(enabled != priv->rfkill_off)) {
+		priv->rfkill_off = enabled;
+		printk(KERN_INFO "rtl8187: wireless radio switch turned %s\n",
+		       enabled ? "on" : "off");
+		wiphy_rfkill_set_hw_state(hw->wiphy, !enabled);
+	}
+	mutex_unlock(&priv->conf_mutex);
+}
+
+void rtl8187_rfkill_exit(struct ieee80211_hw *hw)
+{
+	wiphy_rfkill_stop_polling(hw->wiphy);
+}
diff --git a/drivers/net/wireless/rtl818x/rtl8187_rfkill.h b/drivers/net/wireless/rtl818x/rtl8187_rfkill.h
new file mode 100644
index 0000000..e12575e
--- /dev/null
+++ b/drivers/net/wireless/rtl818x/rtl8187_rfkill.h
@@ -0,0 +1,8 @@
+#ifndef RTL8187_RFKILL_H
+#define RTL8187_RFKILL_H
+
+void rtl8187_rfkill_init(struct ieee80211_hw *hw);
+void rtl8187_rfkill_poll(struct ieee80211_hw *hw);
+void rtl8187_rfkill_exit(struct ieee80211_hw *hw);
+
+#endif /* RTL8187_RFKILL_H */
diff --git a/drivers/net/wireless/rtl818x/rtl818x.h b/drivers/net/wireless/rtl818x/rtl818x.h
index 562222e..8522490 100644
--- a/drivers/net/wireless/rtl818x/rtl818x.h
+++ b/drivers/net/wireless/rtl818x/rtl818x.h
@@ -138,8 +138,9 @@ struct rtl818x_csr {
 	__le32	RF_PARA;
 	__le32	RF_TIMING;
 	u8	GP_ENABLE;
-	u8	GPIO;
-	u8	reserved_12[2];
+	u8	GPIO0;
+	u8	GPIO1;
+	u8	reserved_12;
 	__le32	HSSI_PARA;
 	u8	reserved_13[4];
 	u8	TX_AGC_CTL;
-- 
1.6.4.1


^ permalink raw reply related

* Re: [RFC/RFT] rtl8187: Implement rfkill support
From: Herton Ronaldo Krzesinski @ 2009-08-26 16:57 UTC (permalink / raw)
  To: Hin-Tak Leung
  Cc: Johannes Berg, htl10, Larry Finger, linux-wireless,
	Luis R. Rodriguez
In-Reply-To: <3ace41890908260807t736848d8x57dff6cf3ac581c6@mail.gmail.com>

Em Qua 26 Ago 2009, às 12:07:52, Hin-Tak Leung escreveu:
> On Wed, Aug 26, 2009 at 3:34 PM, Johannes Berg<johannes@sipsolutions.net> wrote:
> > On Wed, 2009-08-26 at 13:33 +0000, Hin-Tak Leung wrote:
> >
> >> > Or wait ... are you using compat-wireless?
> >>
> >> Yes, I am. I mentioned this and did wonder if the _backport/ part
> >> in /sys/class is important.
> >
> > Sorry, didn't see.
> >
> > Anyway, that's pretty clearly the reason -- Luis added NETDEV_PRE_UP to
> > some compat*.h but obviously the kernel won't ever call that notifier,
> > so cfg80211 doesn't get a chance to reject the IFUP. No idea how to
> > handle that -- it'll be working fine in a regular tree.
> >
> > Luis, the only way to handle that would be to manually call the PRE_UP
> > notifier from mac80211's subif_open() and if that returns an error
> > (warning: the calling convention is weird) return the error... that's
> > weird but would work.
> 
> Okay, that explains it. So I can have a Tested-by: ... I just grep for

Ok, I submitted now the patches.

> NETDEV_PRE_UP in compat-wireless and it is only in
> include/net/compat-2.6.31.h (not in 2.6.30) and I am on 2.6.30.5-X . I
> can grab the rawhide 2.6.31 rpms and try it quickly;
> and possibly look at some ugly quick hack backport that? Stay tuned.
> 
> Thanks for the help.
> 
> Hin-Tak
> 

--
[]'s
Herton

^ permalink raw reply

* Re: [PATCH] ath5k: fix print on warning on ath5k_hw_to_driver_rix()
From: Bob Copeland @ 2009-08-26 17:03 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: Luis Rodriguez, linville@tuxdriver.com,
	linux-wireless@vger.kernel.org, Johannes Berg
In-Reply-To: <20090826162941.GA4417@mosca>

On Wed, Aug 26, 2009 at 12:29 PM, Luis R.
Rodriguez<lrodriguez@atheros.com> wrote:

> Not sure I follow. Let me explain the logic here a little better.
> ath5k_reset() had a check to see if we switched channels. The check
> is above, and I moved it ath5k_chan_set() called by the config callback.
> Reason for this is channel change *only* occurs through the config callback
> so we can be certain no other path will call reset with a channel change
> request.

But previously we did all this stuff for _every_ reset except the first
one, now we only do it for channel change resets.  It may make sense your
way, but I'd rather see that as a separate patch rather than part of a
cleanup.  (Also, chan_change is used to skip a bunch of phy register writes
that we only need to do once, not sure if that changes here).

>> There's just no synchronization of this stuff, not too surprising there
>> are races.
>
> config calls for reset seem to be with sc->lock. ath9k uses a mutex to
> protect races between mac80211 callback calls, ath5k seems to use the
> sc->lock *sometimes*, a good review of that may help but for channel
> change this seems protected unless I missed something. Since channel
> change goes through the config callback and since the callback protects
> through sc->lock I can't see how we'd race against changing channels.

rx_tasklet doesn't (can't) take the mutex though.  Here's the race:

cpu 1                       cpu 2
                            1mbit packet received, ack intr and queue it
client changes to 5ghz band
hw->conf.channel = 36
                            ath5k_rx_tasklet runs
                            hmm, we got 1mbit packet on channel 36, wtf
ath5k_chan_change()

This is still racy with curband variables of course, but IMO the
proposed change actually makes the race wider (in current code, we only
update the band after we disable the interrupts, but the tasklet can
still run on queued packets).

The right thing to do is either process or drop all of those packets
with interrupts disabled before updating the band/channel (rx_drainq),
or protect that channel info with a spinlock.   Or perhaps we can
figure it out directly from the rx descriptor -- I looked at this
briefly and didn't think there was enough info there, but didn't spend
much time on it.

-- 
Bob Copeland %% www.bobcopeland.com

^ permalink raw reply

* [PATCH] change rfkill licensing to GPL2
From: John W. Linville @ 2009-08-26 17:05 UTC (permalink / raw)
  To: linux-wireless
  Cc: Johannes Berg, Marcel Holtmann, Tim Gardner, John W. Linville

Also add a Copyright statement for Johannes to core.h...

Signed-off-by: John W. Linville <linville@tuxdriver.com>
---
Rather than wait for rfkill.h relicensing ACKs, since this is
Linus-specific anyway...

 COPYING |  350 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 core.h  |    4 +
 2 files changed, 343 insertions(+), 11 deletions(-)

diff --git a/COPYING b/COPYING
index 8351a30..d511905 100644
--- a/COPYING
+++ b/COPYING
@@ -1,11 +1,339 @@
-Permission to use, copy, modify, and/or distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/core.h b/core.h
index 56cde40..91ce9a3 100644
--- a/core.h
+++ b/core.h
@@ -1,3 +1,7 @@
+/*
+ * Copyright 2009	Johannes Berg <johannes@sipsolutions.net>
+ */
+
 #ifndef __CORE
 #define __CORE
 
-- 
1.6.2.5


^ permalink raw reply related

* Re: [PATCH] rfkill: relicense header file
From: Inaky Perez-Gonzalez @ 2009-08-26 18:05 UTC (permalink / raw)
  To: Johannes Berg
  Cc: John Linville, linux-wireless, Alan Jenkins,
	Henrique de Moraes Holschuh, Ivo van Doorn,
	Jaswinder Singh Rajput, Michael Buesch, Winkler, Tomas
In-Reply-To: <1251303197.15619.29.camel@johannes.local>

On Wed, 2009-08-26 at 10:13 -0600, Johannes Berg wrote:
> This header file is copied into userspace tools that
> need not be GPLv2 licensed, make that easier.
> 
> Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
> Cc: Alan Jenkins <alan-jenkins@tuffmail.co.uk>
> Cc: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
> Cc: Iñaky Pérez-González <inaky.perez-gonzalez@intel.com>
> Cc: Ivo van Doorn <IvDoorn@gmail.com>
> Cc: Jaswinder Singh Rajput <jaswinder@kernel.org>
> Cc: John W. Linville <linville@tuxdriver.com>
> Cc: Michael Buesch <mb@bu3sch.de>
> Cc: Tomas Winkler <tomas.winkler@intel.com>


Acked-By: Inaky Perez-Gonzalez <inaky@linux.intel.com>



^ permalink raw reply

* Re: [PATCH] rfkill: relicense header file
From: Ivo van Doorn @ 2009-08-26 18:11 UTC (permalink / raw)
  To: Johannes Berg
  Cc: John Linville, linux-wireless, Alan Jenkins,
	Henrique de Moraes Holschuh, Iñaky Pérez-González,
	Jaswinder Singh Rajput, Michael Buesch, Tomas Winkler
In-Reply-To: <1251303197.15619.29.camel@johannes.local>

On Wednesday 26 August 2009, Johannes Berg wrote:
> This header file is copied into userspace tools that
> need not be GPLv2 licensed, make that easier.
> 
> Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
> Cc: Alan Jenkins <alan-jenkins@tuffmail.co.uk>
> Cc: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
> Cc: Iñaky Pérez-González <inaky.perez-gonzalez@intel.com>
> Cc: Ivo van Doorn <IvDoorn@gmail.com>
> Cc: Jaswinder Singh Rajput <jaswinder@kernel.org>
> Cc: John W. Linville <linville@tuxdriver.com>
> Cc: Michael Buesch <mb@bu3sch.de>
> Cc: Tomas Winkler <tomas.winkler@intel.com>
> ---
> Need ACK from everybody listed who ever touched this
> file according to git. Please?
> 
>  include/linux/rfkill.h |   25 +++++++++++--------------
>  1 file changed, 11 insertions(+), 14 deletions(-)
> 
> --- wireless-testing.orig/include/linux/rfkill.h	2009-08-26 18:09:57.000000000 +0200
> +++ wireless-testing/include/linux/rfkill.h	2009-08-26 18:10:52.000000000 +0200
> @@ -6,20 +6,17 @@
>   * Copyright (C) 2007 Dmitry Torokhov
>   * Copyright 2009 Johannes Berg <johannes@sipsolutions.net>
>   *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License as published by
> - * the Free Software Foundation; either version 2 of the License, or
> - * (at your option) any later version.
> - *
> - * This program is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> - * GNU General Public License for more details.
> - *
> - * You should have received a copy of the GNU General Public License
> - * along with this program; if not, write to the
> - * Free Software Foundation, Inc.,
> - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
> + * Permission to use, copy, modify, and/or distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>   */
>  
>  #include <linux/types.h>

Acked-by: Ivo van Doorn <IvDoorn@gmail.com>



^ permalink raw reply

* Re: [PATCH] rndis_wlan: set cipher suites for cfg80211
From: Jussi Kivilinna @ 2009-08-26 18:15 UTC (permalink / raw)
  To: Holger Schurig; +Cc: linux-wireless, John W. Linville
In-Reply-To: <200908261521.30050.hs4233@mail.mn-solutions.de>

Quoting "Holger Schurig" <hs4233@mail.mn-solutions.de>:

>> +static const u32 rndis_cipher_suites[] = {
>> +	WLAN_CIPHER_SUITE_WEP40,
>> +	WLAN_CIPHER_SUITE_WEP104,
>> +	WLAN_CIPHER_SUITE_TKIP,
>> +	WLAN_CIPHER_SUITE_CCMP,
>> +};
>> +
>
> Okay, this is static, a.k.a. set-in-stone. Then why ...
>
>> +	memcpy(priv->cipher_suites, rndis_cipher_suites,
>> +						sizeof(rndis_cipher_suites));
>
> ... copy this to priv?
>
>> +	wiphy->cipher_suites = priv->cipher_suites;
>> +	wiphy->n_cipher_suites = ARRAY_SIZE(rndis_cipher_suites);
>
> Wouldn't
>
> +   wiphy->cipher_suide = rndis_cipher_suites;
> +   wiphy->n_cipher_suites = ARRAY_SIZE(rndis_cipher_suites);
>
> do the job?  That way you can drop priv->cipher_suites.
>

Yes, that works just fine, and first version was that way. Reason is  
that rndis_wlan should really check device capabilities and set cipher  
suites
depending by theim (so then per device priv->cipher_suite is needed).  
Current static array is not problem as currently there is only one  
chip that uses rndis_wlan and array matches its capabilities.  
priv->channel/rndis_channels and priv->rate/rndis_rates are the same  
and I plan to add caps checking code later.

-Jussi


^ permalink raw reply

* [PATCH v2] b43: LP-PHY: Fix and simplify Qdiv roundup
From: Gábor Stefanik @ 2009-08-26 18:51 UTC (permalink / raw)
  To: John Linville, Michael Buesch, Larry Finger, Mark Huijgen
  Cc: Broadcom Wireless, linux-wireless

The Qdiv roundup routine is essentially a fixed-point
division algorithm, using only integer math.
However, the version in the specs had a major error
that has been recently fixed (a missing quotient++).

Replace Qdiv roundup with a rewritten, simplified version.

Signed-off-by: Gábor Stefanik <netrolller.3d@gmail.com>
---
v2: Remove divide/modulo operations from the inner loop.

 drivers/net/wireless/b43/phy_lp.c |   19 ++++++++-----------
 1 files changed, 8 insertions(+), 11 deletions(-)

diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c
index 7e70c07..5306f2c 100644
--- a/drivers/net/wireless/b43/phy_lp.c
+++ b/drivers/net/wireless/b43/phy_lp.c
@@ -1032,9 +1032,10 @@ static int lpphy_loopback(struct b43_wldev *dev)
 	return index;
 }
 
+/* Fixed-point division algorithm using only integer math. */
 static u32 lpphy_qdiv_roundup(u32 dividend, u32 divisor, u8 precision)
 {
-	u32 quotient, remainder, rbit, roundup, tmp;
+	u32 quotient, remainder;
 
 	if (divisor == 0)
 		return 0;
@@ -1042,20 +1043,16 @@ static u32 lpphy_qdiv_roundup(u32 dividend, u32 divisor, u8 precision)
 	quotient = dividend / divisor;
 	remainder = dividend % divisor;
 
-	rbit = divisor & 0x1;
-	roundup = (divisor >> 1) + rbit;
-
-	while (precision != 0) {
-		tmp = remainder - roundup;
+	while (precision > 0) {
 		quotient <<= 1;
-		if (remainder >= roundup)
-			remainder = (tmp << 1) + rbit;
-		else
-			remainder <<= 1;
+		if (remainder << 1 >= divisor) {
+			quotient++;
+			remainder = (remainder << 1) - divisor;
+		}
 		precision--;
 	}
 
-	if (remainder >= roundup)
+	if (remainder << 1 >= divisor)
 		quotient++;
 
 	return quotient;
-- 
1.5.6


^ permalink raw reply related

* [PATCH] b43: Fix and update LP-PHY code
From: Gábor Stefanik @ 2009-08-26 18:51 UTC (permalink / raw)
  To: John Linville, Michael Buesch, Larry Finger, Mark Huijgen
  Cc: Broadcom Wireless, linux-wireless
In-Reply-To: <1251312686-32067-1-git-send-email-netrolller.3d@gmail.com>

-Fix a few nasty typos (b43_phy_* operations instead of b43_radio_*)
 in the channel tune routines.
-Fix some typos & spec errors found by MMIO tracing.
-Optimize b43_phy_write & b43_phy_mask/set/maskset to use
 only the minimal number of MMIO accesses. (Write is possible
 using a single 32-bit MMIO write, while set/mask/maskset can
 be done in 3 16-bit MMIOs).
-Set the default channel back to 1, as the bug forcing us to use
 channel 7 is now fixed.

With this, the device comes up, scans, associates, transmits,
receives, monitors and injects on all channels - in other words,
it's fully functional. Sensitivity and TX power are still sub-optimal,
due to the lack of calibration (that's next on my list).

Signed-off-by: Gábor Stefanik <netrolller.3d@gmail.com>
---
 drivers/net/wireless/b43/phy_common.c   |   27 +++++++--
 drivers/net/wireless/b43/phy_common.h   |    3 +
 drivers/net/wireless/b43/phy_lp.c       |   91 +++++++++++++++++--------------
 drivers/net/wireless/b43/phy_lp.h       |    3 +
 drivers/net/wireless/b43/tables_lpphy.c |   79 +++++++++++++++------------
 5 files changed, 122 insertions(+), 81 deletions(-)

diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c
index 51686ec..6e704be 100644
--- a/drivers/net/wireless/b43/phy_common.c
+++ b/drivers/net/wireless/b43/phy_common.c
@@ -249,20 +249,35 @@ void b43_phy_copy(struct b43_wldev *dev, u16 destreg, u16 srcreg)
 
 void b43_phy_mask(struct b43_wldev *dev, u16 offset, u16 mask)
 {
-	b43_phy_write(dev, offset,
-		      b43_phy_read(dev, offset) & mask);
+	if (dev->phy.ops->phy_maskset) {
+		assert_mac_suspended(dev);
+		dev->phy.ops->phy_maskset(dev, offset, mask, 0);
+	} else {
+		b43_phy_write(dev, offset,
+			      b43_phy_read(dev, offset) & mask);
+	}
 }
 
 void b43_phy_set(struct b43_wldev *dev, u16 offset, u16 set)
 {
-	b43_phy_write(dev, offset,
-		      b43_phy_read(dev, offset) | set);
+	if (dev->phy.ops->phy_maskset) {
+		assert_mac_suspended(dev);
+		dev->phy.ops->phy_maskset(dev, offset, 0xFFFF, set);
+	} else {
+		b43_phy_write(dev, offset,
+			      b43_phy_read(dev, offset) | set);
+	}
 }
 
 void b43_phy_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set)
 {
-	b43_phy_write(dev, offset,
-		      (b43_phy_read(dev, offset) & mask) | set);
+	if (dev->phy.ops->phy_maskset) {
+		assert_mac_suspended(dev);
+		dev->phy.ops->phy_maskset(dev, offset, mask, set);
+	} else {
+		b43_phy_write(dev, offset,
+			      (b43_phy_read(dev, offset) & mask) | set);
+	}
 }
 
 int b43_switch_channel(struct b43_wldev *dev, unsigned int new_channel)
diff --git a/drivers/net/wireless/b43/phy_common.h b/drivers/net/wireless/b43/phy_common.h
index 9f9f23c..b47a0f5 100644
--- a/drivers/net/wireless/b43/phy_common.h
+++ b/drivers/net/wireless/b43/phy_common.h
@@ -95,6 +95,8 @@ enum b43_txpwr_result {
  * 			Must not be NULL.
  * @phy_write:		Write to a PHY register.
  * 			Must not be NULL.
+ * @phy_maskset:	Maskset a PHY register, taking shortcuts.
+ *			If it is NULL, a generic algorithm is used.
  * @radio_read:		Read from a Radio register.
  * 			Must not be NULL.
  * @radio_write:	Write to a Radio register.
@@ -154,6 +156,7 @@ struct b43_phy_operations {
 	/* Register access */
 	u16 (*phy_read)(struct b43_wldev *dev, u16 reg);
 	void (*phy_write)(struct b43_wldev *dev, u16 reg, u16 value);
+	void (*phy_maskset)(struct b43_wldev *dev, u16 reg, u16 mask, u16 set);
 	u16 (*radio_read)(struct b43_wldev *dev, u16 reg);
 	void (*radio_write)(struct b43_wldev *dev, u16 reg, u16 value);
 
diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c
index 5306f2c..1a57d33 100644
--- a/drivers/net/wireless/b43/phy_lp.c
+++ b/drivers/net/wireless/b43/phy_lp.c
@@ -44,7 +44,7 @@ static inline u16 channel2freq_lp(u8 channel)
 static unsigned int b43_lpphy_op_get_default_chan(struct b43_wldev *dev)
 {
 	if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
-		return 7; //FIXME temporary - channel 1 is broken
+		return 1;
 	return 36;
 }
 
@@ -182,8 +182,8 @@ static void lpphy_adjust_gain_table(struct b43_wldev *dev, u32 freq)
 	temp[1] = temp[0] + 0x1000;
 	temp[2] = temp[0] + 0x2000;
 
-	b43_lptab_write_bulk(dev, B43_LPTAB16(12, 0), 3, temp);
 	b43_lptab_write_bulk(dev, B43_LPTAB16(13, 0), 3, temp);
+	b43_lptab_write_bulk(dev, B43_LPTAB16(12, 0), 3, temp);
 }
 
 static void lpphy_table_init(struct b43_wldev *dev)
@@ -223,8 +223,8 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
 	b43_phy_maskset(dev, B43_LPPHY_VERYLOWGAINDB, 0xFF00, 0x0006);
 	b43_phy_mask(dev, B43_LPPHY_RX_RADIO_CTL, 0xFFFE);
 	b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFFE0, 0x0005);
-	b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFC10, 0x0180);
-	b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0x83FF, 0x3800);
+	b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFC1F, 0x0180);
+	b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0x83FF, 0x3C00);
 	b43_phy_maskset(dev, B43_LPPHY_GAINDIRECTMISMATCH, 0xFFF0, 0x0005);
 	b43_phy_maskset(dev, B43_LPPHY_GAIN_MISMATCH_LIMIT, 0xFFC0, 0x001A);
 	b43_phy_maskset(dev, B43_LPPHY_CRS_ED_THRESH, 0xFF00, 0x00B3);
@@ -237,7 +237,7 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
 		/* TODO:
 		 * Set the LDO voltage to 0x0028 - FIXME: What is this?
 		 * Call sb_pmu_set_ldo_voltage with 4 and the LDO voltage
-		 * 	as arguments
+		 *      as arguments
 		 * Call sb_pmu_paref_ldo_enable with argument TRUE
 		 */
 		if (dev->phy.rev == 0) {
@@ -340,11 +340,11 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
 	if (dev->phy.rev == 1) {
 		tmp = b43_phy_read(dev, B43_LPPHY_CLIPCTRTHRESH);
 		tmp2 = (tmp & 0x03E0) >> 5;
-		tmp2 |= tmp << 5;
+		tmp2 |= tmp2 << 5;
 		b43_phy_write(dev, B43_LPPHY_4C3, tmp2);
-		tmp = b43_phy_read(dev, B43_LPPHY_OFDMSYNCTHRESH0);
+		tmp = b43_phy_read(dev, B43_LPPHY_GAINDIRECTMISMATCH);
 		tmp2 = (tmp & 0x1F00) >> 8;
-		tmp2 |= tmp << 5;
+		tmp2 |= tmp2 << 5;
 		b43_phy_write(dev, B43_LPPHY_4C4, tmp2);
 		tmp = b43_phy_read(dev, B43_LPPHY_VERYLOWGAINDB);
 		tmp2 = tmp & 0x00FF;
@@ -761,7 +761,7 @@ static void lpphy_disable_crs(struct b43_wldev *dev, bool user)
 	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_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_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);
@@ -956,7 +956,7 @@ static void lpphy_run_ddfs(struct b43_wldev *dev, int i_on, int q_on,
 	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);
+	b43_phy_set(dev, B43_LPPHY_LP_PHY_CTL, 0x20);
 }
 
 static bool lpphy_rx_iq_est(struct b43_wldev *dev, u16 samples, u8 time,
@@ -968,7 +968,7 @@ static bool lpphy_rx_iq_est(struct b43_wldev *dev, u16 samples, u8 time,
 	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);
+	b43_phy_set(dev, B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR, 0x200);
 
 	for (i = 0; i < 500; i++) {
 		if (!(b43_phy_read(dev,
@@ -1135,9 +1135,9 @@ static void lpphy_set_tx_power_control(struct b43_wldev *dev,
 	}
 	if (dev->phy.rev >= 2) {
 		if (mode == B43_LPPHY_TXPCTL_HW)
-			b43_phy_maskset(dev, B43_PHY_OFDM(0xD0), 0xFD, 0x2);
+			b43_phy_set(dev, B43_PHY_OFDM(0xD0), 0x2);
 		else
-			b43_phy_maskset(dev, B43_PHY_OFDM(0xD0), 0xFD, 0);
+			b43_phy_mask(dev, B43_PHY_OFDM(0xD0), 0xFFFD);
 	}
 	lpphy_write_tx_pctl_mode_to_hardware(dev);
 }
@@ -1169,7 +1169,7 @@ static void lpphy_rev0_1_rc_calib(struct b43_wldev *dev)
 	err = b43_lpphy_op_switch_channel(dev, 7);
 	if (err) {
 		b43dbg(dev->wl,
-		       "RC calib: Failed to switch to channel 7, error = %d",
+		       "RC calib: Failed to switch to channel 7, error = %d\n",
 		       err);
 	}
 	old_txg_ovr = !!(b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVR) & 0x40);
@@ -1500,8 +1500,15 @@ static u16 b43_lpphy_op_read(struct b43_wldev *dev, u16 reg)
 
 static void b43_lpphy_op_write(struct b43_wldev *dev, u16 reg, u16 value)
 {
+	b43_write32(dev, B43_MMIO_PHY_CONTROL, ((u32)value << 16) | reg);
+}
+
+static void b43_lpphy_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask,
+				 u16 set)
+{
 	b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
-	b43_write16(dev, B43_MMIO_PHY_DATA, value);
+	b43_write16(dev, B43_MMIO_PHY_DATA,
+		    (b43_read16(dev, B43_MMIO_PHY_DATA) & mask) | set);
 }
 
 static u16 b43_lpphy_op_radio_read(struct b43_wldev *dev, u16 reg)
@@ -1920,8 +1927,8 @@ static void lpphy_b2062_reset_pll_bias(struct b43_wldev *dev)
 
 static void lpphy_b2062_vco_calib(struct b43_wldev *dev)
 {
-	b43_phy_write(dev, B2062_S_RFPLL_CTL21, 0x42);
-	b43_phy_write(dev, B2062_S_RFPLL_CTL21, 0x62);
+	b43_radio_write(dev, B2062_S_RFPLL_CTL21, 0x42);
+	b43_radio_write(dev, B2062_S_RFPLL_CTL21, 0x62);
 	udelay(200);
 }
 
@@ -1980,7 +1987,7 @@ static int lpphy_b2062_tune(struct b43_wldev *dev,
 	tmp6 = tmp5 / tmp4;
 	tmp7 = tmp5 % tmp4;
 	b43_radio_write(dev, B2062_S_RFPLL_CTL29, tmp6 + ((2 * tmp7) / tmp4));
-	tmp8 = b43_phy_read(dev, B2062_S_RFPLL_CTL19);
+	tmp8 = b43_radio_read(dev, B2062_S_RFPLL_CTL19);
 	tmp9 = ((2 * tmp3 * (tmp8 + 1)) + (3 * tmp1)) / (6 * tmp1);
 	b43_radio_write(dev, B2062_S_RFPLL_CTL23, (tmp9 >> 8) + 16);
 	b43_radio_write(dev, B2062_S_RFPLL_CTL24, tmp9 & 0xFF);
@@ -2019,17 +2026,17 @@ static void lpphy_b2063_vco_calib(struct b43_wldev *dev)
 {
 	u16 tmp;
 
-	b43_phy_mask(dev, B2063_PLL_SP1, ~0x40);
-	tmp = b43_phy_read(dev, B2063_PLL_JTAG_CALNRST) & 0xF8;
-	b43_phy_write(dev, B2063_PLL_JTAG_CALNRST, tmp);
+	b43_radio_mask(dev, B2063_PLL_SP1, ~0x40);
+	tmp = b43_radio_read(dev, B2063_PLL_JTAG_CALNRST) & 0xF8;
+	b43_radio_write(dev, B2063_PLL_JTAG_CALNRST, tmp);
 	udelay(1);
-	b43_phy_write(dev, B2063_PLL_JTAG_CALNRST, tmp | 0x4);
+	b43_radio_write(dev, B2063_PLL_JTAG_CALNRST, tmp | 0x4);
 	udelay(1);
-	b43_phy_write(dev, B2063_PLL_JTAG_CALNRST, tmp | 0x6);
+	b43_radio_write(dev, B2063_PLL_JTAG_CALNRST, tmp | 0x6);
 	udelay(1);
-	b43_phy_write(dev, B2063_PLL_JTAG_CALNRST, tmp | 0x7);
+	b43_radio_write(dev, B2063_PLL_JTAG_CALNRST, tmp | 0x7);
 	udelay(300);
-	b43_phy_set(dev, B2063_PLL_SP1, 0x40);
+	b43_radio_set(dev, B2063_PLL_SP1, 0x40);
 }
 
 static int lpphy_b2063_tune(struct b43_wldev *dev,
@@ -2124,31 +2131,31 @@ static int lpphy_b2063_tune(struct b43_wldev *dev,
 		scale = 0;
 		tmp5 = ((tmp4 + (tmp3 >> 1)) / tmp3) - 8;
 	}
-	b43_phy_maskset(dev, B2063_PLL_JTAG_PLL_CP2, 0xFFC0, tmp5);
-	b43_phy_maskset(dev, B2063_PLL_JTAG_PLL_CP2, 0xFFBF, scale << 6);
+	b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_CP2, 0xFFC0, tmp5);
+	b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_CP2, 0xFFBF, scale << 6);
 
 	tmp6 = lpphy_qdiv_roundup(100 * val1, val3, 16);
 	tmp6 *= (tmp5 * 8) * (scale + 1);
 	if (tmp6 > 150)
 		tmp6 = 0;
 
-	b43_phy_maskset(dev, B2063_PLL_JTAG_PLL_CP3, 0xFFE0, tmp6);
-	b43_phy_maskset(dev, B2063_PLL_JTAG_PLL_CP3, 0xFFDF, scale << 5);
+	b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_CP3, 0xFFE0, tmp6);
+	b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_CP3, 0xFFDF, scale << 5);
 
-	b43_phy_maskset(dev, B2063_PLL_JTAG_PLL_XTAL_12, 0xFFFB, 0x4);
+	b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_XTAL_12, 0xFFFB, 0x4);
 	if (crystal_freq > 26000000)
-		b43_phy_set(dev, B2063_PLL_JTAG_PLL_XTAL_12, 0x2);
+		b43_radio_set(dev, B2063_PLL_JTAG_PLL_XTAL_12, 0x2);
 	else
-		b43_phy_mask(dev, B2063_PLL_JTAG_PLL_XTAL_12, 0xFD);
+		b43_radio_mask(dev, B2063_PLL_JTAG_PLL_XTAL_12, 0xFD);
 
 	if (val1 == 45)
-		b43_phy_set(dev, B2063_PLL_JTAG_PLL_VCO1, 0x2);
+		b43_radio_set(dev, B2063_PLL_JTAG_PLL_VCO1, 0x2);
 	else
-		b43_phy_mask(dev, B2063_PLL_JTAG_PLL_VCO1, 0xFD);
+		b43_radio_mask(dev, B2063_PLL_JTAG_PLL_VCO1, 0xFD);
 
-	b43_phy_set(dev, B2063_PLL_SP2, 0x3);
+	b43_radio_set(dev, B2063_PLL_SP2, 0x3);
 	udelay(1);
-	b43_phy_mask(dev, B2063_PLL_SP2, 0xFFFC);
+	b43_radio_mask(dev, B2063_PLL_SP2, 0xFFFC);
 	lpphy_b2063_vco_calib(dev);
 	b43_radio_write(dev, B2063_COMM15, old_comm15);
 
@@ -2158,10 +2165,9 @@ static int lpphy_b2063_tune(struct b43_wldev *dev,
 static int b43_lpphy_op_switch_channel(struct b43_wldev *dev,
 				       unsigned int new_channel)
 {
+	struct b43_phy_lp *lpphy = dev->phy.lp;
 	int err;
 
-	b43_write16(dev, B43_MMIO_CHANNEL, new_channel);
-
 	if (dev->phy.radio_ver == 0x2063) {
 		err = lpphy_b2063_tune(dev, new_channel);
 		if (err)
@@ -2174,6 +2180,9 @@ static int b43_lpphy_op_switch_channel(struct b43_wldev *dev,
 		lpphy_adjust_gain_table(dev, channel2freq_lp(new_channel));
 	}
 
+	lpphy->channel = new_channel;
+	b43_write16(dev, B43_MMIO_CHANNEL, new_channel);
+
 	return 0;
 }
 
@@ -2185,10 +2194,9 @@ static int b43_lpphy_op_init(struct b43_wldev *dev)
 	lpphy_baseband_init(dev);
 	lpphy_radio_init(dev);
 	lpphy_calibrate_rc(dev);
-	err = b43_lpphy_op_switch_channel(dev,
-				b43_lpphy_op_get_default_chan(dev));
+	err = b43_lpphy_op_switch_channel(dev, 7);
 	if (err) {
-		b43dbg(dev->wl, "Switch to init channel failed, error = %d.\n",
+		b43dbg(dev->wl, "Switch to channel 7 failed, error = %d.\n",
 		       err);
 	}
 	lpphy_tx_pctl_init(dev);
@@ -2222,6 +2230,7 @@ const struct b43_phy_operations b43_phyops_lp = {
 	.init			= b43_lpphy_op_init,
 	.phy_read		= b43_lpphy_op_read,
 	.phy_write		= b43_lpphy_op_write,
+	.phy_maskset		= b43_lpphy_op_maskset,
 	.radio_read		= b43_lpphy_op_radio_read,
 	.radio_write		= b43_lpphy_op_radio_write,
 	.software_rfkill	= b43_lpphy_op_software_rfkill,
diff --git a/drivers/net/wireless/b43/phy_lp.h b/drivers/net/wireless/b43/phy_lp.h
index e158d1f..c3232c1 100644
--- a/drivers/net/wireless/b43/phy_lp.h
+++ b/drivers/net/wireless/b43/phy_lp.h
@@ -888,6 +888,9 @@ struct b43_phy_lp {
 	bool crs_usr_disable, crs_sys_disable;
 
 	unsigned int pdiv;
+
+	/* The channel we are tuned to */
+	u8 channel;
 };
 
 enum tssi_mux_mode {
diff --git a/drivers/net/wireless/b43/tables_lpphy.c b/drivers/net/wireless/b43/tables_lpphy.c
index 60d472f..c784def 100644
--- a/drivers/net/wireless/b43/tables_lpphy.c
+++ b/drivers/net/wireless/b43/tables_lpphy.c
@@ -624,30 +624,35 @@ u32 b43_lptab_read(struct b43_wldev *dev, u32 offset)
 void b43_lptab_read_bulk(struct b43_wldev *dev, u32 offset,
 			 unsigned int nr_elements, void *_data)
 {
-	u32 type, value;
+	u32 type;
 	u8 *data = _data;
 	unsigned int i;
 
 	type = offset & B43_LPTAB_TYPEMASK;
+	offset &= ~B43_LPTAB_TYPEMASK;
+	B43_WARN_ON(offset > 0xFFFF);
+
+	b43_phy_write(dev, B43_LPPHY_TABLE_ADDR, offset);
+
 	for (i = 0; i < nr_elements; i++) {
-		value = b43_lptab_read(dev, offset);
 		switch (type) {
 		case B43_LPTAB_8BIT:
-			*data = value;
+			*data = b43_phy_read(dev, B43_LPPHY_TABLEDATALO) & 0xFF;
 			data++;
 			break;
 		case B43_LPTAB_16BIT:
-			*((u16 *)data) = value;
+			*((u16 *)data) = b43_phy_read(dev, B43_LPPHY_TABLEDATALO);
 			data += 2;
 			break;
 		case B43_LPTAB_32BIT:
-			*((u32 *)data) = value;
+			*((u32 *)data) = b43_phy_read(dev, B43_LPPHY_TABLEDATAHI);
+			*((u32 *)data) <<= 16;
+			*((u32 *)data) |= b43_phy_read(dev, B43_LPPHY_TABLEDATALO);
 			data += 4;
 			break;
 		default:
 			B43_WARN_ON(1);
 		}
-		offset++;
 	}
 }
 
@@ -688,26 +693,34 @@ void b43_lptab_write_bulk(struct b43_wldev *dev, u32 offset,
 	unsigned int i;
 
 	type = offset & B43_LPTAB_TYPEMASK;
+	offset &= ~B43_LPTAB_TYPEMASK;
+	B43_WARN_ON(offset > 0xFFFF);
+
+	b43_phy_write(dev, B43_LPPHY_TABLE_ADDR, offset);
+
 	for (i = 0; i < nr_elements; i++) {
 		switch (type) {
 		case B43_LPTAB_8BIT:
 			value = *data;
 			data++;
+			B43_WARN_ON(value & ~0xFF);
+			b43_phy_write(dev, B43_LPPHY_TABLEDATALO, value);
 			break;
 		case B43_LPTAB_16BIT:
 			value = *((u16 *)data);
 			data += 2;
+			B43_WARN_ON(value & ~0xFFFF);
+			b43_phy_write(dev, B43_LPPHY_TABLEDATALO, value);
 			break;
 		case B43_LPTAB_32BIT:
 			value = *((u32 *)data);
 			data += 4;
+			b43_phy_write(dev, B43_LPPHY_TABLEDATAHI, value >> 16);
+			b43_phy_write(dev, B43_LPPHY_TABLEDATALO, value);
 			break;
 		default:
 			B43_WARN_ON(1);
-			value = 0;
 		}
-		b43_lptab_write(dev, offset, value);
-		offset++;
 	}
 }
 
@@ -777,7 +790,7 @@ static const u8 lpphy_pll_fraction_table[] = {
 	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
 };
 
-static const u16 lpphy_iq_local_table[] = {
+static const u16 lpphy_iqlo_cal_table[] = {
 	0x0200, 0x0300, 0x0400, 0x0600, 0x0800, 0x0b00, 0x1000, 0x1001, 0x1002,
 	0x1003, 0x1004, 0x1005, 0x1006, 0x1007, 0x1707, 0x2007, 0x2d07, 0x4007,
 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
@@ -789,10 +802,17 @@ static const u16 lpphy_iq_local_table[] = {
 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4000, 0x0000, 0x0000,
 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-	0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
 };
 
-static const u16 lpphy_ofdm_cck_gain_table[] = {
+static const u16 lpphy_rev0_ofdm_cck_gain_table[] = {
+	0x0001, 0x0001, 0x0001, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001, 0x5001,
+	0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055, 0x2065, 0x2075,
+	0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d, 0x135d, 0x055d, 0x155d,
+	0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d, 0x755d,
+};
+
+static const u16 lpphy_rev1_ofdm_cck_gain_table[] = {
 	0x5000, 0x6000, 0x7000, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001, 0x5001,
 	0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055, 0x2065, 0x2075,
 	0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d, 0x135d, 0x055d, 0x155d,
@@ -2263,11 +2283,18 @@ void lpphy_rev0_1_table_init(struct b43_wldev *dev)
 	b43_lptab_write_bulk(dev, B43_LPTAB8(6, 0),
 		ARRAY_SIZE(lpphy_pll_fraction_table), lpphy_pll_fraction_table);
 	b43_lptab_write_bulk(dev, B43_LPTAB16(0, 0),
-		ARRAY_SIZE(lpphy_iq_local_table), lpphy_iq_local_table);
-	b43_lptab_write_bulk(dev, B43_LPTAB16(13, 0),
-		ARRAY_SIZE(lpphy_ofdm_cck_gain_table), lpphy_ofdm_cck_gain_table);
-	b43_lptab_write_bulk(dev, B43_LPTAB16(12, 0),
-		ARRAY_SIZE(lpphy_ofdm_cck_gain_table), lpphy_ofdm_cck_gain_table);
+		ARRAY_SIZE(lpphy_iqlo_cal_table), lpphy_iqlo_cal_table);
+	if (dev->phy.rev == 0) {
+		b43_lptab_write_bulk(dev, B43_LPTAB16(13, 0),
+			ARRAY_SIZE(lpphy_rev0_ofdm_cck_gain_table), lpphy_rev0_ofdm_cck_gain_table);
+		b43_lptab_write_bulk(dev, B43_LPTAB16(12, 0),
+			ARRAY_SIZE(lpphy_rev0_ofdm_cck_gain_table), lpphy_rev0_ofdm_cck_gain_table);
+	} else {
+		b43_lptab_write_bulk(dev, B43_LPTAB16(13, 0),
+			ARRAY_SIZE(lpphy_rev1_ofdm_cck_gain_table), lpphy_rev1_ofdm_cck_gain_table);
+		b43_lptab_write_bulk(dev, B43_LPTAB16(12, 0),
+			ARRAY_SIZE(lpphy_rev1_ofdm_cck_gain_table), lpphy_rev1_ofdm_cck_gain_table);
+}
 	b43_lptab_write_bulk(dev, B43_LPTAB16(15, 0),
 		ARRAY_SIZE(lpphy_gain_delta_table), lpphy_gain_delta_table);
 	b43_lptab_write_bulk(dev, B43_LPTAB32(10, 0),
@@ -2281,22 +2308,6 @@ void lpphy_rev2plus_table_init(struct b43_wldev *dev)
 
 	B43_WARN_ON(dev->phy.rev < 2);
 
-	/*
-	 * FIXME This code follows the specs, but it looks wrong:
-	 * In each pass, it writes 4 bytes to an offset in table ID 7,
-	 * then increments the offset by 1 for the next pass. This results
-	 * in the first 3 bytes of each pass except the first one getting
-	 * written to a location that has already been zeroed in the previous
-	 * pass.
-	 * This is what the vendor driver does, but it still looks suspicious.
-	 *
-	 * This should probably suffice:
-	 *
-	 * for (i = 0; i < 704; i+=4)
-	 * 	b43_lptab_write(dev, B43_LPTAB32(7, i), 0)
-	 *
-	 * This should be tested once the code is functional.
-	 */
 	for (i = 0; i < 704; i++)
 		b43_lptab_write(dev, B43_LPTAB32(7, i), 0);
 
@@ -2323,7 +2334,7 @@ void lpphy_rev2plus_table_init(struct b43_wldev *dev)
 	b43_lptab_write_bulk(dev, B43_LPTAB8(6, 0),
 		ARRAY_SIZE(lpphy_pll_fraction_table), lpphy_pll_fraction_table);
 	b43_lptab_write_bulk(dev, B43_LPTAB16(0, 0),
-		ARRAY_SIZE(lpphy_iq_local_table), lpphy_iq_local_table);
+		ARRAY_SIZE(lpphy_iqlo_cal_table), lpphy_iqlo_cal_table);
 	b43_lptab_write_bulk(dev, B43_LPTAB32(9, 0),
 		ARRAY_SIZE(lpphy_papd_eps_table), lpphy_papd_eps_table);
 	b43_lptab_write_bulk(dev, B43_LPTAB32(10, 0),
-- 
1.5.6


^ permalink raw reply related

* [PATCH] ssb: Implement PMU LDO control and use it in b43
From: Gábor Stefanik @ 2009-08-26 18:51 UTC (permalink / raw)
  To: John Linville, Michael Buesch, Larry Finger, Mark Huijgen
  Cc: Broadcom Wireless, linux-wireless
In-Reply-To: <1251312686-32067-2-git-send-email-netrolller.3d@gmail.com>

Implement the "PMU LDO set voltage" and "PMU LDO PA ref enable"
functions, and use them during LP-PHY baseband init in b43.

Signed-off-by: Gábor Stefanik <netrolller.3d@gmail.com>
---
 drivers/net/wireless/b43/phy_lp.c         |   10 +--
 drivers/ssb/driver_chipcommon_pmu.c       |   94 +++++++++++++++++++++++++++++
 include/linux/ssb/ssb_driver_chipcommon.h |   10 +++
 3 files changed, 107 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c
index 1a57d33..80f245c 100644
--- a/drivers/net/wireless/b43/phy_lp.c
+++ b/drivers/net/wireless/b43/phy_lp.c
@@ -234,19 +234,15 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
 	if ((bus->sprom.boardflags_lo & B43_BFL_FEM) &&
 	   ((b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ||
 	   (bus->sprom.boardflags_hi & B43_BFH_PAREF))) {
-		/* TODO:
-		 * Set the LDO voltage to 0x0028 - FIXME: What is this?
-		 * Call sb_pmu_set_ldo_voltage with 4 and the LDO voltage
-		 *      as arguments
-		 * Call sb_pmu_paref_ldo_enable with argument TRUE
-		 */
+		ssb_pmu_set_ldo_voltage(&bus->chipco, LDO_PAREF, 0x28);
+		ssb_pmu_set_ldo_paref(&bus->chipco, true);
 		if (dev->phy.rev == 0) {
 			b43_phy_maskset(dev, B43_LPPHY_LP_RF_SIGNAL_LUT,
 					0xFFCF, 0x0010);
 		}
 		b43_lptab_write(dev, B43_LPTAB16(11, 7), 60);
 	} else {
-		//TODO: Call ssb_pmu_paref_ldo_enable with argument FALSE
+		ssb_pmu_set_ldo_paref(&bus->chipco, false);
 		b43_phy_maskset(dev, B43_LPPHY_LP_RF_SIGNAL_LUT,
 				0xFFCF, 0x0020);
 		b43_lptab_write(dev, B43_LPTAB16(11, 7), 100);
diff --git a/drivers/ssb/driver_chipcommon_pmu.c b/drivers/ssb/driver_chipcommon_pmu.c
index 4aaddee..64abd11 100644
--- a/drivers/ssb/driver_chipcommon_pmu.c
+++ b/drivers/ssb/driver_chipcommon_pmu.c
@@ -28,6 +28,21 @@ static void ssb_chipco_pll_write(struct ssb_chipcommon *cc,
 	chipco_write32(cc, SSB_CHIPCO_PLLCTL_DATA, value);
 }
 
+static void ssb_chipco_regctl_maskset(struct ssb_chipcommon *cc,
+				   u32 offset, u32 mask, u32 set)
+{
+	u32 value;
+
+	chipco_read32(cc, SSB_CHIPCO_REGCTL_ADDR);
+	chipco_write32(cc, SSB_CHIPCO_REGCTL_ADDR, offset);
+	chipco_read32(cc, SSB_CHIPCO_REGCTL_ADDR);
+	value = chipco_read32(cc, SSB_CHIPCO_REGCTL_DATA);
+	value &= mask;
+	value |= set;
+	chipco_write32(cc, SSB_CHIPCO_REGCTL_DATA, value);
+	chipco_read32(cc, SSB_CHIPCO_REGCTL_DATA);
+}
+
 struct pmu0_plltab_entry {
 	u16 freq;	/* Crystal frequency in kHz.*/
 	u8 xf;		/* Crystal frequency value for PMU control */
@@ -506,3 +521,82 @@ void ssb_pmu_init(struct ssb_chipcommon *cc)
 	ssb_pmu_pll_init(cc);
 	ssb_pmu_resources_init(cc);
 }
+
+void ssb_pmu_set_ldo_voltage(struct ssb_chipcommon *cc,
+			     enum ssb_pmu_ldo_volt_id id, u32 voltage)
+{
+	struct ssb_bus *bus = cc->dev->bus;
+	u32 addr, shift, mask;
+
+	switch (bus->chip_id) {
+	case 0x4328:
+	case 0x5354:
+		switch (id) {
+		case LDO_VOLT1:
+			addr = 2;
+			shift = 25;
+			mask = 0xF;
+			break;
+		case LDO_VOLT2:
+			addr = 3;
+			shift = 1;
+			mask = 0xF;
+			break;
+		case LDO_VOLT3:
+			addr = 3;
+			shift = 9;
+			mask = 0xF;
+			break;
+		case LDO_PAREF:
+			addr = 3;
+			shift = 17;
+			mask = 0x3F;
+			break;
+		default:
+			SSB_WARN_ON(1);
+			return;
+		}
+		break;
+	case 0x4312:
+		if (SSB_WARN_ON(id != LDO_PAREF))
+			return;
+		addr = 0;
+		shift = 21;
+		mask = 0x3F;
+		break;
+	default:
+		return;
+	}
+
+	ssb_chipco_regctl_maskset(cc, addr, ~(mask << shift),
+				  (voltage & mask) << shift);
+}
+
+void ssb_pmu_set_ldo_paref(struct ssb_chipcommon *cc, bool on)
+{
+	struct ssb_bus *bus = cc->dev->bus;
+	int ldo;
+
+	switch (bus->chip_id) {
+	case 0x4312:
+		ldo = SSB_PMURES_4312_PA_REF_LDO;
+		break;
+	case 0x4328:
+		ldo = SSB_PMURES_4328_PA_REF_LDO;
+		break;
+	case 0x5354:
+		ldo = SSB_PMURES_5354_PA_REF_LDO;
+		break;
+	default:
+		return;
+	}
+
+	if (on)
+		chipco_set32(cc, SSB_CHIPCO_PMU_MINRES_MSK, 1 << ldo);
+	else
+		chipco_mask32(cc, SSB_CHIPCO_PMU_MINRES_MSK, ~(1 << ldo));
+	chipco_read32(cc, SSB_CHIPCO_PMU_MINRES_MSK); //SPEC FIXME found via mmiotrace - dummy read?
+}
+
+EXPORT_SYMBOL(ssb_pmu_set_ldo_voltage);
+EXPORT_SYMBOL(ssb_pmu_set_ldo_paref);
diff --git a/include/linux/ssb/ssb_driver_chipcommon.h b/include/linux/ssb/ssb_driver_chipcommon.h
index d3b1d18..4e27acf 100644
--- a/include/linux/ssb/ssb_driver_chipcommon.h
+++ b/include/linux/ssb/ssb_driver_chipcommon.h
@@ -629,5 +629,15 @@ extern int ssb_chipco_serial_init(struct ssb_chipcommon *cc,
 /* PMU support */
 extern void ssb_pmu_init(struct ssb_chipcommon *cc);
 
+enum ssb_pmu_ldo_volt_id {
+	LDO_PAREF = 0,
+	LDO_VOLT1,
+	LDO_VOLT2,
+	LDO_VOLT3,
+};
+
+void ssb_pmu_set_ldo_voltage(struct ssb_chipcommon *cc,
+			     enum ssb_pmu_ldo_volt_id id, u32 voltage);
+void ssb_pmu_set_ldo_paref(struct ssb_chipcommon *cc, bool on);
 
 #endif /* LINUX_SSB_CHIPCO_H_ */
-- 
1.5.6


^ permalink raw reply related

* [PATCH] rt2x00: Cleanup rt2x00mac_bss_info_changed()
From: Ivo van Doorn @ 2009-08-26 19:04 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless, users

Since patch "rt2x00: bss_info_changed() callback is allowed to sleep" the
variable delayed wasn't used anymore. This means it can be removed
along with the call to schedule_work which depended on that variable.

Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
---
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index a91f316..929b85f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -582,7 +582,6 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
 {
 	struct rt2x00_dev *rt2x00dev = hw->priv;
 	struct rt2x00_intf *intf = vif_to_intf(vif);
-	unsigned int delayed = 0;
 	int update_bssid = 0;
 
 	/*
@@ -645,13 +644,6 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
 	 */
 	if (changes & ~(BSS_CHANGED_ASSOC | BSS_CHANGED_HT))
 		rt2x00lib_config_erp(rt2x00dev, intf, bss_conf);
-
-	spin_lock(&intf->lock);
-	if (delayed) {
-		intf->delayed_flags |= delayed;
-		schedule_work(&rt2x00dev->intf_work);
-	}
-	spin_unlock(&intf->lock);
 }
 EXPORT_SYMBOL_GPL(rt2x00mac_bss_info_changed);
 



^ permalink raw reply related

* libertas wext.c: IW_ENCODE_NOKEY for WEP keys [resend as plain text]
From: Bing Zhao @ 2009-08-26 19:11 UTC (permalink / raw)
  To: libertas-dev@lists.infradead.org
  Cc: dwmw2@infradead.org, Dan Williams, linux-wireless@vger.kernel.org

Hi all,
 
There was a commit to unset the IW_ENCODE_NOKEY flag for WEP keys.
 
"libertas: Don't set IW_ENCODE_NOKEY when returning WEP keys."
  
 
Without this change, the IW_ENCODE_NOKEY flag is set for WEP keys and then iwconfig command would display "****-****-**" as "Encryption key".
  
After this change, the IW_ENCODE_NOKEY flag is NOT set for WEP keys and then iwconfig command will display plain text of the WEP key ("1234-5678-90" in my case, below).
 
eth1      IEEE 802.11b/g  ESSID:"Cisco1-G"
          Mode:Managed  Frequency:2.462 GHz  Access Point: 00:1D:45:CE:20:D0
          Bit Rate:54 Mb/s   Tx-Power=15 dBm
          Retry short limit:8   RTS thr=2347 B   Fragment thr=2346 B
 
          Encryption key:1234-5678-90   Security mode:open
 
          Power Management:off
          Link Quality=92/100  Signal level=-66 dBm  Noise level=-94 dBm
          Rx invalid nwid:0  Rx invalid crypt:0  Rx invalid frag:0
          Tx excessive retries:0  Invalid misc:0   Missed beacon:0
 
 
 
Was there any reason to not set IW_ENCODE_NOKEY for WEP keys?
Is it feasible to set IW_ENCODE_NOKEY for WEP switch case?
 
--- a/drivers/net/wireless/libertas/wext.c
+++ b/drivers/net/wireless/libertas/wext.c
@@ -1165,6 +1165,7 @@ static int lbs_get_encode(struct net_device *dev,
                dwrq->flags |= (index + 1);
                /* Return WEP enabled */
                dwrq->flags &= ~IW_ENCODE_DISABLED;
+               dwrq->flags |= IW_ENCODE_NOKEY;
        } else if ((priv->secinfo.WPAenabled)
                   || (priv->secinfo.WPA2enabled)) {
                /* return WPA enabled */
 

Thanks for your help,
 
Bing


^ permalink raw reply

* ath9k DMA problems
From: Howard Chu @ 2009-08-26 19:38 UTC (permalink / raw)
  To: linux-wireless@vger.kernel.org

Still seeing occasional hangs using the ath9k in 2.6.31-rc6, and even worse 
using compat-wireless 2009-08-22. Today I got this which was even more 
interesting:

[369014.776586] wlan0: associate with AP 00:12:17:26:56:10 (try 1)
[369014.779197] wlan0: RX ReassocResp from 00:12:17:26:56:10 (capab=0x411 
status=0 aid=2)
[369014.779197] wlan0: associated
[369472.707961] ath9k: DMA failed to stop in 10 ms AR_CR=0xdeadbeef 
AR_DIAG_SW=0xdeadbeef

This is on an HP dv5z laptop, it reports an AR9280 at boot.
-- 
   -- Howard Chu
   CTO, Symas Corp.           http://www.symas.com
   Director, Highland Sun     http://highlandsun.com/hyc/
   Chief Architect, OpenLDAP  http://www.openldap.org/project/

^ permalink raw reply

* [PATCH] b43: Remove scary message from LP-PHY's Kconfig
From: Gábor Stefanik @ 2009-08-26 19:48 UTC (permalink / raw)
  To: John Linville, Michael Buesch, Larry Finger, Mark Huijgen
  Cc: Broadcom Wireless, linux-wireless

From: root Gábor Stefanik <netrolller.3d@gmail.com>

The most common LP-PHY device, BCM4312, is now fully functional.
So, no need to say "probably won't work for you" anymore.
It's also not "for debuggers and developers only", as it is
perfectly usable for end-users now (at least for BCM4312).

Signed-off-by: Gábor Stefanik <netrolller.3d@gmail.com>
---
This should only be applied once the "Qdiv roundup" and the "Fix and update"
patches reach the tree, as those 2 patches are needed to make the BCM4312
really work.

 drivers/net/wireless/b43/Kconfig |    3 ---
 1 files changed, 0 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig
index 87d10c8..1c0999b 100644
--- a/drivers/net/wireless/b43/Kconfig
+++ b/drivers/net/wireless/b43/Kconfig
@@ -88,9 +88,6 @@ config B43_PHY_LP
 	  and embedded devices. It supports 802.11a/g
 	  (802.11a support is optional, and currently disabled).
 
-	  This is heavily experimental, and probably will not work for you.
-	  Say N unless you want to help debug the driver.
-
 # This config option automatically enables b43 LEDS support,
 # if it's possible.
 config B43_LEDS
-- 
1.5.6


^ permalink raw reply related

* Re: 2.6.31-rc7-git2: Reported regressions 2.6.29 -> 2.6.30
From: Rafael J. Wysocki @ 2009-08-26 20:11 UTC (permalink / raw)
  To: Rafał Miłecki
  Cc: Linux Kernel Mailing List, DRI, Linux SCSI List,
	Network Development, Linux Wireless List, Natalie Protasevich,
	Linux ACPI, Andrew Morton, Kernel Testers List, Linus Torvalds,
	Linux PM List, Len Brown
In-Reply-To: <b170af450908260147o60427997ne6b9872198893c41@mail.gmail.com>

On Wednesday 26 August 2009, Rafał Miłecki wrote:
> 2009/8/25 Rafael J. Wysocki <rjw@sisk.pl>:
> > Bug-Entry       : http://bugzilla.kernel.org/show_bug.cgi?id=13514
> > Subject         : acer_wmi causes stack corruption
> > Submitter       : Rus <harbour@sfinx.od.ua>
> > Date            : 2009-06-12 08:13 (75 days old)
> 
> It has patch, just Len doesn't seem to... don't know, read the topic?
> http://patchwork.kernel.org/patch/29082/
> 
> Can we ping Len somehow to push this patch directly to Linus's tree?

I have updated the bug entry, hopefully Len will notice it now.

Thanks,
Rafael

^ permalink raw reply

* [PATCH] iwlwifi: fix ICT irq table endianness
From: Johannes Berg @ 2009-08-26 20:15 UTC (permalink / raw)
  To: John Linville; +Cc: Reinette Chatre, linux-wireless

The ICT IRQ table is a set of __le32 values, not u32 values,
so when reading it we need to take into account that it has
to be converted to CPU endianness. This was causing a lot of
trouble on my powerpc box where various things would simply
not work for no apparent reason with 5xxx cards, but worked
with 4965 -- which doesn't use the ICT table.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
Oddly, the __le32 pointer doesn't help one bit, sparse
doesn't warn. Oh well. This makes lots of things work
better for me :)

 drivers/net/wireless/iwlwifi/iwl-core.c |   10 +++++-----
 drivers/net/wireless/iwlwifi/iwl-dev.h  |    2 +-
 2 files changed, 6 insertions(+), 6 deletions(-)

--- wireless-testing.orig/drivers/net/wireless/iwlwifi/iwl-dev.h	2009-08-26 20:37:01.000000000 +0200
+++ wireless-testing/drivers/net/wireless/iwlwifi/iwl-dev.h	2009-08-26 20:37:06.000000000 +0200
@@ -1170,7 +1170,7 @@ struct iwl_priv {
 	struct iwl_hw_params hw_params;
 
 	/* INT ICT Table */
-	u32 *ict_tbl;
+	__le32 *ict_tbl;
 	dma_addr_t ict_tbl_dma;
 	dma_addr_t aligned_ict_tbl_dma;
 	int ict_index;
--- wireless-testing.orig/drivers/net/wireless/iwlwifi/iwl-core.c	2009-08-26 20:39:14.000000000 +0200
+++ wireless-testing/drivers/net/wireless/iwlwifi/iwl-core.c	2009-08-26 20:40:36.000000000 +0200
@@ -1823,7 +1823,7 @@ int iwl_reset_ict(struct iwl_priv *priv)
 	spin_lock_irqsave(&priv->lock, flags);
 	iwl_disable_interrupts(priv);
 
-	memset(&priv->ict_tbl[0],0, sizeof(u32) * ICT_COUNT);
+	memset(&priv->ict_tbl[0], 0, sizeof(u32) * ICT_COUNT);
 
 	val = priv->aligned_ict_tbl_dma >> PAGE_SHIFT;
 
@@ -1901,13 +1901,13 @@ irqreturn_t iwl_isr_ict(int irq, void *d
 	/* read all entries that not 0 start with ict_index */
 	while (priv->ict_tbl[priv->ict_index]) {
 
-		val |= priv->ict_tbl[priv->ict_index];
+		val |= le32_to_cpu(priv->ict_tbl[priv->ict_index]);
 		IWL_DEBUG_ISR(priv, "ICT index %d value 0x%08X\n",
-					priv->ict_index,
-					priv->ict_tbl[priv->ict_index]);
+				priv->ict_index,
+				le32_to_cpu(priv->ict_tbl[priv->ict_index]));
 		priv->ict_tbl[priv->ict_index] = 0;
 		priv->ict_index = iwl_queue_inc_wrap(priv->ict_index,
-								ICT_COUNT);
+						     ICT_COUNT);
 
 	}
 



^ permalink raw reply

* Re: [PATCH] ath5k: fix print on warning on ath5k_hw_to_driver_rix()
From: Luis R. Rodriguez @ 2009-08-26 20:20 UTC (permalink / raw)
  To: Bob Copeland
  Cc: Luis Rodriguez, linville@tuxdriver.com,
	linux-wireless@vger.kernel.org, Johannes Berg, Jouni.Malinen
In-Reply-To: <b6c5339f0908261003g40ed910amc347305e4604ee4a@mail.gmail.com>

On Wed, Aug 26, 2009 at 10:03:09AM -0700, Bob Copeland wrote:
> On Wed, Aug 26, 2009 at 12:29 PM, Luis R.
> Rodriguez<lrodriguez@atheros.com> wrote:
> 
> > Not sure I follow. Let me explain the logic here a little better.
> > ath5k_reset() had a check to see if we switched channels. The check
> > is above, and I moved it ath5k_chan_set() called by the config callback.
> > Reason for this is channel change *only* occurs through the config callback
> > so we can be certain no other path will call reset with a channel change
> > request.
> 
> But previously we did all this stuff for _every_ reset except the first
> one, 

Actually we did it in every ath5k_reset() if and only if chan was not NULL.
We called ath5k_reset() from 3 places:

  * Init
  * Channel change
  * Reset tasklet for hw issues

chan was only null upon init as you point out, so you are right in that
I overlooked that we currently do this also upon hw issues.

> now we only do it for channel change resets.  It may make sense your
> way, but I'd rather see that as a separate patch rather than part of a
> cleanup.

Absolutely, I overlooked this, thanks for picking that up.

> (Also, chan_change is used to skip a bunch of phy register writes
> that we only need to do once, not sure if that changes here).

Yeah since I also used ath5k_reset_init() on the reset hw issue tasklet and
that does pass false for channel_change this patch would have changed that
as well, so I'll fix that.

> >> There's just no synchronization of this stuff, not too surprising there
> >> are races.
> >
> > config calls for reset seem to be with sc->lock. ath9k uses a mutex to
> > protect races between mac80211 callback calls, ath5k seems to use the
> > sc->lock *sometimes*, a good review of that may help but for channel
> > change this seems protected unless I missed something. Since channel
> > change goes through the config callback and since the callback protects
> > through sc->lock I can't see how we'd race against changing channels.
> 
> rx_tasklet doesn't (can't) take the mutex though.  Here's the race:
> 
> cpu 1                       cpu 2
>                             1mbit packet received, ack intr and queue it
> client changes to 5ghz band
> hw->conf.channel = 36
>                             ath5k_rx_tasklet runs
>                             hmm, we got 1mbit packet on channel 36, wtf
> ath5k_chan_change()
> 
> This is still racy with curband variables of course, but IMO the
> proposed change actually makes the race wider (in current code, we only
> update the band after we disable the interrupts, but the tasklet can
> still run on queued packets).

I don't want to bother looking ath ath5k solutions to the race, I rather
we try to fix this if possible with a generic solution on mac80211. I suspect
ath5k is not the only one with this possible race.

> The right thing to do is either process or drop all of those packets

Would be nice if we did not have to, those packets can be very valuable
considering we now support spreading our scan over time.

> with interrupts disabled before updating the band/channel (rx_drainq),

That would be nice, so prior to channel change we need to ensure we:

  * Disable interrupts
  * Disable RX
  * Process all pending frames in RX queue

It is the last part that it seems we are missing. Running tasklet_schedule()
will ensure we can schedule the tasklet but it does not ensure we will
wait until it has run at least once. Johill pointed out tasklet_disable()
followed by a tasklet_enable() would do it, but seems rather odd.

But do we need this?

In the rx tasklet we need band to access the right rate table -- this is
how we got into this conversation but if you think about it you also need
to ensure your harware hasn't already flipped to another band otherwise
you can start sending mac80211 frames for a different band. This certainly
matters for rate control but haven't reviewed all the details of where
inconsistancy between the hw->conf.channel and the skbs received by
mac80211 are.

Processing RXd frames prior to switching channels seems like a good idea
regardless.

>From what I see Atheros RX descriptors do not have the frequency on which the
frame was received on so you do need some sort of house keeping.
mac80211/cfg80211 does this for us so I'd like to try to avoid doing more
on drivers if possible.

Since cfg80211 modifies hw->conf.channel prior to calling drv_config() it
is possible for the driver to not reliably use this variable either right now.

So how about a generic rx_drain() callback for mac80211 drivers and document
that on it we need disable RXing frames, disable interrupts for RX,
and then either have the driver drop pending frames (worst case) or process them.
mac80211 could then use this prior to drv_config() if we are changing channels.

> or protect that channel info with a spinlock.   Or perhaps we can
> figure it out directly from the rx descriptor -- I looked at this
> briefly and didn't think there was enough info there, but didn't spend
> much time on it.

I looked too and did not find it. I can't find a reason to have it in
hardware descriptors though, given that you could just drain rx prior to
a switch.

Only argument I can see which may affect draining RX prior to channel
change is it could delay the time it takes for you to switch. Either way
this seems just a lot cleaner to support.

Thoughts?

  Luis

^ permalink raw reply

* Re: [PATCH] iwlwifi: fix ICT irq table endianness
From: reinette chatre @ 2009-08-26 20:25 UTC (permalink / raw)
  To: Johannes Berg; +Cc: John Linville, linux-wireless
In-Reply-To: <1251317713.14690.0.camel@johannes.local>

On Wed, 2009-08-26 at 13:15 -0700, Johannes Berg wrote:
> The ICT IRQ table is a set of __le32 values, not u32 values,
> so when reading it we need to take into account that it has
> to be converted to CPU endianness. This was causing a lot of
> trouble on my powerpc box where various things would simply
> not work for no apparent reason with 5xxx cards, but worked
> with 4965 -- which doesn't use the ICT table.
> 
> Signed-off-by: Johannes Berg <johannes@sipsolutions.net>

Thank you very much

Acked-by: Reinette Chatre <reinette.chatre@intel.com>

Reinette



^ permalink raw reply

* Re: [RFC/RFT] rtl8187: Implement rfkill support
From: Luis R. Rodriguez @ 2009-08-26 20:33 UTC (permalink / raw)
  To: Johannes Berg
  Cc: htl10, Hin-Tak Leung, Larry Finger, Herton Ronaldo Krzesinski,
	linux-wireless
In-Reply-To: <1251297273.15619.11.camel@johannes.local>

On Wed, Aug 26, 2009 at 7:34 AM, Johannes Berg<johannes@sipsolutions.net> wrote:
> On Wed, 2009-08-26 at 13:33 +0000, Hin-Tak Leung wrote:
>
>> > Or wait ... are you using compat-wireless?
>>
>> Yes, I am. I mentioned this and did wonder if the _backport/ part
>> in /sys/class is important.
>
> Sorry, didn't see.
>
> Anyway, that's pretty clearly the reason -- Luis added NETDEV_PRE_UP to
> some compat*.h but obviously the kernel won't ever call that notifier,
> so cfg80211 doesn't get a chance to reject the IFUP. No idea how to
> handle that -- it'll be working fine in a regular tree.
>
> Luis, the only way to handle that would be to manually call the PRE_UP
> notifier from mac80211's subif_open() and if that returns an error
> (warning: the calling convention is weird) return the error... that's
> weird but would work.

Neat, thanks. Not sure if I'll get to this this anytime soon, but if
someone is interested in it please give it a shot and send a patch.
That would be nice.

  Luis

^ permalink raw reply

* Re: [PATCH] b43: Fix and update LP-PHY code
From: Michael Buesch @ 2009-08-26 20:42 UTC (permalink / raw)
  To: Gábor Stefanik
  Cc: John Linville, Larry Finger, Mark Huijgen, Broadcom Wireless,
	linux-wireless
In-Reply-To: <1251312686-32067-2-git-send-email-netrolller.3d@gmail.com>

On Wednesday 26 August 2009 20:51:25 Gábor Stefanik wrote:
> -Fix a few nasty typos (b43_phy_* operations instead of b43_radio_*)
>  in the channel tune routines.
> -Fix some typos & spec errors found by MMIO tracing.
> -Optimize b43_phy_write & b43_phy_mask/set/maskset to use
>  only the minimal number of MMIO accesses. (Write is possible
>  using a single 32-bit MMIO write, while set/mask/maskset can
>  be done in 3 16-bit MMIOs).

Why does it matter? PHY access is not done in any hotpath. So why
not prefer simple code over optimized code? 

> -Set the default channel back to 1, as the bug forcing us to use
>  channel 7 is now fixed.

And, everything in its own patch, please. I don't see a reason for
patching unrelated things in one big patch.

> 
> With this, the device comes up, scans, associates, transmits,
> receives, monitors and injects on all channels - in other words,
> it's fully functional. Sensitivity and TX power are still sub-optimal,
> due to the lack of calibration (that's next on my list).
> 
> Signed-off-by: Gábor Stefanik <netrolller.3d@gmail.com>
> ---
>  drivers/net/wireless/b43/phy_common.c   |   27 +++++++--
>  drivers/net/wireless/b43/phy_common.h   |    3 +
>  drivers/net/wireless/b43/phy_lp.c       |   91 +++++++++++++++++--------------
>  drivers/net/wireless/b43/phy_lp.h       |    3 +
>  drivers/net/wireless/b43/tables_lpphy.c |   79 +++++++++++++++------------
>  5 files changed, 122 insertions(+), 81 deletions(-)
> 
> diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c
> index 51686ec..6e704be 100644
> --- a/drivers/net/wireless/b43/phy_common.c
> +++ b/drivers/net/wireless/b43/phy_common.c
> @@ -249,20 +249,35 @@ void b43_phy_copy(struct b43_wldev *dev, u16 destreg, u16 srcreg)
>  
>  void b43_phy_mask(struct b43_wldev *dev, u16 offset, u16 mask)
>  {
> -	b43_phy_write(dev, offset,
> -		      b43_phy_read(dev, offset) & mask);
> +	if (dev->phy.ops->phy_maskset) {
> +		assert_mac_suspended(dev);
> +		dev->phy.ops->phy_maskset(dev, offset, mask, 0);
> +	} else {
> +		b43_phy_write(dev, offset,
> +			      b43_phy_read(dev, offset) & mask);
> +	}
>  }
>  
>  void b43_phy_set(struct b43_wldev *dev, u16 offset, u16 set)
>  {
> -	b43_phy_write(dev, offset,
> -		      b43_phy_read(dev, offset) | set);
> +	if (dev->phy.ops->phy_maskset) {
> +		assert_mac_suspended(dev);
> +		dev->phy.ops->phy_maskset(dev, offset, 0xFFFF, set);
> +	} else {
> +		b43_phy_write(dev, offset,
> +			      b43_phy_read(dev, offset) | set);
> +	}
>  }
>  
>  void b43_phy_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set)
>  {
> -	b43_phy_write(dev, offset,
> -		      (b43_phy_read(dev, offset) & mask) | set);
> +	if (dev->phy.ops->phy_maskset) {
> +		assert_mac_suspended(dev);
> +		dev->phy.ops->phy_maskset(dev, offset, mask, set);
> +	} else {
> +		b43_phy_write(dev, offset,
> +			      (b43_phy_read(dev, offset) & mask) | set);
> +	}
>  }
>  
>  int b43_switch_channel(struct b43_wldev *dev, unsigned int new_channel)
> diff --git a/drivers/net/wireless/b43/phy_common.h b/drivers/net/wireless/b43/phy_common.h
> index 9f9f23c..b47a0f5 100644
> --- a/drivers/net/wireless/b43/phy_common.h
> +++ b/drivers/net/wireless/b43/phy_common.h
> @@ -95,6 +95,8 @@ enum b43_txpwr_result {
>   * 			Must not be NULL.
>   * @phy_write:		Write to a PHY register.
>   * 			Must not be NULL.
> + * @phy_maskset:	Maskset a PHY register, taking shortcuts.
> + *			If it is NULL, a generic algorithm is used.
>   * @radio_read:		Read from a Radio register.
>   * 			Must not be NULL.
>   * @radio_write:	Write to a Radio register.
> @@ -154,6 +156,7 @@ struct b43_phy_operations {
>  	/* Register access */
>  	u16 (*phy_read)(struct b43_wldev *dev, u16 reg);
>  	void (*phy_write)(struct b43_wldev *dev, u16 reg, u16 value);
> +	void (*phy_maskset)(struct b43_wldev *dev, u16 reg, u16 mask, u16 set);
>  	u16 (*radio_read)(struct b43_wldev *dev, u16 reg);
>  	void (*radio_write)(struct b43_wldev *dev, u16 reg, u16 value);
>  
> diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c
> index 5306f2c..1a57d33 100644
> --- a/drivers/net/wireless/b43/phy_lp.c
> +++ b/drivers/net/wireless/b43/phy_lp.c
> @@ -44,7 +44,7 @@ static inline u16 channel2freq_lp(u8 channel)
>  static unsigned int b43_lpphy_op_get_default_chan(struct b43_wldev *dev)
>  {
>  	if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
> -		return 7; //FIXME temporary - channel 1 is broken
> +		return 1;
>  	return 36;
>  }
>  
> @@ -182,8 +182,8 @@ static void lpphy_adjust_gain_table(struct b43_wldev *dev, u32 freq)
>  	temp[1] = temp[0] + 0x1000;
>  	temp[2] = temp[0] + 0x2000;
>  
> -	b43_lptab_write_bulk(dev, B43_LPTAB16(12, 0), 3, temp);
>  	b43_lptab_write_bulk(dev, B43_LPTAB16(13, 0), 3, temp);
> +	b43_lptab_write_bulk(dev, B43_LPTAB16(12, 0), 3, temp);
>  }
>  
>  static void lpphy_table_init(struct b43_wldev *dev)
> @@ -223,8 +223,8 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
>  	b43_phy_maskset(dev, B43_LPPHY_VERYLOWGAINDB, 0xFF00, 0x0006);
>  	b43_phy_mask(dev, B43_LPPHY_RX_RADIO_CTL, 0xFFFE);
>  	b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFFE0, 0x0005);
> -	b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFC10, 0x0180);
> -	b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0x83FF, 0x3800);
> +	b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFC1F, 0x0180);
> +	b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0x83FF, 0x3C00);
>  	b43_phy_maskset(dev, B43_LPPHY_GAINDIRECTMISMATCH, 0xFFF0, 0x0005);
>  	b43_phy_maskset(dev, B43_LPPHY_GAIN_MISMATCH_LIMIT, 0xFFC0, 0x001A);
>  	b43_phy_maskset(dev, B43_LPPHY_CRS_ED_THRESH, 0xFF00, 0x00B3);
> @@ -237,7 +237,7 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
>  		/* TODO:
>  		 * Set the LDO voltage to 0x0028 - FIXME: What is this?
>  		 * Call sb_pmu_set_ldo_voltage with 4 and the LDO voltage
> -		 * 	as arguments
> +		 *      as arguments
>  		 * Call sb_pmu_paref_ldo_enable with argument TRUE
>  		 */
>  		if (dev->phy.rev == 0) {
> @@ -340,11 +340,11 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
>  	if (dev->phy.rev == 1) {
>  		tmp = b43_phy_read(dev, B43_LPPHY_CLIPCTRTHRESH);
>  		tmp2 = (tmp & 0x03E0) >> 5;
> -		tmp2 |= tmp << 5;
> +		tmp2 |= tmp2 << 5;
>  		b43_phy_write(dev, B43_LPPHY_4C3, tmp2);
> -		tmp = b43_phy_read(dev, B43_LPPHY_OFDMSYNCTHRESH0);
> +		tmp = b43_phy_read(dev, B43_LPPHY_GAINDIRECTMISMATCH);
>  		tmp2 = (tmp & 0x1F00) >> 8;
> -		tmp2 |= tmp << 5;
> +		tmp2 |= tmp2 << 5;
>  		b43_phy_write(dev, B43_LPPHY_4C4, tmp2);
>  		tmp = b43_phy_read(dev, B43_LPPHY_VERYLOWGAINDB);
>  		tmp2 = tmp & 0x00FF;
> @@ -761,7 +761,7 @@ static void lpphy_disable_crs(struct b43_wldev *dev, bool user)
>  	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_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_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);
> @@ -956,7 +956,7 @@ static void lpphy_run_ddfs(struct b43_wldev *dev, int i_on, int q_on,
>  	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);
> +	b43_phy_set(dev, B43_LPPHY_LP_PHY_CTL, 0x20);
>  }
>  
>  static bool lpphy_rx_iq_est(struct b43_wldev *dev, u16 samples, u8 time,
> @@ -968,7 +968,7 @@ static bool lpphy_rx_iq_est(struct b43_wldev *dev, u16 samples, u8 time,
>  	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);
> +	b43_phy_set(dev, B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR, 0x200);
>  
>  	for (i = 0; i < 500; i++) {
>  		if (!(b43_phy_read(dev,
> @@ -1135,9 +1135,9 @@ static void lpphy_set_tx_power_control(struct b43_wldev *dev,
>  	}
>  	if (dev->phy.rev >= 2) {
>  		if (mode == B43_LPPHY_TXPCTL_HW)
> -			b43_phy_maskset(dev, B43_PHY_OFDM(0xD0), 0xFD, 0x2);
> +			b43_phy_set(dev, B43_PHY_OFDM(0xD0), 0x2);
>  		else
> -			b43_phy_maskset(dev, B43_PHY_OFDM(0xD0), 0xFD, 0);
> +			b43_phy_mask(dev, B43_PHY_OFDM(0xD0), 0xFFFD);
>  	}
>  	lpphy_write_tx_pctl_mode_to_hardware(dev);
>  }
> @@ -1169,7 +1169,7 @@ static void lpphy_rev0_1_rc_calib(struct b43_wldev *dev)
>  	err = b43_lpphy_op_switch_channel(dev, 7);
>  	if (err) {
>  		b43dbg(dev->wl,
> -		       "RC calib: Failed to switch to channel 7, error = %d",
> +		       "RC calib: Failed to switch to channel 7, error = %d\n",
>  		       err);
>  	}
>  	old_txg_ovr = !!(b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVR) & 0x40);
> @@ -1500,8 +1500,15 @@ static u16 b43_lpphy_op_read(struct b43_wldev *dev, u16 reg)
>  
>  static void b43_lpphy_op_write(struct b43_wldev *dev, u16 reg, u16 value)
>  {
> +	b43_write32(dev, B43_MMIO_PHY_CONTROL, ((u32)value << 16) | reg);
> +}
> +
> +static void b43_lpphy_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask,
> +				 u16 set)
> +{
>  	b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
> -	b43_write16(dev, B43_MMIO_PHY_DATA, value);
> +	b43_write16(dev, B43_MMIO_PHY_DATA,
> +		    (b43_read16(dev, B43_MMIO_PHY_DATA) & mask) | set);
>  }
>  
>  static u16 b43_lpphy_op_radio_read(struct b43_wldev *dev, u16 reg)
> @@ -1920,8 +1927,8 @@ static void lpphy_b2062_reset_pll_bias(struct b43_wldev *dev)
>  
>  static void lpphy_b2062_vco_calib(struct b43_wldev *dev)
>  {
> -	b43_phy_write(dev, B2062_S_RFPLL_CTL21, 0x42);
> -	b43_phy_write(dev, B2062_S_RFPLL_CTL21, 0x62);
> +	b43_radio_write(dev, B2062_S_RFPLL_CTL21, 0x42);
> +	b43_radio_write(dev, B2062_S_RFPLL_CTL21, 0x62);
>  	udelay(200);
>  }
>  
> @@ -1980,7 +1987,7 @@ static int lpphy_b2062_tune(struct b43_wldev *dev,
>  	tmp6 = tmp5 / tmp4;
>  	tmp7 = tmp5 % tmp4;
>  	b43_radio_write(dev, B2062_S_RFPLL_CTL29, tmp6 + ((2 * tmp7) / tmp4));
> -	tmp8 = b43_phy_read(dev, B2062_S_RFPLL_CTL19);
> +	tmp8 = b43_radio_read(dev, B2062_S_RFPLL_CTL19);
>  	tmp9 = ((2 * tmp3 * (tmp8 + 1)) + (3 * tmp1)) / (6 * tmp1);
>  	b43_radio_write(dev, B2062_S_RFPLL_CTL23, (tmp9 >> 8) + 16);
>  	b43_radio_write(dev, B2062_S_RFPLL_CTL24, tmp9 & 0xFF);
> @@ -2019,17 +2026,17 @@ static void lpphy_b2063_vco_calib(struct b43_wldev *dev)
>  {
>  	u16 tmp;
>  
> -	b43_phy_mask(dev, B2063_PLL_SP1, ~0x40);
> -	tmp = b43_phy_read(dev, B2063_PLL_JTAG_CALNRST) & 0xF8;
> -	b43_phy_write(dev, B2063_PLL_JTAG_CALNRST, tmp);
> +	b43_radio_mask(dev, B2063_PLL_SP1, ~0x40);
> +	tmp = b43_radio_read(dev, B2063_PLL_JTAG_CALNRST) & 0xF8;
> +	b43_radio_write(dev, B2063_PLL_JTAG_CALNRST, tmp);
>  	udelay(1);
> -	b43_phy_write(dev, B2063_PLL_JTAG_CALNRST, tmp | 0x4);
> +	b43_radio_write(dev, B2063_PLL_JTAG_CALNRST, tmp | 0x4);
>  	udelay(1);
> -	b43_phy_write(dev, B2063_PLL_JTAG_CALNRST, tmp | 0x6);
> +	b43_radio_write(dev, B2063_PLL_JTAG_CALNRST, tmp | 0x6);
>  	udelay(1);
> -	b43_phy_write(dev, B2063_PLL_JTAG_CALNRST, tmp | 0x7);
> +	b43_radio_write(dev, B2063_PLL_JTAG_CALNRST, tmp | 0x7);
>  	udelay(300);
> -	b43_phy_set(dev, B2063_PLL_SP1, 0x40);
> +	b43_radio_set(dev, B2063_PLL_SP1, 0x40);
>  }
>  
>  static int lpphy_b2063_tune(struct b43_wldev *dev,
> @@ -2124,31 +2131,31 @@ static int lpphy_b2063_tune(struct b43_wldev *dev,
>  		scale = 0;
>  		tmp5 = ((tmp4 + (tmp3 >> 1)) / tmp3) - 8;
>  	}
> -	b43_phy_maskset(dev, B2063_PLL_JTAG_PLL_CP2, 0xFFC0, tmp5);
> -	b43_phy_maskset(dev, B2063_PLL_JTAG_PLL_CP2, 0xFFBF, scale << 6);
> +	b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_CP2, 0xFFC0, tmp5);
> +	b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_CP2, 0xFFBF, scale << 6);
>  
>  	tmp6 = lpphy_qdiv_roundup(100 * val1, val3, 16);
>  	tmp6 *= (tmp5 * 8) * (scale + 1);
>  	if (tmp6 > 150)
>  		tmp6 = 0;
>  
> -	b43_phy_maskset(dev, B2063_PLL_JTAG_PLL_CP3, 0xFFE0, tmp6);
> -	b43_phy_maskset(dev, B2063_PLL_JTAG_PLL_CP3, 0xFFDF, scale << 5);
> +	b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_CP3, 0xFFE0, tmp6);
> +	b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_CP3, 0xFFDF, scale << 5);
>  
> -	b43_phy_maskset(dev, B2063_PLL_JTAG_PLL_XTAL_12, 0xFFFB, 0x4);
> +	b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_XTAL_12, 0xFFFB, 0x4);
>  	if (crystal_freq > 26000000)
> -		b43_phy_set(dev, B2063_PLL_JTAG_PLL_XTAL_12, 0x2);
> +		b43_radio_set(dev, B2063_PLL_JTAG_PLL_XTAL_12, 0x2);
>  	else
> -		b43_phy_mask(dev, B2063_PLL_JTAG_PLL_XTAL_12, 0xFD);
> +		b43_radio_mask(dev, B2063_PLL_JTAG_PLL_XTAL_12, 0xFD);
>  
>  	if (val1 == 45)
> -		b43_phy_set(dev, B2063_PLL_JTAG_PLL_VCO1, 0x2);
> +		b43_radio_set(dev, B2063_PLL_JTAG_PLL_VCO1, 0x2);
>  	else
> -		b43_phy_mask(dev, B2063_PLL_JTAG_PLL_VCO1, 0xFD);
> +		b43_radio_mask(dev, B2063_PLL_JTAG_PLL_VCO1, 0xFD);
>  
> -	b43_phy_set(dev, B2063_PLL_SP2, 0x3);
> +	b43_radio_set(dev, B2063_PLL_SP2, 0x3);
>  	udelay(1);
> -	b43_phy_mask(dev, B2063_PLL_SP2, 0xFFFC);
> +	b43_radio_mask(dev, B2063_PLL_SP2, 0xFFFC);
>  	lpphy_b2063_vco_calib(dev);
>  	b43_radio_write(dev, B2063_COMM15, old_comm15);
>  
> @@ -2158,10 +2165,9 @@ static int lpphy_b2063_tune(struct b43_wldev *dev,
>  static int b43_lpphy_op_switch_channel(struct b43_wldev *dev,
>  				       unsigned int new_channel)
>  {
> +	struct b43_phy_lp *lpphy = dev->phy.lp;
>  	int err;
>  
> -	b43_write16(dev, B43_MMIO_CHANNEL, new_channel);
> -
>  	if (dev->phy.radio_ver == 0x2063) {
>  		err = lpphy_b2063_tune(dev, new_channel);
>  		if (err)
> @@ -2174,6 +2180,9 @@ static int b43_lpphy_op_switch_channel(struct b43_wldev *dev,
>  		lpphy_adjust_gain_table(dev, channel2freq_lp(new_channel));
>  	}
>  
> +	lpphy->channel = new_channel;
> +	b43_write16(dev, B43_MMIO_CHANNEL, new_channel);
> +
>  	return 0;
>  }
>  
> @@ -2185,10 +2194,9 @@ static int b43_lpphy_op_init(struct b43_wldev *dev)
>  	lpphy_baseband_init(dev);
>  	lpphy_radio_init(dev);
>  	lpphy_calibrate_rc(dev);
> -	err = b43_lpphy_op_switch_channel(dev,
> -				b43_lpphy_op_get_default_chan(dev));
> +	err = b43_lpphy_op_switch_channel(dev, 7);
>  	if (err) {
> -		b43dbg(dev->wl, "Switch to init channel failed, error = %d.\n",
> +		b43dbg(dev->wl, "Switch to channel 7 failed, error = %d.\n",
>  		       err);
>  	}
>  	lpphy_tx_pctl_init(dev);
> @@ -2222,6 +2230,7 @@ const struct b43_phy_operations b43_phyops_lp = {
>  	.init			= b43_lpphy_op_init,
>  	.phy_read		= b43_lpphy_op_read,
>  	.phy_write		= b43_lpphy_op_write,
> +	.phy_maskset		= b43_lpphy_op_maskset,
>  	.radio_read		= b43_lpphy_op_radio_read,
>  	.radio_write		= b43_lpphy_op_radio_write,
>  	.software_rfkill	= b43_lpphy_op_software_rfkill,
> diff --git a/drivers/net/wireless/b43/phy_lp.h b/drivers/net/wireless/b43/phy_lp.h
> index e158d1f..c3232c1 100644
> --- a/drivers/net/wireless/b43/phy_lp.h
> +++ b/drivers/net/wireless/b43/phy_lp.h
> @@ -888,6 +888,9 @@ struct b43_phy_lp {
>  	bool crs_usr_disable, crs_sys_disable;
>  
>  	unsigned int pdiv;
> +
> +	/* The channel we are tuned to */
> +	u8 channel;
>  };
>  
>  enum tssi_mux_mode {
> diff --git a/drivers/net/wireless/b43/tables_lpphy.c b/drivers/net/wireless/b43/tables_lpphy.c
> index 60d472f..c784def 100644
> --- a/drivers/net/wireless/b43/tables_lpphy.c
> +++ b/drivers/net/wireless/b43/tables_lpphy.c
> @@ -624,30 +624,35 @@ u32 b43_lptab_read(struct b43_wldev *dev, u32 offset)
>  void b43_lptab_read_bulk(struct b43_wldev *dev, u32 offset,
>  			 unsigned int nr_elements, void *_data)
>  {
> -	u32 type, value;
> +	u32 type;
>  	u8 *data = _data;
>  	unsigned int i;
>  
>  	type = offset & B43_LPTAB_TYPEMASK;
> +	offset &= ~B43_LPTAB_TYPEMASK;
> +	B43_WARN_ON(offset > 0xFFFF);
> +
> +	b43_phy_write(dev, B43_LPPHY_TABLE_ADDR, offset);
> +
>  	for (i = 0; i < nr_elements; i++) {
> -		value = b43_lptab_read(dev, offset);
>  		switch (type) {
>  		case B43_LPTAB_8BIT:
> -			*data = value;
> +			*data = b43_phy_read(dev, B43_LPPHY_TABLEDATALO) & 0xFF;
>  			data++;
>  			break;
>  		case B43_LPTAB_16BIT:
> -			*((u16 *)data) = value;
> +			*((u16 *)data) = b43_phy_read(dev, B43_LPPHY_TABLEDATALO);
>  			data += 2;
>  			break;
>  		case B43_LPTAB_32BIT:
> -			*((u32 *)data) = value;
> +			*((u32 *)data) = b43_phy_read(dev, B43_LPPHY_TABLEDATAHI);
> +			*((u32 *)data) <<= 16;
> +			*((u32 *)data) |= b43_phy_read(dev, B43_LPPHY_TABLEDATALO);
>  			data += 4;
>  			break;
>  		default:
>  			B43_WARN_ON(1);
>  		}
> -		offset++;
>  	}
>  }
>  
> @@ -688,26 +693,34 @@ void b43_lptab_write_bulk(struct b43_wldev *dev, u32 offset,
>  	unsigned int i;
>  
>  	type = offset & B43_LPTAB_TYPEMASK;
> +	offset &= ~B43_LPTAB_TYPEMASK;
> +	B43_WARN_ON(offset > 0xFFFF);
> +
> +	b43_phy_write(dev, B43_LPPHY_TABLE_ADDR, offset);
> +
>  	for (i = 0; i < nr_elements; i++) {
>  		switch (type) {
>  		case B43_LPTAB_8BIT:
>  			value = *data;
>  			data++;
> +			B43_WARN_ON(value & ~0xFF);
> +			b43_phy_write(dev, B43_LPPHY_TABLEDATALO, value);
>  			break;
>  		case B43_LPTAB_16BIT:
>  			value = *((u16 *)data);
>  			data += 2;
> +			B43_WARN_ON(value & ~0xFFFF);
> +			b43_phy_write(dev, B43_LPPHY_TABLEDATALO, value);
>  			break;
>  		case B43_LPTAB_32BIT:
>  			value = *((u32 *)data);
>  			data += 4;
> +			b43_phy_write(dev, B43_LPPHY_TABLEDATAHI, value >> 16);
> +			b43_phy_write(dev, B43_LPPHY_TABLEDATALO, value);
>  			break;
>  		default:
>  			B43_WARN_ON(1);
> -			value = 0;
>  		}
> -		b43_lptab_write(dev, offset, value);
> -		offset++;
>  	}
>  }
>  
> @@ -777,7 +790,7 @@ static const u8 lpphy_pll_fraction_table[] = {
>  	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
>  };
>  
> -static const u16 lpphy_iq_local_table[] = {
> +static const u16 lpphy_iqlo_cal_table[] = {
>  	0x0200, 0x0300, 0x0400, 0x0600, 0x0800, 0x0b00, 0x1000, 0x1001, 0x1002,
>  	0x1003, 0x1004, 0x1005, 0x1006, 0x1007, 0x1707, 0x2007, 0x2d07, 0x4007,
>  	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
> @@ -789,10 +802,17 @@ static const u16 lpphy_iq_local_table[] = {
>  	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
>  	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4000, 0x0000, 0x0000,
>  	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
> -	0x0000, 0x0000,
> +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
>  };
>  
> -static const u16 lpphy_ofdm_cck_gain_table[] = {
> +static const u16 lpphy_rev0_ofdm_cck_gain_table[] = {
> +	0x0001, 0x0001, 0x0001, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001, 0x5001,
> +	0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055, 0x2065, 0x2075,
> +	0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d, 0x135d, 0x055d, 0x155d,
> +	0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d, 0x755d,
> +};
> +
> +static const u16 lpphy_rev1_ofdm_cck_gain_table[] = {
>  	0x5000, 0x6000, 0x7000, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001, 0x5001,
>  	0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055, 0x2065, 0x2075,
>  	0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d, 0x135d, 0x055d, 0x155d,
> @@ -2263,11 +2283,18 @@ void lpphy_rev0_1_table_init(struct b43_wldev *dev)
>  	b43_lptab_write_bulk(dev, B43_LPTAB8(6, 0),
>  		ARRAY_SIZE(lpphy_pll_fraction_table), lpphy_pll_fraction_table);
>  	b43_lptab_write_bulk(dev, B43_LPTAB16(0, 0),
> -		ARRAY_SIZE(lpphy_iq_local_table), lpphy_iq_local_table);
> -	b43_lptab_write_bulk(dev, B43_LPTAB16(13, 0),
> -		ARRAY_SIZE(lpphy_ofdm_cck_gain_table), lpphy_ofdm_cck_gain_table);
> -	b43_lptab_write_bulk(dev, B43_LPTAB16(12, 0),
> -		ARRAY_SIZE(lpphy_ofdm_cck_gain_table), lpphy_ofdm_cck_gain_table);
> +		ARRAY_SIZE(lpphy_iqlo_cal_table), lpphy_iqlo_cal_table);
> +	if (dev->phy.rev == 0) {
> +		b43_lptab_write_bulk(dev, B43_LPTAB16(13, 0),
> +			ARRAY_SIZE(lpphy_rev0_ofdm_cck_gain_table), lpphy_rev0_ofdm_cck_gain_table);
> +		b43_lptab_write_bulk(dev, B43_LPTAB16(12, 0),
> +			ARRAY_SIZE(lpphy_rev0_ofdm_cck_gain_table), lpphy_rev0_ofdm_cck_gain_table);
> +	} else {
> +		b43_lptab_write_bulk(dev, B43_LPTAB16(13, 0),
> +			ARRAY_SIZE(lpphy_rev1_ofdm_cck_gain_table), lpphy_rev1_ofdm_cck_gain_table);
> +		b43_lptab_write_bulk(dev, B43_LPTAB16(12, 0),
> +			ARRAY_SIZE(lpphy_rev1_ofdm_cck_gain_table), lpphy_rev1_ofdm_cck_gain_table);
> +}
>  	b43_lptab_write_bulk(dev, B43_LPTAB16(15, 0),
>  		ARRAY_SIZE(lpphy_gain_delta_table), lpphy_gain_delta_table);
>  	b43_lptab_write_bulk(dev, B43_LPTAB32(10, 0),
> @@ -2281,22 +2308,6 @@ void lpphy_rev2plus_table_init(struct b43_wldev *dev)
>  
>  	B43_WARN_ON(dev->phy.rev < 2);
>  
> -	/*
> -	 * FIXME This code follows the specs, but it looks wrong:
> -	 * In each pass, it writes 4 bytes to an offset in table ID 7,
> -	 * then increments the offset by 1 for the next pass. This results
> -	 * in the first 3 bytes of each pass except the first one getting
> -	 * written to a location that has already been zeroed in the previous
> -	 * pass.
> -	 * This is what the vendor driver does, but it still looks suspicious.
> -	 *
> -	 * This should probably suffice:
> -	 *
> -	 * for (i = 0; i < 704; i+=4)
> -	 * 	b43_lptab_write(dev, B43_LPTAB32(7, i), 0)
> -	 *
> -	 * This should be tested once the code is functional.
> -	 */
>  	for (i = 0; i < 704; i++)
>  		b43_lptab_write(dev, B43_LPTAB32(7, i), 0);
>  
> @@ -2323,7 +2334,7 @@ void lpphy_rev2plus_table_init(struct b43_wldev *dev)
>  	b43_lptab_write_bulk(dev, B43_LPTAB8(6, 0),
>  		ARRAY_SIZE(lpphy_pll_fraction_table), lpphy_pll_fraction_table);
>  	b43_lptab_write_bulk(dev, B43_LPTAB16(0, 0),
> -		ARRAY_SIZE(lpphy_iq_local_table), lpphy_iq_local_table);
> +		ARRAY_SIZE(lpphy_iqlo_cal_table), lpphy_iqlo_cal_table);
>  	b43_lptab_write_bulk(dev, B43_LPTAB32(9, 0),
>  		ARRAY_SIZE(lpphy_papd_eps_table), lpphy_papd_eps_table);
>  	b43_lptab_write_bulk(dev, B43_LPTAB32(10, 0),



-- 
Greetings, Michael.

^ permalink raw reply

* Re: [PATCH] rtl8187: Fix for kernel oops when unloading with LEDs enabled
From: Luis R. Rodriguez @ 2009-08-26 20:43 UTC (permalink / raw)
  To: Larry Finger
  Cc: John W. Linville, Richard Farina, Herton Ronaldo Krzesinski,
	Hin-Tak Leung, linux-wireless
In-Reply-To: <4A955CD0.6040604@lwfinger.net>

On Wed, Aug 26, 2009 at 9:03 AM, Larry Finger<Larry.Finger@lwfinger.net> wrote:
> John W. Linville wrote:
>>
>> The above commit is in linux-2.6 since v2.6.31-rc2.  If it isn't in
>> compat-wireless, I have no idea why.
>
> It is - I looked at the code.

Just a heads up -- I pull "stable" code for compat-wireless using
hpa's tree, not Linus:

git://git.kernel.org/pub/scm/linux/kernel/git/hpa/linux-2.6-allstable.git

Its convenient for me as I get to have branches for each kernel
release. Regardless though hpa seems to update this stable tree when
Linus updates his, so its at rc7 now for the master branch. The code
pulled into the stable compat-wireless stuff then is from the latest
stable code 2.6.2x.y or Linus' latest rc as on hpa's master branch.

  Luis

^ permalink raw reply

* Re: [PATCH] ssb: Implement PMU LDO control and use it in b43
From: Michael Buesch @ 2009-08-26 20:46 UTC (permalink / raw)
  To: Gábor Stefanik
  Cc: John Linville, Larry Finger, Mark Huijgen, Broadcom Wireless,
	linux-wireless
In-Reply-To: <1251312686-32067-3-git-send-email-netrolller.3d@gmail.com>

On Wednesday 26 August 2009 20:51:26 Gábor Stefanik wrote:
> Implement the "PMU LDO set voltage" and "PMU LDO PA ref enable"
> functions, and use them during LP-PHY baseband init in b43.
> 
> Signed-off-by: Gábor Stefanik <netrolller.3d@gmail.com>

ack

-- 
Greetings, Michael.

^ permalink raw reply

* Re: [PATCH] b43: Remove scary message from LP-PHY's Kconfig
From: Michael Buesch @ 2009-08-26 20:47 UTC (permalink / raw)
  To: Gábor Stefanik
  Cc: John Linville, Larry Finger, Mark Huijgen, Broadcom Wireless,
	linux-wireless
In-Reply-To: <1251316132-392-1-git-send-email-netrolller.3d@gmail.com>

On Wednesday 26 August 2009 21:48:52 Gábor Stefanik wrote:
> From: root Gábor Stefanik <netrolller.3d@gmail.com>
> 
> The most common LP-PHY device, BCM4312, is now fully functional.
> So, no need to say "probably won't work for you" anymore.
> It's also not "for debuggers and developers only", as it is
> perfectly usable for end-users now (at least for BCM4312).

Please also add
default y

> 
> Signed-off-by: Gábor Stefanik <netrolller.3d@gmail.com>
> ---
> This should only be applied once the "Qdiv roundup" and the "Fix and update"
> patches reach the tree, as those 2 patches are needed to make the BCM4312
> really work.
> 
>  drivers/net/wireless/b43/Kconfig |    3 ---
>  1 files changed, 0 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig
> index 87d10c8..1c0999b 100644
> --- a/drivers/net/wireless/b43/Kconfig
> +++ b/drivers/net/wireless/b43/Kconfig
> @@ -88,9 +88,6 @@ config B43_PHY_LP
>  	  and embedded devices. It supports 802.11a/g
>  	  (802.11a support is optional, and currently disabled).
>  
> -	  This is heavily experimental, and probably will not work for you.
> -	  Say N unless you want to help debug the driver.
> -
>  # This config option automatically enables b43 LEDS support,
>  # if it's possible.
>  config B43_LEDS



-- 
Greetings, Michael.

^ permalink raw reply

* Re: [PATCH] b43: Fix and update LP-PHY code
From: Gábor Stefanik @ 2009-08-26 20:47 UTC (permalink / raw)
  To: Michael Buesch
  Cc: John Linville, Larry Finger, Mark Huijgen, Broadcom Wireless,
	linux-wireless
In-Reply-To: <200908262242.50729.mb@bu3sch.de>

2009/8/26 Michael Buesch <mb@bu3sch.de>:
> On Wednesday 26 August 2009 20:51:25 Gábor Stefanik wrote:
>> -Fix a few nasty typos (b43_phy_* operations instead of b43_radio_*)
>>  in the channel tune routines.
>> -Fix some typos & spec errors found by MMIO tracing.
>> -Optimize b43_phy_write & b43_phy_mask/set/maskset to use
>>  only the minimal number of MMIO accesses. (Write is possible
>>  using a single 32-bit MMIO write, while set/mask/maskset can
>>  be done in 3 16-bit MMIOs).
>
> Why does it matter? PHY access is not done in any hotpath. So why
> not prefer simple code over optimized code?

This is how the MIPS/hybrid driver does it, I simply updated the code
for parity.

>
>> -Set the default channel back to 1, as the bug forcing us to use
>>  channel 7 is now fixed.
>
> And, everything in its own patch, please. I don't see a reason for
> patching unrelated things in one big patch.

Well, this patch is already in wireless-testing, so doing that would
now involve reverting this patch, applying a version without the
channel change, and applying the channel change - certainly more
confusing than the status quo.

>
>>
>> With this, the device comes up, scans, associates, transmits,
>> receives, monitors and injects on all channels - in other words,
>> it's fully functional. Sensitivity and TX power are still sub-optimal,
>> due to the lack of calibration (that's next on my list).
>>
>> Signed-off-by: Gábor Stefanik <netrolller.3d@gmail.com>
>> ---
>>  drivers/net/wireless/b43/phy_common.c   |   27 +++++++--
>>  drivers/net/wireless/b43/phy_common.h   |    3 +
>>  drivers/net/wireless/b43/phy_lp.c       |   91 +++++++++++++++++--------------
>>  drivers/net/wireless/b43/phy_lp.h       |    3 +
>>  drivers/net/wireless/b43/tables_lpphy.c |   79 +++++++++++++++------------
>>  5 files changed, 122 insertions(+), 81 deletions(-)
>>
>> diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c
>> index 51686ec..6e704be 100644
>> --- a/drivers/net/wireless/b43/phy_common.c
>> +++ b/drivers/net/wireless/b43/phy_common.c
>> @@ -249,20 +249,35 @@ void b43_phy_copy(struct b43_wldev *dev, u16 destreg, u16 srcreg)
>>
>>  void b43_phy_mask(struct b43_wldev *dev, u16 offset, u16 mask)
>>  {
>> -     b43_phy_write(dev, offset,
>> -                   b43_phy_read(dev, offset) & mask);
>> +     if (dev->phy.ops->phy_maskset) {
>> +             assert_mac_suspended(dev);
>> +             dev->phy.ops->phy_maskset(dev, offset, mask, 0);
>> +     } else {
>> +             b43_phy_write(dev, offset,
>> +                           b43_phy_read(dev, offset) & mask);
>> +     }
>>  }
>>
>>  void b43_phy_set(struct b43_wldev *dev, u16 offset, u16 set)
>>  {
>> -     b43_phy_write(dev, offset,
>> -                   b43_phy_read(dev, offset) | set);
>> +     if (dev->phy.ops->phy_maskset) {
>> +             assert_mac_suspended(dev);
>> +             dev->phy.ops->phy_maskset(dev, offset, 0xFFFF, set);
>> +     } else {
>> +             b43_phy_write(dev, offset,
>> +                           b43_phy_read(dev, offset) | set);
>> +     }
>>  }
>>
>>  void b43_phy_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set)
>>  {
>> -     b43_phy_write(dev, offset,
>> -                   (b43_phy_read(dev, offset) & mask) | set);
>> +     if (dev->phy.ops->phy_maskset) {
>> +             assert_mac_suspended(dev);
>> +             dev->phy.ops->phy_maskset(dev, offset, mask, set);
>> +     } else {
>> +             b43_phy_write(dev, offset,
>> +                           (b43_phy_read(dev, offset) & mask) | set);
>> +     }
>>  }
>>
>>  int b43_switch_channel(struct b43_wldev *dev, unsigned int new_channel)
>> diff --git a/drivers/net/wireless/b43/phy_common.h b/drivers/net/wireless/b43/phy_common.h
>> index 9f9f23c..b47a0f5 100644
>> --- a/drivers/net/wireless/b43/phy_common.h
>> +++ b/drivers/net/wireless/b43/phy_common.h
>> @@ -95,6 +95,8 @@ enum b43_txpwr_result {
>>   *                   Must not be NULL.
>>   * @phy_write:               Write to a PHY register.
>>   *                   Must not be NULL.
>> + * @phy_maskset:     Maskset a PHY register, taking shortcuts.
>> + *                   If it is NULL, a generic algorithm is used.
>>   * @radio_read:              Read from a Radio register.
>>   *                   Must not be NULL.
>>   * @radio_write:     Write to a Radio register.
>> @@ -154,6 +156,7 @@ struct b43_phy_operations {
>>       /* Register access */
>>       u16 (*phy_read)(struct b43_wldev *dev, u16 reg);
>>       void (*phy_write)(struct b43_wldev *dev, u16 reg, u16 value);
>> +     void (*phy_maskset)(struct b43_wldev *dev, u16 reg, u16 mask, u16 set);
>>       u16 (*radio_read)(struct b43_wldev *dev, u16 reg);
>>       void (*radio_write)(struct b43_wldev *dev, u16 reg, u16 value);
>>
>> diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c
>> index 5306f2c..1a57d33 100644
>> --- a/drivers/net/wireless/b43/phy_lp.c
>> +++ b/drivers/net/wireless/b43/phy_lp.c
>> @@ -44,7 +44,7 @@ static inline u16 channel2freq_lp(u8 channel)
>>  static unsigned int b43_lpphy_op_get_default_chan(struct b43_wldev *dev)
>>  {
>>       if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
>> -             return 7; //FIXME temporary - channel 1 is broken
>> +             return 1;
>>       return 36;
>>  }
>>
>> @@ -182,8 +182,8 @@ static void lpphy_adjust_gain_table(struct b43_wldev *dev, u32 freq)
>>       temp[1] = temp[0] + 0x1000;
>>       temp[2] = temp[0] + 0x2000;
>>
>> -     b43_lptab_write_bulk(dev, B43_LPTAB16(12, 0), 3, temp);
>>       b43_lptab_write_bulk(dev, B43_LPTAB16(13, 0), 3, temp);
>> +     b43_lptab_write_bulk(dev, B43_LPTAB16(12, 0), 3, temp);
>>  }
>>
>>  static void lpphy_table_init(struct b43_wldev *dev)
>> @@ -223,8 +223,8 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
>>       b43_phy_maskset(dev, B43_LPPHY_VERYLOWGAINDB, 0xFF00, 0x0006);
>>       b43_phy_mask(dev, B43_LPPHY_RX_RADIO_CTL, 0xFFFE);
>>       b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFFE0, 0x0005);
>> -     b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFC10, 0x0180);
>> -     b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0x83FF, 0x3800);
>> +     b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFC1F, 0x0180);
>> +     b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0x83FF, 0x3C00);
>>       b43_phy_maskset(dev, B43_LPPHY_GAINDIRECTMISMATCH, 0xFFF0, 0x0005);
>>       b43_phy_maskset(dev, B43_LPPHY_GAIN_MISMATCH_LIMIT, 0xFFC0, 0x001A);
>>       b43_phy_maskset(dev, B43_LPPHY_CRS_ED_THRESH, 0xFF00, 0x00B3);
>> @@ -237,7 +237,7 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
>>               /* TODO:
>>                * Set the LDO voltage to 0x0028 - FIXME: What is this?
>>                * Call sb_pmu_set_ldo_voltage with 4 and the LDO voltage
>> -              *      as arguments
>> +              *      as arguments
>>                * Call sb_pmu_paref_ldo_enable with argument TRUE
>>                */
>>               if (dev->phy.rev == 0) {
>> @@ -340,11 +340,11 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
>>       if (dev->phy.rev == 1) {
>>               tmp = b43_phy_read(dev, B43_LPPHY_CLIPCTRTHRESH);
>>               tmp2 = (tmp & 0x03E0) >> 5;
>> -             tmp2 |= tmp << 5;
>> +             tmp2 |= tmp2 << 5;
>>               b43_phy_write(dev, B43_LPPHY_4C3, tmp2);
>> -             tmp = b43_phy_read(dev, B43_LPPHY_OFDMSYNCTHRESH0);
>> +             tmp = b43_phy_read(dev, B43_LPPHY_GAINDIRECTMISMATCH);
>>               tmp2 = (tmp & 0x1F00) >> 8;
>> -             tmp2 |= tmp << 5;
>> +             tmp2 |= tmp2 << 5;
>>               b43_phy_write(dev, B43_LPPHY_4C4, tmp2);
>>               tmp = b43_phy_read(dev, B43_LPPHY_VERYLOWGAINDB);
>>               tmp2 = tmp & 0x00FF;
>> @@ -761,7 +761,7 @@ static void lpphy_disable_crs(struct b43_wldev *dev, bool user)
>>       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_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_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);
>> @@ -956,7 +956,7 @@ static void lpphy_run_ddfs(struct b43_wldev *dev, int i_on, int q_on,
>>       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);
>> +     b43_phy_set(dev, B43_LPPHY_LP_PHY_CTL, 0x20);
>>  }
>>
>>  static bool lpphy_rx_iq_est(struct b43_wldev *dev, u16 samples, u8 time,
>> @@ -968,7 +968,7 @@ static bool lpphy_rx_iq_est(struct b43_wldev *dev, u16 samples, u8 time,
>>       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);
>> +     b43_phy_set(dev, B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR, 0x200);
>>
>>       for (i = 0; i < 500; i++) {
>>               if (!(b43_phy_read(dev,
>> @@ -1135,9 +1135,9 @@ static void lpphy_set_tx_power_control(struct b43_wldev *dev,
>>       }
>>       if (dev->phy.rev >= 2) {
>>               if (mode == B43_LPPHY_TXPCTL_HW)
>> -                     b43_phy_maskset(dev, B43_PHY_OFDM(0xD0), 0xFD, 0x2);
>> +                     b43_phy_set(dev, B43_PHY_OFDM(0xD0), 0x2);
>>               else
>> -                     b43_phy_maskset(dev, B43_PHY_OFDM(0xD0), 0xFD, 0);
>> +                     b43_phy_mask(dev, B43_PHY_OFDM(0xD0), 0xFFFD);
>>       }
>>       lpphy_write_tx_pctl_mode_to_hardware(dev);
>>  }
>> @@ -1169,7 +1169,7 @@ static void lpphy_rev0_1_rc_calib(struct b43_wldev *dev)
>>       err = b43_lpphy_op_switch_channel(dev, 7);
>>       if (err) {
>>               b43dbg(dev->wl,
>> -                    "RC calib: Failed to switch to channel 7, error = %d",
>> +                    "RC calib: Failed to switch to channel 7, error = %d\n",
>>                      err);
>>       }
>>       old_txg_ovr = !!(b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVR) & 0x40);
>> @@ -1500,8 +1500,15 @@ static u16 b43_lpphy_op_read(struct b43_wldev *dev, u16 reg)
>>
>>  static void b43_lpphy_op_write(struct b43_wldev *dev, u16 reg, u16 value)
>>  {
>> +     b43_write32(dev, B43_MMIO_PHY_CONTROL, ((u32)value << 16) | reg);
>> +}
>> +
>> +static void b43_lpphy_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask,
>> +                              u16 set)
>> +{
>>       b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
>> -     b43_write16(dev, B43_MMIO_PHY_DATA, value);
>> +     b43_write16(dev, B43_MMIO_PHY_DATA,
>> +                 (b43_read16(dev, B43_MMIO_PHY_DATA) & mask) | set);
>>  }
>>
>>  static u16 b43_lpphy_op_radio_read(struct b43_wldev *dev, u16 reg)
>> @@ -1920,8 +1927,8 @@ static void lpphy_b2062_reset_pll_bias(struct b43_wldev *dev)
>>
>>  static void lpphy_b2062_vco_calib(struct b43_wldev *dev)
>>  {
>> -     b43_phy_write(dev, B2062_S_RFPLL_CTL21, 0x42);
>> -     b43_phy_write(dev, B2062_S_RFPLL_CTL21, 0x62);
>> +     b43_radio_write(dev, B2062_S_RFPLL_CTL21, 0x42);
>> +     b43_radio_write(dev, B2062_S_RFPLL_CTL21, 0x62);
>>       udelay(200);
>>  }
>>
>> @@ -1980,7 +1987,7 @@ static int lpphy_b2062_tune(struct b43_wldev *dev,
>>       tmp6 = tmp5 / tmp4;
>>       tmp7 = tmp5 % tmp4;
>>       b43_radio_write(dev, B2062_S_RFPLL_CTL29, tmp6 + ((2 * tmp7) / tmp4));
>> -     tmp8 = b43_phy_read(dev, B2062_S_RFPLL_CTL19);
>> +     tmp8 = b43_radio_read(dev, B2062_S_RFPLL_CTL19);
>>       tmp9 = ((2 * tmp3 * (tmp8 + 1)) + (3 * tmp1)) / (6 * tmp1);
>>       b43_radio_write(dev, B2062_S_RFPLL_CTL23, (tmp9 >> 8) + 16);
>>       b43_radio_write(dev, B2062_S_RFPLL_CTL24, tmp9 & 0xFF);
>> @@ -2019,17 +2026,17 @@ static void lpphy_b2063_vco_calib(struct b43_wldev *dev)
>>  {
>>       u16 tmp;
>>
>> -     b43_phy_mask(dev, B2063_PLL_SP1, ~0x40);
>> -     tmp = b43_phy_read(dev, B2063_PLL_JTAG_CALNRST) & 0xF8;
>> -     b43_phy_write(dev, B2063_PLL_JTAG_CALNRST, tmp);
>> +     b43_radio_mask(dev, B2063_PLL_SP1, ~0x40);
>> +     tmp = b43_radio_read(dev, B2063_PLL_JTAG_CALNRST) & 0xF8;
>> +     b43_radio_write(dev, B2063_PLL_JTAG_CALNRST, tmp);
>>       udelay(1);
>> -     b43_phy_write(dev, B2063_PLL_JTAG_CALNRST, tmp | 0x4);
>> +     b43_radio_write(dev, B2063_PLL_JTAG_CALNRST, tmp | 0x4);
>>       udelay(1);
>> -     b43_phy_write(dev, B2063_PLL_JTAG_CALNRST, tmp | 0x6);
>> +     b43_radio_write(dev, B2063_PLL_JTAG_CALNRST, tmp | 0x6);
>>       udelay(1);
>> -     b43_phy_write(dev, B2063_PLL_JTAG_CALNRST, tmp | 0x7);
>> +     b43_radio_write(dev, B2063_PLL_JTAG_CALNRST, tmp | 0x7);
>>       udelay(300);
>> -     b43_phy_set(dev, B2063_PLL_SP1, 0x40);
>> +     b43_radio_set(dev, B2063_PLL_SP1, 0x40);
>>  }
>>
>>  static int lpphy_b2063_tune(struct b43_wldev *dev,
>> @@ -2124,31 +2131,31 @@ static int lpphy_b2063_tune(struct b43_wldev *dev,
>>               scale = 0;
>>               tmp5 = ((tmp4 + (tmp3 >> 1)) / tmp3) - 8;
>>       }
>> -     b43_phy_maskset(dev, B2063_PLL_JTAG_PLL_CP2, 0xFFC0, tmp5);
>> -     b43_phy_maskset(dev, B2063_PLL_JTAG_PLL_CP2, 0xFFBF, scale << 6);
>> +     b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_CP2, 0xFFC0, tmp5);
>> +     b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_CP2, 0xFFBF, scale << 6);
>>
>>       tmp6 = lpphy_qdiv_roundup(100 * val1, val3, 16);
>>       tmp6 *= (tmp5 * 8) * (scale + 1);
>>       if (tmp6 > 150)
>>               tmp6 = 0;
>>
>> -     b43_phy_maskset(dev, B2063_PLL_JTAG_PLL_CP3, 0xFFE0, tmp6);
>> -     b43_phy_maskset(dev, B2063_PLL_JTAG_PLL_CP3, 0xFFDF, scale << 5);
>> +     b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_CP3, 0xFFE0, tmp6);
>> +     b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_CP3, 0xFFDF, scale << 5);
>>
>> -     b43_phy_maskset(dev, B2063_PLL_JTAG_PLL_XTAL_12, 0xFFFB, 0x4);
>> +     b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_XTAL_12, 0xFFFB, 0x4);
>>       if (crystal_freq > 26000000)
>> -             b43_phy_set(dev, B2063_PLL_JTAG_PLL_XTAL_12, 0x2);
>> +             b43_radio_set(dev, B2063_PLL_JTAG_PLL_XTAL_12, 0x2);
>>       else
>> -             b43_phy_mask(dev, B2063_PLL_JTAG_PLL_XTAL_12, 0xFD);
>> +             b43_radio_mask(dev, B2063_PLL_JTAG_PLL_XTAL_12, 0xFD);
>>
>>       if (val1 == 45)
>> -             b43_phy_set(dev, B2063_PLL_JTAG_PLL_VCO1, 0x2);
>> +             b43_radio_set(dev, B2063_PLL_JTAG_PLL_VCO1, 0x2);
>>       else
>> -             b43_phy_mask(dev, B2063_PLL_JTAG_PLL_VCO1, 0xFD);
>> +             b43_radio_mask(dev, B2063_PLL_JTAG_PLL_VCO1, 0xFD);
>>
>> -     b43_phy_set(dev, B2063_PLL_SP2, 0x3);
>> +     b43_radio_set(dev, B2063_PLL_SP2, 0x3);
>>       udelay(1);
>> -     b43_phy_mask(dev, B2063_PLL_SP2, 0xFFFC);
>> +     b43_radio_mask(dev, B2063_PLL_SP2, 0xFFFC);
>>       lpphy_b2063_vco_calib(dev);
>>       b43_radio_write(dev, B2063_COMM15, old_comm15);
>>
>> @@ -2158,10 +2165,9 @@ static int lpphy_b2063_tune(struct b43_wldev *dev,
>>  static int b43_lpphy_op_switch_channel(struct b43_wldev *dev,
>>                                      unsigned int new_channel)
>>  {
>> +     struct b43_phy_lp *lpphy = dev->phy.lp;
>>       int err;
>>
>> -     b43_write16(dev, B43_MMIO_CHANNEL, new_channel);
>> -
>>       if (dev->phy.radio_ver == 0x2063) {
>>               err = lpphy_b2063_tune(dev, new_channel);
>>               if (err)
>> @@ -2174,6 +2180,9 @@ static int b43_lpphy_op_switch_channel(struct b43_wldev *dev,
>>               lpphy_adjust_gain_table(dev, channel2freq_lp(new_channel));
>>       }
>>
>> +     lpphy->channel = new_channel;
>> +     b43_write16(dev, B43_MMIO_CHANNEL, new_channel);
>> +
>>       return 0;
>>  }
>>
>> @@ -2185,10 +2194,9 @@ static int b43_lpphy_op_init(struct b43_wldev *dev)
>>       lpphy_baseband_init(dev);
>>       lpphy_radio_init(dev);
>>       lpphy_calibrate_rc(dev);
>> -     err = b43_lpphy_op_switch_channel(dev,
>> -                             b43_lpphy_op_get_default_chan(dev));
>> +     err = b43_lpphy_op_switch_channel(dev, 7);
>>       if (err) {
>> -             b43dbg(dev->wl, "Switch to init channel failed, error = %d.\n",
>> +             b43dbg(dev->wl, "Switch to channel 7 failed, error = %d.\n",
>>                      err);
>>       }
>>       lpphy_tx_pctl_init(dev);
>> @@ -2222,6 +2230,7 @@ const struct b43_phy_operations b43_phyops_lp = {
>>       .init                   = b43_lpphy_op_init,
>>       .phy_read               = b43_lpphy_op_read,
>>       .phy_write              = b43_lpphy_op_write,
>> +     .phy_maskset            = b43_lpphy_op_maskset,
>>       .radio_read             = b43_lpphy_op_radio_read,
>>       .radio_write            = b43_lpphy_op_radio_write,
>>       .software_rfkill        = b43_lpphy_op_software_rfkill,
>> diff --git a/drivers/net/wireless/b43/phy_lp.h b/drivers/net/wireless/b43/phy_lp.h
>> index e158d1f..c3232c1 100644
>> --- a/drivers/net/wireless/b43/phy_lp.h
>> +++ b/drivers/net/wireless/b43/phy_lp.h
>> @@ -888,6 +888,9 @@ struct b43_phy_lp {
>>       bool crs_usr_disable, crs_sys_disable;
>>
>>       unsigned int pdiv;
>> +
>> +     /* The channel we are tuned to */
>> +     u8 channel;
>>  };
>>
>>  enum tssi_mux_mode {
>> diff --git a/drivers/net/wireless/b43/tables_lpphy.c b/drivers/net/wireless/b43/tables_lpphy.c
>> index 60d472f..c784def 100644
>> --- a/drivers/net/wireless/b43/tables_lpphy.c
>> +++ b/drivers/net/wireless/b43/tables_lpphy.c
>> @@ -624,30 +624,35 @@ u32 b43_lptab_read(struct b43_wldev *dev, u32 offset)
>>  void b43_lptab_read_bulk(struct b43_wldev *dev, u32 offset,
>>                        unsigned int nr_elements, void *_data)
>>  {
>> -     u32 type, value;
>> +     u32 type;
>>       u8 *data = _data;
>>       unsigned int i;
>>
>>       type = offset & B43_LPTAB_TYPEMASK;
>> +     offset &= ~B43_LPTAB_TYPEMASK;
>> +     B43_WARN_ON(offset > 0xFFFF);
>> +
>> +     b43_phy_write(dev, B43_LPPHY_TABLE_ADDR, offset);
>> +
>>       for (i = 0; i < nr_elements; i++) {
>> -             value = b43_lptab_read(dev, offset);
>>               switch (type) {
>>               case B43_LPTAB_8BIT:
>> -                     *data = value;
>> +                     *data = b43_phy_read(dev, B43_LPPHY_TABLEDATALO) & 0xFF;
>>                       data++;
>>                       break;
>>               case B43_LPTAB_16BIT:
>> -                     *((u16 *)data) = value;
>> +                     *((u16 *)data) = b43_phy_read(dev, B43_LPPHY_TABLEDATALO);
>>                       data += 2;
>>                       break;
>>               case B43_LPTAB_32BIT:
>> -                     *((u32 *)data) = value;
>> +                     *((u32 *)data) = b43_phy_read(dev, B43_LPPHY_TABLEDATAHI);
>> +                     *((u32 *)data) <<= 16;
>> +                     *((u32 *)data) |= b43_phy_read(dev, B43_LPPHY_TABLEDATALO);
>>                       data += 4;
>>                       break;
>>               default:
>>                       B43_WARN_ON(1);
>>               }
>> -             offset++;
>>       }
>>  }
>>
>> @@ -688,26 +693,34 @@ void b43_lptab_write_bulk(struct b43_wldev *dev, u32 offset,
>>       unsigned int i;
>>
>>       type = offset & B43_LPTAB_TYPEMASK;
>> +     offset &= ~B43_LPTAB_TYPEMASK;
>> +     B43_WARN_ON(offset > 0xFFFF);
>> +
>> +     b43_phy_write(dev, B43_LPPHY_TABLE_ADDR, offset);
>> +
>>       for (i = 0; i < nr_elements; i++) {
>>               switch (type) {
>>               case B43_LPTAB_8BIT:
>>                       value = *data;
>>                       data++;
>> +                     B43_WARN_ON(value & ~0xFF);
>> +                     b43_phy_write(dev, B43_LPPHY_TABLEDATALO, value);
>>                       break;
>>               case B43_LPTAB_16BIT:
>>                       value = *((u16 *)data);
>>                       data += 2;
>> +                     B43_WARN_ON(value & ~0xFFFF);
>> +                     b43_phy_write(dev, B43_LPPHY_TABLEDATALO, value);
>>                       break;
>>               case B43_LPTAB_32BIT:
>>                       value = *((u32 *)data);
>>                       data += 4;
>> +                     b43_phy_write(dev, B43_LPPHY_TABLEDATAHI, value >> 16);
>> +                     b43_phy_write(dev, B43_LPPHY_TABLEDATALO, value);
>>                       break;
>>               default:
>>                       B43_WARN_ON(1);
>> -                     value = 0;
>>               }
>> -             b43_lptab_write(dev, offset, value);
>> -             offset++;
>>       }
>>  }
>>
>> @@ -777,7 +790,7 @@ static const u8 lpphy_pll_fraction_table[] = {
>>       0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
>>  };
>>
>> -static const u16 lpphy_iq_local_table[] = {
>> +static const u16 lpphy_iqlo_cal_table[] = {
>>       0x0200, 0x0300, 0x0400, 0x0600, 0x0800, 0x0b00, 0x1000, 0x1001, 0x1002,
>>       0x1003, 0x1004, 0x1005, 0x1006, 0x1007, 0x1707, 0x2007, 0x2d07, 0x4007,
>>       0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
>> @@ -789,10 +802,17 @@ static const u16 lpphy_iq_local_table[] = {
>>       0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
>>       0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4000, 0x0000, 0x0000,
>>       0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
>> -     0x0000, 0x0000,
>> +     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
>>  };
>>
>> -static const u16 lpphy_ofdm_cck_gain_table[] = {
>> +static const u16 lpphy_rev0_ofdm_cck_gain_table[] = {
>> +     0x0001, 0x0001, 0x0001, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001, 0x5001,
>> +     0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055, 0x2065, 0x2075,
>> +     0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d, 0x135d, 0x055d, 0x155d,
>> +     0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d, 0x755d,
>> +};
>> +
>> +static const u16 lpphy_rev1_ofdm_cck_gain_table[] = {
>>       0x5000, 0x6000, 0x7000, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001, 0x5001,
>>       0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055, 0x2065, 0x2075,
>>       0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d, 0x135d, 0x055d, 0x155d,
>> @@ -2263,11 +2283,18 @@ void lpphy_rev0_1_table_init(struct b43_wldev *dev)
>>       b43_lptab_write_bulk(dev, B43_LPTAB8(6, 0),
>>               ARRAY_SIZE(lpphy_pll_fraction_table), lpphy_pll_fraction_table);
>>       b43_lptab_write_bulk(dev, B43_LPTAB16(0, 0),
>> -             ARRAY_SIZE(lpphy_iq_local_table), lpphy_iq_local_table);
>> -     b43_lptab_write_bulk(dev, B43_LPTAB16(13, 0),
>> -             ARRAY_SIZE(lpphy_ofdm_cck_gain_table), lpphy_ofdm_cck_gain_table);
>> -     b43_lptab_write_bulk(dev, B43_LPTAB16(12, 0),
>> -             ARRAY_SIZE(lpphy_ofdm_cck_gain_table), lpphy_ofdm_cck_gain_table);
>> +             ARRAY_SIZE(lpphy_iqlo_cal_table), lpphy_iqlo_cal_table);
>> +     if (dev->phy.rev == 0) {
>> +             b43_lptab_write_bulk(dev, B43_LPTAB16(13, 0),
>> +                     ARRAY_SIZE(lpphy_rev0_ofdm_cck_gain_table), lpphy_rev0_ofdm_cck_gain_table);
>> +             b43_lptab_write_bulk(dev, B43_LPTAB16(12, 0),
>> +                     ARRAY_SIZE(lpphy_rev0_ofdm_cck_gain_table), lpphy_rev0_ofdm_cck_gain_table);
>> +     } else {
>> +             b43_lptab_write_bulk(dev, B43_LPTAB16(13, 0),
>> +                     ARRAY_SIZE(lpphy_rev1_ofdm_cck_gain_table), lpphy_rev1_ofdm_cck_gain_table);
>> +             b43_lptab_write_bulk(dev, B43_LPTAB16(12, 0),
>> +                     ARRAY_SIZE(lpphy_rev1_ofdm_cck_gain_table), lpphy_rev1_ofdm_cck_gain_table);
>> +}
>>       b43_lptab_write_bulk(dev, B43_LPTAB16(15, 0),
>>               ARRAY_SIZE(lpphy_gain_delta_table), lpphy_gain_delta_table);
>>       b43_lptab_write_bulk(dev, B43_LPTAB32(10, 0),
>> @@ -2281,22 +2308,6 @@ void lpphy_rev2plus_table_init(struct b43_wldev *dev)
>>
>>       B43_WARN_ON(dev->phy.rev < 2);
>>
>> -     /*
>> -      * FIXME This code follows the specs, but it looks wrong:
>> -      * In each pass, it writes 4 bytes to an offset in table ID 7,
>> -      * then increments the offset by 1 for the next pass. This results
>> -      * in the first 3 bytes of each pass except the first one getting
>> -      * written to a location that has already been zeroed in the previous
>> -      * pass.
>> -      * This is what the vendor driver does, but it still looks suspicious.
>> -      *
>> -      * This should probably suffice:
>> -      *
>> -      * for (i = 0; i < 704; i+=4)
>> -      *      b43_lptab_write(dev, B43_LPTAB32(7, i), 0)
>> -      *
>> -      * This should be tested once the code is functional.
>> -      */
>>       for (i = 0; i < 704; i++)
>>               b43_lptab_write(dev, B43_LPTAB32(7, i), 0);
>>
>> @@ -2323,7 +2334,7 @@ void lpphy_rev2plus_table_init(struct b43_wldev *dev)
>>       b43_lptab_write_bulk(dev, B43_LPTAB8(6, 0),
>>               ARRAY_SIZE(lpphy_pll_fraction_table), lpphy_pll_fraction_table);
>>       b43_lptab_write_bulk(dev, B43_LPTAB16(0, 0),
>> -             ARRAY_SIZE(lpphy_iq_local_table), lpphy_iq_local_table);
>> +             ARRAY_SIZE(lpphy_iqlo_cal_table), lpphy_iqlo_cal_table);
>>       b43_lptab_write_bulk(dev, B43_LPTAB32(9, 0),
>>               ARRAY_SIZE(lpphy_papd_eps_table), lpphy_papd_eps_table);
>>       b43_lptab_write_bulk(dev, B43_LPTAB32(10, 0),
>
>
>
> --
> Greetings, Michael.
>



-- 
Vista: [V]iruses, [I]ntruders, [S]pyware, [T]rojans and [A]dware. :-)

^ 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