* [PATCH 14/29] wl12xx: make WL1271_FLAG_AP_STARTED flag per-vif
From: Eliad Peller @ 2011-10-10 8:13 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
In-Reply-To: <1318234397-21081-1-git-send-email-eliad@wizery.com>
This flag should be set per-vif, rather than globally.
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
drivers/net/wireless/wl12xx/main.c | 14 +++++++-------
drivers/net/wireless/wl12xx/tx.c | 2 +-
drivers/net/wireless/wl12xx/wl12xx.h | 2 +-
3 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 092b3b5..4c4b34d 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -1235,7 +1235,7 @@ static void wl1271_recovery_work(struct work_struct *work)
*/
wl12xx_for_each_wlvif(wl, wlvif) {
if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags) ||
- test_bit(WL1271_FLAG_AP_STARTED, &wl->flags))
+ test_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags))
wlvif->tx_security_seq +=
WL1271_TX_SQN_POST_RECOVERY_PADDING;
}
@@ -1662,7 +1662,7 @@ static int wl1271_configure_suspend_ap(struct wl1271 *wl,
mutex_lock(&wl->mutex);
- if (!test_bit(WL1271_FLAG_AP_STARTED, &wl->flags))
+ if (!test_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags))
goto out_unlock;
ret = wl1271_ps_elp_wakeup(wl);
@@ -2758,7 +2758,7 @@ static int wl1271_set_key(struct wl1271 *wl, struct wl12xx_vif *wlvif,
hlid = wlvif->ap.bcast_hlid;
}
- if (!test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) {
+ if (!test_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags)) {
/*
* We do not support removing keys after AP shutdown.
* Pretend we do to make mac80211 happy.
@@ -3416,7 +3416,7 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl,
if ((changed & BSS_CHANGED_BEACON_ENABLED)) {
if (bss_conf->enable_beacon) {
- if (!test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) {
+ if (!test_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags)) {
ret = wl12xx_cmd_role_start_ap(wl, wlvif);
if (ret < 0)
goto out;
@@ -3425,16 +3425,16 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl,
if (ret < 0)
goto out;
- set_bit(WL1271_FLAG_AP_STARTED, &wl->flags);
+ set_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags);
wl1271_debug(DEBUG_AP, "started AP");
}
} else {
- if (test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) {
+ if (test_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags)) {
ret = wl12xx_cmd_role_stop_ap(wl, wlvif);
if (ret < 0)
goto out;
- clear_bit(WL1271_FLAG_AP_STARTED, &wl->flags);
+ clear_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags);
wl1271_debug(DEBUG_AP, "stopped AP");
}
}
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index 5ad4173..a6bc979 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -168,7 +168,7 @@ u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif,
} else {
struct ieee80211_hdr *hdr;
- if (!test_bit(WL1271_FLAG_AP_STARTED, &wl->flags))
+ if (!test_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags))
return wl->system_hlid;
hdr = (struct ieee80211_hdr *)skb->data;
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index aa198a6..042ab07 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -325,7 +325,6 @@ enum wl12xx_flags {
WL1271_FLAG_PSPOLL_FAILURE,
WL1271_FLAG_STA_STATE_SENT,
WL1271_FLAG_FW_TX_BUSY,
- WL1271_FLAG_AP_STARTED,
WL1271_FLAG_IF_INITIALIZED,
WL1271_FLAG_DUMMY_PACKET_PENDING,
WL1271_FLAG_SUSPENDED,
@@ -339,6 +338,7 @@ enum wl12xx_flags {
enum wl12xx_vif_flags {
WLVIF_FLAG_STA_ASSOCIATED,
WLVIF_FLAG_IBSS_JOINED,
+ WLVIF_FLAG_AP_STARTED,
};
struct wl1271_link {
--
1.7.6.401.g6a319
^ permalink raw reply related
* [PATCH 15/29] wl12xx: make WL1271_FLAG_PSM flag per-vif
From: Eliad Peller @ 2011-10-10 8:13 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
In-Reply-To: <1318234397-21081-1-git-send-email-eliad@wizery.com>
move WL1271_FLAG_PSM and WL1271_FLAG_PSM_REQUESTED into
per-vif flags.
These flags should be set per-vif, rather than globally.
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
drivers/net/wireless/wl12xx/event.c | 4 ++--
drivers/net/wireless/wl12xx/main.c | 18 +++++++++---------
drivers/net/wireless/wl12xx/ps.c | 25 +++++++++++++++++--------
drivers/net/wireless/wl12xx/wl12xx.h | 4 ++--
4 files changed, 30 insertions(+), 21 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c
index cfb2835..d8b183b 100644
--- a/drivers/net/wireless/wl12xx/event.c
+++ b/drivers/net/wireless/wl12xx/event.c
@@ -84,7 +84,7 @@ static void wl1271_event_pspoll_delivery_fail(struct wl1271 *wl,
"trying to work around it.");
/* force active mode receive data from the AP */
- if (test_bit(WL1271_FLAG_PSM, &wl->flags)) {
+ if (test_bit(WLVIF_FLAG_PSM, &wlvif->flags)) {
ret = wl1271_ps_set_mode(wl, wlvif, STATION_ACTIVE_MODE,
wlvif->basic_rate, true);
if (ret < 0)
@@ -116,7 +116,7 @@ static int wl1271_event_ps_report(struct wl1271 *wl,
case EVENT_ENTER_POWER_SAVE_FAIL:
wl1271_debug(DEBUG_PSM, "PSM entry failed");
- if (!test_bit(WL1271_FLAG_PSM, &wl->flags)) {
+ if (!test_bit(WLVIF_FLAG_PSM, &wlvif->flags)) {
/* remain in active mode */
wlvif->psm_entry_retry = 0;
break;
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 4c4b34d..9c0a1ac 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -1618,7 +1618,7 @@ static int wl1271_configure_suspend_sta(struct wl1271 *wl,
goto out_unlock;
/* enter psm if needed*/
- if (!test_bit(WL1271_FLAG_PSM, &wl->flags)) {
+ if (!test_bit(WLVIF_FLAG_PSM, &wlvif->flags)) {
DECLARE_COMPLETION_ONSTACK(compl);
wlvif->ps_compl = &compl;
@@ -1705,7 +1705,7 @@ static void wl1271_configure_resume(struct wl1271 *wl,
if (is_sta) {
/* exit psm if it wasn't configured */
- if (!test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags))
+ if (!test_bit(WLVIF_FLAG_PSM_REQUESTED, &wlvif->flags))
wl1271_ps_set_mode(wl, wlvif, STATION_ACTIVE_MODE,
wlvif->basic_rate, true);
} else if (is_ap) {
@@ -2502,8 +2502,8 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
clear_bit(WL1271_FLAG_PSPOLL_FAILURE, &wl->flags);
if (conf->flags & IEEE80211_CONF_PS &&
- !test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) {
- set_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags);
+ !test_bit(WLVIF_FLAG_PSM_REQUESTED, &wlvif->flags)) {
+ set_bit(WLVIF_FLAG_PSM_REQUESTED, &wlvif->flags);
/*
* We enter PSM only if we're already associated.
@@ -2517,12 +2517,12 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
wlvif->basic_rate, true);
}
} else if (!(conf->flags & IEEE80211_CONF_PS) &&
- test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) {
+ test_bit(WLVIF_FLAG_PSM_REQUESTED, &wlvif->flags)) {
wl1271_debug(DEBUG_PSM, "psm disabled");
- clear_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags);
+ clear_bit(WLVIF_FLAG_PSM_REQUESTED, &wlvif->flags);
- if (test_bit(WL1271_FLAG_PSM, &wl->flags))
+ if (test_bit(WLVIF_FLAG_PSM, &wlvif->flags))
ret = wl1271_ps_set_mode(wl, wlvif,
STATION_ACTIVE_MODE,
wlvif->basic_rate, true);
@@ -3759,8 +3759,8 @@ sta_not_found:
}
/* If we want to go in PSM but we're not there yet */
- if (test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags) &&
- !test_bit(WL1271_FLAG_PSM, &wl->flags)) {
+ if (test_bit(WLVIF_FLAG_PSM_REQUESTED, &wlvif->flags) &&
+ !test_bit(WLVIF_FLAG_PSM, &wlvif->flags)) {
enum wl1271_cmd_ps_mode mode;
mode = STATION_POWER_SAVE_MODE;
diff --git a/drivers/net/wireless/wl12xx/ps.c b/drivers/net/wireless/wl12xx/ps.c
index ac3f207..8cd81ce 100644
--- a/drivers/net/wireless/wl12xx/ps.c
+++ b/drivers/net/wireless/wl12xx/ps.c
@@ -32,6 +32,7 @@ void wl1271_elp_work(struct work_struct *work)
{
struct delayed_work *dwork;
struct wl1271 *wl;
+ struct wl12xx_vif *wlvif;
dwork = container_of(work, struct delayed_work, work);
wl = container_of(dwork, struct wl1271, elp_work);
@@ -47,11 +48,15 @@ void wl1271_elp_work(struct work_struct *work)
if (unlikely(!test_bit(WL1271_FLAG_ELP_REQUESTED, &wl->flags)))
goto out;
- if (test_bit(WL1271_FLAG_IN_ELP, &wl->flags) ||
- (!test_bit(WL1271_FLAG_PSM, &wl->flags) &&
- !test_bit(WL1271_FLAG_IDLE, &wl->flags)))
+ if (test_bit(WL1271_FLAG_IN_ELP, &wl->flags))
goto out;
+ wl12xx_for_each_wlvif(wl, wlvif) {
+ if (!test_bit(WLVIF_FLAG_PSM, &wlvif->flags) &&
+ !test_bit(WL1271_FLAG_IDLE, &wl->flags))
+ goto out;
+ }
+
wl1271_debug(DEBUG_PSM, "chip to elp");
wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP);
set_bit(WL1271_FLAG_IN_ELP, &wl->flags);
@@ -65,13 +70,17 @@ out:
/* Routines to toggle sleep mode while in ELP */
void wl1271_ps_elp_sleep(struct wl1271 *wl)
{
+ struct wl12xx_vif *wlvif;
+
/* we shouldn't get consecutive sleep requests */
if (WARN_ON(test_and_set_bit(WL1271_FLAG_ELP_REQUESTED, &wl->flags)))
return;
- if (!test_bit(WL1271_FLAG_PSM, &wl->flags) &&
- !test_bit(WL1271_FLAG_IDLE, &wl->flags))
- return;
+ wl12xx_for_each_wlvif(wl, wlvif) {
+ if (!test_bit(WLVIF_FLAG_PSM, &wlvif->flags) &&
+ !test_bit(WL1271_FLAG_IDLE, &wl->flags))
+ return;
+ }
ieee80211_queue_delayed_work(wl->hw, &wl->elp_work,
msecs_to_jiffies(ELP_ENTRY_DELAY));
@@ -162,7 +171,7 @@ int wl1271_ps_set_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif,
if (ret < 0)
return ret;
- set_bit(WL1271_FLAG_PSM, &wl->flags);
+ set_bit(WLVIF_FLAG_PSM, &wlvif->flags);
break;
case STATION_ACTIVE_MODE:
default:
@@ -184,7 +193,7 @@ int wl1271_ps_set_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif,
if (ret < 0)
return ret;
- clear_bit(WL1271_FLAG_PSM, &wl->flags);
+ clear_bit(WLVIF_FLAG_PSM, &wlvif->flags);
break;
}
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index 042ab07..37498f2 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -318,8 +318,6 @@ enum wl12xx_flags {
WL1271_FLAG_TX_PENDING,
WL1271_FLAG_IN_ELP,
WL1271_FLAG_ELP_REQUESTED,
- WL1271_FLAG_PSM,
- WL1271_FLAG_PSM_REQUESTED,
WL1271_FLAG_IRQ_RUNNING,
WL1271_FLAG_IDLE,
WL1271_FLAG_PSPOLL_FAILURE,
@@ -339,6 +337,8 @@ enum wl12xx_vif_flags {
WLVIF_FLAG_STA_ASSOCIATED,
WLVIF_FLAG_IBSS_JOINED,
WLVIF_FLAG_AP_STARTED,
+ WLVIF_FLAG_PSM,
+ WLVIF_FLAG_PSM_REQUESTED,
};
struct wl1271_link {
--
1.7.6.401.g6a319
^ permalink raw reply related
* [PATCH 16/29] wl12xx: make WL1271_FLAG_STA_STATE_SENT flag per-vif
From: Eliad Peller @ 2011-10-10 8:13 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
In-Reply-To: <1318234397-21081-1-git-send-email-eliad@wizery.com>
This flag should be set per-vif, rather than globally.
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
drivers/net/wireless/wl12xx/main.c | 6 +++---
drivers/net/wireless/wl12xx/wl12xx.h | 2 +-
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 9c0a1ac..92f38c5 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -408,7 +408,7 @@ static int wl1271_check_operstate(struct wl1271 *wl, struct wl12xx_vif *wlvif,
if (operstate != IF_OPER_UP)
return 0;
- if (test_and_set_bit(WL1271_FLAG_STA_STATE_SENT, &wl->flags))
+ if (test_and_set_bit(WLVIF_FLAG_STA_STATE_SENT, &wlvif->flags))
return 0;
ret = wl12xx_cmd_set_peer_state(wl, wlvif->sta.hlid);
@@ -3614,8 +3614,8 @@ sta_not_found:
!!test_and_clear_bit(WLVIF_FLAG_STA_ASSOCIATED,
&wlvif->flags);
bool was_ifup =
- !!test_and_clear_bit(WL1271_FLAG_STA_STATE_SENT,
- &wl->flags);
+ !!test_and_clear_bit(WLVIF_FLAG_STA_STATE_SENT,
+ &wlvif->flags);
wlvif->aid = 0;
/* free probe-request template */
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index 37498f2..6a1df2c 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -321,7 +321,6 @@ enum wl12xx_flags {
WL1271_FLAG_IRQ_RUNNING,
WL1271_FLAG_IDLE,
WL1271_FLAG_PSPOLL_FAILURE,
- WL1271_FLAG_STA_STATE_SENT,
WL1271_FLAG_FW_TX_BUSY,
WL1271_FLAG_IF_INITIALIZED,
WL1271_FLAG_DUMMY_PACKET_PENDING,
@@ -339,6 +338,7 @@ enum wl12xx_vif_flags {
WLVIF_FLAG_AP_STARTED,
WLVIF_FLAG_PSM,
WLVIF_FLAG_PSM_REQUESTED,
+ WLVIF_FLAG_STA_STATE_SENT,
};
struct wl1271_link {
--
1.7.6.401.g6a319
^ permalink raw reply related
* [PATCH 17/29] wl12xx: make WL1271_FLAG_RX_STREAMING_STARTED flag per-vif
From: Eliad Peller @ 2011-10-10 8:13 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
In-Reply-To: <1318234397-21081-1-git-send-email-eliad@wizery.com>
This flag should be set per-vif, rather than globally.
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
drivers/net/wireless/wl12xx/main.c | 10 +++++-----
drivers/net/wireless/wl12xx/tx.c | 2 +-
drivers/net/wireless/wl12xx/wl12xx.h | 2 +-
3 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 92f38c5..36c7493 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -514,9 +514,9 @@ static int wl1271_set_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif,
goto out;
if (enable)
- set_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags);
+ set_bit(WLVIF_FLAG_RX_STREAMING_STARTED, &wlvif->flags);
else
- clear_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags);
+ clear_bit(WLVIF_FLAG_RX_STREAMING_STARTED, &wlvif->flags);
out:
return ret;
}
@@ -531,7 +531,7 @@ int wl1271_recalc_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif)
int period = wl->conf.rx_streaming.interval;
/* don't reconfigure if rx_streaming is disabled */
- if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags))
+ if (!test_bit(WLVIF_FLAG_RX_STREAMING_STARTED, &wlvif->flags))
goto out;
/* reconfigure/disable according to new streaming_period */
@@ -558,7 +558,7 @@ static void wl1271_rx_streaming_enable_work(struct work_struct *work)
mutex_lock(&wl->mutex);
- if (test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags) ||
+ if (test_bit(WLVIF_FLAG_RX_STREAMING_STARTED, &wlvif->flags) ||
!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags) ||
(!wl->conf.rx_streaming.always &&
!test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags)))
@@ -594,7 +594,7 @@ static void wl1271_rx_streaming_disable_work(struct work_struct *work)
mutex_lock(&wl->mutex);
- if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags))
+ if (!test_bit(WLVIF_FLAG_RX_STREAMING_STARTED, &wlvif->flags))
goto out;
ret = wl1271_ps_elp_wakeup(wl);
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index a6bc979..9589446 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -670,7 +670,7 @@ void wl12xx_rearm_rx_streaming(struct wl1271 *wl, unsigned long *active_hlids)
continue;
/* enable rx streaming */
- if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags))
+ if (!test_bit(WLVIF_FLAG_RX_STREAMING_STARTED, &wlvif->flags))
ieee80211_queue_work(wl->hw,
&wlvif->rx_streaming_enable_work);
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index 6a1df2c..4741a4b 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -327,7 +327,6 @@ enum wl12xx_flags {
WL1271_FLAG_SUSPENDED,
WL1271_FLAG_PENDING_WORK,
WL1271_FLAG_SOFT_GEMINI,
- WL1271_FLAG_RX_STREAMING_STARTED,
WL1271_FLAG_RECOVERY_IN_PROGRESS,
WL1271_FLAG_CS_PROGRESS,
};
@@ -339,6 +338,7 @@ enum wl12xx_vif_flags {
WLVIF_FLAG_PSM,
WLVIF_FLAG_PSM_REQUESTED,
WLVIF_FLAG_STA_STATE_SENT,
+ WLVIF_FLAG_RX_STREAMING_STARTED,
};
struct wl1271_link {
--
1.7.6.401.g6a319
^ permalink raw reply related
* [PATCH 18/29] wl12xx: make WL1271_FLAG_IF_INITIALIZED per-vif
From: Eliad Peller @ 2011-10-10 8:13 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
In-Reply-To: <1318234397-21081-1-git-send-email-eliad@wizery.com>
Make the initialization flag per-vif, and add some checks for it.
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
drivers/net/wireless/wl12xx/main.c | 32 +++++++++++++++++++++++++-------
drivers/net/wireless/wl12xx/wl12xx.h | 2 +-
2 files changed, 26 insertions(+), 8 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 36c7493..25599ad 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -1817,14 +1817,20 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
wl1271_debug(DEBUG_MAC80211, "mac80211 stop");
- mutex_lock(&wl_list_mutex);
- list_del(&wl->list);
-
+ mutex_lock(&wl->mutex);
+ if (wl->state == WL1271_STATE_OFF) {
+ mutex_unlock(&wl->mutex);
+ return;
+ }
/*
* this must be before the cancel_work calls below, so that the work
* functions don't perform further work.
*/
wl->state = WL1271_STATE_OFF;
+ mutex_unlock(&wl->mutex);
+
+ mutex_lock(&wl_list_mutex);
+ list_del(&wl->list);
mutex_unlock(&wl_list_mutex);
wl1271_disable_interrupts(wl);
@@ -1971,7 +1977,6 @@ static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif)
setup_timer(&wlvif->rx_streaming_timer, wl1271_rx_streaming_timer,
(unsigned long) wlvif);
-
return 0;
}
@@ -2069,7 +2074,8 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
* get here before __wl1271_op_remove_interface is complete, so
* opt out if that is the case.
*/
- if (test_bit(WL1271_FLAG_IF_INITIALIZED, &wl->flags)) {
+ if (test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags) ||
+ test_bit(WLVIF_FLAG_INITIALIZED, &wlvif->flags)) {
ret = -EBUSY;
goto out;
}
@@ -2129,7 +2135,7 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
wl->vif = vif;
list_add(&wlvif->list, &wl->wlvif_list);
- set_bit(WL1271_FLAG_IF_INITIALIZED, &wl->flags);
+ set_bit(WLVIF_FLAG_INITIALIZED, &wlvif->flags);
out:
mutex_unlock(&wl->mutex);
@@ -2150,6 +2156,9 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface");
+ if (!test_and_clear_bit(WLVIF_FLAG_INITIALIZED, &wlvif->flags))
+ return;
+
/* because of hardware recovery, we may get here twice */
if (wl->state != WL1271_STATE_ON)
return;
@@ -2214,8 +2223,14 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct wl1271 *wl = hw->priv;
+ struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
mutex_lock(&wl->mutex);
+
+ if (wl->state == WL1271_STATE_OFF ||
+ !test_bit(WLVIF_FLAG_INITIALIZED, &wlvif->flags))
+ goto out;
+
/*
* wl->vif can be null here if someone shuts down the interface
* just when hardware recovery has been started.
@@ -2224,7 +2239,7 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
WARN_ON(wl->vif != vif);
__wl1271_op_remove_interface(wl, vif, true);
}
-
+out:
mutex_unlock(&wl->mutex);
cancel_work_sync(&wl->recovery_work);
}
@@ -3833,6 +3848,9 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
if (unlikely(wl->state == WL1271_STATE_OFF))
goto out;
+ if (unlikely(!test_bit(WLVIF_FLAG_INITIALIZED, &wlvif->flags)))
+ goto out;
+
ret = wl1271_ps_elp_wakeup(wl);
if (ret < 0)
goto out;
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index 4741a4b..88d48b1 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -322,7 +322,6 @@ enum wl12xx_flags {
WL1271_FLAG_IDLE,
WL1271_FLAG_PSPOLL_FAILURE,
WL1271_FLAG_FW_TX_BUSY,
- WL1271_FLAG_IF_INITIALIZED,
WL1271_FLAG_DUMMY_PACKET_PENDING,
WL1271_FLAG_SUSPENDED,
WL1271_FLAG_PENDING_WORK,
@@ -332,6 +331,7 @@ enum wl12xx_flags {
};
enum wl12xx_vif_flags {
+ WLVIF_FLAG_INITIALIZED,
WLVIF_FLAG_STA_ASSOCIATED,
WLVIF_FLAG_IBSS_JOINED,
WLVIF_FLAG_AP_STARTED,
--
1.7.6.401.g6a319
^ permalink raw reply related
* [PATCH 19/29] wl12xx: make WL1271_FLAG_PSPOLL_FAILURE flag per-vif
From: Eliad Peller @ 2011-10-10 8:13 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
In-Reply-To: <1318234397-21081-1-git-send-email-eliad@wizery.com>
This flag should be set per-vif, rather than globally.
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
drivers/net/wireless/wl12xx/event.c | 4 ++--
drivers/net/wireless/wl12xx/main.c | 2 +-
drivers/net/wireless/wl12xx/wl12xx.h | 2 +-
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c
index d8b183b..1f60a1f 100644
--- a/drivers/net/wireless/wl12xx/event.c
+++ b/drivers/net/wireless/wl12xx/event.c
@@ -49,7 +49,7 @@ void wl1271_pspoll_work(struct work_struct *work)
if (unlikely(wl->state == WL1271_STATE_OFF))
goto out;
- if (!test_and_clear_bit(WL1271_FLAG_PSPOLL_FAILURE, &wl->flags))
+ if (!test_and_clear_bit(WLVIF_FLAG_PSPOLL_FAILURE, &wlvif->flags))
goto out;
if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
@@ -89,7 +89,7 @@ static void wl1271_event_pspoll_delivery_fail(struct wl1271 *wl,
wlvif->basic_rate, true);
if (ret < 0)
return;
- set_bit(WL1271_FLAG_PSPOLL_FAILURE, &wl->flags);
+ set_bit(WLVIF_FLAG_PSPOLL_FAILURE, &wlvif->flags);
ieee80211_queue_delayed_work(wl->hw, &wlvif->pspoll_work,
msecs_to_jiffies(delay));
}
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 25599ad..c54c456 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -2514,7 +2514,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
* incorrectly changed after the pspoll failure active window.
*/
if (changed & IEEE80211_CONF_CHANGE_PS)
- clear_bit(WL1271_FLAG_PSPOLL_FAILURE, &wl->flags);
+ clear_bit(WLVIF_FLAG_PSPOLL_FAILURE, &wlvif->flags);
if (conf->flags & IEEE80211_CONF_PS &&
!test_bit(WLVIF_FLAG_PSM_REQUESTED, &wlvif->flags)) {
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index 88d48b1..9701784 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -320,7 +320,6 @@ enum wl12xx_flags {
WL1271_FLAG_ELP_REQUESTED,
WL1271_FLAG_IRQ_RUNNING,
WL1271_FLAG_IDLE,
- WL1271_FLAG_PSPOLL_FAILURE,
WL1271_FLAG_FW_TX_BUSY,
WL1271_FLAG_DUMMY_PACKET_PENDING,
WL1271_FLAG_SUSPENDED,
@@ -339,6 +338,7 @@ enum wl12xx_vif_flags {
WLVIF_FLAG_PSM_REQUESTED,
WLVIF_FLAG_STA_STATE_SENT,
WLVIF_FLAG_RX_STREAMING_STARTED,
+ WLVIF_FLAG_PSPOLL_FAILURE,
};
struct wl1271_link {
--
1.7.6.401.g6a319
^ permalink raw reply related
* [PATCH 20/29] wl12xx: make WL1271_FLAG_CS_PROGRESS flag per-vif
From: Eliad Peller @ 2011-10-10 8:13 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
In-Reply-To: <1318234397-21081-1-git-send-email-eliad@wizery.com>
This flag should be set per-vif, rather than globally.
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
drivers/net/wireless/wl12xx/event.c | 22 ++++++++++++----------
drivers/net/wireless/wl12xx/main.c | 12 ++++++++----
drivers/net/wireless/wl12xx/wl12xx.h | 2 +-
3 files changed, 21 insertions(+), 15 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c
index 1f60a1f..a47312d 100644
--- a/drivers/net/wireless/wl12xx/event.c
+++ b/drivers/net/wireless/wl12xx/event.c
@@ -345,16 +345,18 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
* 1) channel switch complete with status=0
* 2) channel switch failed status=1
*/
- if (test_and_clear_bit(WL1271_FLAG_CS_PROGRESS, &wl->flags)) {
- /* TODO: configure only the relevant vif */
- wl12xx_for_each_wlvif_sta(wl, wlvif) {
- struct ieee80211_vif *vif =
- wl12xx_wlvif_to_vif(wlvif);
- bool success = mbox->channel_switch_status ?
- false : true;
-
- ieee80211_chswitch_done(vif, success);
- }
+
+ /* TODO: configure only the relevant vif */
+ wl12xx_for_each_wlvif_sta(wl, wlvif) {
+ struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
+ bool success;
+
+ if (!test_and_clear_bit(WLVIF_FLAG_CS_PROGRESS,
+ &wl->flags))
+ continue;
+
+ success = mbox->channel_switch_status ? false : true;
+ ieee80211_chswitch_done(vif, success);
}
}
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index c54c456..90f04f1 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -2307,7 +2307,7 @@ static int wl1271_unjoin(struct wl1271 *wl, struct wl12xx_vif *wlvif)
{
int ret;
- if (test_and_clear_bit(WL1271_FLAG_CS_PROGRESS, &wl->flags)) {
+ if (test_and_clear_bit(WLVIF_FLAG_CS_PROGRESS, &wlvif->flags)) {
wl12xx_cmd_stop_channel_switch(wl);
ieee80211_chswitch_done(wl->vif, false);
}
@@ -4265,6 +4265,7 @@ static void wl12xx_op_channel_switch(struct ieee80211_hw *hw,
struct ieee80211_channel_switch *ch_switch)
{
struct wl1271 *wl = hw->priv;
+ struct wl12xx_vif *wlvif;
int ret;
wl1271_debug(DEBUG_MAC80211, "mac80211 channel switch");
@@ -4281,10 +4282,13 @@ static void wl12xx_op_channel_switch(struct ieee80211_hw *hw,
if (ret < 0)
goto out;
- ret = wl12xx_cmd_channel_switch(wl, ch_switch);
+ /* TODO: change mac80211 to pass vif as param */
+ wl12xx_for_each_wlvif_sta(wl, wlvif) {
+ ret = wl12xx_cmd_channel_switch(wl, ch_switch);
- if (!ret)
- set_bit(WL1271_FLAG_CS_PROGRESS, &wl->flags);
+ if (!ret)
+ set_bit(WLVIF_FLAG_CS_PROGRESS, &wlvif->flags);
+ }
wl1271_ps_elp_sleep(wl);
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index 9701784..b76713d 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -326,7 +326,6 @@ enum wl12xx_flags {
WL1271_FLAG_PENDING_WORK,
WL1271_FLAG_SOFT_GEMINI,
WL1271_FLAG_RECOVERY_IN_PROGRESS,
- WL1271_FLAG_CS_PROGRESS,
};
enum wl12xx_vif_flags {
@@ -339,6 +338,7 @@ enum wl12xx_vif_flags {
WLVIF_FLAG_STA_STATE_SENT,
WLVIF_FLAG_RX_STREAMING_STARTED,
WLVIF_FLAG_PSPOLL_FAILURE,
+ WLVIF_FLAG_CS_PROGRESS,
};
struct wl1271_link {
--
1.7.6.401.g6a319
^ permalink raw reply related
* [PATCH 21/29] wl12xx: add band field to wlvif
From: Eliad Peller @ 2011-10-10 8:13 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
In-Reply-To: <1318234397-21081-1-git-send-email-eliad@wizery.com>
add band field into the per-interface data.
mac80211 configures some values (e.g. band, channel)
globally, while we configure them per-interface.
In order to make it easier to keep track of the
configured value for each value while keeping sync
with mac80211, save these values both globally
and per-vif.
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
drivers/net/wireless/wl12xx/cmd.c | 32 +++++++++++++++++---------------
drivers/net/wireless/wl12xx/cmd.h | 5 +++--
drivers/net/wireless/wl12xx/event.c | 2 +-
drivers/net/wireless/wl12xx/main.c | 32 ++++++++++++++++++++------------
drivers/net/wireless/wl12xx/ps.c | 2 +-
drivers/net/wireless/wl12xx/scan.c | 2 +-
drivers/net/wireless/wl12xx/tx.c | 5 +++--
drivers/net/wireless/wl12xx/wl12xx.h | 3 +++
8 files changed, 49 insertions(+), 34 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c
index ff653e8..6cf8cdc 100644
--- a/drivers/net/wireless/wl12xx/cmd.c
+++ b/drivers/net/wireless/wl12xx/cmd.c
@@ -481,7 +481,7 @@ int wl12xx_cmd_role_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif)
wl1271_debug(DEBUG_CMD, "cmd role start dev %d", wlvif->dev_role_id);
cmd->role_id = wlvif->dev_role_id;
- if (wl->band == IEEE80211_BAND_5GHZ)
+ if (wlvif->band == IEEE80211_BAND_5GHZ)
cmd->band = WL12XX_BAND_5GHZ;
cmd->channel = wl->channel;
@@ -571,7 +571,7 @@ int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif)
wl1271_debug(DEBUG_CMD, "cmd role start sta %d", wlvif->role_id);
cmd->role_id = wlvif->role_id;
- if (wl->band == IEEE80211_BAND_5GHZ)
+ if (wlvif->band == IEEE80211_BAND_5GHZ)
cmd->band = WL12XX_BAND_5GHZ;
cmd->channel = wl->channel;
cmd->sta.basic_rate_set = cpu_to_le32(wlvif->basic_rate_set);
@@ -704,7 +704,7 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif)
cmd->ap.local_rates = cpu_to_le32(0xffffffff);
- switch (wl->band) {
+ switch (wlvif->band) {
case IEEE80211_BAND_2GHZ:
cmd->band = RADIO_BAND_2_4GHZ;
break;
@@ -712,7 +712,7 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif)
cmd->band = RADIO_BAND_5GHZ;
break;
default:
- wl1271_warning("ap start - unknown band: %d", (int)wl->band);
+ wl1271_warning("ap start - unknown band: %d", (int)wlvif->band);
cmd->band = RADIO_BAND_2_4GHZ;
break;
}
@@ -785,7 +785,7 @@ int wl12xx_cmd_role_start_ibss(struct wl1271 *wl, struct wl12xx_vif *wlvif)
wl1271_debug(DEBUG_CMD, "cmd role start ibss %d", wlvif->role_id);
cmd->role_id = wlvif->role_id;
- if (wl->band == IEEE80211_BAND_5GHZ)
+ if (wlvif->band == IEEE80211_BAND_5GHZ)
cmd->band = WL12XX_BAND_5GHZ;
cmd->channel = wl->channel;
cmd->ibss.basic_rate_set = cpu_to_le32(wlvif->basic_rate_set);
@@ -1157,8 +1157,8 @@ struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl,
wl1271_dump(DEBUG_SCAN, "AP PROBE REQ: ", skb->data, skb->len);
- rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[wl->band]);
- if (wl->band == IEEE80211_BAND_2GHZ)
+ rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[wlvif->band]);
+ if (wlvif->band == IEEE80211_BAND_2GHZ)
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4,
skb->data, skb->len, 0, rate);
else
@@ -1428,7 +1428,8 @@ out:
return ret;
}
-int wl12xx_cmd_add_peer(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid)
+int wl12xx_cmd_add_peer(struct wl1271 *wl, struct wl12xx_vif *wlvif,
+ struct ieee80211_sta *sta, u8 hlid)
{
struct wl12xx_cmd_add_peer *cmd;
int i, ret;
@@ -1455,13 +1456,13 @@ int wl12xx_cmd_add_peer(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid)
else
cmd->psd_type[i] = WL1271_PSD_LEGACY;
- sta_rates = sta->supp_rates[wl->band];
+ sta_rates = sta->supp_rates[wlvif->band];
if (sta->ht_cap.ht_supported)
sta_rates |= sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET;
cmd->supported_rates =
cpu_to_le32(wl1271_tx_enabled_rates_get(wl, sta_rates,
- wl->band));
+ wlvif->band));
wl1271_debug(DEBUG_CMD, "new peer rates=0x%x queues=0x%x",
cmd->supported_rates, sta->uapsd_queues);
@@ -1601,7 +1602,8 @@ out:
return ret;
}
-static int wl12xx_cmd_roc(struct wl1271 *wl, u8 role_id)
+static int wl12xx_cmd_roc(struct wl1271 *wl, struct wl12xx_vif *wlvif,
+ u8 role_id)
{
struct wl12xx_cmd_roc *cmd;
int ret = 0;
@@ -1619,7 +1621,7 @@ static int wl12xx_cmd_roc(struct wl1271 *wl, u8 role_id)
cmd->role_id = role_id;
cmd->channel = wl->channel;
- switch (wl->band) {
+ switch (wlvif->band) {
case IEEE80211_BAND_2GHZ:
cmd->band = RADIO_BAND_2_4GHZ;
break;
@@ -1627,7 +1629,7 @@ static int wl12xx_cmd_roc(struct wl1271 *wl, u8 role_id)
cmd->band = RADIO_BAND_5GHZ;
break;
default:
- wl1271_error("roc - unknown band: %d", (int)wl->band);
+ wl1271_error("roc - unknown band: %d", (int)wlvif->band);
ret = -EINVAL;
goto out_free;
}
@@ -1674,14 +1676,14 @@ out:
return ret;
}
-int wl12xx_roc(struct wl1271 *wl, u8 role_id)
+int wl12xx_roc(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 role_id)
{
int ret = 0;
if (WARN_ON(test_bit(role_id, wl->roc_map)))
return 0;
- ret = wl12xx_cmd_roc(wl, role_id);
+ ret = wl12xx_cmd_roc(wl, wlvif, role_id);
if (ret < 0)
goto out;
diff --git a/drivers/net/wireless/wl12xx/cmd.h b/drivers/net/wireless/wl12xx/cmd.h
index 8182cf1..968d5bd 100644
--- a/drivers/net/wireless/wl12xx/cmd.h
+++ b/drivers/net/wireless/wl12xx/cmd.h
@@ -80,9 +80,10 @@ int wl1271_cmd_set_ap_key(struct wl1271 *wl, struct wl12xx_vif *wlvif,
u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32,
u16 tx_seq_16);
int wl12xx_cmd_set_peer_state(struct wl1271 *wl, u8 hlid);
-int wl12xx_roc(struct wl1271 *wl, u8 role_id);
+int wl12xx_roc(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 role_id);
int wl12xx_croc(struct wl1271 *wl, u8 role_id);
-int wl12xx_cmd_add_peer(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid);
+int wl12xx_cmd_add_peer(struct wl1271 *wl, struct wl12xx_vif *wlvif,
+ struct ieee80211_sta *sta, u8 hlid);
int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid);
int wl12xx_cmd_config_fwlog(struct wl1271 *wl);
int wl12xx_cmd_start_fwlog(struct wl1271 *wl);
diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c
index a47312d..fd2e7b2 100644
--- a/drivers/net/wireless/wl12xx/event.c
+++ b/drivers/net/wireless/wl12xx/event.c
@@ -145,7 +145,7 @@ static int wl1271_event_ps_report(struct wl1271 *wl,
* BET has only a minor effect in 5GHz and masks
* channel switch IEs, so we only enable BET on 2.4GHz
*/
- if (wl->band == IEEE80211_BAND_2GHZ)
+ if (wlvif->band == IEEE80211_BAND_2GHZ)
/* enable beacon early termination */
ret = wl1271_acx_bet_enable(wl, wlvif, true);
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 90f04f1..0974ed6 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -1968,6 +1968,12 @@ static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif)
wlvif->rate_set = CONF_TX_RATE_MASK_BASIC;
wlvif->beacon_int = WL1271_DEFAULT_BEACON_INT;
+ /*
+ * mac80211 configures some values globally, while we treat them
+ * per-interface. thus, on init, we have to copy them from wl
+ */
+ wlvif->band = wl->band;
+
INIT_WORK(&wlvif->rx_streaming_enable_work,
wl1271_rx_streaming_enable_work);
INIT_WORK(&wlvif->rx_streaming_disable_work,
@@ -2327,7 +2333,7 @@ out:
static void wl1271_set_band_rate(struct wl1271 *wl, struct wl12xx_vif *wlvif)
{
- wlvif->basic_rate_set = wlvif->bitrate_masks[wl->band];
+ wlvif->basic_rate_set = wlvif->bitrate_masks[wlvif->band];
wlvif->rate_set = wlvif->basic_rate_set;
}
@@ -2380,7 +2386,7 @@ static int wl1271_sta_handle_idle(struct wl1271 *wl, struct wl12xx_vif *wlvif,
if (ret < 0)
goto out;
- ret = wl12xx_roc(wl, wlvif->dev_role_id);
+ ret = wl12xx_roc(wl, wlvif, wlvif->dev_role_id);
if (ret < 0)
goto out;
clear_bit(WL1271_FLAG_IDLE, &wl->flags);
@@ -2441,11 +2447,12 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
/* if the channel changes while joined, join again */
if (changed & IEEE80211_CONF_CHANGE_CHANNEL &&
- ((wl->band != conf->channel->band) ||
+ ((wlvif->band != conf->channel->band) ||
(wl->channel != channel))) {
/* send all pending packets */
wl1271_tx_work_locked(wl);
wl->band = conf->channel->band;
+ wlvif->band = conf->channel->band;
wl->channel = channel;
if (!is_ap) {
@@ -2492,7 +2499,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
if (ret < 0)
goto out_sleep;
- ret = wl12xx_roc(wl,
+ ret = wl12xx_roc(wl, wlvif,
wlvif->dev_role_id);
if (ret < 0)
wl1271_warning("roc failed %d",
@@ -3410,7 +3417,7 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl,
u32 rates = bss_conf->basic_rates;
wlvif->basic_rate_set = wl1271_tx_enabled_rates_get(wl, rates,
- wl->band);
+ wlvif->band);
wlvif->basic_rate = wl1271_tx_min_rate_get(wl,
wlvif->basic_rate_set);
@@ -3506,7 +3513,7 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
&wlvif->flags)) {
wl1271_unjoin(wl, wlvif);
wl12xx_cmd_role_start_dev(wl, wlvif);
- wl12xx_roc(wl, wlvif->dev_role_id);
+ wl12xx_roc(wl, wlvif, wlvif->dev_role_id);
}
}
}
@@ -3585,7 +3592,7 @@ sta_not_found:
rates = bss_conf->basic_rates;
wlvif->basic_rate_set =
wl1271_tx_enabled_rates_get(wl, rates,
- wl->band);
+ wlvif->band);
wlvif->basic_rate =
wl1271_tx_min_rate_get(wl,
wlvif->basic_rate_set);
@@ -3593,7 +3600,7 @@ sta_not_found:
wlvif->rate_set =
wl1271_tx_enabled_rates_get(wl,
sta_rate_set,
- wl->band);
+ wlvif->band);
ret = wl1271_acx_sta_rate_policies(wl, wlvif);
if (ret < 0)
goto out;
@@ -3684,7 +3691,8 @@ sta_not_found:
wl1271_unjoin(wl, wlvif);
if (!(conf_flags & IEEE80211_CONF_IDLE)) {
wl12xx_cmd_role_start_dev(wl, wlvif);
- wl12xx_roc(wl, wlvif->dev_role_id);
+ wl12xx_roc(wl, wlvif,
+ wlvif->dev_role_id);
}
}
}
@@ -3698,7 +3706,7 @@ sta_not_found:
u32 rates = bss_conf->basic_rates;
wlvif->basic_rate_set =
wl1271_tx_enabled_rates_get(wl, rates,
- wl->band);
+ wlvif->band);
wlvif->basic_rate =
wl1271_tx_min_rate_get(wl,
wlvif->basic_rate_set);
@@ -3752,7 +3760,7 @@ sta_not_found:
/* ROC until connected (after EAPOL exchange) */
if (!is_ibss) {
- ret = wl12xx_roc(wl, wlvif->role_id);
+ ret = wl12xx_roc(wl, wlvif, wlvif->role_id);
if (ret < 0)
goto out;
@@ -4058,7 +4066,7 @@ static int wl1271_op_sta_add(struct ieee80211_hw *hw,
if (ret < 0)
goto out_free_sta;
- ret = wl12xx_cmd_add_peer(wl, sta, hlid);
+ ret = wl12xx_cmd_add_peer(wl, wlvif, sta, hlid);
if (ret < 0)
goto out_sleep;
diff --git a/drivers/net/wireless/wl12xx/ps.c b/drivers/net/wireless/wl12xx/ps.c
index 8cd81ce..8153408 100644
--- a/drivers/net/wireless/wl12xx/ps.c
+++ b/drivers/net/wireless/wl12xx/ps.c
@@ -178,7 +178,7 @@ int wl1271_ps_set_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif,
wl1271_debug(DEBUG_PSM, "leaving psm");
/* disable beacon early termination */
- if (wl->band == IEEE80211_BAND_2GHZ) {
+ if (wlvif->band == IEEE80211_BAND_2GHZ) {
ret = wl1271_acx_bet_enable(wl, wlvif, false);
if (ret < 0)
return ret;
diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c
index 765f08b..2711438 100644
--- a/drivers/net/wireless/wl12xx/scan.c
+++ b/drivers/net/wireless/wl12xx/scan.c
@@ -77,7 +77,7 @@ void wl1271_scan_complete_work(struct work_struct *work)
!test_bit(wlvif->dev_role_id, wl->roc_map)) {
/* restore remain on channel */
wl12xx_cmd_role_start_dev(wl, wlvif);
- wl12xx_roc(wl, wlvif->dev_role_id);
+ wl12xx_roc(wl, wlvif, wlvif->dev_role_id);
}
wl1271_ps_elp_sleep(wl);
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index 9589446..be06abf 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -102,7 +102,7 @@ static int wl1271_tx_update_filters(struct wl1271 *wl,
if (ret < 0)
goto out;
- ret = wl12xx_roc(wl, wlvif->dev_role_id);
+ ret = wl12xx_roc(wl, wlvif, wlvif->dev_role_id);
if (ret < 0)
goto out;
out:
@@ -809,7 +809,8 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
if (result->status == TX_SUCCESS) {
if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
info->flags |= IEEE80211_TX_STAT_ACK;
- rate = wl1271_rate_to_idx(result->rate_class_index, wl->band);
+ rate = wl1271_rate_to_idx(result->rate_class_index,
+ wlvif->band);
retries = result->ack_failures;
} else if (result->status == TX_RETRY_EXCEEDED) {
wl->stats.excessive_retries++;
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index b76713d..20188ea 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -589,6 +589,9 @@ struct wl12xx_vif {
u8 ssid[IEEE80211_MAX_SSID_LEN + 1];
u8 ssid_len;
+ /* The current band */
+ enum ieee80211_band band;
+
u32 bitrate_masks[IEEE80211_NUM_BANDS];
u32 basic_rate_set;
--
1.7.6.401.g6a319
^ permalink raw reply related
* [PATCH 22/29] wl12xx: add channel field to wlvif
From: Eliad Peller @ 2011-10-10 8:13 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
In-Reply-To: <1318234397-21081-1-git-send-email-eliad@wizery.com>
add channel into the per-interface data.
mac80211 configures some values (e.g. band, channel)
globally, while we configure them per-interface.
In order to make it easier to keep track of the
configured value for each value while keeping sync
with mac80211, save these values both globally
and per-vif.
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
drivers/net/wireless/wl12xx/cmd.c | 12 ++++++------
drivers/net/wireless/wl12xx/main.c | 6 ++++--
drivers/net/wireless/wl12xx/wl12xx.h | 1 +
3 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c
index 6cf8cdc..4c5c518 100644
--- a/drivers/net/wireless/wl12xx/cmd.c
+++ b/drivers/net/wireless/wl12xx/cmd.c
@@ -483,7 +483,7 @@ int wl12xx_cmd_role_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif)
cmd->role_id = wlvif->dev_role_id;
if (wlvif->band == IEEE80211_BAND_5GHZ)
cmd->band = WL12XX_BAND_5GHZ;
- cmd->channel = wl->channel;
+ cmd->channel = wlvif->channel;
if (wlvif->dev_hlid == WL12XX_INVALID_LINK_ID) {
ret = wl12xx_allocate_link(wl, wlvif, &wlvif->dev_hlid);
@@ -573,7 +573,7 @@ int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif)
cmd->role_id = wlvif->role_id;
if (wlvif->band == IEEE80211_BAND_5GHZ)
cmd->band = WL12XX_BAND_5GHZ;
- cmd->channel = wl->channel;
+ cmd->channel = wlvif->channel;
cmd->sta.basic_rate_set = cpu_to_le32(wlvif->basic_rate_set);
cmd->sta.beacon_interval = cpu_to_le16(wlvif->beacon_int);
cmd->sta.ssid_type = WL12XX_SSID_TYPE_ANY;
@@ -689,7 +689,7 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif)
cmd->ap.beacon_interval = cpu_to_le16(wlvif->beacon_int);
cmd->ap.dtim_interval = bss_conf->dtim_period;
cmd->ap.beacon_expiry = WL1271_AP_DEF_BEACON_EXP;
- cmd->channel = wl->channel;
+ cmd->channel = wlvif->channel;
if (!bss_conf->hidden_ssid) {
/* take the SSID from the beacon for backward compatibility */
@@ -787,7 +787,7 @@ int wl12xx_cmd_role_start_ibss(struct wl1271 *wl, struct wl12xx_vif *wlvif)
cmd->role_id = wlvif->role_id;
if (wlvif->band == IEEE80211_BAND_5GHZ)
cmd->band = WL12XX_BAND_5GHZ;
- cmd->channel = wl->channel;
+ cmd->channel = wlvif->channel;
cmd->ibss.basic_rate_set = cpu_to_le32(wlvif->basic_rate_set);
cmd->ibss.beacon_interval = cpu_to_le16(wlvif->beacon_int);
cmd->ibss.dtim_interval = bss_conf->dtim_period;
@@ -1608,7 +1608,7 @@ static int wl12xx_cmd_roc(struct wl1271 *wl, struct wl12xx_vif *wlvif,
struct wl12xx_cmd_roc *cmd;
int ret = 0;
- wl1271_debug(DEBUG_CMD, "cmd roc %d (%d)", wl->channel, role_id);
+ wl1271_debug(DEBUG_CMD, "cmd roc %d (%d)", wlvif->channel, role_id);
if (WARN_ON(role_id == WL12XX_INVALID_ROLE_ID))
return -EINVAL;
@@ -1620,7 +1620,7 @@ static int wl12xx_cmd_roc(struct wl1271 *wl, struct wl12xx_vif *wlvif,
}
cmd->role_id = role_id;
- cmd->channel = wl->channel;
+ cmd->channel = wlvif->channel;
switch (wlvif->band) {
case IEEE80211_BAND_2GHZ:
cmd->band = RADIO_BAND_2_4GHZ;
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 0974ed6..0536808 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -1973,6 +1973,7 @@ static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif)
* per-interface. thus, on init, we have to copy them from wl
*/
wlvif->band = wl->band;
+ wlvif->channel = wl->channel;
INIT_WORK(&wlvif->rx_streaming_enable_work,
wl1271_rx_streaming_enable_work);
@@ -2448,12 +2449,13 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
/* if the channel changes while joined, join again */
if (changed & IEEE80211_CONF_CHANGE_CHANNEL &&
((wlvif->band != conf->channel->band) ||
- (wl->channel != channel))) {
+ (wlvif->channel != channel))) {
/* send all pending packets */
wl1271_tx_work_locked(wl);
wl->band = conf->channel->band;
- wlvif->band = conf->channel->band;
wl->channel = channel;
+ wlvif->band = conf->channel->band;
+ wlvif->channel = channel;
if (!is_ap) {
/*
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index 20188ea..16e1022 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -591,6 +591,7 @@ struct wl12xx_vif {
/* The current band */
enum ieee80211_band band;
+ int channel;
u32 bitrate_masks[IEEE80211_NUM_BANDS];
u32 basic_rate_set;
--
1.7.6.401.g6a319
^ permalink raw reply related
* [PATCH 23/29] wl12xx: add power_level field to wlvif
From: Eliad Peller @ 2011-10-10 8:13 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
In-Reply-To: <1318234397-21081-1-git-send-email-eliad@wizery.com>
move power_level into the per-interface data.
mac80211 configures some values (e.g. band, channel)
globally, while we configure them per-interface.
In order to make it easier to keep track of the
configured value for each value while keeping sync
with mac80211, save these values both globally
and per-vif.
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
drivers/net/wireless/wl12xx/init.c | 2 +-
drivers/net/wireless/wl12xx/main.c | 4 +++-
drivers/net/wireless/wl12xx/wl12xx.h | 3 +++
3 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c
index e596f5c..42a696b 100644
--- a/drivers/net/wireless/wl12xx/init.c
+++ b/drivers/net/wireless/wl12xx/init.c
@@ -554,7 +554,7 @@ static int wl12xx_init_ap_role(struct wl1271 *wl, struct wl12xx_vif *wlvif)
return ret;
/* initialize Tx power */
- ret = wl1271_acx_tx_power(wl, wlvif, wl->power_level);
+ ret = wl1271_acx_tx_power(wl, wlvif, wlvif->power_level);
if (ret < 0)
return ret;
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 0536808..c8b5290 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -1974,6 +1974,7 @@ static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif)
*/
wlvif->band = wl->band;
wlvif->channel = wl->channel;
+ wlvif->power_level = wl->power_level;
INIT_WORK(&wlvif->rx_streaming_enable_work,
wl1271_rx_streaming_enable_work);
@@ -2552,12 +2553,13 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
wlvif->basic_rate, true);
}
- if (conf->power_level != wl->power_level) {
+ if (conf->power_level != wlvif->power_level) {
ret = wl1271_acx_tx_power(wl, wlvif, conf->power_level);
if (ret < 0)
goto out_sleep;
wl->power_level = conf->power_level;
+ wlvif->power_level = conf->power_level;
}
out_sleep:
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index 16e1022..0f1dfd2 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -629,6 +629,9 @@ struct wl12xx_vif {
/* retry counter for PSM entries */
u8 psm_entry_retry;
+ /* in dBm */
+ int power_level;
+
int rssi_thold;
int last_rssi_event;
--
1.7.6.401.g6a319
^ permalink raw reply related
* [PATCH 24/29] wl12xx: make op_config configure all vifs
From: Eliad Peller @ 2011-10-10 8:13 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
In-Reply-To: <1318234397-21081-1-git-send-email-eliad@wizery.com>
When mac80211 changes a global (hw) config, iterate
through all the relevant vifs and update them.
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
drivers/net/wireless/wl12xx/main.c | 112 +++++++++++++++++++----------------
1 files changed, 61 insertions(+), 51 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index c8b5290..43cd276 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -2398,63 +2398,20 @@ out:
return ret;
}
-static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
+static int wl12xx_config_vif(struct wl1271 *wl, struct wl12xx_vif *wlvif,
+ struct ieee80211_conf *conf, u32 changed)
{
- struct wl1271 *wl = hw->priv;
- struct ieee80211_vif *vif = wl->vif; /* TODO: reconfig all vifs */
- struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
- struct ieee80211_conf *conf = &hw->conf;
- int channel, ret = 0;
- bool is_ap;
+ bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS);
+ int channel, ret;
channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
- wl1271_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d %s"
- " changed 0x%x",
- channel,
- conf->flags & IEEE80211_CONF_PS ? "on" : "off",
- conf->power_level,
- conf->flags & IEEE80211_CONF_IDLE ? "idle" : "in use",
- changed);
-
- /*
- * mac80211 will go to idle nearly immediately after transmitting some
- * frames, such as the deauth. To make sure those frames reach the air,
- * wait here until the TX queue is fully flushed.
- */
- if ((changed & IEEE80211_CONF_CHANGE_IDLE) &&
- (conf->flags & IEEE80211_CONF_IDLE))
- wl1271_tx_flush(wl);
-
- mutex_lock(&wl->mutex);
-
- if (unlikely(wl->state == WL1271_STATE_OFF)) {
- /* we support configuring the channel and band while off */
- if ((changed & IEEE80211_CONF_CHANGE_CHANNEL)) {
- wl->band = conf->channel->band;
- wl->channel = channel;
- }
-
- if ((changed & IEEE80211_CONF_CHANGE_POWER))
- wl->power_level = conf->power_level;
-
- goto out;
- }
-
- is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS);
-
- ret = wl1271_ps_elp_wakeup(wl);
- if (ret < 0)
- goto out;
-
/* if the channel changes while joined, join again */
if (changed & IEEE80211_CONF_CHANGE_CHANNEL &&
((wlvif->band != conf->channel->band) ||
(wlvif->channel != channel))) {
/* send all pending packets */
wl1271_tx_work_locked(wl);
- wl->band = conf->channel->band;
- wl->channel = channel;
wlvif->band = conf->channel->band;
wlvif->channel = channel;
@@ -2483,7 +2440,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
ret = wl12xx_croc(wl,
wlvif->dev_role_id);
if (ret < 0)
- goto out_sleep;
+ return ret;
}
ret = wl1271_join(wl, wlvif, false);
if (ret < 0)
@@ -2500,7 +2457,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
ret = wl12xx_croc(wl,
wlvif->dev_role_id);
if (ret < 0)
- goto out_sleep;
+ return ret;
ret = wl12xx_roc(wl, wlvif,
wlvif->dev_role_id);
@@ -2556,12 +2513,65 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
if (conf->power_level != wlvif->power_level) {
ret = wl1271_acx_tx_power(wl, wlvif, conf->power_level);
if (ret < 0)
- goto out_sleep;
+ return ret;
- wl->power_level = conf->power_level;
wlvif->power_level = conf->power_level;
}
+ return 0;
+}
+
+static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
+{
+ struct wl1271 *wl = hw->priv;
+ struct wl12xx_vif *wlvif;
+ struct ieee80211_conf *conf = &hw->conf;
+ int channel, ret = 0;
+
+ channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
+
+ wl1271_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d %s"
+ " changed 0x%x",
+ channel,
+ conf->flags & IEEE80211_CONF_PS ? "on" : "off",
+ conf->power_level,
+ conf->flags & IEEE80211_CONF_IDLE ? "idle" : "in use",
+ changed);
+
+ /*
+ * mac80211 will go to idle nearly immediately after transmitting some
+ * frames, such as the deauth. To make sure those frames reach the air,
+ * wait here until the TX queue is fully flushed.
+ */
+ if ((changed & IEEE80211_CONF_CHANGE_IDLE) &&
+ (conf->flags & IEEE80211_CONF_IDLE))
+ wl1271_tx_flush(wl);
+
+ mutex_lock(&wl->mutex);
+
+ /* we support configuring the channel and band even while off */
+ if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
+ wl->band = conf->channel->band;
+ wl->channel = channel;
+ }
+
+ if (changed & IEEE80211_CONF_CHANGE_POWER)
+ wl->power_level = conf->power_level;
+
+ if (unlikely(wl->state == WL1271_STATE_OFF))
+ goto out;
+
+ ret = wl1271_ps_elp_wakeup(wl);
+ if (ret < 0)
+ goto out;
+
+ /* configure each interface */
+ wl12xx_for_each_wlvif(wl, wlvif) {
+ ret = wl12xx_config_vif(wl, wlvif, conf, changed);
+ if (ret < 0)
+ goto out_sleep;
+ }
+
out_sleep:
wl1271_ps_elp_sleep(wl);
--
1.7.6.401.g6a319
^ permalink raw reply related
* [PATCH 25/29] wl12xx: replace all remaining wl->vif references
From: Eliad Peller @ 2011-10-10 8:13 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
In-Reply-To: <1318234397-21081-1-git-send-email-eliad@wizery.com>
wl->vif is appropriate only when a single vif is being used.
Instead, pass wlvif as parameter or iterate through all
the vifs (e.g. when a global configuration was changed)
Leave wl->vif only to determine whether a vif was already
added (this check will be removed as well after both the
driver and fw will support multiple vifs)
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
drivers/net/wireless/wl12xx/cmd.c | 15 +++--
drivers/net/wireless/wl12xx/debugfs.c | 11 +---
drivers/net/wireless/wl12xx/main.c | 112 ++++++++++++++++++++-------------
drivers/net/wireless/wl12xx/ps.c | 11 ++-
drivers/net/wireless/wl12xx/ps.h | 5 +-
drivers/net/wireless/wl12xx/tx.c | 2 +-
6 files changed, 91 insertions(+), 65 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c
index 4c5c518..65bf952 100644
--- a/drivers/net/wireless/wl12xx/cmd.c
+++ b/drivers/net/wireless/wl12xx/cmd.c
@@ -654,7 +654,8 @@ out:
int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif)
{
struct wl12xx_cmd_role_start *cmd;
- struct ieee80211_bss_conf *bss_conf = &wl->vif->bss_conf;
+ struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
+ struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
int ret;
wl1271_debug(DEBUG_CMD, "cmd role start ap %d", wlvif->role_id);
@@ -773,7 +774,7 @@ int wl12xx_cmd_role_start_ibss(struct wl1271 *wl, struct wl12xx_vif *wlvif)
{
struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
struct wl12xx_cmd_role_start *cmd;
- struct ieee80211_bss_conf *bss_conf = &wl->vif->bss_conf;
+ struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
int ret;
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
@@ -1096,10 +1097,11 @@ out:
int wl1271_cmd_build_ps_poll(struct wl1271 *wl, struct wl12xx_vif *wlvif,
u16 aid)
{
+ struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
struct sk_buff *skb;
int ret = 0;
- skb = ieee80211_pspoll_get(wl->hw, wl->vif);
+ skb = ieee80211_pspoll_get(wl->hw, vif);
if (!skb)
goto out;
@@ -1176,6 +1178,7 @@ int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, struct wl12xx_vif *wlvif,
__be32 ip_addr)
{
int ret;
+ struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
struct wl12xx_arp_rsp_template tmpl;
struct ieee80211_hdr_3addr *hdr;
struct arphdr *arp_hdr;
@@ -1187,8 +1190,8 @@ int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, struct wl12xx_vif *wlvif,
hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
IEEE80211_STYPE_DATA |
IEEE80211_FCTL_TODS);
- memcpy(hdr->addr1, wl->vif->bss_conf.bssid, ETH_ALEN);
- memcpy(hdr->addr2, wl->vif->addr, ETH_ALEN);
+ memcpy(hdr->addr1, vif->bss_conf.bssid, ETH_ALEN);
+ memcpy(hdr->addr2, vif->addr, ETH_ALEN);
memset(hdr->addr3, 0xff, ETH_ALEN);
/* llc layer */
@@ -1204,7 +1207,7 @@ int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, struct wl12xx_vif *wlvif,
arp_hdr->ar_op = cpu_to_be16(ARPOP_REPLY);
/* arp payload */
- memcpy(tmpl.sender_hw, wl->vif->addr, ETH_ALEN);
+ memcpy(tmpl.sender_hw, vif->addr, ETH_ALEN);
tmpl.sender_ip = ip_addr;
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_ARP_RSP,
diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c
index 4abff82..d6c2d0c 100644
--- a/drivers/net/wireless/wl12xx/debugfs.c
+++ b/drivers/net/wireless/wl12xx/debugfs.c
@@ -615,19 +615,12 @@ static ssize_t beacon_filtering_write(struct file *file,
size_t count, loff_t *ppos)
{
struct wl1271 *wl = file->private_data;
- struct ieee80211_vif *vif;
struct wl12xx_vif *wlvif;
char buf[10];
size_t len;
unsigned long value;
int ret;
- if (!wl->vif)
- return -EINVAL;
-
- vif = wl->vif;
- wlvif = wl12xx_vif_to_data(vif);
-
len = min(count, sizeof(buf) - 1);
if (copy_from_user(buf, user_buf, len))
return -EFAULT;
@@ -645,7 +638,9 @@ static ssize_t beacon_filtering_write(struct file *file,
if (ret < 0)
goto out;
- ret = wl1271_acx_beacon_filter_opt(wl, wlvif, !!value);
+ wl12xx_for_each_wlvif(wl, wlvif) {
+ ret = wl1271_acx_beacon_filter_opt(wl, wlvif, !!value);
+ }
wl1271_ps_elp_sleep(wl);
out:
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 43cd276..e9120c2 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -779,7 +779,9 @@ static int wl1271_plt_init(struct wl1271 *wl)
return ret;
}
-static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl, u8 hlid, u8 tx_pkts)
+static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl,
+ struct wl12xx_vif *wlvif,
+ u8 hlid, u8 tx_pkts)
{
bool fw_ps, single_sta;
@@ -791,7 +793,7 @@ static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl, u8 hlid, u8 tx_pkts)
* packets in FW or if the STA is awake.
*/
if (!fw_ps || tx_pkts < WL1271_PS_STA_MAX_PACKETS)
- wl1271_ps_link_end(wl, hlid);
+ wl12xx_ps_link_end(wl, wlvif, hlid);
/*
* Start high-level PS if the STA is asleep with enough blocks in FW.
@@ -799,7 +801,7 @@ static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl, u8 hlid, u8 tx_pkts)
* case FW-memory congestion is not a problem.
*/
else if (!single_sta && fw_ps && tx_pkts >= WL1271_PS_STA_MAX_PACKETS)
- wl1271_ps_link_start(wl, hlid, true);
+ wl12xx_ps_link_start(wl, wlvif, hlid, true);
}
static void wl12xx_irq_update_links_status(struct wl1271 *wl,
@@ -829,15 +831,15 @@ static void wl12xx_irq_update_links_status(struct wl1271 *wl,
lnk->prev_freed_pkts = status->tx_lnk_free_pkts[hlid];
lnk->allocated_pkts -= cnt;
- wl12xx_irq_ps_regulate_link(wl, hlid, lnk->allocated_pkts);
+ wl12xx_irq_ps_regulate_link(wl, wlvif, hlid,
+ lnk->allocated_pkts);
}
}
static void wl12xx_fw_status(struct wl1271 *wl,
struct wl12xx_fw_status *status)
{
- struct ieee80211_vif *vif = wl->vif; /* TODO: get as param */
- struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
+ struct wl12xx_vif *wlvif;
struct timespec ts;
u32 old_tx_blk_count = wl->tx_blocks_available;
int avail, freed_blocks;
@@ -892,8 +894,9 @@ static void wl12xx_fw_status(struct wl1271 *wl,
clear_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags);
/* for AP update num of allocated TX blocks per link and ps status */
- if (wlvif->bss_type == BSS_TYPE_AP_BSS)
+ wl12xx_for_each_wlvif_ap(wl, wlvif) {
wl12xx_irq_update_links_status(wl, wlvif, status);
+ }
/* update the host-chipset time offset */
getnstimeofday(&ts);
@@ -1212,6 +1215,7 @@ static void wl1271_recovery_work(struct work_struct *work)
struct wl1271 *wl =
container_of(work, struct wl1271, recovery_work);
struct wl12xx_vif *wlvif;
+ struct ieee80211_vif *vif;
mutex_lock(&wl->mutex);
@@ -1249,7 +1253,12 @@ static void wl1271_recovery_work(struct work_struct *work)
}
/* reboot the chipset */
- __wl1271_op_remove_interface(wl, wl->vif, false);
+ while (!list_empty(&wl->wlvif_list)) {
+ wlvif = list_first_entry(&wl->wlvif_list,
+ struct wl12xx_vif, list);
+ vif = wl12xx_wlvif_to_vif(wlvif);
+ __wl1271_op_remove_interface(wl, vif, false);
+ }
clear_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags);
@@ -1721,18 +1730,19 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw,
struct cfg80211_wowlan *wow)
{
struct wl1271 *wl = hw->priv;
- struct ieee80211_vif *vif = wl->vif; /* TODO: get as param */
- struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
+ struct wl12xx_vif *wlvif;
int ret;
wl1271_debug(DEBUG_MAC80211, "mac80211 suspend wow=%d", !!wow);
WARN_ON(!wow || !wow->any);
wl->wow_enabled = true;
- ret = wl1271_configure_suspend(wl, wlvif);
- if (ret < 0) {
- wl1271_warning("couldn't prepare device to suspend");
- return ret;
+ wl12xx_for_each_wlvif(wl, wlvif) {
+ ret = wl1271_configure_suspend(wl, wlvif);
+ if (ret < 0) {
+ wl1271_warning("couldn't prepare device to suspend");
+ return ret;
+ }
}
/* flush any remaining work */
wl1271_debug(DEBUG_MAC80211, "flushing remaining works");
@@ -1751,7 +1761,9 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw,
wl1271_enable_interrupts(wl);
flush_work(&wl->tx_work);
- flush_delayed_work(&wlvif->pspoll_work);
+ wl12xx_for_each_wlvif(wl, wlvif) {
+ flush_delayed_work(&wlvif->pspoll_work);
+ }
flush_delayed_work(&wl->elp_work);
return 0;
@@ -1760,8 +1772,7 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw,
static int wl1271_op_resume(struct ieee80211_hw *hw)
{
struct wl1271 *wl = hw->priv;
- struct ieee80211_vif *vif = wl->vif; /* TODO: get as param */
- struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
+ struct wl12xx_vif *wlvif;
unsigned long flags;
bool run_irq_work = false;
@@ -1785,7 +1796,9 @@ static int wl1271_op_resume(struct ieee80211_hw *hw)
wl1271_irq(0, wl);
wl1271_enable_interrupts(wl);
}
- wl1271_configure_resume(wl, wlvif);
+ wl12xx_for_each_wlvif(wl, wlvif) {
+ wl1271_configure_resume(wl, wlvif);
+ }
wl->wow_enabled = false;
return 0;
@@ -2232,6 +2245,7 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
{
struct wl1271 *wl = hw->priv;
struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
+ struct wl12xx_vif *iter;
mutex_lock(&wl->mutex);
@@ -2243,10 +2257,14 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
* wl->vif can be null here if someone shuts down the interface
* just when hardware recovery has been started.
*/
- if (wl->vif) {
- WARN_ON(wl->vif != vif);
+ wl12xx_for_each_wlvif(wl, iter) {
+ if (iter != wlvif)
+ continue;
+
__wl1271_op_remove_interface(wl, vif, true);
+ break;
}
+ WARN_ON(iter != wlvif);
out:
mutex_unlock(&wl->mutex);
cancel_work_sync(&wl->recovery_work);
@@ -2316,8 +2334,10 @@ static int wl1271_unjoin(struct wl1271 *wl, struct wl12xx_vif *wlvif)
int ret;
if (test_and_clear_bit(WLVIF_FLAG_CS_PROGRESS, &wlvif->flags)) {
+ struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
+
wl12xx_cmd_stop_channel_switch(wl);
- ieee80211_chswitch_done(wl->vif, false);
+ ieee80211_chswitch_done(vif, false);
}
/* to stop listening to a channel, we disconnect */
@@ -2632,8 +2652,7 @@ static void wl1271_op_configure_filter(struct ieee80211_hw *hw,
{
struct wl1271_filter_params *fp = (void *)(unsigned long)multicast;
struct wl1271 *wl = hw->priv;
- struct ieee80211_vif *vif = wl->vif; /* TODO: get as param */
- struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
+ struct wl12xx_vif *wlvif;
int ret;
@@ -2652,17 +2671,20 @@ static void wl1271_op_configure_filter(struct ieee80211_hw *hw,
if (ret < 0)
goto out;
- if (wlvif->bss_type != BSS_TYPE_AP_BSS) {
- if (*total & FIF_ALLMULTI)
- ret = wl1271_acx_group_address_tbl(wl, wlvif, false,
- NULL, 0);
- else if (fp)
- ret = wl1271_acx_group_address_tbl(wl, wlvif,
- fp->enabled,
- fp->mc_list,
- fp->mc_list_length);
- if (ret < 0)
- goto out_sleep;
+ wl12xx_for_each_wlvif(wl, wlvif) {
+ if (wlvif->bss_type != BSS_TYPE_AP_BSS) {
+ if (*total & FIF_ALLMULTI)
+ ret = wl1271_acx_group_address_tbl(wl, wlvif,
+ false,
+ NULL, 0);
+ else if (fp)
+ ret = wl1271_acx_group_address_tbl(wl, wlvif,
+ fp->enabled,
+ fp->mc_list,
+ fp->mc_list_length);
+ if (ret < 0)
+ goto out_sleep;
+ }
}
/*
@@ -3152,8 +3174,7 @@ out:
static int wl1271_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
{
struct wl1271 *wl = hw->priv;
- struct ieee80211_vif *vif = wl->vif;
- struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
+ struct wl12xx_vif *wlvif;
int ret = 0;
mutex_lock(&wl->mutex);
@@ -3167,10 +3188,11 @@ static int wl1271_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
if (ret < 0)
goto out;
- ret = wl1271_acx_rts_threshold(wl, wlvif, value);
- if (ret < 0)
- wl1271_warning("wl1271_op_set_rts_threshold failed: %d", ret);
-
+ wl12xx_for_each_wlvif(wl, wlvif) {
+ ret = wl1271_acx_rts_threshold(wl, wlvif, value);
+ if (ret < 0)
+ wl1271_warning("set rts threshold failed: %d", ret);
+ }
wl1271_ps_elp_sleep(wl);
out:
@@ -3659,7 +3681,7 @@ sta_not_found:
wlvif->probereq = NULL;
/* re-enable dynamic ps - just in case */
- ieee80211_enable_dyn_ps(wl->vif);
+ ieee80211_enable_dyn_ps(vif);
/* revert back to minimum rates for the current band */
wl1271_set_band_rate(wl, wlvif);
@@ -4295,9 +4317,11 @@ static void wl12xx_op_channel_switch(struct ieee80211_hw *hw,
mutex_lock(&wl->mutex);
if (unlikely(wl->state == WL1271_STATE_OFF)) {
- mutex_unlock(&wl->mutex);
- ieee80211_chswitch_done(wl->vif, false);
- return;
+ wl12xx_for_each_wlvif_sta(wl, wlvif) {
+ struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
+ ieee80211_chswitch_done(vif, false);
+ }
+ goto out;
}
ret = wl1271_ps_elp_wakeup(wl);
diff --git a/drivers/net/wireless/wl12xx/ps.c b/drivers/net/wireless/wl12xx/ps.c
index 8153408..84a1afa 100644
--- a/drivers/net/wireless/wl12xx/ps.c
+++ b/drivers/net/wireless/wl12xx/ps.c
@@ -232,9 +232,11 @@ static void wl1271_ps_filter_frames(struct wl1271 *wl, u8 hlid)
wl1271_handle_tx_low_watermark(wl);
}
-void wl1271_ps_link_start(struct wl1271 *wl, u8 hlid, bool clean_queues)
+void wl12xx_ps_link_start(struct wl1271 *wl, struct wl12xx_vif *wlvif,
+ u8 hlid, bool clean_queues)
{
struct ieee80211_sta *sta;
+ struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
if (test_bit(hlid, &wl->ap_ps_map))
return;
@@ -244,7 +246,7 @@ void wl1271_ps_link_start(struct wl1271 *wl, u8 hlid, bool clean_queues)
clean_queues);
rcu_read_lock();
- sta = ieee80211_find_sta(wl->vif, wl->links[hlid].addr);
+ sta = ieee80211_find_sta(vif, wl->links[hlid].addr);
if (!sta) {
wl1271_error("could not find sta %pM for starting ps",
wl->links[hlid].addr);
@@ -262,9 +264,10 @@ void wl1271_ps_link_start(struct wl1271 *wl, u8 hlid, bool clean_queues)
__set_bit(hlid, &wl->ap_ps_map);
}
-void wl1271_ps_link_end(struct wl1271 *wl, u8 hlid)
+void wl12xx_ps_link_end(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid)
{
struct ieee80211_sta *sta;
+ struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
if (!test_bit(hlid, &wl->ap_ps_map))
return;
@@ -274,7 +277,7 @@ void wl1271_ps_link_end(struct wl1271 *wl, u8 hlid)
__clear_bit(hlid, &wl->ap_ps_map);
rcu_read_lock();
- sta = ieee80211_find_sta(wl->vif, wl->links[hlid].addr);
+ sta = ieee80211_find_sta(vif, wl->links[hlid].addr);
if (!sta) {
wl1271_error("could not find sta %pM for ending ps",
wl->links[hlid].addr);
diff --git a/drivers/net/wireless/wl12xx/ps.h b/drivers/net/wireless/wl12xx/ps.h
index 6ad0a0b..a12052f 100644
--- a/drivers/net/wireless/wl12xx/ps.h
+++ b/drivers/net/wireless/wl12xx/ps.h
@@ -32,8 +32,9 @@ int wl1271_ps_set_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif,
void wl1271_ps_elp_sleep(struct wl1271 *wl);
int wl1271_ps_elp_wakeup(struct wl1271 *wl);
void wl1271_elp_work(struct work_struct *work);
-void wl1271_ps_link_start(struct wl1271 *wl, u8 hlid, bool clean_queues);
-void wl1271_ps_link_end(struct wl1271 *wl, u8 hlid);
+void wl12xx_ps_link_start(struct wl1271 *wl, struct wl12xx_vif *wlvif,
+ u8 hlid, bool clean_queues);
+void wl12xx_ps_link_end(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid);
#define WL1271_PS_COMPLETE_TIMEOUT 500
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index be06abf..a0eefe7 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -146,7 +146,7 @@ static void wl1271_tx_regulate_link(struct wl1271 *wl,
* case FW-memory congestion is not a problem.
*/
if (!single_sta && fw_ps && tx_pkts >= WL1271_PS_STA_MAX_PACKETS)
- wl1271_ps_link_start(wl, hlid, true);
+ wl12xx_ps_link_start(wl, wlvif, hlid, true);
}
bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb)
--
1.7.6.401.g6a319
^ permalink raw reply related
* [PATCH 26/29] wl12xx: call stop() on recovery
From: Eliad Peller @ 2011-10-10 8:13 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
In-Reply-To: <1318234397-21081-1-git-send-email-eliad@wizery.com>
The recovery work should call stop() after it removed
all the existing interfaces.
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
drivers/net/wireless/wl12xx/main.c | 9 ++++++---
1 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index e9120c2..da89ff2 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -379,6 +379,7 @@ static bool bug_on_recovery;
static void __wl1271_op_remove_interface(struct wl1271 *wl,
struct ieee80211_vif *vif,
bool reset_tx_queues);
+static void wl1271_op_stop(struct ieee80211_hw *hw);
static void wl1271_free_ap_keys(struct wl1271 *wl, struct wl12xx_vif *wlvif);
@@ -1220,7 +1221,7 @@ static void wl1271_recovery_work(struct work_struct *work)
mutex_lock(&wl->mutex);
if (wl->state != WL1271_STATE_ON)
- goto out;
+ goto out_unlock;
/* Avoid a recursive recovery */
set_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags);
@@ -1259,6 +1260,8 @@ static void wl1271_recovery_work(struct work_struct *work)
vif = wl12xx_wlvif_to_vif(wlvif);
__wl1271_op_remove_interface(wl, vif, false);
}
+ mutex_unlock(&wl->mutex);
+ wl1271_op_stop(wl->hw);
clear_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags);
@@ -1269,8 +1272,8 @@ static void wl1271_recovery_work(struct work_struct *work)
* to restart the HW.
*/
ieee80211_wake_queues(wl->hw);
-
-out:
+ return;
+out_unlock:
mutex_unlock(&wl->mutex);
}
--
1.7.6.401.g6a319
^ permalink raw reply related
* [PATCH 27/29] wl12xx: use dynamic rate policies
From: Eliad Peller @ 2011-10-10 8:13 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
In-Reply-To: <1318234397-21081-1-git-send-email-eliad@wizery.com>
allocate the rate policies dynamically, instead of using hardcoded
indexes. this is needed for proper multi-role configuration.
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
drivers/net/wireless/wl12xx/acx.c | 6 ++--
drivers/net/wireless/wl12xx/acx.h | 5 ---
drivers/net/wireless/wl12xx/init.c | 7 ++--
drivers/net/wireless/wl12xx/main.c | 52 ++++++++++++++++++++++++++++++---
drivers/net/wireless/wl12xx/tx.c | 10 +++---
drivers/net/wireless/wl12xx/wl12xx.h | 12 ++++++++
6 files changed, 71 insertions(+), 21 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c
index 21e74ca..e2e4670 100644
--- a/drivers/net/wireless/wl12xx/acx.c
+++ b/drivers/net/wireless/wl12xx/acx.c
@@ -766,7 +766,7 @@ int wl1271_acx_sta_rate_policies(struct wl1271 *wl, struct wl12xx_vif *wlvif)
wlvif->basic_rate, wlvif->rate_set);
/* configure one basic rate class */
- acx->rate_policy_idx = cpu_to_le32(ACX_TX_BASIC_RATE);
+ acx->rate_policy_idx = cpu_to_le32(wlvif->sta.basic_rate_idx);
acx->rate_policy.enabled_rates = cpu_to_le32(wlvif->basic_rate);
acx->rate_policy.short_retry_limit = c->short_retry_limit;
acx->rate_policy.long_retry_limit = c->long_retry_limit;
@@ -779,7 +779,7 @@ int wl1271_acx_sta_rate_policies(struct wl1271 *wl, struct wl12xx_vif *wlvif)
}
/* configure one AP supported rate class */
- acx->rate_policy_idx = cpu_to_le32(ACX_TX_AP_FULL_RATE);
+ acx->rate_policy_idx = cpu_to_le32(wlvif->sta.ap_rate_idx);
acx->rate_policy.enabled_rates = cpu_to_le32(wlvif->rate_set);
acx->rate_policy.short_retry_limit = c->short_retry_limit;
acx->rate_policy.long_retry_limit = c->long_retry_limit;
@@ -796,7 +796,7 @@ int wl1271_acx_sta_rate_policies(struct wl1271 *wl, struct wl12xx_vif *wlvif)
* (p2p packets should always go out with OFDM rates, even
* if we are currently connected to 11b AP)
*/
- acx->rate_policy_idx = cpu_to_le32(ACX_TX_BASIC_RATE_P2P);
+ acx->rate_policy_idx = cpu_to_le32(wlvif->sta.p2p_rate_idx);
acx->rate_policy.enabled_rates =
cpu_to_le32(CONF_TX_RATE_MASK_BASIC_P2P);
acx->rate_policy.short_retry_limit = c->short_retry_limit;
diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h
index c06119b..b2d85be 100644
--- a/drivers/net/wireless/wl12xx/acx.h
+++ b/drivers/net/wireless/wl12xx/acx.h
@@ -654,11 +654,6 @@ struct acx_rate_class {
u8 reserved;
};
-#define ACX_TX_BASIC_RATE 0
-#define ACX_TX_AP_FULL_RATE 1
-#define ACX_TX_BASIC_RATE_P2P 2
-#define ACX_TX_AP_MODE_MGMT_RATE 4
-#define ACX_TX_AP_MODE_BCST_RATE 5
struct acx_rate_policy {
struct acx_header header;
diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c
index 42a696b..a4e510a 100644
--- a/drivers/net/wireless/wl12xx/init.c
+++ b/drivers/net/wireless/wl12xx/init.c
@@ -434,7 +434,7 @@ int wl1271_init_ap_rates(struct wl1271 *wl, struct wl12xx_vif *wlvif)
rc.long_retry_limit = 10;
rc.short_retry_limit = 10;
rc.aflags = 0;
- ret = wl1271_acx_ap_rate_policy(wl, &rc, ACX_TX_AP_MODE_MGMT_RATE);
+ ret = wl1271_acx_ap_rate_policy(wl, &rc, wlvif->ap.mgmt_rate_idx);
if (ret < 0)
return ret;
@@ -443,7 +443,7 @@ int wl1271_init_ap_rates(struct wl1271 *wl, struct wl12xx_vif *wlvif)
rc.short_retry_limit = 10;
rc.long_retry_limit = 10;
rc.aflags = 0;
- ret = wl1271_acx_ap_rate_policy(wl, &rc, ACX_TX_AP_MODE_BCST_RATE);
+ ret = wl1271_acx_ap_rate_policy(wl, &rc, wlvif->ap.bcast_rate_idx);
if (ret < 0)
return ret;
@@ -465,7 +465,8 @@ int wl1271_init_ap_rates(struct wl1271 *wl, struct wl12xx_vif *wlvif)
rc.short_retry_limit = 10;
rc.long_retry_limit = 10;
rc.aflags = 0;
- ret = wl1271_acx_ap_rate_policy(wl, &rc, i);
+ ret = wl1271_acx_ap_rate_policy(wl, &rc,
+ wlvif->ap.ucast_rate_idx[i]);
if (ret < 0)
return ret;
}
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index da89ff2..20a2a4b 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -1910,6 +1910,27 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
mutex_unlock(&wl->mutex);
}
+static int wl12xx_allocate_rate_policy(struct wl1271 *wl, u8 *idx)
+{
+ u8 policy = find_first_zero_bit(wl->rate_policies_map,
+ WL12XX_MAX_RATE_POLICIES);
+ if (policy >= WL12XX_MAX_RATE_POLICIES)
+ return -EBUSY;
+
+ __set_bit(policy, wl->rate_policies_map);
+ *idx = policy;
+ return 0;
+}
+
+static void wl12xx_free_rate_policy(struct wl1271 *wl, u8 *idx)
+{
+ if (WARN_ON(*idx >= WL12XX_MAX_RATE_POLICIES))
+ return;
+
+ __clear_bit(*idx, wl->rate_policies_map);
+ *idx = WL12XX_MAX_RATE_POLICIES;
+}
+
static u8 wl12xx_get_role_type(struct wl1271 *wl, struct wl12xx_vif *wlvif)
{
switch (wlvif->bss_type) {
@@ -1937,6 +1958,7 @@ static u8 wl12xx_get_role_type(struct wl1271 *wl, struct wl12xx_vif *wlvif)
static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif)
{
struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
+ int i;
/* clear everything but the persistent data */
memset(wlvif, 0, offsetof(struct wl12xx_vif, persistent));
@@ -1970,11 +1992,18 @@ static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif)
wlvif->bss_type == BSS_TYPE_IBSS) {
/* init sta/ibss data */
wlvif->sta.hlid = WL12XX_INVALID_LINK_ID;
-
+ wl12xx_allocate_rate_policy(wl, &wlvif->sta.basic_rate_idx);
+ wl12xx_allocate_rate_policy(wl, &wlvif->sta.ap_rate_idx);
+ wl12xx_allocate_rate_policy(wl, &wlvif->sta.p2p_rate_idx);
} else {
/* init ap data */
wlvif->ap.bcast_hlid = WL12XX_INVALID_LINK_ID;
wlvif->ap.global_hlid = WL12XX_INVALID_LINK_ID;
+ wl12xx_allocate_rate_policy(wl, &wlvif->ap.mgmt_rate_idx);
+ wl12xx_allocate_rate_policy(wl, &wlvif->ap.bcast_rate_idx);
+ for (i = 0; i < CONF_TX_MAX_AC_COUNT; i++)
+ wl12xx_allocate_rate_policy(wl,
+ &wlvif->ap.ucast_rate_idx[i]);
}
wlvif->bitrate_masks[IEEE80211_BAND_2GHZ] = wl->conf.tx.basic_rate;
@@ -2176,7 +2205,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
bool reset_tx_queues)
{
struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
- int ret;
+ int i, ret;
wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface");
@@ -2222,10 +2251,23 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
}
deinit:
/* clear all hlids (except system_hlid) */
- wlvif->sta.hlid = WL12XX_INVALID_LINK_ID;
wlvif->dev_hlid = WL12XX_INVALID_LINK_ID;
- wlvif->ap.bcast_hlid = WL12XX_INVALID_LINK_ID;
- wlvif->ap.global_hlid = WL12XX_INVALID_LINK_ID;
+
+ if (wlvif->bss_type == BSS_TYPE_STA_BSS ||
+ wlvif->bss_type == BSS_TYPE_IBSS) {
+ wlvif->sta.hlid = WL12XX_INVALID_LINK_ID;
+ wl12xx_free_rate_policy(wl, &wlvif->sta.basic_rate_idx);
+ wl12xx_free_rate_policy(wl, &wlvif->sta.ap_rate_idx);
+ wl12xx_free_rate_policy(wl, &wlvif->sta.p2p_rate_idx);
+ } else {
+ wlvif->ap.bcast_hlid = WL12XX_INVALID_LINK_ID;
+ wlvif->ap.global_hlid = WL12XX_INVALID_LINK_ID;
+ wl12xx_free_rate_policy(wl, &wlvif->ap.mgmt_rate_idx);
+ wl12xx_free_rate_policy(wl, &wlvif->ap.bcast_rate_idx);
+ for (i = 0; i < CONF_TX_MAX_AC_COUNT; i++)
+ wl12xx_free_rate_policy(wl,
+ &wlvif->ap.ucast_rate_idx[i]);
+ }
wl12xx_tx_reset_wlvif(wl, wlvif);
wl1271_free_ap_keys(wl, wlvif);
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index a0eefe7..f434331 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -339,16 +339,16 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct wl12xx_vif *wlvif,
send them with AP rate policies, otherwise use default
basic rates */
if (control->control.sta)
- rate_idx = ACX_TX_AP_FULL_RATE;
+ rate_idx = wlvif->sta.ap_rate_idx;
else
- rate_idx = ACX_TX_BASIC_RATE;
+ rate_idx = wlvif->sta.basic_rate_idx;
} else {
if (hlid == wlvif->ap.global_hlid)
- rate_idx = ACX_TX_AP_MODE_MGMT_RATE;
+ rate_idx = wlvif->ap.mgmt_rate_idx;
else if (hlid == wlvif->ap.bcast_hlid)
- rate_idx = ACX_TX_AP_MODE_BCST_RATE;
+ rate_idx = wlvif->ap.bcast_rate_idx;
else
- rate_idx = ac;
+ rate_idx = wlvif->ap.ucast_rate_idx[ac];
}
tx_attr |= rate_idx << TX_HW_ATTR_OFST_RATE_POLICY;
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index 0f1dfd2..3673994 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -142,6 +142,8 @@ extern u32 wl12xx_debug_level;
#define WL12XX_INVALID_ROLE_ID 0xff
#define WL12XX_INVALID_LINK_ID 0xff
+#define WL12XX_MAX_RATE_POLICIES 16
+
/* Defined by FW as 0. Will not be freed or allocated. */
#define WL12XX_SYSTEM_HLID 0
@@ -396,6 +398,8 @@ struct wl1271 {
unsigned long links_map[BITS_TO_LONGS(WL12XX_MAX_LINKS)];
unsigned long roles_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)];
unsigned long roc_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)];
+ unsigned long rate_policies_map[
+ BITS_TO_LONGS(WL12XX_MAX_RATE_POLICIES)];
struct list_head wlvif_list;
@@ -567,6 +571,10 @@ struct wl12xx_vif {
struct {
u8 hlid;
u8 ba_rx_bitmap;
+
+ u8 basic_rate_idx;
+ u8 ap_rate_idx;
+ u8 p2p_rate_idx;
} sta;
struct {
u8 global_hlid;
@@ -578,6 +586,10 @@ struct wl12xx_vif {
/* recoreded keys - set here before AP startup */
struct wl1271_ap_key *recorded_keys[MAX_NUM_KEYS];
+
+ u8 mgmt_rate_idx;
+ u8 bcast_rate_idx;
+ u8 ucast_rate_idx[CONF_TX_MAX_AC_COUNT];
} ap;
};
--
1.7.6.401.g6a319
^ permalink raw reply related
* [PATCH 28/29] wl12xx: add elp wakeup/sleep calls to add_interface
From: Eliad Peller @ 2011-10-10 8:13 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
In-Reply-To: <1318234397-21081-1-git-send-email-eliad@wizery.com>
add_interface might be called while the chip is
in elp. add elp_wakeup/sleep calls to handle it.
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
drivers/net/wireless/wl12xx/main.c | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 20a2a4b..e5edf64 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -2115,6 +2115,10 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
ieee80211_vif_type_p2p(vif), vif->addr);
mutex_lock(&wl->mutex);
+ ret = wl1271_ps_elp_wakeup(wl);
+ if (ret < 0)
+ goto out_unlock;
+
if (wl->vif) {
wl1271_debug(DEBUG_MAC80211,
"multiple vifs are not supported yet");
@@ -2190,6 +2194,8 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
list_add(&wlvif->list, &wl->wlvif_list);
set_bit(WLVIF_FLAG_INITIALIZED, &wlvif->flags);
out:
+ wl1271_ps_elp_sleep(wl);
+out_unlock:
mutex_unlock(&wl->mutex);
mutex_lock(&wl_list_mutex);
--
1.7.6.401.g6a319
^ permalink raw reply related
* [PATCH 29/29] wl12xx: use round-robin policy for tx
From: Eliad Peller @ 2011-10-10 8:13 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
In-Reply-To: <1318234397-21081-1-git-send-email-eliad@wizery.com>
Currently, a single vif might starve all the other vifs.
Save the last vif we dequeued a packet from, and continue
with the following one using a round-robin policy.
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
drivers/net/wireless/wl12xx/main.c | 2 ++
drivers/net/wireless/wl12xx/tx.c | 26 ++++++++++++++++++++------
drivers/net/wireless/wl12xx/wl12xx.h | 6 ++++++
3 files changed, 28 insertions(+), 6 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index e5edf64..e1d33b2 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -2277,6 +2277,8 @@ deinit:
wl12xx_tx_reset_wlvif(wl, wlvif);
wl1271_free_ap_keys(wl, wlvif);
+ if (wl->last_wlvif == wlvif)
+ wl->last_wlvif = NULL;
list_del(&wlvif->list);
memset(wlvif->ap.sta_hlid_map, 0, sizeof(wlvif->ap.sta_hlid_map));
wlvif->role_id = WL12XX_INVALID_ROLE_ID;
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index f434331..05968c6 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -590,14 +590,28 @@ static struct sk_buff *wl12xx_vif_skb_dequeue(struct wl1271 *wl,
static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl)
{
unsigned long flags;
- struct wl12xx_vif *wlvif;
+ struct wl12xx_vif *wlvif = wl->last_wlvif;
struct sk_buff *skb = NULL;
- /* TODO: rememeber last vif and consider it */
- wl12xx_for_each_wlvif(wl, wlvif) {
- skb = wl12xx_vif_skb_dequeue(wl, wlvif);
- if (skb)
- break;
+ if (wlvif) {
+ wl12xx_for_each_wlvif_continue(wl, wlvif) {
+ skb = wl12xx_vif_skb_dequeue(wl, wlvif);
+ if (skb) {
+ wl->last_wlvif = wlvif;
+ break;
+ }
+ }
+ }
+
+ /* do another pass */
+ if (!skb) {
+ wl12xx_for_each_wlvif(wl, wlvif) {
+ skb = wl12xx_vif_skb_dequeue(wl, wlvif);
+ if (skb) {
+ wl->last_wlvif = wlvif;
+ break;
+ }
+ }
}
if (!skb &&
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index 3673994..94b24c2 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -549,6 +549,9 @@ struct wl1271 {
/* AP-mode - number of currently connected stations */
int active_sta_count;
+
+ /* last wlvif we transmitted from */
+ struct wl12xx_vif *last_wlvif;
};
struct wl1271_station {
@@ -690,6 +693,9 @@ struct ieee80211_vif *wl12xx_wlvif_to_vif(struct wl12xx_vif *wlvif)
#define wl12xx_for_each_wlvif(wl, wlvif) \
list_for_each_entry(wlvif, &wl->wlvif_list, list)
+#define wl12xx_for_each_wlvif_continue(wl, wlvif) \
+ list_for_each_entry_continue(wlvif, &wl->wlvif_list, list)
+
#define wl12xx_for_each_wlvif_bss_type(wl, wlvif, _bss_type) \
wl12xx_for_each_wlvif(wl, wlvif) \
if (wlvif->bss_type == _bss_type)
--
1.7.6.401.g6a319
^ permalink raw reply related
* Re: [PATCH 0/8] wireless: add DFS master support
From: Zefir Kurtisi @ 2011-10-10 9:13 UTC (permalink / raw)
To: Luis R. Rodriguez; +Cc: linux-wireless, linville, Johannes Berg
In-Reply-To: <CAB=NE6UouofityugcjTvcXpBFx6cYEbAQ_FAe3gPO-GaS8Vh3w@mail.gmail.com>
On 10/08/2011 08:26 PM, Luis R. Rodriguez wrote:
> On Sat, Oct 8, 2011 at 10:46 AM, Zefir Kurtisi
> <zefir.kurtisi@neratec.com> wrote:
>> On 08.10.2011 00:32, Luis R. Rodriguez wrote:
>>>
>>> On Fri, Oct 7, 2011 at 3:29 PM, Luis R. Rodriguez
>>> <mcgrof@qca.qualcomm.com> wrote:
>>>>
>>>> On Fri, Oct 7, 2011 at 2:11 PM, Luis R. Rodriguez
>>>> <mcgrof@qca.qualcomm.com> wrote:
>>>>>
>>>>> On Tue, Oct 4, 2011 at 5:14 PM, Luis R. Rodriguez
>>>>> <mcgrof@qca.qualcomm.com> wrote:
>>>>>>
>>>>>> On Tue, Oct 4, 2011 at 4:47 PM, Luis R. Rodriguez
>>>>>> <mcgrof@qca.qualcomm.com> wrote:
>>>>>>>
>>>>>>> This set of 8 patches adds DFS master support to the Linux wireless
>>>>>>> subsystem.
>>>>>>> I've reviewed future possible changes to DFS master regions and it
>>>>>>> seems that
>>>>>>> we are not going to be having multiple DFS regions for one country,
>>>>>>> instead
>>>>>>> we'll always have one DFS region for one country.
>>>>>>>
>>>>>>> The changes here are spread out throughout wireless-regdb, crda the
>>>>>>> kernel and
>>>>>>> lastly iw. The changes made allow for older verions of CRDA to work
>>>>>>> with new
>>>>>>> wireless-regdb files with DFS region support. If you want DFS master
>>>>>>> region
>>>>>>> support you'll need to upgrade your CRDA, your kernel and then hope
>>>>>>> someone
>>>>>>> implements DFS master support for your respective driver.
>>>>>>>
>>>>>>> This patch series does not have specific driver changes, although some
>>>>>>> seem to
>>>>>>> be backing in the oven right now.
>>>>>>
>>>>>> Here's a puzzle though... If we change this series to use the other
>>>>>> pad byte that was available, the first pad byte, instead of the last
>>>>>> one, we loose backward compatibility support and I cannot figure out
>>>>>> why. What I ended up seeing was that crda sends the message, and for
>>>>>> some reason (return code is 222 from nl_wait_for_ack(), whatever that
>>>>>> is) the kernel rejects it. I suspect it may have to do with some sort
>>>>>> of offset to the *other* data that makes some of the rules output
>>>>>> invalid data for the attribute policy, but at least when I hexdump the
>>>>>> wireless-regdb the only changes I see are in the signature and the pad
>>>>>> shift.
>>>>>>
>>>>>> I got tired of trying though and after seeing flipping the pad bytes
>>>>>> things worked decided to stay with it. In my original RFC in December
>>>>>> I had used u16 instead, but since the data was in the last pad byte
>>>>>> things still worked. So something is fishy about only using the first
>>>>>> pad byte. The change below, as far as I can tell, should not have any
>>>>>> issues but it does with the older version of CRDA and even a new one.
>>>>>
>>>>> Johannes spotted the issue, I'll send the fix, thanks to Johannes.
>>>>> John, Johannes the patches still apply my fix goes on top of these
>>>>> changes, the fix is not addressing a regression introduced by this
>>>>> patchset, instead it fixes a long standing issue which would prevent
>>>>> us from using the next available pad byte.
>>>>
>>>> I'm going to respin this to make use of 2 bits:
>>>>
>>>> 00 unset
>>>> 01 FCC
>>>> 10 ETSI
>>>> 11 JP
>>>>
>>>> We may need some more DFS values later but
>>>
>>> Sorry I did not finish this e-mail I meant that we may later have a
>>> requirement for more DFS values but at this time we don't, we should
>>> consider whether or not we will want to leave more bits for usage of
>>> more DFS values and if so how many? Using two bits will give us
>>> support for what we know today but nothing for the future.
>>>
>> For the future things we do not know of today we should add another bit and
>> define
>>
>> 111 unknown / other
>>
>> to be able to mark special countrycodes that do not fully belong to the
>> three known domains.
>
> I thought about this a bit more, so we'd have to define this as a U8
> attribute either way, so I would instead of calling NL80211_DFS_REGION
> call it something like NL80211_CTRY_REQS and for now only use 2 bits
> for the known DFS regions. We'd mask out the rest of the values. If we
> ever decide we need a new DFS region we could just extend the values
> on NL80211_CTRY_REQS after the last region. If we want to add a new
> requirement that is country specific other than DFS we could start at
> the end of the u8 instead of after the last DFS region. We could do
> this without making any explicit reservations.
>
>> We could use some invalid coding for those CCs (like no
>> DFS domain set in CC
>
> Sure, I should point out today every single regulatory domain will
> have this set except US, only because I added a patch to match US to
> DFS-FCC DFS region.
>
>> but flag set for frequency band) to identify those
>> special domains,
>
> So you're saying in case later we find out we need band specific DFS data later?
>
No, I guess I initially misinterpreted the meaning of '00 unset' as a flag for countrycodes not restricted by DFS at all, but in fact this is done by not setting the per-band DFS flags.
So, if we consider the per-country DFS domain as an enabler for DFS support on top of per-band DFS restrictions (that otherwise remain disabled), we can support 'fancy' CCs by not setting the domain. The concern I brought up is therefore void.
WRT band specific DFS data, we agreed that this will break backwards compatibility and therefore needs some detailed planning. Adrian already brought up some issues we will face and why he is using per-band (or even per-channel) DFS properties.
I opt for keeping this proposed per-country DFS domain scheme until we get DFS fully working and find its limitations significant enough to start a major revision.
>> but using an additional bit would make things easier to
>> handle.
>
> We can extend this as we go, and just ensure upon review of new code
> that we accommodate non -DFS crap at the end of the u8. Whatdya think?
>
> Luis
Zefir
^ permalink raw reply
* [PATCH 0/5] ath6kl: Debugging and roaming
From: Jouni Malinen @ 2011-10-10 10:43 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, Jouni Malinen
This set of patches adds some more ath6kl debugging information and
control to debugfs and enables additional roaming functionality.
Jouni Malinen (5):
ath6kl: Add endpoint_stats debugfs file
ath6kl: Add debugfs file for target roam table
ath6kl: Add debugfs files for roaming control
ath6kl: Add debugfs control for keepalive and disconnection timeout
ath6kl: Allow CCKM AKM and KRK to be configured
drivers/net/wireless/ath/ath6kl/cfg80211.c | 14 ++
drivers/net/wireless/ath/ath6kl/core.h | 7 +
drivers/net/wireless/ath/ath6kl/debug.c | 346 ++++++++++++++++++++++++++++
drivers/net/wireless/ath/ath6kl/wmi.c | 89 +++++++
drivers/net/wireless/ath/ath6kl/wmi.h | 28 ++-
5 files changed, 478 insertions(+), 6 deletions(-)
--
1.7.4.1
^ permalink raw reply
* [PATCH 1/5] ath6kl: Add endpoint_stats debugfs file
From: Jouni Malinen @ 2011-10-10 10:43 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, Jouni Malinen
In-Reply-To: <1318243411-16110-1-git-send-email-jouni@qca.qualcomm.com>
This file can be used to fetch endpoint statistics counters and
to clear them by writing 0 to it.
Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
---
drivers/net/wireless/ath/ath6kl/debug.c | 102 +++++++++++++++++++++++++++++++
1 files changed, 102 insertions(+), 0 deletions(-)
diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c
index ba3f23d..b9bf28d 100644
--- a/drivers/net/wireless/ath/ath6kl/debug.c
+++ b/drivers/net/wireless/ath/ath6kl/debug.c
@@ -595,6 +595,105 @@ static const struct file_operations fops_credit_dist_stats = {
.llseek = default_llseek,
};
+static unsigned int print_endpoint_stat(struct htc_target *target, char *buf,
+ unsigned int buf_len, unsigned int len,
+ int offset, const char *name)
+{
+ int i;
+ struct htc_endpoint_stats *ep_st;
+ u32 *counter;
+
+ len += scnprintf(buf + len, buf_len - len, "%s:", name);
+ for (i = 0; i < ENDPOINT_MAX; i++) {
+ ep_st = &target->endpoint[i].ep_st;
+ counter = ((u32 *) ep_st) + (offset / 4);
+ len += scnprintf(buf + len, buf_len - len, " %u", *counter);
+ }
+ len += scnprintf(buf + len, buf_len - len, "\n");
+
+ return len;
+}
+
+static ssize_t ath6kl_endpoint_stats_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath6kl *ar = file->private_data;
+ struct htc_target *target = ar->htc_target;
+ char *buf;
+ unsigned int buf_len, len = 0;
+ ssize_t ret_cnt;
+
+ buf_len = 1000 + ENDPOINT_MAX * 100;
+ buf = kzalloc(buf_len, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+#define EPSTAT(name) \
+ len = print_endpoint_stat(target, buf, buf_len, len, \
+ offsetof(struct htc_endpoint_stats, name), \
+ #name)
+ EPSTAT(cred_low_indicate);
+ EPSTAT(tx_issued);
+ EPSTAT(tx_pkt_bundled);
+ EPSTAT(tx_bundles);
+ EPSTAT(tx_dropped);
+ EPSTAT(tx_cred_rpt);
+ EPSTAT(cred_rpt_from_rx);
+ EPSTAT(cred_rpt_ep0);
+ EPSTAT(cred_from_rx);
+ EPSTAT(cred_from_other);
+ EPSTAT(cred_from_ep0);
+ EPSTAT(cred_cosumd);
+ EPSTAT(cred_retnd);
+ EPSTAT(rx_pkts);
+ EPSTAT(rx_lkahds);
+ EPSTAT(rx_bundl);
+ EPSTAT(rx_bundle_lkahd);
+ EPSTAT(rx_bundle_from_hdr);
+ EPSTAT(rx_alloc_thresh_hit);
+ EPSTAT(rxalloc_thresh_byte);
+#undef EPSTAT
+
+ if (len > buf_len)
+ len = buf_len;
+
+ ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+ kfree(buf);
+ return ret_cnt;
+}
+
+static ssize_t ath6kl_endpoint_stats_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath6kl *ar = file->private_data;
+ struct htc_target *target = ar->htc_target;
+ int ret, i;
+ u32 val;
+ struct htc_endpoint_stats *ep_st;
+
+ ret = kstrtou32_from_user(user_buf, count, 0, &val);
+ if (ret)
+ return ret;
+ if (val == 0) {
+ for (i = 0; i < ENDPOINT_MAX; i++) {
+ ep_st = &target->endpoint[i].ep_st;
+ memset(ep_st, 0, sizeof(*ep_st));
+ }
+ }
+
+ return count;
+}
+
+static const struct file_operations fops_endpoint_stats = {
+ .open = ath6kl_debugfs_open,
+ .read = ath6kl_endpoint_stats_read,
+ .write = ath6kl_endpoint_stats_write,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
static unsigned long ath6kl_get_num_reg(void)
{
int i;
@@ -901,6 +1000,9 @@ int ath6kl_debug_init(struct ath6kl *ar)
debugfs_create_file("credit_dist_stats", S_IRUSR, ar->debugfs_phy, ar,
&fops_credit_dist_stats);
+ debugfs_create_file("endpoint_stats", S_IRUSR | S_IWUSR,
+ ar->debugfs_phy, ar, &fops_endpoint_stats);
+
debugfs_create_file("fwlog", S_IRUSR, ar->debugfs_phy, ar,
&fops_fwlog);
--
1.7.4.1
^ permalink raw reply related
* [PATCH 2/5] ath6kl: Add debugfs file for target roam table
From: Jouni Malinen @ 2011-10-10 10:43 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, Jouni Malinen
In-Reply-To: <1318243411-16110-1-git-send-email-jouni@qca.qualcomm.com>
The new roam_table debugfs file can be used to display the current
roam table from the target.
Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
---
drivers/net/wireless/ath/ath6kl/core.h | 4 ++
drivers/net/wireless/ath/ath6kl/debug.c | 75 +++++++++++++++++++++++++++++++
drivers/net/wireless/ath/ath6kl/wmi.c | 41 +++++++++++++++++
drivers/net/wireless/ath/ath6kl/wmi.h | 7 +++
4 files changed, 127 insertions(+), 0 deletions(-)
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h
index 6d8a484..c58cfad 100644
--- a/drivers/net/wireless/ath/ath6kl/core.h
+++ b/drivers/net/wireless/ath/ath6kl/core.h
@@ -397,6 +397,7 @@ struct ath6kl_req_key {
#define TESTMODE 13
#define CLEAR_BSSFILTER_ON_BEACON 14
#define DTIM_PERIOD_AVAIL 15
+#define ROAM_TBL_PEND 16
struct ath6kl {
struct device *dev;
@@ -529,6 +530,9 @@ struct ath6kl {
struct {
unsigned int invalid_rate;
} war_stats;
+
+ u8 *roam_tbl;
+ unsigned int roam_tbl_len;
} debug;
#endif /* CONFIG_ATH6KL_DEBUG */
};
diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c
index b9bf28d..0b7fa26 100644
--- a/drivers/net/wireless/ath/ath6kl/debug.c
+++ b/drivers/net/wireless/ath/ath6kl/debug.c
@@ -966,6 +966,77 @@ static const struct file_operations fops_diag_reg_write = {
.llseek = default_llseek,
};
+static ssize_t ath6kl_roam_table_read(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath6kl *ar = file->private_data;
+ int ret;
+ long left;
+ struct wmi_target_roam_tbl *tbl;
+ u16 num_entries, i;
+ char *buf;
+ unsigned int len, buf_len;
+ ssize_t ret_cnt;
+
+ if (down_interruptible(&ar->sem))
+ return -EBUSY;
+
+ set_bit(ROAM_TBL_PEND, &ar->flag);
+
+ ret = ath6kl_wmi_get_roam_tbl_cmd(ar->wmi);
+ if (ret) {
+ up(&ar->sem);
+ return ret;
+ }
+
+ left = wait_event_interruptible_timeout(
+ ar->event_wq, !test_bit(ROAM_TBL_PEND, &ar->flag), WMI_TIMEOUT);
+ up(&ar->sem);
+
+ if (left <= 0)
+ return -ETIMEDOUT;
+
+ if (ar->debug.roam_tbl == NULL)
+ return -ENOMEM;
+
+ tbl = (struct wmi_target_roam_tbl *) ar->debug.roam_tbl;
+ num_entries = le16_to_cpu(tbl->num_entries);
+
+ buf_len = 100 + num_entries * 100;
+ buf = kzalloc(buf_len, GFP_KERNEL);
+ if (buf == NULL)
+ return -ENOMEM;
+ len = 0;
+ len += scnprintf(buf + len, buf_len - len,
+ "roam_mode=%u\n\n"
+ "# roam_util bssid rssi rssidt last_rssi util bias\n",
+ le16_to_cpu(tbl->roam_mode));
+
+ for (i = 0; i < num_entries; i++) {
+ struct wmi_bss_roam_info *info = &tbl->info[i];
+ len += scnprintf(buf + len, buf_len - len,
+ "%d %pM %d %d %d %d %d\n",
+ a_sle32_to_cpu(info->roam_util), info->bssid,
+ info->rssi, info->rssidt, info->last_rssi,
+ info->util, info->bias);
+ }
+
+ if (len > buf_len)
+ len = buf_len;
+
+ ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+
+ kfree(buf);
+ return ret_cnt;
+}
+
+static const struct file_operations fops_roam_table = {
+ .read = ath6kl_roam_table_read,
+ .open = ath6kl_debugfs_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
int ath6kl_debug_init(struct ath6kl *ar)
{
ar->debug.fwlog_buf.buf = vmalloc(ATH6KL_FWLOG_SIZE);
@@ -1024,6 +1095,9 @@ int ath6kl_debug_init(struct ath6kl *ar)
debugfs_create_file("war_stats", S_IRUSR, ar->debugfs_phy, ar,
&fops_war_stats);
+ debugfs_create_file("roam_table", S_IRUSR, ar->debugfs_phy, ar,
+ &fops_roam_table);
+
return 0;
}
@@ -1031,6 +1105,7 @@ void ath6kl_debug_cleanup(struct ath6kl *ar)
{
vfree(ar->debug.fwlog_buf.buf);
kfree(ar->debug.fwlog_tmp);
+ kfree(ar->debug.roam_tbl);
}
#endif
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c
index ab782d7..425efb5 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.c
+++ b/drivers/net/wireless/ath/ath6kl/wmi.c
@@ -2407,6 +2407,11 @@ int ath6kl_wmi_get_tx_pwr_cmd(struct wmi *wmi)
return ath6kl_wmi_simple_cmd(wmi, WMI_GET_TX_PWR_CMDID);
}
+int ath6kl_wmi_get_roam_tbl_cmd(struct wmi *wmi)
+{
+ return ath6kl_wmi_simple_cmd(wmi, WMI_GET_ROAM_TBL_CMDID);
+}
+
int ath6kl_wmi_set_lpreamble_cmd(struct wmi *wmi, u8 status, u8 preamble_policy)
{
struct sk_buff *skb;
@@ -2844,6 +2849,41 @@ static int ath6kl_wmi_control_rx_xtnd(struct wmi *wmi, struct sk_buff *skb)
return ret;
}
+static int ath6kl_wmi_roam_tbl_event_rx(struct wmi *wmi, u8 *datap, int len)
+{
+#ifdef CONFIG_ATH6KL_DEBUG
+ struct ath6kl *ar = wmi->parent_dev;
+ struct wmi_target_roam_tbl *tbl;
+ u16 num_entries;
+
+ if (len < sizeof(*tbl))
+ return -EINVAL;
+
+ tbl = (struct wmi_target_roam_tbl *) datap;
+ num_entries = le16_to_cpu(tbl->num_entries);
+ if (sizeof(*tbl) + num_entries * sizeof(struct wmi_bss_roam_info) > len)
+ return -EINVAL;
+
+ if (ar->debug.roam_tbl == NULL ||
+ ar->debug.roam_tbl_len < (unsigned int) len) {
+ kfree(ar->debug.roam_tbl);
+ ar->debug.roam_tbl = kmalloc(len, GFP_ATOMIC);
+ if (ar->debug.roam_tbl == NULL)
+ return -ENOMEM;
+ }
+
+ memcpy(ar->debug.roam_tbl, datap, len);
+ ar->debug.roam_tbl_len = len;
+
+ if (test_bit(ROAM_TBL_PEND, &ar->flag)) {
+ clear_bit(ROAM_TBL_PEND, &ar->flag);
+ wake_up(&ar->event_wq);
+ }
+#endif /* CONFIG_ATH6KL_DEBUG */
+
+ return 0;
+}
+
/* Control Path */
int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
{
@@ -2948,6 +2988,7 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
break;
case WMI_REPORT_ROAM_TBL_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REPORT_ROAM_TBL_EVENTID\n");
+ ret = ath6kl_wmi_roam_tbl_event_rx(wmi, datap, len);
break;
case WMI_EXTENSION_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_EXTENSION_EVENTID\n");
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h
index 96102c6..f986da1 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.h
+++ b/drivers/net/wireless/ath/ath6kl/wmi.h
@@ -1624,6 +1624,12 @@ struct wmi_bss_roam_info {
u8 reserved;
} __packed;
+struct wmi_target_roam_tbl {
+ __le16 roam_mode;
+ __le16 num_entries;
+ struct wmi_bss_roam_info info[];
+} __packed;
+
/* WMI_CAC_EVENTID */
enum cac_indication {
CAC_INDICATION_ADMISSION = 0x00,
@@ -2221,6 +2227,7 @@ int ath6kl_wmi_setpmkid_cmd(struct wmi *wmi, const u8 *bssid,
const u8 *pmkid, bool set);
int ath6kl_wmi_set_tx_pwr_cmd(struct wmi *wmi, u8 dbM);
int ath6kl_wmi_get_tx_pwr_cmd(struct wmi *wmi);
+int ath6kl_wmi_get_roam_tbl_cmd(struct wmi *wmi);
int ath6kl_wmi_set_wmm_txop(struct wmi *wmi, enum wmi_txop_cfg cfg);
int ath6kl_wmi_set_keepalive_cmd(struct wmi *wmi, u8 keep_alive_intvl);
--
1.7.4.1
^ permalink raw reply related
* [PATCH 3/5] ath6kl: Add debugfs files for roaming control
From: Jouni Malinen @ 2011-10-10 10:43 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, Jouni Malinen
In-Reply-To: <1318243411-16110-1-git-send-email-jouni@qca.qualcomm.com>
Roaming mode can be changed by writing roam mode (default, bssbias, or
lock) to roam_mode. Forced roam can be requested by writing the BSSID
into force_roam.
Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
---
drivers/net/wireless/ath/ath6kl/debug.c | 84 +++++++++++++++++++++++++++++++
drivers/net/wireless/ath/ath6kl/wmi.c | 40 +++++++++++++++
drivers/net/wireless/ath/ath6kl/wmi.h | 21 ++++++--
3 files changed, 139 insertions(+), 6 deletions(-)
diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c
index 0b7fa26..51eb626 100644
--- a/drivers/net/wireless/ath/ath6kl/debug.c
+++ b/drivers/net/wireless/ath/ath6kl/debug.c
@@ -1037,6 +1037,84 @@ static const struct file_operations fops_roam_table = {
.llseek = default_llseek,
};
+static ssize_t ath6kl_force_roam_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath6kl *ar = file->private_data;
+ int ret;
+ char buf[20];
+ size_t len;
+ u8 bssid[ETH_ALEN];
+ int i;
+ int addr[ETH_ALEN];
+
+ len = min(count, sizeof(buf) - 1);
+ if (copy_from_user(buf, user_buf, len))
+ return -EFAULT;
+ buf[len] = '\0';
+
+ if (sscanf(buf, "%02x:%02x:%02x:%02x:%02x:%02x",
+ &addr[0], &addr[1], &addr[2], &addr[3], &addr[4], &addr[5])
+ != ETH_ALEN)
+ return -EINVAL;
+ for (i = 0; i < ETH_ALEN; i++)
+ bssid[i] = addr[i];
+
+ ret = ath6kl_wmi_force_roam_cmd(ar->wmi, bssid);
+ if (ret)
+ return ret;
+
+ return count;
+}
+
+static const struct file_operations fops_force_roam = {
+ .write = ath6kl_force_roam_write,
+ .open = ath6kl_debugfs_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
+static ssize_t ath6kl_roam_mode_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath6kl *ar = file->private_data;
+ int ret;
+ char buf[20];
+ size_t len;
+ enum wmi_roam_mode mode;
+
+ len = min(count, sizeof(buf) - 1);
+ if (copy_from_user(buf, user_buf, len))
+ return -EFAULT;
+ buf[len] = '\0';
+ if (len > 0 && buf[len - 1] == '\n')
+ buf[len - 1] = '\0';
+
+ if (strcasecmp(buf, "default") == 0)
+ mode = WMI_DEFAULT_ROAM_MODE;
+ else if (strcasecmp(buf, "bssbias") == 0)
+ mode = WMI_HOST_BIAS_ROAM_MODE;
+ else if (strcasecmp(buf, "lock") == 0)
+ mode = WMI_LOCK_BSS_MODE;
+ else
+ return -EINVAL;
+
+ ret = ath6kl_wmi_set_roam_mode_cmd(ar->wmi, mode);
+ if (ret)
+ return ret;
+
+ return count;
+}
+
+static const struct file_operations fops_roam_mode = {
+ .write = ath6kl_roam_mode_write,
+ .open = ath6kl_debugfs_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
int ath6kl_debug_init(struct ath6kl *ar)
{
ar->debug.fwlog_buf.buf = vmalloc(ATH6KL_FWLOG_SIZE);
@@ -1098,6 +1176,12 @@ int ath6kl_debug_init(struct ath6kl *ar)
debugfs_create_file("roam_table", S_IRUSR, ar->debugfs_phy, ar,
&fops_roam_table);
+ debugfs_create_file("force_roam", S_IWUSR, ar->debugfs_phy, ar,
+ &fops_force_roam);
+
+ debugfs_create_file("roam_mode", S_IWUSR, ar->debugfs_phy, ar,
+ &fops_roam_mode);
+
return 0;
}
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c
index 425efb5..fdb3712 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.c
+++ b/drivers/net/wireless/ath/ath6kl/wmi.c
@@ -682,6 +682,46 @@ int ath6kl_wmi_set_roam_lrssi_cmd(struct wmi *wmi, u8 lrssi)
return 0;
}
+int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid)
+{
+ struct sk_buff *skb;
+ struct roam_ctrl_cmd *cmd;
+
+ skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
+ if (!skb)
+ return -ENOMEM;
+
+ cmd = (struct roam_ctrl_cmd *) skb->data;
+ memset(cmd, 0, sizeof(*cmd));
+
+ memcpy(cmd->info.bssid, bssid, ETH_ALEN);
+ cmd->roam_ctrl = WMI_FORCE_ROAM;
+
+ ath6kl_dbg(ATH6KL_DBG_WMI, "force roam to %pM\n", bssid);
+ return ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_ROAM_CTRL_CMDID,
+ NO_SYNC_WMIFLAG);
+}
+
+int ath6kl_wmi_set_roam_mode_cmd(struct wmi *wmi, enum wmi_roam_mode mode)
+{
+ struct sk_buff *skb;
+ struct roam_ctrl_cmd *cmd;
+
+ skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
+ if (!skb)
+ return -ENOMEM;
+
+ cmd = (struct roam_ctrl_cmd *) skb->data;
+ memset(cmd, 0, sizeof(*cmd));
+
+ cmd->info.roam_mode = mode;
+ cmd->roam_ctrl = WMI_SET_ROAM_MODE;
+
+ ath6kl_dbg(ATH6KL_DBG_WMI, "set roam mode %d\n", mode);
+ return ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_ROAM_CTRL_CMDID,
+ NO_SYNC_WMIFLAG);
+}
+
static int ath6kl_wmi_connect_event_rx(struct wmi *wmi, u8 *datap, int len)
{
struct wmi_connect_event *ev;
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h
index f986da1..f0ca899 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.h
+++ b/drivers/net/wireless/ath/ath6kl/wmi.h
@@ -1354,14 +1354,20 @@ enum wmi_roam_ctrl {
WMI_SET_LRSSI_SCAN_PARAMS,
};
+enum wmi_roam_mode {
+ WMI_DEFAULT_ROAM_MODE = 1, /* RSSI based roam */
+ WMI_HOST_BIAS_ROAM_MODE = 2, /* Host bias based roam */
+ WMI_LOCK_BSS_MODE = 3, /* Lock to the current BSS */
+};
+
struct bss_bias {
u8 bssid[ETH_ALEN];
- u8 bias;
+ s8 bias;
} __packed;
struct bss_bias_info {
u8 num_bss;
- struct bss_bias bss_bias[1];
+ struct bss_bias bss_bias[0];
} __packed;
struct low_rssi_scan_params {
@@ -1374,10 +1380,11 @@ struct low_rssi_scan_params {
struct roam_ctrl_cmd {
union {
- u8 bssid[ETH_ALEN];
- u8 roam_mode;
- struct bss_bias_info bss;
- struct low_rssi_scan_params params;
+ u8 bssid[ETH_ALEN]; /* WMI_FORCE_ROAM */
+ u8 roam_mode; /* WMI_SET_ROAM_MODE */
+ struct bss_bias_info bss; /* WMI_SET_HOST_BIAS */
+ struct low_rssi_scan_params params; /* WMI_SET_LRSSI_SCAN_PARAMS
+ */
} __packed info;
u8 roam_ctrl;
} __packed;
@@ -2237,6 +2244,8 @@ s32 ath6kl_wmi_get_rate(s8 rate_index);
int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, struct wmi_set_ip_cmd *ip_cmd);
int ath6kl_wmi_set_roam_lrssi_cmd(struct wmi *wmi, u8 lrssi);
+int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid);
+int ath6kl_wmi_set_roam_mode_cmd(struct wmi *wmi, enum wmi_roam_mode mode);
/* AP mode */
int ath6kl_wmi_ap_profile_commit(struct wmi *wmip, struct wmi_connect_cmd *p);
--
1.7.4.1
^ permalink raw reply related
* [PATCH 4/5] ath6kl: Add debugfs control for keepalive and disconnection timeout
From: Jouni Malinen @ 2011-10-10 10:43 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, Jouni Malinen
In-Reply-To: <1318243411-16110-1-git-send-email-jouni@qca.qualcomm.com>
The new debugfs files keepalive and disconnect_timeout can be used to
fetch the current values and to change the values for keepalive and
disconnect event timeout (both in seconds).
Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
---
drivers/net/wireless/ath/ath6kl/core.h | 3 +
drivers/net/wireless/ath/ath6kl/debug.c | 85 +++++++++++++++++++++++++++++++
drivers/net/wireless/ath/ath6kl/wmi.c | 8 +++
3 files changed, 96 insertions(+), 0 deletions(-)
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h
index c58cfad..31e5c7e 100644
--- a/drivers/net/wireless/ath/ath6kl/core.h
+++ b/drivers/net/wireless/ath/ath6kl/core.h
@@ -533,6 +533,9 @@ struct ath6kl {
u8 *roam_tbl;
unsigned int roam_tbl_len;
+
+ u8 keepalive;
+ u8 disc_timeout;
} debug;
#endif /* CONFIG_ATH6KL_DEBUG */
};
diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c
index 51eb626..9035002 100644
--- a/drivers/net/wireless/ath/ath6kl/debug.c
+++ b/drivers/net/wireless/ath/ath6kl/debug.c
@@ -1115,6 +1115,85 @@ static const struct file_operations fops_roam_mode = {
.llseek = default_llseek,
};
+static ssize_t ath6kl_keepalive_read(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath6kl *ar = file->private_data;
+ char buf[16];
+ int len;
+
+ len = snprintf(buf, sizeof(buf), "%u\n", ar->debug.keepalive);
+
+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t ath6kl_keepalive_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath6kl *ar = file->private_data;
+ int ret;
+ u8 val;
+
+ ret = kstrtou8_from_user(user_buf, count, 0, &val);
+ if (ret)
+ return ret;
+
+ ret = ath6kl_wmi_set_keepalive_cmd(ar->wmi, val);
+ if (ret)
+ return ret;
+
+ return count;
+}
+
+static const struct file_operations fops_keepalive = {
+ .open = ath6kl_debugfs_open,
+ .read = ath6kl_keepalive_read,
+ .write = ath6kl_keepalive_write,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
+static ssize_t ath6kl_disconnect_timeout_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath6kl *ar = file->private_data;
+ char buf[16];
+ int len;
+
+ len = snprintf(buf, sizeof(buf), "%u\n", ar->debug.disc_timeout);
+
+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t ath6kl_disconnect_timeout_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath6kl *ar = file->private_data;
+ int ret;
+ u8 val;
+
+ ret = kstrtou8_from_user(user_buf, count, 0, &val);
+ if (ret)
+ return ret;
+
+ ret = ath6kl_wmi_disctimeout_cmd(ar->wmi, val);
+ if (ret)
+ return ret;
+
+ return count;
+}
+
+static const struct file_operations fops_disconnect_timeout = {
+ .open = ath6kl_debugfs_open,
+ .read = ath6kl_disconnect_timeout_read,
+ .write = ath6kl_disconnect_timeout_write,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
int ath6kl_debug_init(struct ath6kl *ar)
{
ar->debug.fwlog_buf.buf = vmalloc(ATH6KL_FWLOG_SIZE);
@@ -1182,6 +1261,12 @@ int ath6kl_debug_init(struct ath6kl *ar)
debugfs_create_file("roam_mode", S_IWUSR, ar->debugfs_phy, ar,
&fops_roam_mode);
+ debugfs_create_file("keepalive", S_IRUSR | S_IWUSR, ar->debugfs_phy, ar,
+ &fops_keepalive);
+
+ debugfs_create_file("disconnect_timeout", S_IRUSR | S_IWUSR,
+ ar->debugfs_phy, ar, &fops_disconnect_timeout);
+
return 0;
}
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c
index fdb3712..dd8110c 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.c
+++ b/drivers/net/wireless/ath/ath6kl/wmi.c
@@ -1940,6 +1940,10 @@ int ath6kl_wmi_disctimeout_cmd(struct wmi *wmi, u8 timeout)
ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_DISC_TIMEOUT_CMDID,
NO_SYNC_WMIFLAG);
+#ifdef CONFIG_ATH6KL_DEBUG
+ if (ret == 0)
+ wmi->parent_dev->debug.disc_timeout = timeout;
+#endif /* CONFIG_ATH6KL_DEBUG */
return ret;
}
@@ -2524,6 +2528,10 @@ int ath6kl_wmi_set_keepalive_cmd(struct wmi *wmi, u8 keep_alive_intvl)
ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_KEEPALIVE_CMDID,
NO_SYNC_WMIFLAG);
+#ifdef CONFIG_ATH6KL_DEBUG
+ if (ret == 0)
+ wmi->parent_dev->debug.keepalive = keep_alive_intvl;
+#endif /* CONFIG_ATH6KL_DEBUG */
return ret;
}
--
1.7.4.1
^ permalink raw reply related
* [PATCH 5/5] ath6kl: Allow CCKM AKM and KRK to be configured
From: Jouni Malinen @ 2011-10-10 10:43 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, Jouni Malinen
In-Reply-To: <1318243411-16110-1-git-send-email-jouni@qca.qualcomm.com>
Use vendor-specific suite selectors to allow CCKM to be configured.
Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
---
drivers/net/wireless/ath/ath6kl/cfg80211.c | 14 ++++++++++++++
1 files changed, 14 insertions(+), 0 deletions(-)
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
index b7b2c57..6b30b75 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -121,6 +121,8 @@ static struct ieee80211_supported_band ath6kl_band_5ghz = {
.bitrates = ath6kl_a_rates,
};
+#define CCKM_KRK_CIPHER_SUITE 0x004096ff /* use for KRK */
+
static int ath6kl_set_wpa_version(struct ath6kl *ar,
enum nl80211_wpa_versions wpa_version)
{
@@ -217,6 +219,11 @@ static void ath6kl_set_key_mgmt(struct ath6kl *ar, u32 key_mgmt)
ar->auth_mode = WPA_PSK_AUTH;
else if (ar->auth_mode == WPA2_AUTH)
ar->auth_mode = WPA2_PSK_AUTH;
+ } else if (key_mgmt == 0x00409600) {
+ if (ar->auth_mode == WPA_AUTH)
+ ar->auth_mode = WPA_AUTH_CCKM;
+ else if (ar->auth_mode == WPA2_AUTH)
+ ar->auth_mode = WPA2_AUTH_CCKM;
} else if (key_mgmt != WLAN_AKM_SUITE_8021X) {
ar->auth_mode = NONE_AUTH;
}
@@ -758,6 +765,12 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
if (!ath6kl_cfg80211_ready(ar))
return -EIO;
+ if (params->cipher == CCKM_KRK_CIPHER_SUITE) {
+ if (params->key_len != WMI_KRK_LEN)
+ return -EINVAL;
+ return ath6kl_wmi_add_krk_cmd(ar->wmi, params->key);
+ }
+
if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) {
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
"%s: key index %d out of bounds\n", __func__,
@@ -1228,6 +1241,7 @@ static const u32 cipher_suites[] = {
WLAN_CIPHER_SUITE_WEP104,
WLAN_CIPHER_SUITE_TKIP,
WLAN_CIPHER_SUITE_CCMP,
+ CCKM_KRK_CIPHER_SUITE,
};
static bool is_rate_legacy(s32 rate)
--
1.7.4.1
^ permalink raw reply related
* Re: [alsa-devel] Using spdiff for backporting
From: Takashi Iwai @ 2011-10-10 12:41 UTC (permalink / raw)
To: Luis R. Rodriguez
Cc: Jesper Andersen, linux-wireless, alsa-devel, julia, linux-kernel
In-Reply-To: <CAB=NE6X81KPvx-yt33MghmoftUznoP-jYO8sBxoeW_0fzQ1pdA@mail.gmail.com>
At Fri, 7 Oct 2011 10:41:06 -0700,
Luis R. Rodriguez wrote:
>
> > Also, in the slides from the plumbers-conf. I think I saw it mentioned
> > that there's also an alsa-compat git-tree somewhere. Maybe that is a
> > more compelling usecase? I was unable to find it though so I'd
> > appreciate a link.
>
> It was on kernel.org, but if it got rm -rf'd then its gone as I do not
> have a local copy.
Oh, I didn't know of such a tree. So you created alsa driver build
system with your spdiff? That's interesting.
> The compat-alsa stuff though was determined to be
> superflous with the ALSA's team's own backport work which is currently
> independent.
Yes, the external alsa-driver build tree has existed since 10 years
ago :) It was even possible to build with 2.2/2.4 kernels until
recently.
The current tree is found in github,
git://github.com/tiwai/alsa-driver-build.git
> My hope though is to unify these through the compat.git /
> compat-kernel (currently just called compat-wireless) effort.
The common framework would be really nice to have.
V4L also have own build system, and possible other subsystem trees too.
thanks,
Takashi
^ permalink raw reply
* Re: [PATCH 04/20] staging: brcm80211: various __iomem additions to softmac.
From: Rafał Miłecki @ 2011-10-10 14:23 UTC (permalink / raw)
To: Franky Lin; +Cc: gregkh, devel, linux-wireless
In-Reply-To: <1317575685-3156-5-git-send-email-frankyl@broadcom.com>
2011/10/2 Franky Lin <frankyl@broadcom.com>:
> From: Roland Vossen <rvossen@broadcom.com>
>
> So it is clear to the reader what memory is IO mapped
>
> Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
> Reviewed-by: Arend van Spriel <arend@broadcom.com>
> Signed-off-by: Franky Lin <frankyl@broadcom.com>
> ---
> drivers/staging/brcm80211/brcmsmac/aiutils.c | 107 ++++++++++++++------------
> drivers/staging/brcm80211/brcmsmac/aiutils.h | 16 ++--
> drivers/staging/brcm80211/brcmsmac/main.c | 2 +-
> drivers/staging/brcm80211/brcmsmac/nicpci.c | 45 ++++++-----
> drivers/staging/brcm80211/brcmsmac/nicpci.h | 9 +-
> drivers/staging/brcm80211/brcmsmac/otp.c | 9 +-
> drivers/staging/brcm80211/brcmsmac/pmu.c | 16 ++--
> drivers/staging/brcm80211/brcmsmac/srom.c | 20 +++--
> drivers/staging/brcm80211/brcmsmac/srom.h | 2 +-
> 9 files changed, 123 insertions(+), 103 deletions(-)
>
> diff --git a/drivers/staging/brcm80211/brcmsmac/aiutils.c b/drivers/staging/brcm80211/brcmsmac/aiutils.c
> index 790fdce..0b3ba6a 100644
> --- a/drivers/staging/brcm80211/brcmsmac/aiutils.c
> +++ b/drivers/staging/brcm80211/brcmsmac/aiutils.c
> @@ -323,7 +323,8 @@
> (((si)->pub.buscoretype == PCI_CORE_ID) && \
> (si)->pub.buscorerev >= 13))
>
> -#define CCREGS_FAST(si) (((char *)((si)->curmap) + PCI_16KB0_CCREGS_OFFSET))
> +#define CCREGS_FAST(si) (((char __iomem *)((si)->curmap) + \
> + PCI_16KB0_CCREGS_OFFSET))
I've a question (not to just you), should we prefer u8/u16/u32 types in code?
If so, you could think to changing this since you already touch this code.
--
Rafał
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox