2009-01-21 05:31:30

by Reinette Chatre

[permalink] [raw]
Subject: [PATCH 0/5] iwlwifi driver updates 01/20/2009

This series contains three fixes to iwlwifi rate scaling. Of most interest is
a fix for the "rs_get_rate()" problem that is tracked on kerneloops.org. A
similar fix that applies to 2.6.29 will be sent separately.

We also include a fix for the "MAC is in deep sleep" problem tracked in
http://www.intellinuxwireless.org/bugzilla/show_bug.cgi?id=1845 and
http://www.intellinuxwireless.org/bugzilla/show_bug.cgi?id=1834

We include one 3945 porting patch.

[PATCH 1/5] iwlwifi: fix rs_get_rate WARN_ON()
[PATCH 2/5] iwlwifi: allow user to set max rate
[PATCH 3/5] iwlagn: fix agn rate scaling
[PATCH 4/5] iwl3945: Use iwl-rfkill
[PATCH 5/5] iwl3945: fix deep sleep when removing the driver.


Thank you

Reinette


2009-01-21 05:31:31

by Reinette Chatre

[permalink] [raw]
Subject: [PATCH 5/5] iwl3945: fix deep sleep when removing the driver.

From: Abbas, Mohamed <[email protected]>

A warning message "MAC is in deep sleep" sometimes happen when user removes
the driver. This warning is related to card not being ready. In __iwl3945_down
function some of the going down steps are in wrong order, to fix this this patch
do the following:
1- make sure we are calling iwl3945_apm_reset and iwl3945_apm_stop
in the right order.

2- make sure we set CSR_GP_CNTRL_REG_FLAG_INIT_DONE in apm_reset before
poll on CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY.

3- set correct polling counter.

This fixes bug
http://www.intellinuxwireless.org/bugzilla/show_bug.cgi?id=1834

Signed-off-by: mohamed abbas <[email protected]>
Signed-off-by: Reinette Chatre <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-3945.c | 8 +++-----
drivers/net/wireless/iwlwifi/iwl-io.h | 2 +-
drivers/net/wireless/iwlwifi/iwl3945-base.c | 7 ++++++-
3 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
index e6d4503..8b486c9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -1332,6 +1332,9 @@ static int iwl3945_apm_reset(struct iwl_priv *priv)
spin_lock_irqsave(&priv->lock, flags);

iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
+ udelay(10);
+
+ iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);

iwl_poll_direct_bit(priv, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
@@ -1341,11 +1344,6 @@ static int iwl3945_apm_reset(struct iwl_priv *priv)
iwl_write_prph(priv, APMG_CLK_CTRL_REG,
APMG_CLK_VAL_BSM_CLK_RQT);

- udelay(10);
-
- iwl_set_bit(priv, CSR_GP_CNTRL,
- CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
-
iwl_write_prph(priv, APMG_RTC_INT_MSK_REG, 0x0);
iwl_write_prph(priv, APMG_RTC_INT_STT_REG,
0xFFFFFFFF);
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h
index bc3f3da..7341a2d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-io.h
+++ b/drivers/net/wireless/iwlwifi/iwl-io.h
@@ -165,7 +165,7 @@ static inline int _iwl_grab_nic_access(struct iwl_priv *priv)
ret = _iwl_poll_bit(priv, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN,
(CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY |
- CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 50);
+ CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 15000);
if (ret < 0) {
IWL_ERR(priv, "MAC is in deep sleep!\n");
return -EIO;
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index be02272..e595c5a 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -5295,6 +5295,7 @@ static void __iwl3945_down(struct iwl_priv *priv)
test_bit(STATUS_EXIT_PENDING, &priv->status) <<
STATUS_EXIT_PENDING;

+ priv->cfg->ops->lib->apm_ops.reset(priv);
spin_lock_irqsave(&priv->lock, flags);
iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
spin_unlock_irqrestore(&priv->lock, flags);
@@ -5312,7 +5313,11 @@ static void __iwl3945_down(struct iwl_priv *priv)

udelay(5);

- priv->cfg->ops->lib->apm_ops.reset(priv);
+ if (exit_pending || test_bit(STATUS_IN_SUSPEND, &priv->status))
+ priv->cfg->ops->lib->apm_ops.stop(priv);
+ else
+ priv->cfg->ops->lib->apm_ops.reset(priv);
+
exit:
memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp));

--
1.5.4.3


2009-01-21 14:47:10

by Samuel Ortiz

[permalink] [raw]
Subject: Re: [ipw3945-devel] [PATCH 4/5] iwl3945: Use iwl-rfkill

Hi Helmut,

On Wed, Jan 21, 2009 at 12:01:22AM -0700, Helmut Schaa wrote:
> Hi,
>
> Am Mittwoch, 21. Januar 2009 schrieb Reinette Chatre:
> > From: Samuel Ortiz <[email protected]>
> >
> > Here again, the rfkill routines are duplicated between agn and 3945. Let's
> > move the agn one to iwlcore, and so we can get rid of the 3945 ones.
>
> [...]
>
> > +void iwl_bg_rf_kill(struct work_struct *work)
> > +{
> > + struct iwl_priv *priv = container_of(work, struct iwl_priv, rf_kill);
> > +
> > + wake_up_interruptible(&priv->wait_command_queue);
> > +
> > + if (test_bit(STATUS_EXIT_PENDING, &priv->status))
> > + return;
> > +
> > + mutex_lock(&priv->mutex);
> > +
> > + if (!iwl_is_rfkill(priv)) {
> > + IWL_DEBUG(IWL_DL_RF_KILL,
> > + "HW and/or SW RF Kill no longer active, restarting "
> > + "device\n");
> > + if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
> > + queue_work(priv->workqueue, &priv->restart);
>
> I've changed this check in both rf-kill patches (3945 and agn) to
>
> if (!test_bit(STATUS_EXIT_PENDING, &priv->status) &&
> test_bit(STATUS_ALIVE, &priv->status))
>
> in order to avoid restarting the adapter when notified about rfkill changes
> by interrupt/polling.
>
> I guess this is just an oversight, right?
Good catch. It is an oversight, yes.
John, Reinette, do you want a new version of this patch or an additional one
on top of wireless-testing ?

Cheers,
Samuel.

--
Intel Open Source Technology Centre
http://oss.intel.com/
---------------------------------------------------------------------
Intel Corporation SAS (French simplified joint stock company)
Registered headquarters: "Les Montalets"- 2, rue de Paris,
92196 Meudon Cedex, France
Registration Number: 302 456 199 R.C.S. NANTERRE
Capital: 4,572,000 Euros

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.


2009-01-21 05:31:30

by Reinette Chatre

[permalink] [raw]
Subject: [PATCH 3/5] iwlagn: fix agn rate scaling

From: Abbas, Mohamed <[email protected]>

Sometime Tx reply rate different than what rate scale expecting
causing rate scale to bail out. This could cause failing to
commit LQ cmd. This patch will try to solve this instead of just
bail out. It also make sure we start with a valid rate.

Signed-off-by: mohamed abbas <[email protected]>
Signed-off-by: Reinette Chatre <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 31 +++++++++++++++++++++-------
1 files changed, 23 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index 12c5e5d..13039a0 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -49,6 +49,8 @@
#define IWL_RATE_MIN_FAILURE_TH 6 /* min failures to calc tpt */
#define IWL_RATE_MIN_SUCCESS_TH 8 /* min successes to calc tpt */

+/* max allowed rate miss before sync LQ cmd */
+#define IWL_MISSED_RATE_MAX 15
/* max time to accum history 2 seconds */
#define IWL_RATE_SCALE_FLUSH_INTVL (2*HZ)

@@ -149,6 +151,7 @@ struct iwl_lq_sta {
u16 active_mimo3_rate;
u16 active_rate_basic;
s8 max_rate_idx; /* Max rate set by user */
+ u8 missed_rate_counter;

struct iwl_link_quality_cmd lq;
struct iwl_scale_tbl_info lq_info[LQ_SIZE]; /* "active", "search" */
@@ -841,10 +844,15 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
/* the last LQ command could failed so the LQ in ucode not
* the same in driver sync up
*/
- iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
+ lq_sta->missed_rate_counter++;
+ if (lq_sta->missed_rate_counter > IWL_MISSED_RATE_MAX) {
+ lq_sta->missed_rate_counter = 0;
+ iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
+ }
goto out;
}

+ lq_sta->missed_rate_counter = 0;
/* Update frame history window with "failure" for each Tx retry. */
while (retries) {
/* Look up the rate and other info used for each tx attempt.
@@ -2212,6 +2220,8 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
struct ieee80211_conf *conf = &priv->hw->conf;
struct iwl_lq_sta *lq_sta = priv_sta;
u16 mask_bit = 0;
+ int count;
+ int start_rate = 0;

lq_sta->flush_timer = 0;
lq_sta->supp_rates = sta->supp_rates[sband->band];
@@ -2247,6 +2257,7 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,

lq_sta->is_dup = 0;
lq_sta->max_rate_idx = -1;
+ lq_sta->missed_rate_counter = IWL_MISSED_RATE_MAX;
lq_sta->is_green = rs_use_green(priv, conf);
lq_sta->active_legacy_rate = priv->active_rate & ~(0x1000);
lq_sta->active_rate_basic = priv->active_rate_basic;
@@ -2285,16 +2296,20 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
lq_sta->drv = priv;

/* Find highest tx rate supported by hardware and destination station */
- mask_bit = sta->supp_rates[sband->band] & lq_sta->active_legacy_rate;
- lq_sta->last_txrate_idx = 3;
- for (i = 0; i < sband->n_bitrates; i++)
+ mask_bit = sta->supp_rates[sband->band];
+ count = sband->n_bitrates;
+ if (sband->band == IEEE80211_BAND_5GHZ) {
+ count += IWL_FIRST_OFDM_RATE;
+ start_rate = IWL_FIRST_OFDM_RATE;
+ mask_bit <<= IWL_FIRST_OFDM_RATE;
+ }
+
+ mask_bit = mask_bit & lq_sta->active_legacy_rate;
+ lq_sta->last_txrate_idx = 4;
+ for (i = start_rate; i < count; i++)
if (mask_bit & BIT(i))
lq_sta->last_txrate_idx = i;

- /* For MODE_IEEE80211A, skip over cck rates in global rate table */
- if (sband->band == IEEE80211_BAND_5GHZ)
- lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
-
rs_initialize_lq(priv, conf, sta, lq_sta);
}

--
1.5.4.3


2009-01-21 05:31:28

by Reinette Chatre

[permalink] [raw]
Subject: [PATCH 2/5] iwlwifi: allow user to set max rate

From: Abbas, Mohamed <[email protected]>

allow user to set max rate through #iwconfig <inteface> rate XXX.
mac80211 will try to force this if user set it, but driver is not
in sync which cause mac80211 to report wrong current rate. This
patch will check if max rate is set and force it in rate scaling

Signed-off-by: mohamed abbas <[email protected]>
Signed-off-by: Reinette Chatre <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 18 ++++++++++++++++++
drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 27 +++++++++++++++++++++++++++
2 files changed, 45 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
index 25b4356..044abf7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
@@ -651,6 +651,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta,
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
u16 fc;
u16 rate_mask = 0;
+ s8 max_rate_idx = -1;
struct iwl_priv *priv = (struct iwl_priv *)priv_r;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);

@@ -675,6 +676,13 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta,
return;
}

+ /* get user max rate if set */
+ max_rate_idx = txrc->max_rate_idx;
+ if ((sband->band == IEEE80211_BAND_5GHZ) && (max_rate_idx != -1))
+ max_rate_idx += IWL_FIRST_OFDM_RATE;
+ if ((max_rate_idx < 0) || (max_rate_idx >= IWL_RATE_COUNT))
+ max_rate_idx = -1;
+
index = min(rs_sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT_3945 - 1);

if (sband->band == IEEE80211_BAND_5GHZ)
@@ -706,6 +714,12 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta,
rs_sta->start_rate = IWL_RATE_INVALID;
}

+ /* force user max rate if set by user */
+ if ((max_rate_idx != -1) && (max_rate_idx < index)) {
+ if (rate_mask & (1 << max_rate_idx))
+ index = max_rate_idx;
+ }
+
window = &(rs_sta->win[index]);

fail_count = window->counter - window->success_counter;
@@ -732,6 +746,10 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta,
low = high_low & 0xff;
high = (high_low >> 8) & 0xff;

+ /* If user set max rate, dont allow higher than user constrain */
+ if ((max_rate_idx != -1) && (max_rate_idx < high))
+ high = IWL_RATE_INVALID;
+
if (low != IWL_RATE_INVALID)
low_tpt = rs_sta->win[low].average_tpt;

diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index a82cce5..12c5e5d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -148,6 +148,7 @@ struct iwl_lq_sta {
u16 active_mimo2_rate;
u16 active_mimo3_rate;
u16 active_rate_basic;
+ s8 max_rate_idx; /* Max rate set by user */

struct iwl_link_quality_cmd lq;
struct iwl_scale_tbl_info lq_info[LQ_SIZE]; /* "active", "search" */
@@ -1759,6 +1760,15 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
return;
}

+ /* force user max rate if set by user */
+ if ((lq_sta->max_rate_idx != -1) &&
+ (lq_sta->max_rate_idx < index)) {
+ index = lq_sta->max_rate_idx;
+ update_lq = 1;
+ window = &(tbl->win[index]);
+ goto lq_update;
+ }
+
window = &(tbl->win[index]);

/*
@@ -1850,6 +1860,11 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
low = high_low & 0xff;
high = (high_low >> 8) & 0xff;

+ /* If user set max rate, dont allow higher than user constrain */
+ if ((lq_sta->max_rate_idx != -1) &&
+ (lq_sta->max_rate_idx < high))
+ high = IWL_RATE_INVALID;
+
sr = window->success_ratio;

/* Collect measured throughputs for current and adjacent rates */
@@ -2110,6 +2125,17 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta,

IWL_DEBUG_RATE_LIMIT("rate scale calculate new rate for skb\n");

+ /* Get max rate if user set max rate */
+ if (lq_sta) {
+ lq_sta->max_rate_idx = txrc->max_rate_idx;
+ if ((sband->band == IEEE80211_BAND_5GHZ) &&
+ (lq_sta->max_rate_idx != -1))
+ lq_sta->max_rate_idx += IWL_FIRST_OFDM_RATE;
+ if ((lq_sta->max_rate_idx < 0) ||
+ (lq_sta->max_rate_idx >= IWL_RATE_COUNT))
+ lq_sta->max_rate_idx = -1;
+ }
+
if (sta)
mask_bit = sta->supp_rates[sband->band];

@@ -2220,6 +2246,7 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
}

lq_sta->is_dup = 0;
+ lq_sta->max_rate_idx = -1;
lq_sta->is_green = rs_use_green(priv, conf);
lq_sta->active_legacy_rate = priv->active_rate & ~(0x1000);
lq_sta->active_rate_basic = priv->active_rate_basic;
--
1.5.4.3


2009-01-21 17:25:30

by Samuel Ortiz

[permalink] [raw]
Subject: [PATCH v2 4/5] iwl3945: Use iwl-rfkill

From: Samuel Ortiz <[email protected]>

Here again, the rfkill routines are duplicated between agn and 3945. Let's
move the agn one to iwlcore, and so we can get rid of the 3945 ones.

Signed-off-by: Samuel Ortiz <[email protected]>
Signed-off-by: Reinette Chatre <[email protected]>
---

Changes from v1:
- Add Helmut's code back, after a merge mistake.

---
drivers/net/wireless/iwlwifi/Kconfig | 6 +-
drivers/net/wireless/iwlwifi/iwl-3945.h | 12 --
drivers/net/wireless/iwlwifi/iwl-agn.c | 34 ------
drivers/net/wireless/iwlwifi/iwl-core.c | 36 +++++++
drivers/net/wireless/iwlwifi/iwl-core.h | 2 +-
drivers/net/wireless/iwlwifi/iwl3945-base.c | 151 +--------------------------
6 files changed, 43 insertions(+), 198 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
index 47bee0e..4b2d57a 100644
--- a/drivers/net/wireless/iwlwifi/Kconfig
+++ b/drivers/net/wireless/iwlwifi/Kconfig
@@ -110,7 +110,7 @@ config IWL3945
select IWLWIFI
select MAC80211_LEDS if IWL3945_LEDS
select LEDS_CLASS if IWL3945_LEDS
- select RFKILL if IWL3945_RFKILL
+ select RFKILL if IWLWIFI_RFKILL
---help---
Select to build the driver supporting the:

@@ -133,10 +133,6 @@ config IWL3945
say M here and read <file:Documentation/kbuild/modules.txt>. The
module will be called iwl3945.ko.

-config IWL3945_RFKILL
- bool "Enable RF kill support in iwl3945 drivers"
- depends on IWL3945
-
config IWL3945_SPECTRUM_MEASUREMENT
bool "Enable Spectrum Measurement in iwl3945 drivers"
depends on IWL3945
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h
index 97dfa7c..156c828 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.h
@@ -301,18 +301,6 @@ extern int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv);
extern u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id,
u16 tx_rate, u8 flags);

-#ifdef CONFIG_IWL3945_RFKILL
-struct iwl_priv;
-
-void iwl3945_rfkill_set_hw_state(struct iwl_priv *priv);
-void iwl3945_rfkill_unregister(struct iwl_priv *priv);
-int iwl3945_rfkill_init(struct iwl_priv *priv);
-#else
-static inline void iwl3945_rfkill_set_hw_state(struct iwl_priv *priv) {}
-static inline void iwl3945_rfkill_unregister(struct iwl_priv *priv) {}
-static inline int iwl3945_rfkill_init(struct iwl_priv *priv) { return 0; }
-#endif
-
static inline int iwl3945_is_associated(struct iwl_priv *priv)
{
return (priv->active39_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0;
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index d1994de..c4fadb6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -2143,40 +2143,6 @@ static void iwl_bg_alive_start(struct work_struct *data)
mutex_unlock(&priv->mutex);
}

-static void iwl_bg_rf_kill(struct work_struct *work)
-{
- struct iwl_priv *priv = container_of(work, struct iwl_priv, rf_kill);
-
- wake_up_interruptible(&priv->wait_command_queue);
-
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
- return;
-
- mutex_lock(&priv->mutex);
-
- if (!iwl_is_rfkill(priv)) {
- IWL_DEBUG(IWL_DL_RF_KILL,
- "HW and/or SW RF Kill no longer active, restarting "
- "device\n");
- if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
- queue_work(priv->workqueue, &priv->restart);
- } else {
- /* make sure mac80211 stop sending Tx frame */
- if (priv->mac80211_registered)
- ieee80211_stop_queues(priv->hw);
-
- if (!test_bit(STATUS_RF_KILL_HW, &priv->status))
- IWL_DEBUG_RF_KILL("Can not turn radio back on - "
- "disabled by SW switch\n");
- else
- IWL_WARN(priv, "Radio Frequency Kill Switch is On:\n"
- "Kill switch must be turned off for "
- "wireless networking to work.\n");
- }
- mutex_unlock(&priv->mutex);
- iwl_rfkill_set_hw_state(priv);
-}
-
static void iwl_bg_run_time_calib_work(struct work_struct *work)
{
struct iwl_priv *priv = container_of(work, struct iwl_priv,
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index d2ef3e1..f24d3b4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -1465,3 +1465,39 @@ int iwl_radio_kill_sw_enable_radio(struct iwl_priv *priv)
return 1;
}
EXPORT_SYMBOL(iwl_radio_kill_sw_enable_radio);
+
+void iwl_bg_rf_kill(struct work_struct *work)
+{
+ struct iwl_priv *priv = container_of(work, struct iwl_priv, rf_kill);
+
+ wake_up_interruptible(&priv->wait_command_queue);
+
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ return;
+
+ mutex_lock(&priv->mutex);
+
+ if (!iwl_is_rfkill(priv)) {
+ IWL_DEBUG(IWL_DL_RF_KILL,
+ "HW and/or SW RF Kill no longer active, restarting "
+ "device\n");
+ if (!test_bit(STATUS_EXIT_PENDING, &priv->status) &&
+ test_bit(STATUS_ALIVE, &priv->status))
+ queue_work(priv->workqueue, &priv->restart);
+ } else {
+ /* make sure mac80211 stop sending Tx frame */
+ if (priv->mac80211_registered)
+ ieee80211_stop_queues(priv->hw);
+
+ if (!test_bit(STATUS_RF_KILL_HW, &priv->status))
+ IWL_DEBUG_RF_KILL("Can not turn radio back on - "
+ "disabled by SW switch\n");
+ else
+ IWL_WARN(priv, "Radio Frequency Kill Switch is On:\n"
+ "Kill switch must be turned off for "
+ "wireless networking to work.\n");
+ }
+ mutex_unlock(&priv->mutex);
+ iwl_rfkill_set_hw_state(priv);
+}
+EXPORT_SYMBOL(iwl_bg_rf_kill);
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 466130f..5ceeedc 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -267,7 +267,7 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force);
* RF -Kill - here and not in iwl-rfkill.h to be available when
* RF-kill subsystem is not compiled.
****************************************************/
-void iwl_rf_kill(struct iwl_priv *priv);
+void iwl_bg_rf_kill(struct work_struct *work);
void iwl_radio_kill_sw_disable_radio(struct iwl_priv *priv);
int iwl_radio_kill_sw_enable_radio(struct iwl_priv *priv);

diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index ee7bccf..be02272 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -5464,39 +5464,6 @@ static void iwl3945_bg_alive_start(struct work_struct *data)
mutex_unlock(&priv->mutex);
}

-static void iwl3945_bg_rf_kill(struct work_struct *work)
-{
- struct iwl_priv *priv = container_of(work, struct iwl_priv, rf_kill);
-
- wake_up_interruptible(&priv->wait_command_queue);
-
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
- return;
-
- mutex_lock(&priv->mutex);
-
- if (!iwl_is_rfkill(priv)) {
- IWL_DEBUG(IWL_DL_INFO | IWL_DL_RF_KILL,
- "HW and/or SW RF Kill no longer active, restarting "
- "device\n");
- if (!test_bit(STATUS_EXIT_PENDING, &priv->status) &&
- test_bit(STATUS_ALIVE, &priv->status))
- queue_work(priv->workqueue, &priv->restart);
- } else {
-
- if (!test_bit(STATUS_RF_KILL_HW, &priv->status))
- IWL_DEBUG_RF_KILL("Can not turn radio back on - "
- "disabled by SW switch\n");
- else
- IWL_WARN(priv, "Radio Frequency Kill Switch is On:\n"
- "Kill switch must be turned off for "
- "wireless networking to work.\n");
- }
-
- mutex_unlock(&priv->mutex);
- iwl3945_rfkill_set_hw_state(priv);
-}
-
static void iwl3945_rfkill_poll(struct work_struct *data)
{
struct iwl_priv *priv =
@@ -5745,7 +5712,7 @@ static void iwl3945_bg_up(struct work_struct *data)
mutex_lock(&priv->mutex);
__iwl3945_up(priv);
mutex_unlock(&priv->mutex);
- iwl3945_rfkill_set_hw_state(priv);
+ iwl_rfkill_set_hw_state(priv);
}

static void iwl3945_bg_restart(struct work_struct *data)
@@ -5938,7 +5905,7 @@ static int iwl3945_mac_start(struct ieee80211_hw *hw)

mutex_unlock(&priv->mutex);

- iwl3945_rfkill_set_hw_state(priv);
+ iwl_rfkill_set_hw_state(priv);

if (ret)
goto out_release_irq;
@@ -7208,7 +7175,7 @@ static void iwl3945_setup_deferred_work(struct iwl_priv *priv)
INIT_WORK(&priv->scan_completed, iwl3945_bg_scan_completed);
INIT_WORK(&priv->request_scan, iwl3945_bg_request_scan);
INIT_WORK(&priv->abort_scan, iwl3945_bg_abort_scan);
- INIT_WORK(&priv->rf_kill, iwl3945_bg_rf_kill);
+ INIT_WORK(&priv->rf_kill, iwl_bg_rf_kill);
INIT_WORK(&priv->beacon_update, iwl3945_bg_beacon_update);
INIT_DELAYED_WORK(&priv->init_alive_start, iwl3945_bg_init_alive_start);
INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start);
@@ -7536,7 +7503,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
priv->hw->conf.beacon_int = 100;
priv->mac80211_registered = 1;

- err = iwl3945_rfkill_init(priv);
+ err = iwl_rfkill_init(priv);
if (err)
IWL_ERR(priv, "Unable to initialize RFKILL system. "
"Ignoring error: %d\n", err);
@@ -7602,7 +7569,7 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)

sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group);

- iwl3945_rfkill_unregister(priv);
+ iwl_rfkill_unregister(priv);
cancel_delayed_work(&priv->rfkill_poll);

iwl3945_dealloc_ucode_pci(priv);
@@ -7675,114 +7642,6 @@ static int iwl3945_pci_resume(struct pci_dev *pdev)

#endif /* CONFIG_PM */

-/*************** RFKILL FUNCTIONS **********/
-#ifdef CONFIG_IWL3945_RFKILL
-/* software rf-kill from user */
-static int iwl3945_rfkill_soft_rf_kill(void *data, enum rfkill_state state)
-{
- struct iwl_priv *priv = data;
- int err = 0;
-
- if (!priv->rfkill)
- return 0;
-
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
- return 0;
-
- IWL_DEBUG_RF_KILL("we received soft RFKILL set to state %d\n", state);
- mutex_lock(&priv->mutex);
-
- switch (state) {
- case RFKILL_STATE_UNBLOCKED:
- if (iwl_is_rfkill_hw(priv)) {
- err = -EBUSY;
- goto out_unlock;
- }
- iwl3945_radio_kill_sw(priv, 0);
- break;
- case RFKILL_STATE_SOFT_BLOCKED:
- iwl3945_radio_kill_sw(priv, 1);
- break;
- default:
- IWL_WARN(priv, "received unexpected RFKILL state %d\n", state);
- break;
- }
-out_unlock:
- mutex_unlock(&priv->mutex);
-
- return err;
-}
-
-int iwl3945_rfkill_init(struct iwl_priv *priv)
-{
- struct device *device = wiphy_dev(priv->hw->wiphy);
- int ret = 0;
-
- BUG_ON(device == NULL);
-
- IWL_DEBUG_RF_KILL("Initializing RFKILL.\n");
- priv->rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN);
- if (!priv->rfkill) {
- IWL_ERR(priv, "Unable to allocate rfkill device.\n");
- ret = -ENOMEM;
- goto error;
- }
-
- priv->rfkill->name = priv->cfg->name;
- priv->rfkill->data = priv;
- priv->rfkill->state = RFKILL_STATE_UNBLOCKED;
- priv->rfkill->toggle_radio = iwl3945_rfkill_soft_rf_kill;
- priv->rfkill->user_claim_unsupported = 1;
-
- priv->rfkill->dev.class->suspend = NULL;
- priv->rfkill->dev.class->resume = NULL;
-
- ret = rfkill_register(priv->rfkill);
- if (ret) {
- IWL_ERR(priv, "Unable to register rfkill: %d\n", ret);
- goto freed_rfkill;
- }
-
- IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n");
- return ret;
-
-freed_rfkill:
- if (priv->rfkill != NULL)
- rfkill_free(priv->rfkill);
- priv->rfkill = NULL;
-
-error:
- IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n");
- return ret;
-}
-
-void iwl3945_rfkill_unregister(struct iwl_priv *priv)
-{
- if (priv->rfkill)
- rfkill_unregister(priv->rfkill);
-
- priv->rfkill = NULL;
-}
-
-/* set rf-kill to the right state. */
-void iwl3945_rfkill_set_hw_state(struct iwl_priv *priv)
-{
-
- if (!priv->rfkill)
- return;
-
- if (iwl_is_rfkill_hw(priv)) {
- rfkill_force_state(priv->rfkill, RFKILL_STATE_HARD_BLOCKED);
- return;
- }
-
- if (!iwl_is_rfkill_sw(priv))
- rfkill_force_state(priv->rfkill, RFKILL_STATE_UNBLOCKED);
- else
- rfkill_force_state(priv->rfkill, RFKILL_STATE_SOFT_BLOCKED);
-}
-#endif
-
/*****************************************************************************
*
* driver and module entry point
--
1.6.0.4.766.g6fc4a.dirty

--
Intel Open Source Technology Centre
http://oss.intel.com/
---------------------------------------------------------------------
Intel Corporation SAS (French simplified joint stock company)
Registered headquarters: "Les Montalets"- 2, rue de Paris,
92196 Meudon Cedex, France
Registration Number: 302 456 199 R.C.S. NANTERRE
Capital: 4,572,000 Euros

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.


2009-01-21 05:31:31

by Reinette Chatre

[permalink] [raw]
Subject: [PATCH 1/5] iwlwifi: fix rs_get_rate WARN_ON()

From: Abbas, Mohamed <[email protected]>

In ieee80211_sta structure there is u64 supp_rates[IEEE80211_NUM_BANDS]
this is filled with all support rate from assoc_resp. If we associate
with G-band AP only supp_rates of G-band will be set the other band
supp_rates will be set to 0. If the user type this command
this will cause mac80211 to set to new channel, mac80211
does not disassociate in setting new channel, so the active
band is now A-band. then in handling the new essid mac80211 will
kick in the assoc steps which involve sending disassociation frame.
in this mac80211 will WARN_ON sta->supp_rates[A_BAND] == 0.

This fixes:
http://www.intellinuxwireless.org/bugzilla/show_bug.cgi?id=1822
http://www.kerneloops.org/searchweek.php?search=rs_get_rate

Signed-off-by: mohamed abbas <[email protected]>
Signed-off-by: Reinette Chatre <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 14 +++++++++++---
drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 14 ++++++++++++--
2 files changed, 23 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
index ba64034..25b4356 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
@@ -649,12 +649,16 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta,
s8 scale_action = 0;
unsigned long flags;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- u16 fc, rate_mask;
+ u16 fc;
+ u16 rate_mask = 0;
struct iwl_priv *priv = (struct iwl_priv *)priv_r;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);

IWL_DEBUG_RATE("enter\n");

+ if (sta)
+ rate_mask = sta->supp_rates[sband->band];
+
/* Send management frames and broadcast/multicast data using lowest
* rate. */
fc = le16_to_cpu(hdr->frame_control);
@@ -662,11 +666,15 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta,
is_multicast_ether_addr(hdr->addr1) ||
!sta || !priv_sta) {
IWL_DEBUG_RATE("leave: No STA priv data to update!\n");
- info->control.rates[0].idx = rate_lowest_index(sband, sta);
+ if (!rate_mask)
+ info->control.rates[0].idx =
+ rate_lowest_index(sband, NULL);
+ else
+ info->control.rates[0].idx =
+ rate_lowest_index(sband, sta);
return;
}

- rate_mask = sta->supp_rates[sband->band];
index = min(rs_sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT_3945 - 1);

if (sband->band == IEEE80211_BAND_5GHZ)
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index 4c460b1..a82cce5 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -945,7 +945,8 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
}

/* See if there's a better rate or modulation mode to try. */
- rs_rate_scale_perform(priv, hdr, sta, lq_sta);
+ if (sta && sta->supp_rates[sband->band])
+ rs_rate_scale_perform(priv, hdr, sta, lq_sta);
out:
return;
}
@@ -2105,14 +2106,23 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta,
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct iwl_lq_sta *lq_sta = priv_sta;
int rate_idx;
+ u64 mask_bit = 0;

IWL_DEBUG_RATE_LIMIT("rate scale calculate new rate for skb\n");

+ if (sta)
+ mask_bit = sta->supp_rates[sband->band];
+
/* Send management frames and broadcast/multicast data using lowest
* rate. */
if (!ieee80211_is_data(hdr->frame_control) ||
is_multicast_ether_addr(hdr->addr1) || !sta || !lq_sta) {
- info->control.rates[0].idx = rate_lowest_index(sband, sta);
+ if (!mask_bit)
+ info->control.rates[0].idx =
+ rate_lowest_index(sband, NULL);
+ else
+ info->control.rates[0].idx =
+ rate_lowest_index(sband, sta);
return;
}

--
1.5.4.3


2009-01-21 05:31:30

by Reinette Chatre

[permalink] [raw]
Subject: [PATCH 4/5] iwl3945: Use iwl-rfkill

From: Samuel Ortiz <[email protected]>

Here again, the rfkill routines are duplicated between agn and 3945. Let's
move the agn one to iwlcore, and so we can get rid of the 3945 ones.

Signed-off-by: Samuel Ortiz <[email protected]>
Signed-off-by: Reinette Chatre <[email protected]>
---
drivers/net/wireless/iwlwifi/Kconfig | 6 +-
drivers/net/wireless/iwlwifi/iwl-3945.h | 12 --
drivers/net/wireless/iwlwifi/iwl-agn.c | 34 ------
drivers/net/wireless/iwlwifi/iwl-core.c | 35 ++++++
drivers/net/wireless/iwlwifi/iwl-core.h | 2 +-
drivers/net/wireless/iwlwifi/iwl3945-base.c | 151 +--------------------------
6 files changed, 42 insertions(+), 198 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
index 47bee0e..4b2d57a 100644
--- a/drivers/net/wireless/iwlwifi/Kconfig
+++ b/drivers/net/wireless/iwlwifi/Kconfig
@@ -110,7 +110,7 @@ config IWL3945
select IWLWIFI
select MAC80211_LEDS if IWL3945_LEDS
select LEDS_CLASS if IWL3945_LEDS
- select RFKILL if IWL3945_RFKILL
+ select RFKILL if IWLWIFI_RFKILL
---help---
Select to build the driver supporting the:

@@ -133,10 +133,6 @@ config IWL3945
say M here and read <file:Documentation/kbuild/modules.txt>. The
module will be called iwl3945.ko.

-config IWL3945_RFKILL
- bool "Enable RF kill support in iwl3945 drivers"
- depends on IWL3945
-
config IWL3945_SPECTRUM_MEASUREMENT
bool "Enable Spectrum Measurement in iwl3945 drivers"
depends on IWL3945
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h
index 97dfa7c..156c828 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.h
@@ -301,18 +301,6 @@ extern int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv);
extern u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id,
u16 tx_rate, u8 flags);

-#ifdef CONFIG_IWL3945_RFKILL
-struct iwl_priv;
-
-void iwl3945_rfkill_set_hw_state(struct iwl_priv *priv);
-void iwl3945_rfkill_unregister(struct iwl_priv *priv);
-int iwl3945_rfkill_init(struct iwl_priv *priv);
-#else
-static inline void iwl3945_rfkill_set_hw_state(struct iwl_priv *priv) {}
-static inline void iwl3945_rfkill_unregister(struct iwl_priv *priv) {}
-static inline int iwl3945_rfkill_init(struct iwl_priv *priv) { return 0; }
-#endif
-
static inline int iwl3945_is_associated(struct iwl_priv *priv)
{
return (priv->active39_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0;
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index d1994de..c4fadb6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -2143,40 +2143,6 @@ static void iwl_bg_alive_start(struct work_struct *data)
mutex_unlock(&priv->mutex);
}

-static void iwl_bg_rf_kill(struct work_struct *work)
-{
- struct iwl_priv *priv = container_of(work, struct iwl_priv, rf_kill);
-
- wake_up_interruptible(&priv->wait_command_queue);
-
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
- return;
-
- mutex_lock(&priv->mutex);
-
- if (!iwl_is_rfkill(priv)) {
- IWL_DEBUG(IWL_DL_RF_KILL,
- "HW and/or SW RF Kill no longer active, restarting "
- "device\n");
- if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
- queue_work(priv->workqueue, &priv->restart);
- } else {
- /* make sure mac80211 stop sending Tx frame */
- if (priv->mac80211_registered)
- ieee80211_stop_queues(priv->hw);
-
- if (!test_bit(STATUS_RF_KILL_HW, &priv->status))
- IWL_DEBUG_RF_KILL("Can not turn radio back on - "
- "disabled by SW switch\n");
- else
- IWL_WARN(priv, "Radio Frequency Kill Switch is On:\n"
- "Kill switch must be turned off for "
- "wireless networking to work.\n");
- }
- mutex_unlock(&priv->mutex);
- iwl_rfkill_set_hw_state(priv);
-}
-
static void iwl_bg_run_time_calib_work(struct work_struct *work)
{
struct iwl_priv *priv = container_of(work, struct iwl_priv,
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index d2ef3e1..f64e3a4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -1465,3 +1465,38 @@ int iwl_radio_kill_sw_enable_radio(struct iwl_priv *priv)
return 1;
}
EXPORT_SYMBOL(iwl_radio_kill_sw_enable_radio);
+
+void iwl_bg_rf_kill(struct work_struct *work)
+{
+ struct iwl_priv *priv = container_of(work, struct iwl_priv, rf_kill);
+
+ wake_up_interruptible(&priv->wait_command_queue);
+
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ return;
+
+ mutex_lock(&priv->mutex);
+
+ if (!iwl_is_rfkill(priv)) {
+ IWL_DEBUG(IWL_DL_RF_KILL,
+ "HW and/or SW RF Kill no longer active, restarting "
+ "device\n");
+ if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
+ queue_work(priv->workqueue, &priv->restart);
+ } else {
+ /* make sure mac80211 stop sending Tx frame */
+ if (priv->mac80211_registered)
+ ieee80211_stop_queues(priv->hw);
+
+ if (!test_bit(STATUS_RF_KILL_HW, &priv->status))
+ IWL_DEBUG_RF_KILL("Can not turn radio back on - "
+ "disabled by SW switch\n");
+ else
+ IWL_WARN(priv, "Radio Frequency Kill Switch is On:\n"
+ "Kill switch must be turned off for "
+ "wireless networking to work.\n");
+ }
+ mutex_unlock(&priv->mutex);
+ iwl_rfkill_set_hw_state(priv);
+}
+EXPORT_SYMBOL(iwl_bg_rf_kill);
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 466130f..5ceeedc 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -267,7 +267,7 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force);
* RF -Kill - here and not in iwl-rfkill.h to be available when
* RF-kill subsystem is not compiled.
****************************************************/
-void iwl_rf_kill(struct iwl_priv *priv);
+void iwl_bg_rf_kill(struct work_struct *work);
void iwl_radio_kill_sw_disable_radio(struct iwl_priv *priv);
int iwl_radio_kill_sw_enable_radio(struct iwl_priv *priv);

diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index ee7bccf..be02272 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -5464,39 +5464,6 @@ static void iwl3945_bg_alive_start(struct work_struct *data)
mutex_unlock(&priv->mutex);
}

-static void iwl3945_bg_rf_kill(struct work_struct *work)
-{
- struct iwl_priv *priv = container_of(work, struct iwl_priv, rf_kill);
-
- wake_up_interruptible(&priv->wait_command_queue);
-
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
- return;
-
- mutex_lock(&priv->mutex);
-
- if (!iwl_is_rfkill(priv)) {
- IWL_DEBUG(IWL_DL_INFO | IWL_DL_RF_KILL,
- "HW and/or SW RF Kill no longer active, restarting "
- "device\n");
- if (!test_bit(STATUS_EXIT_PENDING, &priv->status) &&
- test_bit(STATUS_ALIVE, &priv->status))
- queue_work(priv->workqueue, &priv->restart);
- } else {
-
- if (!test_bit(STATUS_RF_KILL_HW, &priv->status))
- IWL_DEBUG_RF_KILL("Can not turn radio back on - "
- "disabled by SW switch\n");
- else
- IWL_WARN(priv, "Radio Frequency Kill Switch is On:\n"
- "Kill switch must be turned off for "
- "wireless networking to work.\n");
- }
-
- mutex_unlock(&priv->mutex);
- iwl3945_rfkill_set_hw_state(priv);
-}
-
static void iwl3945_rfkill_poll(struct work_struct *data)
{
struct iwl_priv *priv =
@@ -5745,7 +5712,7 @@ static void iwl3945_bg_up(struct work_struct *data)
mutex_lock(&priv->mutex);
__iwl3945_up(priv);
mutex_unlock(&priv->mutex);
- iwl3945_rfkill_set_hw_state(priv);
+ iwl_rfkill_set_hw_state(priv);
}

static void iwl3945_bg_restart(struct work_struct *data)
@@ -5938,7 +5905,7 @@ static int iwl3945_mac_start(struct ieee80211_hw *hw)

mutex_unlock(&priv->mutex);

- iwl3945_rfkill_set_hw_state(priv);
+ iwl_rfkill_set_hw_state(priv);

if (ret)
goto out_release_irq;
@@ -7208,7 +7175,7 @@ static void iwl3945_setup_deferred_work(struct iwl_priv *priv)
INIT_WORK(&priv->scan_completed, iwl3945_bg_scan_completed);
INIT_WORK(&priv->request_scan, iwl3945_bg_request_scan);
INIT_WORK(&priv->abort_scan, iwl3945_bg_abort_scan);
- INIT_WORK(&priv->rf_kill, iwl3945_bg_rf_kill);
+ INIT_WORK(&priv->rf_kill, iwl_bg_rf_kill);
INIT_WORK(&priv->beacon_update, iwl3945_bg_beacon_update);
INIT_DELAYED_WORK(&priv->init_alive_start, iwl3945_bg_init_alive_start);
INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start);
@@ -7536,7 +7503,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
priv->hw->conf.beacon_int = 100;
priv->mac80211_registered = 1;

- err = iwl3945_rfkill_init(priv);
+ err = iwl_rfkill_init(priv);
if (err)
IWL_ERR(priv, "Unable to initialize RFKILL system. "
"Ignoring error: %d\n", err);
@@ -7602,7 +7569,7 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)

sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group);

- iwl3945_rfkill_unregister(priv);
+ iwl_rfkill_unregister(priv);
cancel_delayed_work(&priv->rfkill_poll);

iwl3945_dealloc_ucode_pci(priv);
@@ -7675,114 +7642,6 @@ static int iwl3945_pci_resume(struct pci_dev *pdev)

#endif /* CONFIG_PM */

-/*************** RFKILL FUNCTIONS **********/
-#ifdef CONFIG_IWL3945_RFKILL
-/* software rf-kill from user */
-static int iwl3945_rfkill_soft_rf_kill(void *data, enum rfkill_state state)
-{
- struct iwl_priv *priv = data;
- int err = 0;
-
- if (!priv->rfkill)
- return 0;
-
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
- return 0;
-
- IWL_DEBUG_RF_KILL("we received soft RFKILL set to state %d\n", state);
- mutex_lock(&priv->mutex);
-
- switch (state) {
- case RFKILL_STATE_UNBLOCKED:
- if (iwl_is_rfkill_hw(priv)) {
- err = -EBUSY;
- goto out_unlock;
- }
- iwl3945_radio_kill_sw(priv, 0);
- break;
- case RFKILL_STATE_SOFT_BLOCKED:
- iwl3945_radio_kill_sw(priv, 1);
- break;
- default:
- IWL_WARN(priv, "received unexpected RFKILL state %d\n", state);
- break;
- }
-out_unlock:
- mutex_unlock(&priv->mutex);
-
- return err;
-}
-
-int iwl3945_rfkill_init(struct iwl_priv *priv)
-{
- struct device *device = wiphy_dev(priv->hw->wiphy);
- int ret = 0;
-
- BUG_ON(device == NULL);
-
- IWL_DEBUG_RF_KILL("Initializing RFKILL.\n");
- priv->rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN);
- if (!priv->rfkill) {
- IWL_ERR(priv, "Unable to allocate rfkill device.\n");
- ret = -ENOMEM;
- goto error;
- }
-
- priv->rfkill->name = priv->cfg->name;
- priv->rfkill->data = priv;
- priv->rfkill->state = RFKILL_STATE_UNBLOCKED;
- priv->rfkill->toggle_radio = iwl3945_rfkill_soft_rf_kill;
- priv->rfkill->user_claim_unsupported = 1;
-
- priv->rfkill->dev.class->suspend = NULL;
- priv->rfkill->dev.class->resume = NULL;
-
- ret = rfkill_register(priv->rfkill);
- if (ret) {
- IWL_ERR(priv, "Unable to register rfkill: %d\n", ret);
- goto freed_rfkill;
- }
-
- IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n");
- return ret;
-
-freed_rfkill:
- if (priv->rfkill != NULL)
- rfkill_free(priv->rfkill);
- priv->rfkill = NULL;
-
-error:
- IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n");
- return ret;
-}
-
-void iwl3945_rfkill_unregister(struct iwl_priv *priv)
-{
- if (priv->rfkill)
- rfkill_unregister(priv->rfkill);
-
- priv->rfkill = NULL;
-}
-
-/* set rf-kill to the right state. */
-void iwl3945_rfkill_set_hw_state(struct iwl_priv *priv)
-{
-
- if (!priv->rfkill)
- return;
-
- if (iwl_is_rfkill_hw(priv)) {
- rfkill_force_state(priv->rfkill, RFKILL_STATE_HARD_BLOCKED);
- return;
- }
-
- if (!iwl_is_rfkill_sw(priv))
- rfkill_force_state(priv->rfkill, RFKILL_STATE_UNBLOCKED);
- else
- rfkill_force_state(priv->rfkill, RFKILL_STATE_SOFT_BLOCKED);
-}
-#endif
-
/*****************************************************************************
*
* driver and module entry point
--
1.5.4.3


2009-01-21 07:01:49

by Helmut Schaa

[permalink] [raw]
Subject: Re: [ipw3945-devel] [PATCH 4/5] iwl3945: Use iwl-rfkill

Hi,

Am Mittwoch, 21. Januar 2009 schrieb Reinette Chatre:
> From: Samuel Ortiz <[email protected]>
>
> Here again, the rfkill routines are duplicated between agn and 3945. Let's
> move the agn one to iwlcore, and so we can get rid of the 3945 ones.

[...]

> +void iwl_bg_rf_kill(struct work_struct *work)
> +{
> + struct iwl_priv *priv = container_of(work, struct iwl_priv, rf_kill);
> +
> + wake_up_interruptible(&priv->wait_command_queue);
> +
> + if (test_bit(STATUS_EXIT_PENDING, &priv->status))
> + return;
> +
> + mutex_lock(&priv->mutex);
> +
> + if (!iwl_is_rfkill(priv)) {
> + IWL_DEBUG(IWL_DL_RF_KILL,
> + "HW and/or SW RF Kill no longer active, restarting "
> + "device\n");
> + if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
> + queue_work(priv->workqueue, &priv->restart);

I've changed this check in both rf-kill patches (3945 and agn) to

if (!test_bit(STATUS_EXIT_PENDING, &priv->status) &&
test_bit(STATUS_ALIVE, &priv->status))

in order to avoid restarting the adapter when notified about rfkill changes
by interrupt/polling.

I guess this is just an oversight, right?

Thanks,
Helmut