Linux wireless drivers development
 help / color / mirror / Atom feed
* [PATCH] rtlwifi: rtl8192ce: Fix driver problem when radio switch off at module load
From: Larry Finger @ 2010-12-22  1:40 UTC (permalink / raw)
  To: John W Linville; +Cc: chaoming_li, linux-wireless

If the radio enable switch is off when the driver is loaded, it is not
possible to get radio output until the driver is unloaded and reloaded
with the switch on.

Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
---

Index: wireless-testing/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
===================================================================
--- wireless-testing.orig/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
+++ wireless-testing/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
@@ -962,17 +962,6 @@ int rtl92ce_hw_init(struct ieee80211_hw
 	rtl_cam_reset_all_entry(hw);
 	rtl92ce_enable_hw_security_config(hw);
 	ppsc->rfpwr_state = ERFON;
-	tmp_u1b = rtl_read_byte(rtlpriv, REG_MAC_PINMUX_CFG)&(~BIT(3));
-	rtl_write_byte(rtlpriv, REG_MAC_PINMUX_CFG, tmp_u1b);
-	tmp_u1b = rtl_read_byte(rtlpriv, REG_GPIO_IO_SEL);
-	ppsc->rfoff_reason |= (tmp_u1b & BIT(3)) ? 0 : RF_CHANGE_BY_HW;
-	if (ppsc->rfoff_reason > RF_CHANGE_BY_PS)
-		rtl_ps_set_rf_state(hw, ERFOFF, ppsc->rfoff_reason, true);
-	else {
-		ppsc->rfpwr_state = ERFON;
-		ppsc->rfoff_reason = 0;
-		rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_ON);
-	}
 	rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr);
 	_rtl92ce_enable_aspm_back_door(hw);
 	rtlpriv->intf_ops->enable_aspm(hw);
Index: wireless-testing/drivers/net/wireless/rtlwifi/base.c
===================================================================
--- wireless-testing.orig/drivers/net/wireless/rtlwifi/base.c
+++ wireless-testing/drivers/net/wireless/rtlwifi/base.c
@@ -251,16 +251,14 @@ void rtl_init_rfkill(struct ieee80211_hw
 	bool blocked;
 	u8 valid = 0;
 
-	/*set init state to rf on */
-	rtlpriv->rfkill.rfkill_state = 1;
-
 	radio_state = rtlpriv->cfg->ops->radio_onoff_checking(hw, &valid);
 
-	if (valid) {
-		RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
-			 (KERN_INFO "wireless switch is %s\n",
-			  rtlpriv->rfkill.rfkill_state ? "on" : "off"));
+	/*set init state to that of switch */
+	rtlpriv->rfkill.rfkill_state = radio_state;
+	printk(KERN_INFO "rtlwifi: wireless switch is %s\n",
+	       rtlpriv->rfkill.rfkill_state ? "on" : "off");
 
+	if (valid) {
 		rtlpriv->rfkill.rfkill_state = radio_state;
 
 		blocked = (rtlpriv->rfkill.rfkill_state == 1) ? 0 : 1;


^ permalink raw reply

* [PATCH] mwifiex: replace struct ieee_htinfo with ieee80211_ht_info
From: Bing Zhao @ 2010-12-21 23:41 UTC (permalink / raw)
  To: linux-wireless
  Cc: John W. Linville, Johannes Berg, Amitkumar Karwar, Kiran Divekar,
	Frank Huang, Bing Zhao

struct ieee80211_ht_info is defined in include/linux/ieee80211.h

Signed-off-by: Bing Zhao <bzhao@marvell.com>
Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
---
 drivers/net/wireless/mwifiex/11n.c  |   10 +++++-----
 drivers/net/wireless/mwifiex/fw.h   |    2 +-
 drivers/net/wireless/mwifiex/ieee.h |   10 +---------
 drivers/net/wireless/mwifiex/join.c |   13 +++++++------
 4 files changed, 14 insertions(+), 21 deletions(-)

diff --git a/drivers/net/wireless/mwifiex/11n.c b/drivers/net/wireless/mwifiex/11n.c
index 73d2fb7..93de7ca 100644
--- a/drivers/net/wireless/mwifiex/11n.c
+++ b/drivers/net/wireless/mwifiex/11n.c
@@ -852,7 +852,7 @@ mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv,
 			ht_info->header.type =
 					cpu_to_le16(WLAN_EID_HT_INFORMATION);
 			ht_info->header.len =
-				cpu_to_le16(sizeof(struct ieee_htinfo));
+				cpu_to_le16(sizeof(struct ieee80211_ht_info));
 
 			memcpy((u8 *) ht_info +
 			       sizeof(struct mwifiex_ie_types_header),
@@ -864,7 +864,7 @@ mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv,
 			    (priv->adapter->hw_dot_11n_dev_cap)
 			    || !ISSUPP_CHANWIDTH40(priv->adapter->
 						   usr_dot_11n_dev_cap)) {
-				RESET_CHANWIDTH40(ht_info->ht_info.field2);
+				RESET_CHANWIDTH40(ht_info->ht_info.ht_param);
 			}
 
 			*buffer += sizeof(struct mwifiex_ie_types_htinfo);
@@ -880,18 +880,18 @@ mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv,
 			sizeof(struct mwifiex_ie_types_chan_list_param_set) -
 			sizeof(struct mwifiex_ie_types_header));
 		chan_list->chan_scan_param[0].chan_number =
-			bss_desc->bcn_ht_info->ht_info.pri_chan;
+			bss_desc->bcn_ht_info->ht_info.control_chan;
 		chan_list->chan_scan_param[0].radio_type =
 			mwifiex_band_to_radio_type((u8) bss_desc->bss_band);
 
 		if ((ISSUPP_CHANWIDTH40(priv->adapter->hw_dot_11n_dev_cap) &&
 		     ISSUPP_CHANWIDTH40(priv->adapter->usr_dot_11n_dev_cap))
 		    && ISALLOWED_CHANWIDTH40(bss_desc->bcn_ht_info->ht_info.
-					     field2))
+					     ht_param))
 			SET_SECONDARYCHAN(chan_list->chan_scan_param[0].
 					  radio_type,
 					  GET_SECONDARYCHAN(bss_desc->
-					  bcn_ht_info->ht_info.field2));
+					  bcn_ht_info->ht_info.ht_param));
 
 		HEXDUMP("ChanList", (u8 *) chan_list,
 			sizeof(struct mwifiex_ie_types_chan_list_param_set));
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h
index 834122c..f166991 100644
--- a/drivers/net/wireless/mwifiex/fw.h
+++ b/drivers/net/wireless/mwifiex/fw.h
@@ -1175,7 +1175,7 @@ struct mwifiex_ie_types_htcap {
 
 struct mwifiex_ie_types_htinfo {
 	struct mwifiex_ie_types_header header;
-	struct ieee_htinfo ht_info;
+	struct ieee80211_ht_info ht_info;
 } __packed;
 
 struct mwifiex_ie_types_2040bssco {
diff --git a/drivers/net/wireless/mwifiex/ieee.h b/drivers/net/wireless/mwifiex/ieee.h
index 263380c..8888106 100644
--- a/drivers/net/wireless/mwifiex/ieee.h
+++ b/drivers/net/wireless/mwifiex/ieee.h
@@ -167,14 +167,6 @@ struct ieee_htcap {
 	u8 asel;
 } __packed;
 
-struct ieee_htinfo {
-	u8 pri_chan;
-	u8 field2;
-	u16 field3;
-	u16 field4;
-	u8 basic_mcs_set[16];
-} __packed;
-
 struct ieee_bssco_2040 {
 	u8 bss_co_2040_value;
 } __packed;
@@ -200,7 +192,7 @@ struct ieee_types_htcap {
 
 struct ieee_types_htinfo {
 	struct ieee_types_header ieee_hdr;
-	struct ieee_htinfo ht_info;
+	struct ieee80211_ht_info ht_info;
 } __packed;
 
 struct ieee_types_2040bssco {
diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c
index 9ac0c2f..9504107 100644
--- a/drivers/net/wireless/mwifiex/join.c
+++ b/drivers/net/wireless/mwifiex/join.c
@@ -1154,17 +1154,18 @@ mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,
 			ht_info->header.type =
 				cpu_to_le16(WLAN_EID_HT_INFORMATION);
 			ht_info->header.len =
-				cpu_to_le16(sizeof(struct ieee_htinfo));
-			ht_info->ht_info.pri_chan =
+				cpu_to_le16(sizeof(struct ieee80211_ht_info));
+			ht_info->ht_info.control_chan =
 				(u8) priv->curr_bss_params.bss_descriptor.
 				channel;
 			if (adapter->chan_offset) {
-				ht_info->ht_info.field2 =
+				ht_info->ht_info.ht_param =
 					adapter->chan_offset;
-				SET_CHANWIDTH40(ht_info->ht_info.field2);
+				SET_CHANWIDTH40(ht_info->ht_info.ht_param);
 			}
-			ht_info->ht_info.field3 = NON_GREENFIELD_STAS;
-			ht_info->ht_info.basic_mcs_set[0] = 0xff;
+			ht_info->ht_info.operation_mode =
+				cpu_to_le16(NON_GREENFIELD_STAS);
+			ht_info->ht_info.basic_set[0] = 0xff;
 			HEXDUMP("ADHOC_START: HT_INFORMATION IE",
 				(u8 *) ht_info,
 				sizeof(struct mwifiex_ie_types_htinfo));
-- 
1.7.0.2


^ permalink raw reply related

* [PATCH 2/2 V2] b43: N-PHY: update 2056 radio on channel switch on rev3+
From: Rafał Miłecki @ 2010-12-21 22:57 UTC (permalink / raw)
  To: linux-wireless, John W. Linville; +Cc: b43-dev, Rafał Miłecki
In-Reply-To: <1292972268-26327-1-git-send-email-zajec5@gmail.com>

Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
---
V2: break lines to match 80 chars width

John: not a big problem at all :)
---
 drivers/net/wireless/b43/phy_n.c |   95 +++++++++++++++++++++++++++++++++++++-
 1 files changed, 94 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c
index dded231..ab81ed8 100644
--- a/drivers/net/wireless/b43/phy_n.c
+++ b/drivers/net/wireless/b43/phy_n.c
@@ -139,6 +139,99 @@ static void b43_chantab_radio_upload(struct b43_wldev *dev,
 	b43_radio_write(dev, B2055_C2_TX_MXBGTRIM, e->radio_c2_tx_mxbgtrim);
 }
 
+static void b43_chantab_radio_2056_upload(struct b43_wldev *dev,
+				const struct b43_nphy_channeltab_entry_rev3 *e)
+{
+	b43_radio_write(dev, B2056_SYN_PLL_VCOCAL1, e->radio_syn_pll_vcocal1);
+	b43_radio_write(dev, B2056_SYN_PLL_VCOCAL2, e->radio_syn_pll_vcocal2);
+	b43_radio_write(dev, B2056_SYN_PLL_REFDIV, e->radio_syn_pll_refdiv);
+	b43_radio_write(dev, B2056_SYN_PLL_MMD2, e->radio_syn_pll_mmd2);
+	b43_radio_write(dev, B2056_SYN_PLL_MMD1, e->radio_syn_pll_mmd1);
+	b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER1,
+					e->radio_syn_pll_loopfilter1);
+	b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER2,
+					e->radio_syn_pll_loopfilter2);
+	b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER3,
+					e->radio_syn_pll_loopfilter3);
+	b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4,
+					e->radio_syn_pll_loopfilter4);
+	b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER5,
+					e->radio_syn_pll_loopfilter5);
+	b43_radio_write(dev, B2056_SYN_RESERVED_ADDR27,
+					e->radio_syn_reserved_addr27);
+	b43_radio_write(dev, B2056_SYN_RESERVED_ADDR28,
+					e->radio_syn_reserved_addr28);
+	b43_radio_write(dev, B2056_SYN_RESERVED_ADDR29,
+					e->radio_syn_reserved_addr29);
+	b43_radio_write(dev, B2056_SYN_LOGEN_VCOBUF1,
+					e->radio_syn_logen_vcobuf1);
+	b43_radio_write(dev, B2056_SYN_LOGEN_MIXER2, e->radio_syn_logen_mixer2);
+	b43_radio_write(dev, B2056_SYN_LOGEN_BUF3, e->radio_syn_logen_buf3);
+	b43_radio_write(dev, B2056_SYN_LOGEN_BUF4, e->radio_syn_logen_buf4);
+
+	b43_radio_write(dev, B2056_RX0 | B2056_RX_LNAA_TUNE,
+					e->radio_rx0_lnaa_tune);
+	b43_radio_write(dev, B2056_RX0 | B2056_RX_LNAG_TUNE,
+					e->radio_rx0_lnag_tune);
+
+	b43_radio_write(dev, B2056_TX0 | B2056_TX_INTPAA_BOOST_TUNE,
+					e->radio_tx0_intpaa_boost_tune);
+	b43_radio_write(dev, B2056_TX0 | B2056_TX_INTPAG_BOOST_TUNE,
+					e->radio_tx0_intpag_boost_tune);
+	b43_radio_write(dev, B2056_TX0 | B2056_TX_PADA_BOOST_TUNE,
+					e->radio_tx0_pada_boost_tune);
+	b43_radio_write(dev, B2056_TX0 | B2056_TX_PADG_BOOST_TUNE,
+					e->radio_tx0_padg_boost_tune);
+	b43_radio_write(dev, B2056_TX0 | B2056_TX_PGAA_BOOST_TUNE,
+					e->radio_tx0_pgaa_boost_tune);
+	b43_radio_write(dev, B2056_TX0 | B2056_TX_PGAG_BOOST_TUNE,
+					e->radio_tx0_pgag_boost_tune);
+	b43_radio_write(dev, B2056_TX0 | B2056_TX_MIXA_BOOST_TUNE,
+					e->radio_tx0_mixa_boost_tune);
+	b43_radio_write(dev, B2056_TX0 | B2056_TX_MIXG_BOOST_TUNE,
+					e->radio_tx0_mixg_boost_tune);
+
+	b43_radio_write(dev, B2056_RX1 | B2056_RX_LNAA_TUNE,
+					e->radio_rx1_lnaa_tune);
+	b43_radio_write(dev, B2056_RX1 | B2056_RX_LNAG_TUNE,
+					e->radio_rx1_lnag_tune);
+
+	b43_radio_write(dev, B2056_TX1 | B2056_TX_INTPAA_BOOST_TUNE,
+					e->radio_tx1_intpaa_boost_tune);
+	b43_radio_write(dev, B2056_TX1 | B2056_TX_INTPAG_BOOST_TUNE,
+					e->radio_tx1_intpag_boost_tune);
+	b43_radio_write(dev, B2056_TX1 | B2056_TX_PADA_BOOST_TUNE,
+					e->radio_tx1_pada_boost_tune);
+	b43_radio_write(dev, B2056_TX1 | B2056_TX_PADG_BOOST_TUNE,
+					e->radio_tx1_padg_boost_tune);
+	b43_radio_write(dev, B2056_TX1 | B2056_TX_PGAA_BOOST_TUNE,
+					e->radio_tx1_pgaa_boost_tune);
+	b43_radio_write(dev, B2056_TX1 | B2056_TX_PGAG_BOOST_TUNE,
+					e->radio_tx1_pgag_boost_tune);
+	b43_radio_write(dev, B2056_TX1 | B2056_TX_MIXA_BOOST_TUNE,
+					e->radio_tx1_mixa_boost_tune);
+	b43_radio_write(dev, B2056_TX1 | B2056_TX_MIXG_BOOST_TUNE,
+					e->radio_tx1_mixg_boost_tune);
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/Radio/2056Setup */
+static void b43_radio_2056_setup(struct b43_wldev *dev,
+				const struct b43_nphy_channeltab_entry_rev3 *e)
+{
+	B43_WARN_ON(dev->phy.rev < 3);
+
+	b43_chantab_radio_2056_upload(dev, e);
+	/* TODO */
+	udelay(50);
+	/* VCO calibration */
+	b43_radio_write(dev, B2056_SYN_PLL_VCOCAL12, 0x00);
+	b43_radio_write(dev, B2056_TX_INTPAA_PA_MISC, 0x38);
+	b43_radio_write(dev, B2056_TX_INTPAA_PA_MISC, 0x18);
+	b43_radio_write(dev, B2056_TX_INTPAA_PA_MISC, 0x38);
+	b43_radio_write(dev, B2056_TX_INTPAA_PA_MISC, 0x39);
+	udelay(300);
+}
+
 static void b43_chantab_phy_upload(struct b43_wldev *dev,
 				   const struct b43_phy_n_sfo_cfg *e)
 {
@@ -3635,7 +3728,7 @@ static int b43_nphy_set_channel(struct b43_wldev *dev,
 	if (dev->phy.rev >= 3) {
 		tmp = (channel->band == IEEE80211_BAND_5GHZ) ? 4 : 0;
 		b43_radio_maskset(dev, 0x08, 0xFFFB, tmp);
-		/* TODO: PHY Radio2056 Setup (dev, tabent_r3); */
+		b43_radio_2056_setup(dev, tabent_r3);
 		b43_nphy_channel_setup(dev, &(tabent_r3->phy_regs), channel);
 	} else {
 		tmp = (channel->band == IEEE80211_BAND_5GHZ) ? 0x0020 : 0x0050;
-- 
1.6.3.3


^ permalink raw reply related

* Re: [PATCH 2/2] b43: N-PHY: update 2056 radio on channel switch on rev3+
From: John W. Linville @ 2010-12-21 22:32 UTC (permalink / raw)
  To: Rafał Miłecki; +Cc: linux-wireless, b43-dev
In-Reply-To: <1292956819-21166-2-git-send-email-zajec5@gmail.com>

On Tue, Dec 21, 2010 at 07:40:19PM +0100, Rafał Miłecki wrote:
> Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
> ---
> John: I ignored over 80 chars warnings, as this is very simple code
> (write-by-write, line-by-line) and I believe this can improve readibility.

Not if you are looking at it with line breaks...

Do you really object to breaking a function call at its third
parameter?

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

^ permalink raw reply

* Re: [PATCH 2/4] b43: N-PHY: implement radio 2056 init steps
From: Rafał Miłecki @ 2010-12-21 22:33 UTC (permalink / raw)
  To: Michael Büsch; +Cc: linux-wireless, b43-dev
In-Reply-To: <1292970354.27806.10.camel@maggie>

W dniu 21 grudnia 2010 23:25 użytkownik Michael Büsch <mb@bu3sch.de> napisał:
> On Tue, 2010-12-21 at 13:20 +0100, Rafał Miłecki wrote:
>> W dniu 21 grudnia 2010 12:34 użytkownik Michael Büsch <mb@bu3sch.de> napisał:
>> > On Tue, 2010-12-21 at 11:50 +0100, Rafał Miłecki wrote:
>> >> +static void b43_radio_init2056_post(struct b43_wldev *dev)
>> >> +{
>> >> +     b43_radio_set(dev, B2056_SYN_COM_CTRL, 0xB);
>> >> +     b43_radio_set(dev, B2056_SYN_COM_PU, 0x2);
>> >> +     b43_radio_set(dev, B2056_SYN_COM_RESET, 0x2);
>> >> +     mdelay(1);
>> >
>> > Please don't use mdelay() ever. The driver is fully preemptible.
>> > Use msleep() instead.
>>
>> So, using "msleep" allows kernel to switch context, while using
>> "mdelay" does not?
>
> Yeah well. msleep() does switch context (at least to the idle task,
> if there's nothing else to do). Whereas mdelay() busy-waits in a tight
> loop. So on a non-preemptible kernel you will lock up the CPU (and if
> there's only one CPU, the whole system) for a millisecond by using
> mdelay(). On a preemptible kernel it's somewhat mitigated, but I think
> explicit sleep is still better there. Also for advanced speedstep and
> powersaving considerations.
> In the past we did significant efforts to make the whole driver (Except
> the very tiny hardirq handler) preemptible. This improved things a
> lot. In the old days, bringing the interface up came along with
> about one-second system lockup (on UP, nonpreempt) and the periodic work
> frequently caused things like audio to break. Today that's not an issue
> anymore due to removal of huge mdelay() calls and preemptible locking.
> Always remember that a millisecond really is a _huge_ amount of time
> on a modern CPU.
>
>> If so, should be convert our longer udelay calls (like 300us) to usleep?
>
> Well, in my opinion, yes. I'm pretty sure opinions on that will diverge
> from developer to developer, but I think at least in stuff like
> periodically happening tasks we should avoid those delays and
> use msleep(1) instead.

Thank you.

-- 
Rafał

^ permalink raw reply

* Re: [PATCH 2/4] b43: N-PHY: implement radio 2056 init steps
From: Michael Büsch @ 2010-12-21 22:25 UTC (permalink / raw)
  To: Rafał Miłecki; +Cc: linux-wireless, b43-dev
In-Reply-To: <AANLkTi=--XSasFtDpiq-uXDrMWjQzrK-cnGZVyqFsSif@mail.gmail.com>

On Tue, 2010-12-21 at 13:20 +0100, Rafał Miłecki wrote: 
> W dniu 21 grudnia 2010 12:34 użytkownik Michael Büsch <mb@bu3sch.de> napisał:
> > On Tue, 2010-12-21 at 11:50 +0100, Rafał Miłecki wrote:
> >> +static void b43_radio_init2056_post(struct b43_wldev *dev)
> >> +{
> >> +     b43_radio_set(dev, B2056_SYN_COM_CTRL, 0xB);
> >> +     b43_radio_set(dev, B2056_SYN_COM_PU, 0x2);
> >> +     b43_radio_set(dev, B2056_SYN_COM_RESET, 0x2);
> >> +     mdelay(1);
> >
> > Please don't use mdelay() ever. The driver is fully preemptible.
> > Use msleep() instead.
> 
> So, using "msleep" allows kernel to switch context, while using
> "mdelay" does not?

Yeah well. msleep() does switch context (at least to the idle task,
if there's nothing else to do). Whereas mdelay() busy-waits in a tight
loop. So on a non-preemptible kernel you will lock up the CPU (and if
there's only one CPU, the whole system) for a millisecond by using
mdelay(). On a preemptible kernel it's somewhat mitigated, but I think
explicit sleep is still better there. Also for advanced speedstep and
powersaving considerations.
In the past we did significant efforts to make the whole driver (Except
the very tiny hardirq handler) preemptible. This improved things a
lot. In the old days, bringing the interface up came along with 
about one-second system lockup (on UP, nonpreempt) and the periodic work
frequently caused things like audio to break. Today that's not an issue
anymore due to removal of huge mdelay() calls and preemptible locking.
Always remember that a millisecond really is a _huge_ amount of time
on a modern CPU.

> If so, should be convert our longer udelay calls (like 300us) to usleep?

Well, in my opinion, yes. I'm pretty sure opinions on that will diverge
from developer to developer, but I think at least in stuff like
periodically happening tasks we should avoid those delays and
use msleep(1) instead.

-- 
Greetings Michael.


^ permalink raw reply

* Re: [linux-pm] subtle pm_runtime_put_sync race and sdio functions
From: Kevin Hilman @ 2010-12-21 22:23 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Ohad Ben-Cohen, Alan Stern, linux-pm, Johannes Berg,
	linux-wireless, linux-mmc, Ido Yariv
In-Reply-To: <201012191122.09581.rjw@sisk.pl>

"Rafael J. Wysocki" <rjw@sisk.pl> writes:

> On Saturday, December 18, 2010, Rafael J. Wysocki wrote:
>> On Saturday, December 18, 2010, Ohad Ben-Cohen wrote:
>> > On Sat, Dec 18, 2010 at 5:07 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
>> > > On Saturday, December 18, 2010, Ohad Ben-Cohen wrote:
>> > >> On Sat, Dec 11, 2010 at 4:50 PM, Alan Stern <stern@rowland.harvard.edu> wrote:
>> > >> >> Think of a device which you have no way to reset other than powering
>> > >> >> it down and up again.
>> > >> >>
>> > >> >> If that device is managed by runtime PM, the only way to do that is by
>> > >> >> using put_sync() followed by a get_sync(). Sure, if someone else
>> > >> >> increased the usage_count of that device this won't work, but then of
>> > >> >> course it means that the driver is not using runtime PM correctly.
>> > >> >
>> > >> > Not so.  Even if a driver uses runtime PM correctly, there will still
>> > >> > be times when someone else has increased the usage_count.  This happens
>> > >> > during probing and during system resume, for example.
>> > >>
>> > >> I'm aware of these two examples; normally we're good with them since
>> > >> during probing we're not toggling the power, and during suspend/resume
>> > >> the SDIO core is responsible for manipulating the power (and it does
>> > >> so directly). Are there (or do you think there will be) additional
>> > >> examples where this can happen ?
>> > >>
>> > >> But this leads me to a real problem which we have encountered.
>> > >>
>> > >> During system suspend, our driver is asked (by mac80211's suspend
>> > >> handler) to power off its device. When this happens, the driver has no
>> > >> idea that the system is suspending - regular driver code (responsible
>> > >> to remove the wlan interface and stop the device) is being called.
>> > >
>> > > That's where the problem is.  If there's a difference, from the driver's
>> > > point of view, between suspend and some other operation, there should be a
>> > > way to tell the driver what case it actually is dealing with.
>> > 
>> > Yes, the problem will be solved if the driver would bypass the runtime
>> > PM framework on system suspend. mac80211 obviously has this
>> > information, and technically it's very easy to let the driver know
>> > about it.
>> > 
>> > But the difference between suspend and normal operation is really
>> > artificial: in both cases mac80211 just asks the driver to power its
>> > device down, and the end result is exactly the same (a GPIO line of
>> > the device is de-asserted in our case). The difference between these
>> > two scenarios
>> > exist only because runtime PM is effectively disabled during system
>> > suspend, and therefore the driver has to look for an alternative way
>> > to power down the device.
>> 
>> That's not correct, sorry.
>> 
>> There is a bug and the bug is that you use the runtime PM to power down
>> the device in every situation, although you obviously shouldn't do that
>> (e.g. because it may be disabled by user space or it _is_ disabled by
>> the PM core during system suspend).
>> 
>> > > BTW, what would you do in that case if the runtime PM of the device were
>> > > disabled by user space by writing "on" to the device's
>> > > /sys/devices/.../power/control file?
>> > 
>> > That's a good point.
>> > 
>> > Blocking runtime PM for this device is fatal since this particular
>> > device has functionality tied up with its power control (no other way
>> > to reset it).
>> > 
>> > It might call for a device-specific dev_pm_info bit flag to prohibit this...
>> 
>> No way.
>
> That said, I think we may do something different that perhaps will make your
> life somewhat easier.
>
> Namely, if your driver doesn't implement any system suspend callbacks
> (i.e. ->suspend(), ->resume(), ->freeze(), ->thaw() etc.) and it doesn't
> want the analogous subsystem callbacks to be executed for the device, it will
> make sense to flag the device as "runtime only", or something like this,
> which make the PM core skip the device in dpm_suspend() etc.
>
> In that case, if a device if flagged as "runtime only", we can avoid
> calling pm_runtime_get_noirq() for it in dpm_prepare() and, analogously,
> calling pm_runtime_put_sync() for it in dpm_complete().  However, we will have
> to fail system suspend (or hibernation) if a "runtime only" device has the
> power.runtime_auto flag unset.
>
> So, I think we can add a "runtime only" flag working as described above.
> I guess it will also help in the case I've been discussing with Kevin for some
> time (i2c device using runtime PM used by an RTC in a semi-transparent
> fashion).

[sorry for being late to the discussion]

Something like thi would certainly work for the case we've discussed at
LPC and some other similar ones we have on OMAP where we have "runtime
only" drivers.

That being said, another thing we discussed briefly at LPC was wondering
about reason(s) behind the DPM core locking out runtime PM transitions
in the first place.

Currently runtime PM transitions are blocked in dpm_prepare() and only
allowed again in dpm_complete().  How about locking out runtime PM
transitions only until the DPM suspend operation is complete.  IOW,
rather than waiting for dpm_complete() to re-allow runtime PM
transitions, what about allowing them after dpm_suspend()?  I haven't
actually tested this yet, since I'm busy with getting OMAP PM stuff
ready for the merge window, so it's just and idea so far.  Of course
similar will be needed to block runtime PM transitions during
dpm_resume().  

Kevin

^ permalink raw reply

* Re: [linux-pm] subtle pm_runtime_put_sync race and sdio functions
From: Rafael J. Wysocki @ 2010-12-21 21:31 UTC (permalink / raw)
  To: Alan Stern
  Cc: Ohad Ben-Cohen, linux-pm, Johannes Berg, linux-wireless,
	linux-mmc, Ido Yariv, Kevin Hilman
In-Reply-To: <Pine.LNX.4.44L0.1012201946330.19558-100000@netrider.rowland.org>

On Tuesday, December 21, 2010, Alan Stern wrote:
> On Mon, 20 Dec 2010, Rafael J. Wysocki wrote:
> 
> > > > In that case, if a device if flagged as "runtime only", we can avoid
> > > > calling pm_runtime_get_noirq() for it in dpm_prepare() and, analogously,
> > > > calling pm_runtime_put_sync() for it in dpm_complete().  However, we will have
> > > > to fail system suspend (or hibernation) if a "runtime only" device has the
> > > > power.runtime_auto flag unset.
> > > 
> > > Or more generally, if pm_runtime_suspended() doesn't return 'true' for 
> > > the device.
> > 
> > That's not necessary, because the device may be suspended using
> > pm_runtime_suspend() later than we check pm_runtime_suspended().
> 
> What if the device has a child in the RPM_ACTIVE state?  Then 
> pm_runtime_suspend() won't do anything, even if the child really is 
> dpm-suspended.

Well, in fact I was thinking of leaf devices.  Following all of the children
for non-leaf devices would pretty much nullify the whole possible gain.

> > I'd use the "runtime only" (or perhaps better "no_dpm") flag as a declaration
> > (if set) that the device is going to be suspended with the help of "runtime"
> > callbacks and the driver takes the responsibility for getting things right.
> 
> I'm still not sure about this; the design isn't clear.  Are these
> runtime callbacks going to come from the PM core or from the driver?  
> If from the driver, how will the driver know when to issue them?  What
> about coordinating async suspends (the device must be suspended after
> its children and before its parent)?

It basically goes like this.  There's device A that is only resumed when it's
needed to carry out an operation and is suspended immediately after that.
There's another device B that needs A to do something during its suspend.
So, when the suspend of B is started, A is woken up, does its work and is
suspended again (using pm_runtime_suspend()).  Then B is suspended.

We currently require that ->suspend() and ->resume() callbacks be defined
for A (presumably pointing to the same code as its runtime callbacks) so that
things work correctly, but perhaps we can just relax this requirement a bit?
I'm not 100% sure that's a good idea, just considering it.

Rafael

^ permalink raw reply

* [PATCH 7/7] rndis_wlan: add support for set_power_mgmt
From: Jussi Kivilinna @ 2010-12-21 20:44 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless
In-Reply-To: <20101221204405.12250.35410.stgit@fate.lan>

Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
---
 drivers/net/wireless/rndis_wlan.c |   48 +++++++++++++++++++++++++++++++++++++
 1 files changed, 48 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index 0cd971a..848cc2c 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -129,6 +129,7 @@ MODULE_PARM_DESC(workaround_interval,
 #define OID_802_11_RTS_THRESHOLD		cpu_to_le32(0x0d01020a)
 #define OID_802_11_SUPPORTED_RATES		cpu_to_le32(0x0d01020e)
 #define OID_802_11_CONFIGURATION		cpu_to_le32(0x0d010211)
+#define OID_802_11_POWER_MODE			cpu_to_le32(0x0d010216)
 #define OID_802_11_BSSID_LIST			cpu_to_le32(0x0d010217)
 
 
@@ -239,6 +240,12 @@ enum ndis_80211_addwep_bits {
 	NDIS_80211_ADDWEP_TRANSMIT_KEY = cpu_to_le32(1 << 31)
 };
 
+enum ndis_80211_power_mode {
+	NDIS_80211_POWER_MODE_CAM,
+	NDIS_80211_POWER_MODE_MAX_PSP,
+	NDIS_80211_POWER_MODE_FAST_PSP,
+};
+
 struct ndis_80211_auth_request {
 	__le32 length;
 	u8 bssid[6];
@@ -503,6 +510,7 @@ struct rndis_wlan_private {
 
 	/* hardware state */
 	bool radio_on;
+	int power_mode;
 	int infra_mode;
 	bool connected;
 	u8 bssid[ETH_ALEN];
@@ -572,6 +580,9 @@ static int rndis_del_pmksa(struct wiphy *wiphy, struct net_device *netdev,
 
 static int rndis_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev);
 
+static int rndis_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
+				bool enabled, int timeout);
+
 static int rndis_set_cqm_rssi_config(struct wiphy *wiphy,
 					struct net_device *dev,
 					s32 rssi_thold, u32 rssi_hyst);
@@ -595,6 +606,7 @@ static const struct cfg80211_ops rndis_config_ops = {
 	.set_pmksa = rndis_set_pmksa,
 	.del_pmksa = rndis_del_pmksa,
 	.flush_pmksa = rndis_flush_pmksa,
+	.set_power_mgmt = rndis_set_power_mgmt,
 	.set_cqm_rssi_config = rndis_set_cqm_rssi_config,
 };
 
@@ -694,6 +706,7 @@ static const char *oid_to_string(__le32 oid)
 		OID_STR(OID_802_11_ADD_KEY);
 		OID_STR(OID_802_11_REMOVE_KEY);
 		OID_STR(OID_802_11_ASSOCIATION_INFORMATION);
+		OID_STR(OID_802_11_CAPABILITY);
 		OID_STR(OID_802_11_PMKID);
 		OID_STR(OID_802_11_NETWORK_TYPES_SUPPORTED);
 		OID_STR(OID_802_11_NETWORK_TYPE_IN_USE);
@@ -704,6 +717,7 @@ static const char *oid_to_string(__le32 oid)
 		OID_STR(OID_802_11_RTS_THRESHOLD);
 		OID_STR(OID_802_11_SUPPORTED_RATES);
 		OID_STR(OID_802_11_CONFIGURATION);
+		OID_STR(OID_802_11_POWER_MODE);
 		OID_STR(OID_802_11_BSSID_LIST);
 #undef OID_STR
 	}
@@ -2574,6 +2588,38 @@ static int rndis_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev)
 	return rndis_set_oid(usbdev, OID_802_11_PMKID, &pmkid, sizeof(pmkid));
 }
 
+static int rndis_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
+				bool enabled, int timeout)
+{
+	struct rndis_wlan_private *priv = wiphy_priv(wiphy);
+	struct usbnet *usbdev = priv->usbdev;
+	int power_mode;
+	__le32 mode;
+	int ret;
+
+	netdev_dbg(usbdev->net, "%s(): %s, %d\n", __func__,
+				enabled ? "enabled" : "disabled",
+				timeout);
+
+	if (enabled)
+		power_mode = NDIS_80211_POWER_MODE_FAST_PSP;
+	else
+		power_mode = NDIS_80211_POWER_MODE_CAM;
+
+	if (power_mode == priv->power_mode)
+		return 0;
+
+	priv->power_mode = power_mode;
+
+	mode = cpu_to_le32(power_mode);
+	ret = rndis_set_oid(usbdev, OID_802_11_POWER_MODE, &mode, sizeof(mode));
+
+	netdev_dbg(usbdev->net, "%s(): OID_802_11_POWER_MODE -> %d\n",
+				__func__, ret);
+
+	return ret;
+}
+
 static int rndis_set_cqm_rssi_config(struct wiphy *wiphy,
 					struct net_device *dev,
 					s32 rssi_thold, u32 rssi_hyst)
@@ -3441,6 +3487,8 @@ static int rndis_wlan_bind(struct usbnet *usbdev, struct usb_interface *intf)
 
 	set_default_iw_params(usbdev);
 
+	priv->power_mode = -1;
+
 	/* set default rts/frag */
 	rndis_set_wiphy_params(wiphy,
 			WIPHY_PARAM_FRAG_THRESHOLD | WIPHY_PARAM_RTS_THRESHOLD);


^ permalink raw reply related

* [PATCH 5/7] rndis_wlan: remove unused variable from priv structure
From: Jussi Kivilinna @ 2010-12-21 20:44 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless
In-Reply-To: <20101221204405.12250.35410.stgit@fate.lan>

Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
---
 drivers/net/wireless/rndis_wlan.c |    2 --
 1 files changed, 0 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index d0992fc..aa21d86 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -503,7 +503,6 @@ struct rndis_wlan_private {
 	int infra_mode;
 	bool connected;
 	u8 bssid[ETH_ALEN];
-	struct ndis_80211_ssid essid;
 	__le32 current_command_oid;
 
 	/* encryption stuff */
@@ -1026,7 +1025,6 @@ static int set_essid(struct usbnet *usbdev, struct ndis_80211_ssid *ssid)
 		return ret;
 	}
 	if (ret == 0) {
-		memcpy(&priv->essid, ssid, sizeof(priv->essid));
 		priv->radio_on = true;
 		netdev_dbg(usbdev->net, "%s(): radio_on = true\n", __func__);
 	}


^ permalink raw reply related

* [PATCH 6/7] rndis_wlan: add support for set_cqm_rssi_config
From: Jussi Kivilinna @ 2010-12-21 20:44 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless
In-Reply-To: <20101221204405.12250.35410.stgit@fate.lan>

Device poller already reads current RSSI, so add support for
set_cqm_rssi_config there.

Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
---
 drivers/net/wireless/rndis_wlan.c |   51 ++++++++++++++++++++++++++++++++++++-
 1 files changed, 50 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index aa21d86..0cd971a 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -478,6 +478,9 @@ struct rndis_wlan_private {
 	struct mutex command_lock;
 	unsigned long work_pending;
 	int last_qual;
+	s32 cqm_rssi_thold;
+	u32 cqm_rssi_hyst;
+	int last_cqm_event_rssi;
 
 	struct ieee80211_supported_band band;
 	struct ieee80211_channel channels[ARRAY_SIZE(rndis_channels)];
@@ -569,6 +572,10 @@ static int rndis_del_pmksa(struct wiphy *wiphy, struct net_device *netdev,
 
 static int rndis_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev);
 
+static int rndis_set_cqm_rssi_config(struct wiphy *wiphy,
+					struct net_device *dev,
+					s32 rssi_thold, u32 rssi_hyst);
+
 static const struct cfg80211_ops rndis_config_ops = {
 	.change_virtual_intf = rndis_change_virtual_intf,
 	.scan = rndis_scan,
@@ -588,6 +595,7 @@ static const struct cfg80211_ops rndis_config_ops = {
 	.set_pmksa = rndis_set_pmksa,
 	.del_pmksa = rndis_del_pmksa,
 	.flush_pmksa = rndis_flush_pmksa,
+	.set_cqm_rssi_config = rndis_set_cqm_rssi_config,
 };
 
 static void *rndis_wiphy_privid = &rndis_wiphy_privid;
@@ -2566,6 +2574,19 @@ static int rndis_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev)
 	return rndis_set_oid(usbdev, OID_802_11_PMKID, &pmkid, sizeof(pmkid));
 }
 
+static int rndis_set_cqm_rssi_config(struct wiphy *wiphy,
+					struct net_device *dev,
+					s32 rssi_thold, u32 rssi_hyst)
+{
+	struct rndis_wlan_private *priv = wiphy_priv(wiphy);
+
+	priv->cqm_rssi_thold = rssi_thold;
+	priv->cqm_rssi_hyst = rssi_hyst;
+	priv->last_cqm_event_rssi = 0;
+
+	return 0;
+}
+
 static void rndis_wlan_craft_connected_bss(struct usbnet *usbdev, u8 *bssid,
 					   struct ndis_80211_assoc_info *info)
 {
@@ -3095,6 +3116,32 @@ static int rndis_wlan_get_caps(struct usbnet *usbdev, struct wiphy *wiphy)
 	return retval;
 }
 
+static void rndis_do_cqm(struct usbnet *usbdev, s32 rssi)
+{
+	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
+	enum nl80211_cqm_rssi_threshold_event event;
+	int thold, hyst, last_event;
+
+	if (priv->cqm_rssi_thold >= 0 || rssi >= 0)
+		return;
+	if (priv->infra_mode != NDIS_80211_INFRA_INFRA)
+		return;
+
+	last_event = priv->last_cqm_event_rssi;
+	thold = priv->cqm_rssi_thold;
+	hyst = priv->cqm_rssi_hyst;
+
+	if (rssi < thold && (last_event == 0 || rssi < last_event - hyst))
+		event = NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW;
+	else if (rssi > thold && (last_event == 0 || rssi > last_event + hyst))
+		event = NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH;
+	else
+		return;
+
+	priv->last_cqm_event_rssi = rssi;
+	cfg80211_cqm_rssi_notify(usbdev->net, event, GFP_KERNEL);
+}
+
 #define DEVICE_POLLER_JIFFIES (HZ)
 static void rndis_device_poller(struct work_struct *work)
 {
@@ -3129,8 +3176,10 @@ static void rndis_device_poller(struct work_struct *work)
 
 	len = sizeof(rssi);
 	ret = rndis_query_oid(usbdev, OID_802_11_RSSI, &rssi, &len);
-	if (ret == 0)
+	if (ret == 0) {
 		priv->last_qual = level_to_qual(le32_to_cpu(rssi));
+		rndis_do_cqm(usbdev, le32_to_cpu(rssi));
+	}
 
 	netdev_dbg(usbdev->net, "dev-poller: OID_802_11_RSSI -> %d, rssi:%d, qual: %d\n",
 		   ret, le32_to_cpu(rssi), level_to_qual(le32_to_cpu(rssi)));


^ permalink raw reply related

* [PATCH 4/7] rndis_wlan: constify rndis_config_ops
From: Jussi Kivilinna @ 2010-12-21 20:44 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless
In-Reply-To: <20101221204405.12250.35410.stgit@fate.lan>

Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
---
 drivers/net/wireless/rndis_wlan.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index 42e19e8..d0992fc 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -570,7 +570,7 @@ static int rndis_del_pmksa(struct wiphy *wiphy, struct net_device *netdev,
 
 static int rndis_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev);
 
-static struct cfg80211_ops rndis_config_ops = {
+static const struct cfg80211_ops rndis_config_ops = {
 	.change_virtual_intf = rndis_change_virtual_intf,
 	.scan = rndis_scan,
 	.set_wiphy_params = rndis_set_wiphy_params,


^ permalink raw reply related

* [PATCH 3/7] rndis_wlan: turn radio off before interface is bring up
From: Jussi Kivilinna @ 2010-12-21 20:44 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless
In-Reply-To: <20101221204405.12250.35410.stgit@fate.lan>

Radio should be off when interface is down.

Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
---
 drivers/net/wireless/rndis_wlan.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index 9e6105c..42e19e8 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -3398,9 +3398,9 @@ static int rndis_wlan_bind(struct usbnet *usbdev, struct usb_interface *intf)
 	rndis_set_wiphy_params(wiphy,
 			WIPHY_PARAM_FRAG_THRESHOLD | WIPHY_PARAM_RTS_THRESHOLD);
 
-	/* turn radio on */
-	priv->radio_on = true;
-	disassociate(usbdev, true);
+	/* turn radio off on init */
+	priv->radio_on = false;
+	disassociate(usbdev, false);
 	netif_carrier_off(usbdev->net);
 
 	return 0;


^ permalink raw reply related

* [PATCH 2/7] rndis_wlan: do not set default_key if not WEP key
From: Jussi Kivilinna @ 2010-12-21 20:44 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless
In-Reply-To: <20101221204405.12250.35410.stgit@fate.lan>

rndis_set_default_key did call add_wep_key to set default key on device, even
if key is WPA. This caused rndis_wlan not work with wpa_supplicant in nl80211
mode (causing disconnect from AP).

Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
---
 drivers/net/wireless/rndis_wlan.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index de4c050..9e6105c 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -2435,6 +2435,9 @@ static int rndis_set_default_key(struct wiphy *wiphy, struct net_device *netdev,
 
 	priv->encr_tx_key_index = key_index;
 
+	if (is_wpa_key(priv, key_index))
+		return 0;
+
 	key = priv->encr_keys[key_index];
 
 	return add_wep_key(usbdev, key.material, key.len, key_index);


^ permalink raw reply related

* [PATCH 1/7] [v2] rndis_wlan: scanning, workaround device returning incorrect bssid-list item count.
From: Jussi Kivilinna @ 2010-12-21 20:44 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless

Sometimes device returns wrong number of items in bssid-list. Appears that
some specific beacons trigger this problem and leads to very poor scanning
results. Workaround by ignoring num_items received from device and walkthrough
full bssid-list buffer.

v2: Fix buffer range checks and reading next item length. Old code read
    behind buffer on last item but didn't use those values as 'count' would
    also reach zero. Also fix resizing of buffer if device has larger buffer,
    old code assumed that BSSID-list OID would return same buffer size
    when it really can return yet another new larger length.

Tested-by: Luís Picciochi <Pitxyoki@gmail.com>
Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
---
 drivers/net/wireless/rndis_wlan.c |   80 +++++++++++++++++++++++++++++--------
 1 files changed, 62 insertions(+), 18 deletions(-)

diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index 4a4f005..de4c050 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -1967,8 +1967,8 @@ static struct cfg80211_bss *rndis_bss_info_update(struct usbnet *usbdev,
 	int ie_len, bssid_len;
 	u8 *ie;
 
-	netdev_dbg(usbdev->net, " found bssid: '%.32s' [%pM]\n",
-		   bssid->ssid.essid, bssid->mac);
+	netdev_dbg(usbdev->net, " found bssid: '%.32s' [%pM], len: %d\n",
+		   bssid->ssid.essid, bssid->mac, le32_to_cpu(bssid->length));
 
 	/* parse bssid structure */
 	bssid_len = le32_to_cpu(bssid->length);
@@ -2002,54 +2002,98 @@ static struct cfg80211_bss *rndis_bss_info_update(struct usbnet *usbdev,
 		GFP_KERNEL);
 }
 
+static struct ndis_80211_bssid_ex *next_bssid_list_item(
+					struct ndis_80211_bssid_ex *bssid,
+					int *bssid_len, void *buf, int len)
+{
+	void *buf_end, *bssid_end;
+
+	buf_end = (char *)buf + len;
+	bssid_end = (char *)bssid + *bssid_len;
+
+	if ((int)(buf_end - bssid_end) < sizeof(bssid->length)) {
+		*bssid_len = 0;
+		return NULL;
+	} else {
+		bssid = (void *)((char *)bssid + *bssid_len);
+		*bssid_len = le32_to_cpu(bssid->length);
+		return bssid;
+	}
+}
+
+static bool check_bssid_list_item(struct ndis_80211_bssid_ex *bssid,
+				  int bssid_len, void *buf, int len)
+{
+	void *buf_end, *bssid_end;
+
+	if (!bssid || bssid_len <= 0 || bssid_len > len)
+		return false;
+
+	buf_end = (char *)buf + len;
+	bssid_end = (char *)bssid + bssid_len;
+
+	return (int)(buf_end - bssid_end) >= 0 && (int)(bssid_end - buf) >= 0;
+}
+
 static int rndis_check_bssid_list(struct usbnet *usbdev, u8 *match_bssid,
 					bool *matched)
 {
 	void *buf = NULL;
 	struct ndis_80211_bssid_list_ex *bssid_list;
 	struct ndis_80211_bssid_ex *bssid;
-	int ret = -EINVAL, len, count, bssid_len;
-	bool resized = false;
+	int ret = -EINVAL, len, count, bssid_len, real_count, new_len;
 
-	netdev_dbg(usbdev->net, "check_bssid_list\n");
+	netdev_dbg(usbdev->net, "%s()\n", __func__);
 
 	len = CONTROL_BUFFER_SIZE;
 resize_buf:
-	buf = kmalloc(len, GFP_KERNEL);
+	buf = kzalloc(len, GFP_KERNEL);
 	if (!buf) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
-	ret = rndis_query_oid(usbdev, OID_802_11_BSSID_LIST, buf, &len);
-	if (ret != 0)
+	/* BSSID-list might have got bigger last time we checked, keep
+	 * resizing until it won't get any bigger.
+	 */
+	new_len = len;
+	ret = rndis_query_oid(usbdev, OID_802_11_BSSID_LIST, buf, &new_len);
+	if (ret != 0 || new_len < sizeof(struct ndis_80211_bssid_list_ex))
 		goto out;
 
-	if (!resized && len > CONTROL_BUFFER_SIZE) {
-		resized = true;
+	if (new_len > len) {
+		len = new_len;
 		kfree(buf);
 		goto resize_buf;
 	}
 
+	len = new_len;
+
 	bssid_list = buf;
-	bssid = bssid_list->bssid;
-	bssid_len = le32_to_cpu(bssid->length);
 	count = le32_to_cpu(bssid_list->num_items);
-	netdev_dbg(usbdev->net, "check_bssid_list: %d BSSIDs found (buflen: %d)\n",
-		   count, len);
+	real_count = 0;
+	netdev_dbg(usbdev->net, "%s(): buflen: %d\n", __func__, len);
+
+	bssid_len = 0;
+	bssid = next_bssid_list_item(bssid_list->bssid, &bssid_len, buf, len);
 
-	while (count && ((void *)bssid + bssid_len) <= (buf + len)) {
+	/* Device returns incorrect 'num_items'. Workaround by ignoring the
+	 * received 'num_items' and walking through full bssid buffer instead.
+	 */
+	while (check_bssid_list_item(bssid, bssid_len, buf, len)) {
 		if (rndis_bss_info_update(usbdev, bssid) && match_bssid &&
 		    matched) {
 			if (compare_ether_addr(bssid->mac, match_bssid))
 				*matched = true;
 		}
 
-		bssid = (void *)bssid + bssid_len;
-		bssid_len = le32_to_cpu(bssid->length);
-		count--;
+		real_count++;
+		bssid = next_bssid_list_item(bssid, &bssid_len, buf, len);
 	}
 
+	netdev_dbg(usbdev->net, "%s(): num_items from device: %d, really found:"
+				" %d\n", __func__, count, real_count);
+
 out:
 	kfree(buf);
 	return ret;


^ permalink raw reply related

* [PATCH] b43: N-PHY: enable support for PHYs rev 3 and higher
From: Rafał Miłecki @ 2010-12-21 20:29 UTC (permalink / raw)
  To: linux-wireless, John W. Linville; +Cc: b43-dev, Rafał Miłecki

Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
---
John: can we still make it for 2.6.38 merge? It was tested with 14e4:432b,
support seems to be on the same level as for PHYs 1 and 2.
---
 drivers/net/wireless/b43/main.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 5fb0bc6..22bc9f1 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -4056,7 +4056,7 @@ static int b43_phy_versioning(struct b43_wldev *dev)
 		break;
 #ifdef CONFIG_B43_PHY_N
 	case B43_PHYTYPE_N:
-		if (phy_rev > 2)
+		if (phy_rev > 9)
 			unsupported = 1;
 		break;
 #endif
-- 
1.6.3.3


^ permalink raw reply related

* compat-wireless for 2.6.37-rc6
From: Luis R. Rodriguez @ 2010-12-21 20:21 UTC (permalink / raw)
  To: linux-wireless; +Cc: linux-bluetooth, linux-kernel, Greg KH

Two tarballs are out based on 2.6.37-rc6, the vanilla release and the
release with pending-stable patches and a few cherry picked patches.

http://wireless.kernel.org/en/users/Download/stable
http://www.orbit-lab.org/kernel/compat-wireless-2.6-stable/v2.6.37/compat-wireless-2.6.37-rc6-3.tar.bz2
http://www.orbit-lab.org/kernel/compat-wireless-2.6-stable/v2.6.37/compat-wireless-2.6.37-rc6-3-sn.tar.bz2

Build tested and loaded with ath9k on AR9280 against 2.6.31.

The list of pending stable patches:

mcgrof@tux ~/tmp/compat-wireless-2.6.37-rc6-3 $ ls -1 pending-stable
0001-cfg80211-pass-the-reg-hint-initiator-to-helpers.patch
0002-cfg80211-fix-allowing-country-IEs-for-WIPHY_FLAG_STR.patch
0003-cfg80211-fix-disabling-channels-based-on-hints.patch
0008-ath9k_hw-Fix-XPABIAS-level-configuration-for-AR9003.patch
0009-ath9k-Fix-bug-in-delimiter-padding-computation.patch
0010-p54usb-add-5-more-USBIDs.patch
0012-ath9k-fix-assumptions-for-idle-calls-on-suspend-resu.patch
0013-ath-Missed-to-clear-key4-of-micentry.patch
0014-p54usb-New-USB-ID-for-Gemtek-WUBI-100GW.patch

The list of pending-stable patches which required a backport:

mcgrof@tux ~/tmp/compat-wireless-2.6.37-rc6-3 $ ls -1 pending-stable/backports/
0001-ath9k-simplify-hw-reset-locking.patch
0002-ath9k-move-the-PCU-lock-to-the-sc-structure.patch
0003-ath9k-content-DMA-start-stop-through-the-PCU-lock.patch
0004-ath9k-Fix-power-save-count-imbalance-on-ath_radio_en.patch
0005-ath9k_hw-fix-potential-spurious-tx-error-bit-interpr.patch

There are only two cherry picked patches now as the ath3k/btusb patch
went upstream:

mcgrof@tux ~/tmp/compat-wireless-2.6.37-rc6-3 $ ls -1 linux-next-cherry-picks/
01-ath9k-OTP.patch
04-ath9k_hw-fix-A-MPDU-key-search-issues-on-AR9003.patch

  Luis

^ permalink raw reply

* Compat-wireless release for 2010-12-21 is baked
From: Compat-wireless cronjob account @ 2010-12-21 20:14 UTC (permalink / raw)
  To: linux-wireless

>From git://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/compat-wireless-2.6
   af01533..52e96b5  linux-2.6.37.y -> origin/linux-2.6.37.y
 * [new tag]         compat-wireless-v2.6.37-rc6-1 -> compat-wireless-v2.6.37-rc6-1
fatal: The remote end hung up unexpectedly
fatal: protocol error: bad pack header

compat-wireless code metrics

    777014 - Total upstream lines of code being pulled
      2223 - backport code changes
      1946 - backport code additions
       277 - backport code deletions
      6669 - backport from compat module
      8892 - total backport code
    1.1444 - % of code consists of backport work
      1532 - Crap changes not yet posted
      1489 - Crap additions not yet posted
        43 - Crap deletions not yet posted
    0.1972 - % of crap code

Base tree: linux-next.git
Base tree version: next-20101220
compat-wireless release: compat-wireless-2010-12-20-pc

^ permalink raw reply

* Re: vendor IEs?
From: Johannes Berg @ 2010-12-21 19:45 UTC (permalink / raw)
  To: Daniel Halperin; +Cc: linux-wireless
In-Reply-To: <AANLkTimGci-yzhbQwJSjFPGMq0vdQV=4iARb8DUZZZf_@mail.gmail.com>

On Tue, 2010-12-21 at 11:38 -0800, Daniel Halperin wrote:
> On Tue, Dec 21, 2010 at 2:41 AM, Johannes Berg
> <johannes@sipsolutions.net> wrote:
> > On Sun, 2010-12-19 at 16:53 -0800, Daniel Halperin wrote:
> >> Is there a compiled list of vendor-specific IEs out there?  Googling
> >> didn't offer much help.
> >
> > I'm not aware of any list, nor can there really be one since everybody
> > who has an OUI is free to define their own IEs.
> >
> > That said, some of them are of course mostly standardised, like the WFA
> > ones for WPA, WSC/WPS and P2P for instance. I don't think there's a even
> > a comprehensive list of WFA ones though other than in what you get by
> > combining all those standards.
> 
> On that note, if you wanted to define a custom IE what would you do?

I'd work with a vendor to get to use their OUI :-)

> How did the WFA get an OUI?  Is there a Linux OUI?

http://standards.ieee.org/develop/regauth/oui/index.html

I'm not aware of a Linux OUI.

johannes


^ permalink raw reply

* Re: WL1271
From: Elvis Dowson @ 2010-12-21 19:39 UTC (permalink / raw)
  To: David Lynch Jr.; +Cc: linux-wireless
In-Reply-To: <1292957433.20560.109.camel@t-dhlii>

Hi,

On Dec 21, 2010, at 10:50 PM, David Lynch Jr. wrote:

> 	I am essentially doing exactly the same thing as you are - but I am a
> few days behind you. I noted a post of yours about 10 days ago in
> linux-omap that you were having voltage/SDIO detection problems. I am
> having exactly that problem at this moment.  
> 	How did you work arround it ?
> 	The WL1271 is attached to MMC2 on my system. All the examples in the
> linux wireless tree are on SPI or MMC3. But I think I managed changing
> things correctly - except that the error reports are mmc1:
> 	Also the comments suggest that the WL1271 has its own internal voltage
> regulation. 
> 	That and a CY8CTMG-200 touch screen are the only major items I need
> working to polish off this project. 

If you could send me the schematics, I could comment on it.

There were a couple of hardware related problems that prevented the device from
booting up. 

Here are some of the key things to watch out for:

a. You need a slow clock (SYS 32K signal from the omap processor) to the wlan module

b. You need to ensure that you have a 26Mhz TXCO signal coming in for the fast clock.

This would be controlled by a fixed voltage regulator. The wlan module asserts a WL_CLK_REQ
signal high, which is a signal sent to the LDO to turn on the 26MHz TXCO.

c. You need to probe MMC2 CLK signals to ensure that a 24MHz signal is being generated at the 
output, when the MMC2 controller is initialized.

d. You need to update the mux settings to ensure that the MMC2 CMD, CLK, DAT 0 to DAT3, plus
GPIO pins for WLAN_EN and WLAN_IRQ are muxed correctly.

This should take care of it. 

The SDIO detection problems occured because the 26MHZ TXCO was not being turn on.

You should also be aware of the TI WL1271 power up sequence, which is 10ms pulse high, 64us low,
and then asserted high for atleast 64ms. This is taken care of in the driver code.

Also use the linux-2.6.37-rc6 kernel patch, and apply the patch to read the MAC address from the nvs file.

Also put the firmware and nvs file in /lib/firmware folder, and configure wpa_supplicant.conf to connect
to a secured access point.

Best regards,

Elvis

^ permalink raw reply

* Re: vendor IEs?
From: Daniel Halperin @ 2010-12-21 19:38 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless
In-Reply-To: <1292928100.3563.3.camel@jlt3.sipsolutions.net>

On Tue, Dec 21, 2010 at 2:41 AM, Johannes Berg
<johannes@sipsolutions.net> wrote:
> On Sun, 2010-12-19 at 16:53 -0800, Daniel Halperin wrote:
>> Is there a compiled list of vendor-specific IEs out there?  Googling
>> didn't offer much help.
>
> I'm not aware of any list, nor can there really be one since everybody
> who has an OUI is free to define their own IEs.
>
> That said, some of them are of course mostly standardised, like the WFA
> ones for WPA, WSC/WPS and P2P for instance. I don't think there's a even
> a comprehensive list of WFA ones though other than in what you get by
> combining all those standards.

On that note, if you wanted to define a custom IE what would you do?
How did the WFA get an OUI?  Is there a Linux OUI?

Dan

^ permalink raw reply

* Re: WL1271
From: David Lynch Jr. @ 2010-12-21 18:50 UTC (permalink / raw)
  To: Elvis Dowson; +Cc: linux-wireless
In-Reply-To: <4CC0832C-93B4-4212-BB5C-1901BB6A63D7@mac.com>

	I am essentially doing exactly the same thing as you are - but I am a
few days behind you. I noted a post of yours about 10 days ago in
linux-omap that you were having voltage/SDIO detection problems. I am
having exactly that problem at this moment.  
	How did you work arround it ?
	The WL1271 is attached to MMC2 on my system. All the examples in the
linux wireless tree are on SPI or MMC3. But I think I managed changing
things correctly - except that the error reports are mmc1:
	Also the comments suggest that the WL1271 has its own internal voltage
regulation. 
	That and a CY8CTMG-200 touch screen are the only major items I need
working to polish off this project. 


On Tue, 2010-12-21 at 01:31 +0400, Elvis Dowson wrote:
> Hi,
> 
> On Dec 21, 2010, at 1:04 AM, David Lynch Jr. wrote:
> 
> > 	I am looking to get the TI WL1271 WiFi working in an Android Froyo
> > system. 
> > 	I have Linux kernel experience including network and wifi drivers. 
> > 	I am gathering that there are atleast two different efforts to support
> > the TI1271 one based on the normal Linux kernel development process and
> > one that seems to be part of the TI Android community. 
> > 	Can anyone comment on the relative merits of these approaches ?
> > 
> > 	Is it reasonable to assume that if I add the WL1271 to the Android
> > 2.6.32 kernel tree using compat-wireless that it will properly integrate
> > with Android ? If not could someone point me towards resources specific
> > to Android's wireless implimentation ?
> 
> I too am working on the very same subject, which is to get the Murata
> TI WL1271 chip working with Android 2.2.1.
> 
> Chip integration with the board was verified using the mainline wl1271
> drivers (linux-2.6.37-rc6). 
> 
> With the proprietary TI drivers, I ran into issues getting it to work with my platform
> so, while that issue is being addressed, in parallel, I am going to try to use
> the compat-wireless package to get wl1271 working with android-2.6.32 and
> android-2.2.1.
> 
> The only issue I see is I'm not sure if the mainline wl1271 driver currently supports
> the android specific wireless commands, and its integration with wpa_supplicant
> WEXT driver in the android repo. One could use the AWEXT wrapper core, in this
> case, but it is something that I need to see once I get to that stage, in a couple of days.
> 
> Elvis Dowson
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


^ permalink raw reply

* [PATCH 2/2] b43: N-PHY: update 2056 radio on channel switch on rev3+
From: Rafał Miłecki @ 2010-12-21 18:40 UTC (permalink / raw)
  To: linux-wireless, John W. Linville; +Cc: b43-dev, Rafał Miłecki
In-Reply-To: <1292956819-21166-1-git-send-email-zajec5@gmail.com>

Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
---
John: I ignored over 80 chars warnings, as this is very simple code
(write-by-write, line-by-line) and I believe this can improve readibility.
---
 drivers/net/wireless/b43/phy_n.c |   66 +++++++++++++++++++++++++++++++++++++-
 1 files changed, 65 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c
index dded231..b9bda46 100644
--- a/drivers/net/wireless/b43/phy_n.c
+++ b/drivers/net/wireless/b43/phy_n.c
@@ -139,6 +139,70 @@ static void b43_chantab_radio_upload(struct b43_wldev *dev,
 	b43_radio_write(dev, B2055_C2_TX_MXBGTRIM, e->radio_c2_tx_mxbgtrim);
 }
 
+static void b43_chantab_radio_2056_upload(struct b43_wldev *dev,
+				const struct b43_nphy_channeltab_entry_rev3 *e)
+{
+	b43_radio_write(dev, B2056_SYN_PLL_VCOCAL1, e->radio_syn_pll_vcocal1);
+	b43_radio_write(dev, B2056_SYN_PLL_VCOCAL2, e->radio_syn_pll_vcocal2);
+	b43_radio_write(dev, B2056_SYN_PLL_REFDIV, e->radio_syn_pll_refdiv);
+	b43_radio_write(dev, B2056_SYN_PLL_MMD2, e->radio_syn_pll_mmd2);
+	b43_radio_write(dev, B2056_SYN_PLL_MMD1, e->radio_syn_pll_mmd1);
+	b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER1, e->radio_syn_pll_loopfilter1);
+	b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER2, e->radio_syn_pll_loopfilter2);
+	b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER3, e->radio_syn_pll_loopfilter3);
+	b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4, e->radio_syn_pll_loopfilter4);
+	b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER5, e->radio_syn_pll_loopfilter5);
+	b43_radio_write(dev, B2056_SYN_RESERVED_ADDR27, e->radio_syn_reserved_addr27);
+	b43_radio_write(dev, B2056_SYN_RESERVED_ADDR28, e->radio_syn_reserved_addr28);
+	b43_radio_write(dev, B2056_SYN_RESERVED_ADDR29, e->radio_syn_reserved_addr29);
+	b43_radio_write(dev, B2056_SYN_LOGEN_VCOBUF1, e->radio_syn_logen_vcobuf1);
+	b43_radio_write(dev, B2056_SYN_LOGEN_MIXER2, e->radio_syn_logen_mixer2);
+	b43_radio_write(dev, B2056_SYN_LOGEN_BUF3, e->radio_syn_logen_buf3);
+	b43_radio_write(dev, B2056_SYN_LOGEN_BUF4, e->radio_syn_logen_buf4);
+
+	b43_radio_write(dev, B2056_RX0 | B2056_RX_LNAA_TUNE, e->radio_rx0_lnaa_tune);
+	b43_radio_write(dev, B2056_RX0 | B2056_RX_LNAG_TUNE, e->radio_rx0_lnag_tune);
+
+	b43_radio_write(dev, B2056_TX0 | B2056_TX_INTPAA_BOOST_TUNE, e->radio_tx0_intpaa_boost_tune);
+	b43_radio_write(dev, B2056_TX0 | B2056_TX_INTPAG_BOOST_TUNE, e->radio_tx0_intpag_boost_tune);
+	b43_radio_write(dev, B2056_TX0 | B2056_TX_PADA_BOOST_TUNE, e->radio_tx0_pada_boost_tune);
+	b43_radio_write(dev, B2056_TX0 | B2056_TX_PADG_BOOST_TUNE, e->radio_tx0_padg_boost_tune);
+	b43_radio_write(dev, B2056_TX0 | B2056_TX_PGAA_BOOST_TUNE, e->radio_tx0_pgaa_boost_tune);
+	b43_radio_write(dev, B2056_TX0 | B2056_TX_PGAG_BOOST_TUNE, e->radio_tx0_pgag_boost_tune);
+	b43_radio_write(dev, B2056_TX0 | B2056_TX_MIXA_BOOST_TUNE, e->radio_tx0_mixa_boost_tune);
+	b43_radio_write(dev, B2056_TX0 | B2056_TX_MIXG_BOOST_TUNE, e->radio_tx0_mixg_boost_tune);
+
+	b43_radio_write(dev, B2056_RX1 | B2056_RX_LNAA_TUNE, e->radio_rx1_lnaa_tune);
+	b43_radio_write(dev, B2056_RX1 | B2056_RX_LNAG_TUNE, e->radio_rx1_lnag_tune);
+
+	b43_radio_write(dev, B2056_TX1 | B2056_TX_INTPAA_BOOST_TUNE, e->radio_tx1_intpaa_boost_tune);
+	b43_radio_write(dev, B2056_TX1 | B2056_TX_INTPAG_BOOST_TUNE, e->radio_tx1_intpag_boost_tune);
+	b43_radio_write(dev, B2056_TX1 | B2056_TX_PADA_BOOST_TUNE, e->radio_tx1_pada_boost_tune);
+	b43_radio_write(dev, B2056_TX1 | B2056_TX_PADG_BOOST_TUNE, e->radio_tx1_padg_boost_tune);
+	b43_radio_write(dev, B2056_TX1 | B2056_TX_PGAA_BOOST_TUNE, e->radio_tx1_pgaa_boost_tune);
+	b43_radio_write(dev, B2056_TX1 | B2056_TX_PGAG_BOOST_TUNE, e->radio_tx1_pgag_boost_tune);
+	b43_radio_write(dev, B2056_TX1 | B2056_TX_MIXA_BOOST_TUNE, e->radio_tx1_mixa_boost_tune);
+	b43_radio_write(dev, B2056_TX1 | B2056_TX_MIXG_BOOST_TUNE, e->radio_tx1_mixg_boost_tune);
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/Radio/2056Setup */
+static void b43_radio_2056_setup(struct b43_wldev *dev,
+				const struct b43_nphy_channeltab_entry_rev3 *e)
+{
+	B43_WARN_ON(dev->phy.rev < 3);
+
+	b43_chantab_radio_2056_upload(dev, e);
+	/* TODO */
+	udelay(50);
+	/* VCO calibration */
+	b43_radio_write(dev, B2056_SYN_PLL_VCOCAL12, 0x00);
+	b43_radio_write(dev, B2056_TX_INTPAA_PA_MISC, 0x38);
+	b43_radio_write(dev, B2056_TX_INTPAA_PA_MISC, 0x18);
+	b43_radio_write(dev, B2056_TX_INTPAA_PA_MISC, 0x38);
+	b43_radio_write(dev, B2056_TX_INTPAA_PA_MISC, 0x39);
+	udelay(300);
+}
+
 static void b43_chantab_phy_upload(struct b43_wldev *dev,
 				   const struct b43_phy_n_sfo_cfg *e)
 {
@@ -3635,7 +3699,7 @@ static int b43_nphy_set_channel(struct b43_wldev *dev,
 	if (dev->phy.rev >= 3) {
 		tmp = (channel->band == IEEE80211_BAND_5GHZ) ? 4 : 0;
 		b43_radio_maskset(dev, 0x08, 0xFFFB, tmp);
-		/* TODO: PHY Radio2056 Setup (dev, tabent_r3); */
+		b43_radio_2056_setup(dev, tabent_r3);
 		b43_nphy_channel_setup(dev, &(tabent_r3->phy_regs), channel);
 	} else {
 		tmp = (channel->band == IEEE80211_BAND_5GHZ) ? 0x0020 : 0x0050;
-- 
1.6.3.3


^ permalink raw reply related

* [PATCH 1/2] b43: N-PHY: use correct channel tables for rev4+
From: Rafał Miłecki @ 2010-12-21 18:40 UTC (permalink / raw)
  To: linux-wireless, John W. Linville; +Cc: b43-dev, Rafał Miłecki

Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
---
 drivers/net/wireless/b43/phy_n.c      |    1 -
 drivers/net/wireless/b43/radio_2056.c |   37 +++++++++++++++++++++++++++++---
 2 files changed, 33 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c
index f6e90a1..dded231 100644
--- a/drivers/net/wireless/b43/phy_n.c
+++ b/drivers/net/wireless/b43/phy_n.c
@@ -3607,7 +3607,6 @@ static int b43_nphy_set_channel(struct b43_wldev *dev,
 	if (dev->phy.rev >= 3) {
 		tabent_r3 = b43_nphy_get_chantabent_rev3(dev,
 							channel->center_freq);
-		tabent_r3 = NULL;
 		if (!tabent_r3)
 			return -ESRCH;
 	} else {
diff --git a/drivers/net/wireless/b43/radio_2056.c b/drivers/net/wireless/b43/radio_2056.c
index 3cb98da..8890df0 100644
--- a/drivers/net/wireless/b43/radio_2056.c
+++ b/drivers/net/wireless/b43/radio_2056.c
@@ -9053,15 +9053,44 @@ void b2056_upload_inittabs(struct b43_wldev *dev,
 				B2056_RX1, pts->rx, pts->rx_length);
 }
 
-/* TODO: add support for rev4+ devices by searching in rev4+ tables */
 const struct b43_nphy_channeltab_entry_rev3 *
 b43_nphy_get_chantabent_rev3(struct b43_wldev *dev, u16 freq)
 {
 	const struct b43_nphy_channeltab_entry_rev3 *e;
-	unsigned int i;
+	unsigned int length, i;
 
-	for (i = 0; i < ARRAY_SIZE(b43_nphy_channeltab_rev3); i++) {
-		e = &(b43_nphy_channeltab_rev3[i]);
+	switch (dev->phy.rev) {
+	case 3:
+		e = b43_nphy_channeltab_rev3;
+		length = ARRAY_SIZE(b43_nphy_channeltab_rev3);
+		break;
+	case 4:
+		e = b43_nphy_channeltab_rev4;
+		length = ARRAY_SIZE(b43_nphy_channeltab_rev4);
+		break;
+	case 5:
+		e = b43_nphy_channeltab_rev5;
+		length = ARRAY_SIZE(b43_nphy_channeltab_rev5);
+		break;
+	case 6:
+		e = b43_nphy_channeltab_rev6;
+		length = ARRAY_SIZE(b43_nphy_channeltab_rev6);
+		break;
+	case 7:
+	case 9:
+		e = b43_nphy_channeltab_rev7_9;
+		length = ARRAY_SIZE(b43_nphy_channeltab_rev7_9);
+		break;
+	case 8:
+		e = b43_nphy_channeltab_rev8;
+		length = ARRAY_SIZE(b43_nphy_channeltab_rev8);
+		break;
+	default:
+		B43_WARN_ON(1);
+		return NULL;
+	}
+
+	for (i = 0; i < length; i++, e++) {
 		if (e->freq == freq)
 			return e;
 	}
-- 
1.6.3.3


^ permalink raw reply related

* Re: vendor IEs?
From: Henry Ptasinski @ 2010-12-21 18:33 UTC (permalink / raw)
  To: Johannes Berg; +Cc: Daniel Halperin, linux-wireless@vger.kernel.org
In-Reply-To: <1292928100.3563.3.camel@jlt3.sipsolutions.net>

On 12/21/2010 02:41 AM, Johannes Berg wrote:
> On Sun, 2010-12-19 at 16:53 -0800, Daniel Halperin wrote:
>> Is there a compiled list of vendor-specific IEs out there?  Googling
>> didn't offer much help.
>
> I'm not aware of any list, nor can there really be one since everybody
> who has an OUI is free to define their own IEs.
>
> That said, some of them are of course mostly standardised, like the WFA
> ones for WPA, WSC/WPS and P2P for instance. I don't think there's a even
> a comprehensive list of WFA ones though other than in what you get by
> combining all those standards.

The most complete info I've seen is in the wireshark dissector, but even 
that is not very complete.

- Henry



^ 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