* [PATCH 01/29] wl12xx: refactor fw init into a new function
2011-10-10 8:12 [PATCH 00/29] make the driver ready for multi-vif support Eliad Peller
@ 2011-10-10 8:12 ` Eliad Peller
2011-10-10 8:12 ` [PATCH 02/29] wl12xx: move last_tx_hlid into wlvif Eliad Peller
` (28 subsequent siblings)
29 siblings, 0 replies; 51+ messages in thread
From: Eliad Peller @ 2011-10-10 8:12 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
The fw boot and initialization currently happens inside the
add_interface() callback. This is wrong, as add_interface is
called for each new vif. However, we due to some fw limitation
(we have to know the actual mac address on boot), we can't
completely move it into the start() callback.
Until the fw will be fixed, refactor the fw init into
a new function, and call it from add_interface()
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
drivers/net/wireless/wl12xx/main.c | 171 +++++++++++++++++++----------------
1 files changed, 93 insertions(+), 78 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 194d7cc..3667acf 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -1888,60 +1888,12 @@ static int wl12xx_init_vif_data(struct ieee80211_vif *vif)
return 0;
}
-static int wl1271_op_add_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+static bool wl12xx_init_fw(struct wl1271 *wl)
{
- struct wl1271 *wl = hw->priv;
- struct wiphy *wiphy = hw->wiphy;
- struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
int retries = WL1271_BOOT_RETRIES;
- int ret = 0;
- u8 role_type;
bool booted = false;
-
- wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM",
- ieee80211_vif_type_p2p(vif), vif->addr);
-
- mutex_lock(&wl->mutex);
- if (wl->vif) {
- wl1271_debug(DEBUG_MAC80211,
- "multiple vifs are not supported yet");
- ret = -EBUSY;
- goto out;
- }
-
- /*
- * in some very corner case HW recovery scenarios its possible to
- * 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)) {
- ret = -EBUSY;
- goto out;
- }
-
- ret = wl12xx_init_vif_data(vif);
- if (ret < 0)
- goto out;
-
- wlvif->wl = wl;
- role_type = wl12xx_get_role_type(wl, wlvif);
- if (role_type == WL12XX_INVALID_ROLE_TYPE) {
- ret = -EINVAL;
- goto out;
- }
- /*
- * we still need this in order to configure the fw
- * while uploading the nvs
- */
- memcpy(wl->mac_addr, vif->addr, ETH_ALEN);
-
- if (wl->state != WL1271_STATE_OFF) {
- wl1271_error("cannot start because not in off state: %d",
- wl->state);
- ret = -EBUSY;
- goto out;
- }
+ struct wiphy *wiphy = wl->hw->wiphy;
+ int ret;
while (retries) {
retries--;
@@ -1957,30 +1909,6 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
if (ret < 0)
goto irq_disable;
- if (wlvif->bss_type == BSS_TYPE_STA_BSS ||
- wlvif->bss_type == BSS_TYPE_IBSS) {
- /*
- * The device role is a special role used for
- * rx and tx frames prior to association (as
- * the STA role can get packets only from
- * its associated bssid)
- */
- ret = wl12xx_cmd_role_enable(wl, vif->addr,
- WL1271_ROLE_DEVICE,
- &wlvif->dev_role_id);
- if (ret < 0)
- goto irq_disable;
- }
-
- ret = wl12xx_cmd_role_enable(wl, vif->addr,
- role_type, &wlvif->role_id);
- if (ret < 0)
- goto irq_disable;
-
- ret = wl1271_init_vif_specific(wl, vif);
- if (ret < 0)
- goto irq_disable;
-
booted = true;
break;
@@ -2007,9 +1935,6 @@ power_off:
goto out;
}
- wl->vif = vif;
- wl->state = WL1271_STATE_ON;
- set_bit(WL1271_FLAG_IF_INITIALIZED, &wl->flags);
wl1271_info("firmware booted (%s)", wl->chip.fw_ver_str);
/* update hw/fw version info in wiphy struct */
@@ -2027,6 +1952,96 @@ power_off:
wl1271_debug(DEBUG_MAC80211, "11a is %ssupported",
wl->enable_11a ? "" : "not ");
+ wl->state = WL1271_STATE_ON;
+out:
+ return booted;
+}
+
+static int wl1271_op_add_interface(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
+{
+ struct wl1271 *wl = hw->priv;
+ struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
+ int ret = 0;
+ u8 role_type;
+ bool booted = false;
+
+ wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM",
+ ieee80211_vif_type_p2p(vif), vif->addr);
+
+ mutex_lock(&wl->mutex);
+ if (wl->vif) {
+ wl1271_debug(DEBUG_MAC80211,
+ "multiple vifs are not supported yet");
+ ret = -EBUSY;
+ goto out;
+ }
+
+ /*
+ * in some very corner case HW recovery scenarios its possible to
+ * 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)) {
+ ret = -EBUSY;
+ goto out;
+ }
+
+ ret = wl12xx_init_vif_data(vif);
+ if (ret < 0)
+ goto out;
+
+ wlvif->wl = wl;
+ role_type = wl12xx_get_role_type(wl, wlvif);
+ if (role_type == WL12XX_INVALID_ROLE_TYPE) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /*
+ * TODO: after the nvs issue will be solved, move this block
+ * to start(), and make sure here the driver is ON.
+ */
+ if (wl->state == WL1271_STATE_OFF) {
+ /*
+ * we still need this in order to configure the fw
+ * while uploading the nvs
+ */
+ memcpy(wl->mac_addr, vif->addr, ETH_ALEN);
+
+ booted = wl12xx_init_fw(wl);
+ if (!booted) {
+ ret = -EINVAL;
+ goto out;
+ }
+ }
+
+ if (wlvif->bss_type == BSS_TYPE_STA_BSS ||
+ wlvif->bss_type == BSS_TYPE_IBSS) {
+ /*
+ * The device role is a special role used for
+ * rx and tx frames prior to association (as
+ * the STA role can get packets only from
+ * its associated bssid)
+ */
+ ret = wl12xx_cmd_role_enable(wl, vif->addr,
+ WL1271_ROLE_DEVICE,
+ &wlvif->dev_role_id);
+ if (ret < 0)
+ goto out;
+ }
+
+ ret = wl12xx_cmd_role_enable(wl, vif->addr,
+ role_type, &wlvif->role_id);
+ if (ret < 0)
+ goto out;
+
+ ret = wl1271_init_vif_specific(wl, vif);
+ if (ret < 0)
+ goto out;
+
+ wl->vif = vif;
+ set_bit(WL1271_FLAG_IF_INITIALIZED, &wl->flags);
out:
mutex_unlock(&wl->mutex);
--
1.7.6.401.g6a319
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 02/29] wl12xx: move last_tx_hlid into wlvif
2011-10-10 8:12 [PATCH 00/29] make the driver ready for multi-vif support Eliad Peller
2011-10-10 8:12 ` [PATCH 01/29] wl12xx: refactor fw init into a new function Eliad Peller
@ 2011-10-10 8:12 ` Eliad Peller
2011-10-10 17:52 ` Luciano Coelho
2011-10-10 8:12 ` [PATCH 03/29] wl12xx: unify STA and AP tx_queue mechanism Eliad Peller
` (27 subsequent siblings)
29 siblings, 1 reply; 51+ messages in thread
From: Eliad Peller @ 2011-10-10 8:12 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
move last_tx_hlid into the per-interface data, rather than
being global.
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
drivers/net/wireless/wl12xx/debugfs.c | 1 -
drivers/net/wireless/wl12xx/main.c | 1 -
drivers/net/wireless/wl12xx/tx.c | 10 +++++-----
drivers/net/wireless/wl12xx/wl12xx.h | 6 +++---
4 files changed, 8 insertions(+), 10 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c
index f0398d0..bbc8004 100644
--- a/drivers/net/wireless/wl12xx/debugfs.c
+++ b/drivers/net/wireless/wl12xx/debugfs.c
@@ -355,7 +355,6 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf,
DRIVER_STATE_PRINT_INT(sg_enabled);
DRIVER_STATE_PRINT_INT(enable_11a);
DRIVER_STATE_PRINT_INT(noise);
- DRIVER_STATE_PRINT_INT(last_tx_hlid);
DRIVER_STATE_PRINT_HEX(ap_fw_ps_map);
DRIVER_STATE_PRINT_LHEX(ap_ps_map);
DRIVER_STATE_PRINT_HEX(quirks);
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 3667acf..0606b0d 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -4901,7 +4901,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
wl->flags = 0;
wl->sg_enabled = true;
wl->hw_pg_ver = -1;
- wl->last_tx_hlid = 0;
wl->ap_ps_map = 0;
wl->ap_fw_ps_map = 0;
wl->quirks = 0;
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index 1b3d8e3..951ff03 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -570,7 +570,7 @@ static struct sk_buff *wl1271_ap_skb_dequeue(struct wl1271 *wl,
struct sk_buff_head *queue;
/* start from the link after the last one */
- start_hlid = (wl->last_tx_hlid + 1) % WL12XX_MAX_LINKS;
+ start_hlid = (wlvif->last_tx_hlid + 1) % WL12XX_MAX_LINKS;
/* dequeue according to AC, round robin on each link */
for (i = 0; i < WL12XX_MAX_LINKS; i++) {
@@ -591,12 +591,12 @@ static struct sk_buff *wl1271_ap_skb_dequeue(struct wl1271 *wl,
if (skb) {
int q = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
- wl->last_tx_hlid = h;
+ wlvif->last_tx_hlid = h;
spin_lock_irqsave(&wl->wl_lock, flags);
wl->tx_queue_count[q]--;
spin_unlock_irqrestore(&wl->wl_lock, flags);
} else {
- wl->last_tx_hlid = 0;
+ wlvif->last_tx_hlid = 0;
}
return skb;
@@ -641,7 +641,7 @@ static void wl1271_skb_queue_head(struct wl1271 *wl, struct ieee80211_vif *vif,
skb_queue_head(&wl->links[hlid].tx_queue[q], skb);
/* make sure we dequeue the same packet next time */
- wl->last_tx_hlid = (hlid + WL12XX_MAX_LINKS - 1) %
+ wlvif->last_tx_hlid = (hlid + WL12XX_MAX_LINKS - 1) %
WL12XX_MAX_LINKS;
} else {
skb_queue_head(&wl->tx_queue[q], skb);
@@ -924,7 +924,7 @@ void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues)
wl->links[i].prev_freed_pkts = 0;
}
- wl->last_tx_hlid = 0;
+ wlvif->last_tx_hlid = 0;
} else {
for (i = 0; i < NUM_TX_QUEUES; i++) {
while ((skb = skb_dequeue(&wl->tx_queue[i]))) {
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index 074de4e..b350f0b 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -542,9 +542,6 @@ struct wl1271 {
*/
struct wl1271_link links[WL12XX_MAX_LINKS];
- /* the hlid of the link where the last transmitted skb came from */
- int last_tx_hlid;
-
/* AP-mode - a bitmap of links currently in PS mode according to FW */
u32 ap_fw_ps_map;
@@ -596,6 +593,9 @@ struct wl12xx_vif {
} ap;
};
+ /* the hlid of the last transmitted skb */
+ int last_tx_hlid;
+
unsigned long links_map[BITS_TO_LONGS(WL12XX_MAX_LINKS)];
u8 ssid[IEEE80211_MAX_SSID_LEN + 1];
--
1.7.6.401.g6a319
^ permalink raw reply related [flat|nested] 51+ messages in thread* Re: [PATCH 02/29] wl12xx: move last_tx_hlid into wlvif
2011-10-10 8:12 ` [PATCH 02/29] wl12xx: move last_tx_hlid into wlvif Eliad Peller
@ 2011-10-10 17:52 ` Luciano Coelho
2011-10-10 19:16 ` Eliad Peller
0 siblings, 1 reply; 51+ messages in thread
From: Luciano Coelho @ 2011-10-10 17:52 UTC (permalink / raw)
To: Eliad Peller; +Cc: linux-wireless
On Mon, 2011-10-10 at 10:12 +0200, Eliad Peller wrote:
> move last_tx_hlid into the per-interface data, rather than
> being global.
>
> Signed-off-by: Eliad Peller <eliad@wizery.com>
> ---
> drivers/net/wireless/wl12xx/debugfs.c | 1 -
> drivers/net/wireless/wl12xx/main.c | 1 -
> drivers/net/wireless/wl12xx/tx.c | 10 +++++-----
> drivers/net/wireless/wl12xx/wl12xx.h | 6 +++---
> 4 files changed, 8 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c
> index f0398d0..bbc8004 100644
> --- a/drivers/net/wireless/wl12xx/debugfs.c
> +++ b/drivers/net/wireless/wl12xx/debugfs.c
> @@ -355,7 +355,6 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf,
> DRIVER_STATE_PRINT_INT(sg_enabled);
> DRIVER_STATE_PRINT_INT(enable_11a);
> DRIVER_STATE_PRINT_INT(noise);
> - DRIVER_STATE_PRINT_INT(last_tx_hlid);
> DRIVER_STATE_PRINT_HEX(ap_fw_ps_map);
> DRIVER_STATE_PRINT_LHEX(ap_ps_map);
> DRIVER_STATE_PRINT_HEX(quirks);
No big deal at this point, so I'll apply this, but maybe we should print
the last_tx_hlid from inside all the vifs as well?
--
Cheers,
Luca.
^ permalink raw reply [flat|nested] 51+ messages in thread
* Re: [PATCH 02/29] wl12xx: move last_tx_hlid into wlvif
2011-10-10 17:52 ` Luciano Coelho
@ 2011-10-10 19:16 ` Eliad Peller
0 siblings, 0 replies; 51+ messages in thread
From: Eliad Peller @ 2011-10-10 19:16 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
On Mon, Oct 10, 2011 at 7:52 PM, Luciano Coelho <coelho@ti.com> wrote:
> On Mon, 2011-10-10 at 10:12 +0200, Eliad Peller wrote:
>> move last_tx_hlid into the per-interface data, rather than
>> being global.
>>
>> Signed-off-by: Eliad Peller <eliad@wizery.com>
>> ---
>> drivers/net/wireless/wl12xx/debugfs.c | 1 -
>> drivers/net/wireless/wl12xx/main.c | 1 -
>> drivers/net/wireless/wl12xx/tx.c | 10 +++++-----
>> drivers/net/wireless/wl12xx/wl12xx.h | 6 +++---
>> 4 files changed, 8 insertions(+), 10 deletions(-)
>>
>> diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c
>> index f0398d0..bbc8004 100644
>> --- a/drivers/net/wireless/wl12xx/debugfs.c
>> +++ b/drivers/net/wireless/wl12xx/debugfs.c
>> @@ -355,7 +355,6 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf,
>> DRIVER_STATE_PRINT_INT(sg_enabled);
>> DRIVER_STATE_PRINT_INT(enable_11a);
>> DRIVER_STATE_PRINT_INT(noise);
>> - DRIVER_STATE_PRINT_INT(last_tx_hlid);
>> DRIVER_STATE_PRINT_HEX(ap_fw_ps_map);
>> DRIVER_STATE_PRINT_LHEX(ap_ps_map);
>> DRIVER_STATE_PRINT_HEX(quirks);
>
> No big deal at this point, so I'll apply this, but maybe we should print
> the last_tx_hlid from inside all the vifs as well?
>
yes.
i plan to add a new vif_state debugfs key that will print all the relevant info.
Eliad.
^ permalink raw reply [flat|nested] 51+ messages in thread
* [PATCH 03/29] wl12xx: unify STA and AP tx_queue mechanism
2011-10-10 8:12 [PATCH 00/29] make the driver ready for multi-vif support Eliad Peller
2011-10-10 8:12 ` [PATCH 01/29] wl12xx: refactor fw init into a new function Eliad Peller
2011-10-10 8:12 ` [PATCH 02/29] wl12xx: move last_tx_hlid into wlvif Eliad Peller
@ 2011-10-10 8:12 ` Eliad Peller
2011-10-10 8:12 ` [PATCH 04/29] wl12xx: move some functions from remove_interface() to stop() Eliad Peller
` (26 subsequent siblings)
29 siblings, 0 replies; 51+ messages in thread
From: Eliad Peller @ 2011-10-10 8:12 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
Make sta use the global wl->links[hlid].tx_queue (by
considering its links map) instead of wl->tx_queue,
and then unify the tx and tx_reset flows for the
various vifs.
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
drivers/net/wireless/wl12xx/main.c | 32 ++++------
drivers/net/wireless/wl12xx/tx.c | 109 ++++++++++++----------------------
drivers/net/wireless/wl12xx/tx.h | 5 +-
drivers/net/wireless/wl12xx/wl12xx.h | 1 -
4 files changed, 55 insertions(+), 92 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 0606b0d..abe5ef8 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -1474,31 +1474,26 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
unsigned long flags;
int q, mapping;
- u8 hlid = 0;
+ u8 hlid;
mapping = skb_get_queue_mapping(skb);
q = wl1271_tx_get_queue(mapping);
- if (wlvif->bss_type == BSS_TYPE_AP_BSS)
- hlid = wl12xx_tx_get_hlid_ap(wl, wlvif, skb);
+ hlid = wl12xx_tx_get_hlid(wl, wlvif, skb);
spin_lock_irqsave(&wl->wl_lock, flags);
/* queue the packet */
- if (wlvif->bss_type == BSS_TYPE_AP_BSS) {
- if (!test_bit(hlid, wlvif->links_map)) {
- wl1271_debug(DEBUG_TX, "DROP skb hlid %d q %d",
- hlid, q);
- dev_kfree_skb(skb);
- goto out;
- }
-
- wl1271_debug(DEBUG_TX, "queue skb hlid %d q %d", hlid, q);
- skb_queue_tail(&wl->links[hlid].tx_queue[q], skb);
- } else {
- skb_queue_tail(&wl->tx_queue[q], skb);
+ if (hlid == WL12XX_INVALID_LINK_ID ||
+ !test_bit(hlid, wlvif->links_map)) {
+ wl1271_debug(DEBUG_TX, "DROP skb hlid %d q %d", hlid, q);
+ dev_kfree_skb(skb);
+ goto out;
}
+ wl1271_debug(DEBUG_TX, "queue skb hlid %d q %d", hlid, q);
+ skb_queue_tail(&wl->links[hlid].tx_queue[q], skb);
+
wl->tx_queue_count[q]++;
/*
@@ -2131,7 +2126,8 @@ deinit:
mutex_lock(&wl->mutex);
/* let's notify MAC80211 about the remaining pending TX frames */
- wl1271_tx_reset(wl, reset_tx_queues);
+ wl12xx_tx_reset_wlvif(wl, wlvif);
+ wl12xx_tx_reset(wl, reset_tx_queues);
wl1271_power_off(wl);
wl->band = IEEE80211_BAND_2GHZ;
@@ -3968,7 +3964,6 @@ static int wl1271_allocate_sta(struct wl1271 *wl,
return 0;
}
-/* TODO: change wl1271_tx_reset(), so we can get sta as param */
void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid)
{
if (!test_bit(hlid, wlvif->ap.sta_hlid_map))
@@ -4868,9 +4863,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
wl->plat_dev = plat_dev;
for (i = 0; i < NUM_TX_QUEUES; i++)
- skb_queue_head_init(&wl->tx_queue[i]);
-
- for (i = 0; i < NUM_TX_QUEUES; i++)
for (j = 0; j < WL12XX_MAX_LINKS; j++)
skb_queue_head_init(&wl->links[j].tx_queue[i]);
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index 951ff03..6c0135b 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -179,12 +179,10 @@ u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif,
}
}
-static u8 wl1271_tx_get_hlid(struct wl1271 *wl, struct ieee80211_vif *vif,
- struct sk_buff *skb)
+u8 wl12xx_tx_get_hlid(struct wl1271 *wl, struct wl12xx_vif *wlvif,
+ struct sk_buff *skb)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
-
if (wl12xx_is_dummy_packet(wl, skb))
return wl->system_hlid;
@@ -429,7 +427,7 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb,
wlvif->default_key = idx;
}
}
- hlid = wl1271_tx_get_hlid(wl, vif, skb);
+ hlid = wl12xx_tx_get_hlid(wl, wlvif, skb);
if (hlid == WL12XX_INVALID_LINK_ID) {
wl1271_error("invalid hlid. dropping skb 0x%p", skb);
return -EINVAL;
@@ -538,19 +536,18 @@ static struct sk_buff_head *wl1271_select_queue(struct wl1271 *wl,
return &queues[q];
}
-static struct sk_buff *wl1271_sta_skb_dequeue(struct wl1271 *wl)
+static struct sk_buff *wl12xx_lnk_skb_dequeue(struct wl1271 *wl,
+ struct wl1271_link *lnk)
{
- struct sk_buff *skb = NULL;
+ struct sk_buff *skb;
unsigned long flags;
struct sk_buff_head *queue;
- queue = wl1271_select_queue(wl, wl->tx_queue);
+ queue = wl1271_select_queue(wl, lnk->tx_queue);
if (!queue)
- goto out;
+ return NULL;
skb = skb_dequeue(queue);
-
-out:
if (skb) {
int q = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
spin_lock_irqsave(&wl->wl_lock, flags);
@@ -561,13 +558,11 @@ out:
return skb;
}
-static struct sk_buff *wl1271_ap_skb_dequeue(struct wl1271 *wl,
- struct wl12xx_vif *wlvif)
+static struct sk_buff *wl12xx_vif_skb_dequeue(struct wl1271 *wl,
+ struct wl12xx_vif *wlvif)
{
struct sk_buff *skb = NULL;
- unsigned long flags;
int i, h, start_hlid;
- struct sk_buff_head *queue;
/* start from the link after the last one */
start_hlid = (wlvif->last_tx_hlid + 1) % WL12XX_MAX_LINKS;
@@ -580,24 +575,16 @@ static struct sk_buff *wl1271_ap_skb_dequeue(struct wl1271 *wl,
if (!test_bit(h, wlvif->links_map))
continue;
- queue = wl1271_select_queue(wl, wl->links[h].tx_queue);
- if (!queue)
+ skb = wl12xx_lnk_skb_dequeue(wl, &wl->links[h]);
+ if (!skb)
continue;
- skb = skb_dequeue(queue);
- if (skb)
- break;
+ wlvif->last_tx_hlid = h;
+ break;
}
- if (skb) {
- int q = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
- wlvif->last_tx_hlid = h;
- spin_lock_irqsave(&wl->wl_lock, flags);
- wl->tx_queue_count[q]--;
- spin_unlock_irqrestore(&wl->wl_lock, flags);
- } else {
+ if (!skb)
wlvif->last_tx_hlid = 0;
- }
return skb;
}
@@ -608,11 +595,7 @@ static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl,
unsigned long flags;
struct sk_buff *skb = NULL;
- if (wlvif->bss_type == BSS_TYPE_AP_BSS)
- skb = wl1271_ap_skb_dequeue(wl, wlvif);
- else
- skb = wl1271_sta_skb_dequeue(wl);
-
+ skb = wl12xx_vif_skb_dequeue(wl, wlvif);
if (!skb &&
test_and_clear_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags)) {
int q;
@@ -627,24 +610,21 @@ static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl,
return skb;
}
-static void wl1271_skb_queue_head(struct wl1271 *wl, struct ieee80211_vif *vif,
+static void wl1271_skb_queue_head(struct wl1271 *wl, struct wl12xx_vif *wlvif,
struct sk_buff *skb)
{
- struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
unsigned long flags;
int q = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
if (wl12xx_is_dummy_packet(wl, skb)) {
set_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags);
- } else if (wlvif->bss_type == BSS_TYPE_AP_BSS) {
- u8 hlid = wl1271_tx_get_hlid(wl, vif, skb);
+ } else {
+ u8 hlid = wl12xx_tx_get_hlid(wl, wlvif, skb);
skb_queue_head(&wl->links[hlid].tx_queue[q], skb);
/* make sure we dequeue the same packet next time */
wlvif->last_tx_hlid = (hlid + WL12XX_MAX_LINKS - 1) %
- WL12XX_MAX_LINKS;
- } else {
- skb_queue_head(&wl->tx_queue[q], skb);
+ WL12XX_MAX_LINKS;
}
spin_lock_irqsave(&wl->wl_lock, flags);
@@ -682,7 +662,7 @@ void wl1271_tx_work_locked(struct wl1271 *wl, struct ieee80211_vif *vif)
* Aggregation buffer is full.
* Flush buffer and try again.
*/
- wl1271_skb_queue_head(wl, vif, skb);
+ wl1271_skb_queue_head(wl, wlvif, skb);
wl1271_write(wl, WL1271_SLV_MEM_DATA, wl->aggr_buf,
buf_offset, true);
sent_packets = true;
@@ -693,7 +673,7 @@ void wl1271_tx_work_locked(struct wl1271 *wl, struct ieee80211_vif *vif)
* Firmware buffer is full.
* Queue back last skb, and stop aggregating.
*/
- wl1271_skb_queue_head(wl, vif, skb);
+ wl1271_skb_queue_head(wl, wlvif, skb);
/* No work left, avoid scheduling redundant tx work */
set_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags);
goto out_ack;
@@ -907,41 +887,30 @@ void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid)
}
/* caller must hold wl->mutex and TX must be stopped */
-void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues)
+void wl12xx_tx_reset_wlvif(struct wl1271 *wl, struct wl12xx_vif *wlvif)
{
- struct ieee80211_vif *vif = wl->vif; /* TODO: get as param */
- struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
int i;
- struct sk_buff *skb;
- struct ieee80211_tx_info *info;
/* TX failure */
- if (wlvif->bss_type == BSS_TYPE_AP_BSS) {
- for (i = 0; i < WL12XX_MAX_LINKS; i++) {
+ for_each_set_bit(i, wlvif->links_map, WL12XX_MAX_LINKS) {
+ if (wlvif->bss_type == BSS_TYPE_AP_BSS)
wl1271_free_sta(wl, wlvif, i);
- wl1271_tx_reset_link_queues(wl, i);
- wl->links[i].allocated_pkts = 0;
- wl->links[i].prev_freed_pkts = 0;
- }
-
- wlvif->last_tx_hlid = 0;
- } else {
- for (i = 0; i < NUM_TX_QUEUES; i++) {
- while ((skb = skb_dequeue(&wl->tx_queue[i]))) {
- wl1271_debug(DEBUG_TX, "freeing skb 0x%p",
- skb);
-
- if (!wl12xx_is_dummy_packet(wl, skb)) {
- info = IEEE80211_SKB_CB(skb);
- info->status.rates[0].idx = -1;
- info->status.rates[0].count = 0;
- ieee80211_tx_status_ni(wl->hw, skb);
- }
- }
- }
+ else
+ wlvif->sta.ba_rx_bitmap = 0;
- wlvif->sta.ba_rx_bitmap = 0;
+ wl1271_tx_reset_link_queues(wl, i);
+ wl->links[i].allocated_pkts = 0;
+ wl->links[i].prev_freed_pkts = 0;
}
+ wlvif->last_tx_hlid = 0;
+
+}
+/* caller must hold wl->mutex and TX must be stopped */
+void wl12xx_tx_reset(struct wl1271 *wl, bool reset_tx_queues)
+{
+ int i;
+ struct sk_buff *skb;
+ struct ieee80211_tx_info *info;
for (i = 0; i < NUM_TX_QUEUES; i++)
wl->tx_queue_count[i] = 0;
diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/tx.h
index add4402..050a047 100644
--- a/drivers/net/wireless/wl12xx/tx.h
+++ b/drivers/net/wireless/wl12xx/tx.h
@@ -206,7 +206,8 @@ static inline int wl1271_tx_total_queue_count(struct wl1271 *wl)
void wl1271_tx_work(struct work_struct *work);
void wl1271_tx_work_locked(struct wl1271 *wl, struct ieee80211_vif *vif);
void wl1271_tx_complete(struct wl1271 *wl);
-void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues);
+void wl12xx_tx_reset_wlvif(struct wl1271 *wl, struct wl12xx_vif *wlvif);
+void wl12xx_tx_reset(struct wl1271 *wl, bool reset_tx_queues);
void wl1271_tx_flush(struct wl1271 *wl);
u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band);
u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set,
@@ -214,6 +215,8 @@ u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set,
u32 wl1271_tx_min_rate_get(struct wl1271 *wl, u32 rate_set);
u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif,
struct sk_buff *skb);
+u8 wl12xx_tx_get_hlid(struct wl1271 *wl, struct wl12xx_vif *wlvif,
+ struct sk_buff *skb);
void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid);
void wl1271_handle_tx_low_watermark(struct wl1271 *wl);
bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb);
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index b350f0b..4802f68 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -416,7 +416,6 @@ struct wl1271 {
s64 time_offset;
/* Frames scheduled for transmission, not handled yet */
- struct sk_buff_head tx_queue[NUM_TX_QUEUES];
int tx_queue_count[NUM_TX_QUEUES];
long stopped_queues_map;
--
1.7.6.401.g6a319
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 04/29] wl12xx: move some functions from remove_interface() to stop()
2011-10-10 8:12 [PATCH 00/29] make the driver ready for multi-vif support Eliad Peller
` (2 preceding siblings ...)
2011-10-10 8:12 ` [PATCH 03/29] wl12xx: unify STA and AP tx_queue mechanism Eliad Peller
@ 2011-10-10 8:12 ` Eliad Peller
2011-10-10 8:12 ` [PATCH 05/29] wl12xx: move bitrate_masks into wlvif Eliad Peller
` (25 subsequent siblings)
29 siblings, 0 replies; 51+ messages in thread
From: Eliad Peller @ 2011-10-10 8:12 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
Leave only vif-specific deinit stuff in remove_interface().
Move the global deinit (including power_off) to stop().
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
drivers/net/wireless/wl12xx/main.c | 157 +++++++++++++++++++-----------------
1 files changed, 83 insertions(+), 74 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index abe5ef8..e53829a 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -1803,7 +1803,83 @@ static int wl1271_op_start(struct ieee80211_hw *hw)
static void wl1271_op_stop(struct ieee80211_hw *hw)
{
+ struct wl1271 *wl = hw->priv;
+ int i;
+
wl1271_debug(DEBUG_MAC80211, "mac80211 stop");
+
+ mutex_lock(&wl_list_mutex);
+ list_del(&wl->list);
+
+ /*
+ * 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_list_mutex);
+
+ wl1271_disable_interrupts(wl);
+ wl1271_flush_deferred_work(wl);
+ cancel_delayed_work_sync(&wl->scan_complete_work);
+ cancel_work_sync(&wl->netstack_work);
+ cancel_work_sync(&wl->tx_work);
+ del_timer_sync(&wl->rx_streaming_timer);
+ cancel_work_sync(&wl->rx_streaming_enable_work);
+ cancel_work_sync(&wl->rx_streaming_disable_work);
+ cancel_delayed_work_sync(&wl->elp_work);
+
+ /* let's notify MAC80211 about the remaining pending TX frames */
+ wl12xx_tx_reset(wl, true);
+ mutex_lock(&wl->mutex);
+
+ wl1271_power_off(wl);
+
+ wl->band = IEEE80211_BAND_2GHZ;
+
+ wl->rx_counter = 0;
+ wl->power_level = WL1271_DEFAULT_POWER_LEVEL;
+ wl->tx_blocks_available = 0;
+ wl->tx_allocated_blocks = 0;
+ wl->tx_results_count = 0;
+ wl->tx_packets_count = 0;
+ wl->time_offset = 0;
+ wl->vif = NULL;
+ wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT;
+ wl->ap_fw_ps_map = 0;
+ wl->ap_ps_map = 0;
+ wl->sched_scanning = false;
+ memset(wl->roles_map, 0, sizeof(wl->roles_map));
+ memset(wl->links_map, 0, sizeof(wl->links_map));
+ memset(wl->roc_map, 0, sizeof(wl->roc_map));
+ wl->active_sta_count = 0;
+
+ /* The system link is always allocated */
+ __set_bit(WL12XX_SYSTEM_HLID, wl->links_map);
+
+ /*
+ * this is performed after the cancel_work calls and the associated
+ * mutex_lock, so that wl1271_op_add_interface does not accidentally
+ * get executed before all these vars have been reset.
+ */
+ wl->flags = 0;
+
+ wl->tx_blocks_freed = 0;
+
+ for (i = 0; i < NUM_TX_QUEUES; i++) {
+ wl->tx_pkts_freed[i] = 0;
+ wl->tx_allocated_pkts[i] = 0;
+ }
+
+ wl1271_debugfs_reset(wl);
+
+ kfree(wl->fw_status);
+ wl->fw_status = NULL;
+ kfree(wl->tx_res_if);
+ wl->tx_res_if = NULL;
+ kfree(wl->target_mem_map);
+ wl->target_mem_map = NULL;
+
+ mutex_unlock(&wl->mutex);
}
static u8 wl12xx_get_role_type(struct wl1271 *wl, struct wl12xx_vif *wlvif)
@@ -2053,7 +2129,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, i;
+ int ret;
wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface");
@@ -2063,15 +2139,12 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
wl1271_info("down");
- mutex_lock(&wl_list_mutex);
- list_del(&wl->list);
- mutex_unlock(&wl_list_mutex);
-
/* enable dyn ps just in case (if left on due to fw crash etc) */
if (wlvif->bss_type == BSS_TYPE_STA_BSS)
- ieee80211_enable_dyn_ps(wl->vif);
+ ieee80211_enable_dyn_ps(vif);
- if (wl->scan.state != WL1271_SCAN_STATE_IDLE) {
+ if (wl->scan.state != WL1271_SCAN_STATE_IDLE &&
+ wl->scan_vif == vif) {
wl->scan.state = WL1271_SCAN_STATE_IDLE;
memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch));
wl->scan_vif = NULL;
@@ -2104,82 +2177,18 @@ deinit:
wlvif->ap.bcast_hlid = WL12XX_INVALID_LINK_ID;
wlvif->ap.global_hlid = WL12XX_INVALID_LINK_ID;
- /*
- * 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);
-
- wl1271_disable_interrupts(wl);
- wl1271_flush_deferred_work(wl);
- cancel_delayed_work_sync(&wl->scan_complete_work);
- cancel_work_sync(&wl->netstack_work);
- cancel_work_sync(&wl->tx_work);
- del_timer_sync(&wl->rx_streaming_timer);
- cancel_work_sync(&wl->rx_streaming_enable_work);
- cancel_work_sync(&wl->rx_streaming_disable_work);
- cancel_delayed_work_sync(&wlvif->pspoll_work);
- cancel_delayed_work_sync(&wl->elp_work);
-
- mutex_lock(&wl->mutex);
-
- /* let's notify MAC80211 about the remaining pending TX frames */
wl12xx_tx_reset_wlvif(wl, wlvif);
- wl12xx_tx_reset(wl, reset_tx_queues);
- wl1271_power_off(wl);
-
- wl->band = IEEE80211_BAND_2GHZ;
-
- wl->rx_counter = 0;
- wl->power_level = WL1271_DEFAULT_POWER_LEVEL;
- wl->tx_blocks_available = 0;
- wl->tx_allocated_blocks = 0;
- wl->tx_results_count = 0;
- wl->tx_packets_count = 0;
- wl->time_offset = 0;
wl->bitrate_masks[IEEE80211_BAND_2GHZ] = wl->conf.tx.basic_rate;
wl->bitrate_masks[IEEE80211_BAND_5GHZ] = wl->conf.tx.basic_rate_5;
- wl->vif = NULL;
- wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT;
wl1271_free_ap_keys(wl, wlvif);
memset(wlvif->ap.sta_hlid_map, 0, sizeof(wlvif->ap.sta_hlid_map));
- wl->ap_fw_ps_map = 0;
- wl->ap_ps_map = 0;
- wl->sched_scanning = false;
wlvif->role_id = WL12XX_INVALID_ROLE_ID;
wlvif->dev_role_id = WL12XX_INVALID_ROLE_ID;
- memset(wl->roles_map, 0, sizeof(wl->roles_map));
- memset(wl->links_map, 0, sizeof(wl->links_map));
- memset(wl->roc_map, 0, sizeof(wl->roc_map));
- wl->active_sta_count = 0;
- /* The system link is always allocated */
- __set_bit(WL12XX_SYSTEM_HLID, wl->links_map);
-
- /*
- * this is performed after the cancel_work calls and the associated
- * mutex_lock, so that wl1271_op_add_interface does not accidentally
- * get executed before all these vars have been reset.
- */
- wl->flags = 0;
-
- wl->tx_blocks_freed = 0;
-
- for (i = 0; i < NUM_TX_QUEUES; i++) {
- wl->tx_pkts_freed[i] = 0;
- wl->tx_allocated_pkts[i] = 0;
- }
-
- wl1271_debugfs_reset(wl);
+ mutex_unlock(&wl->mutex);
+ cancel_delayed_work_sync(&wlvif->pspoll_work);
- kfree(wl->fw_status);
- wl->fw_status = NULL;
- kfree(wl->tx_res_if);
- wl->tx_res_if = NULL;
- kfree(wl->target_mem_map);
- wl->target_mem_map = NULL;
+ mutex_lock(&wl->mutex);
}
static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
--
1.7.6.401.g6a319
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 05/29] wl12xx: move bitrate_masks into wlvif
2011-10-10 8:12 [PATCH 00/29] make the driver ready for multi-vif support Eliad Peller
` (3 preceding siblings ...)
2011-10-10 8:12 ` [PATCH 04/29] wl12xx: move some functions from remove_interface() to stop() Eliad Peller
@ 2011-10-10 8:12 ` Eliad Peller
2011-10-10 18:20 ` Luciano Coelho
2011-10-10 8:12 ` [PATCH 06/29] wl12xx: add vifs list Eliad Peller
` (24 subsequent siblings)
29 siblings, 1 reply; 51+ messages in thread
From: Eliad Peller @ 2011-10-10 8:12 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
move bitrate_masks into the per-interface data, rather than
being global.
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
drivers/net/wireless/wl12xx/cmd.c | 13 ++++++++-----
drivers/net/wireless/wl12xx/cmd.h | 3 ++-
drivers/net/wireless/wl12xx/main.c | 16 ++++++++--------
drivers/net/wireless/wl12xx/scan.c | 21 +++++++++++----------
drivers/net/wireless/wl12xx/wl12xx.h | 3 +--
5 files changed, 30 insertions(+), 26 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c
index 102a8a5..ff653e8 100644
--- a/drivers/net/wireless/wl12xx/cmd.c
+++ b/drivers/net/wireless/wl12xx/cmd.c
@@ -1111,15 +1111,16 @@ out:
return ret;
}
-int wl1271_cmd_build_probe_req(struct wl1271 *wl,
+int wl1271_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif,
const u8 *ssid, size_t ssid_len,
const u8 *ie, size_t ie_len, u8 band)
{
+ struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
struct sk_buff *skb;
int ret;
u32 rate;
- skb = ieee80211_probereq_get(wl->hw, wl->vif, ssid, ssid_len,
+ skb = ieee80211_probereq_get(wl->hw, vif, ssid, ssid_len,
ie, ie_len);
if (!skb) {
ret = -ENOMEM;
@@ -1128,7 +1129,7 @@ int wl1271_cmd_build_probe_req(struct wl1271 *wl,
wl1271_dump(DEBUG_SCAN, "PROBE REQ: ", skb->data, skb->len);
- rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]);
+ rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[band]);
if (band == IEEE80211_BAND_2GHZ)
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4,
skb->data, skb->len, 0, rate);
@@ -1142,19 +1143,21 @@ out:
}
struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl,
+ struct wl12xx_vif *wlvif,
struct sk_buff *skb)
{
+ struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
int ret;
u32 rate;
if (!skb)
- skb = ieee80211_ap_probereq_get(wl->hw, wl->vif);
+ skb = ieee80211_ap_probereq_get(wl->hw, vif);
if (!skb)
goto out;
wl1271_dump(DEBUG_SCAN, "AP PROBE REQ: ", skb->data, skb->len);
- rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[wl->band]);
+ rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[wl->band]);
if (wl->band == IEEE80211_BAND_2GHZ)
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4,
skb->data, skb->len, 0, rate);
diff --git a/drivers/net/wireless/wl12xx/cmd.h b/drivers/net/wireless/wl12xx/cmd.h
index d2670d3..8182cf1 100644
--- a/drivers/net/wireless/wl12xx/cmd.h
+++ b/drivers/net/wireless/wl12xx/cmd.h
@@ -59,10 +59,11 @@ int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id,
int wl12xx_cmd_build_null_data(struct wl1271 *wl, struct wl12xx_vif *wlvif);
int wl1271_cmd_build_ps_poll(struct wl1271 *wl, struct wl12xx_vif *wlvif,
u16 aid);
-int wl1271_cmd_build_probe_req(struct wl1271 *wl,
+int wl1271_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif,
const u8 *ssid, size_t ssid_len,
const u8 *ie, size_t ie_len, u8 band);
struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl,
+ struct wl12xx_vif *wlvif,
struct sk_buff *skb);
int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, struct wl12xx_vif *wlvif,
__be32 ip_addr);
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index e53829a..acfc497 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -1906,7 +1906,7 @@ static u8 wl12xx_get_role_type(struct wl1271 *wl, struct wl12xx_vif *wlvif)
return WL12XX_INVALID_ROLE_TYPE;
}
-static int wl12xx_init_vif_data(struct ieee80211_vif *vif)
+static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif)
{
struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
@@ -1949,6 +1949,8 @@ static int wl12xx_init_vif_data(struct ieee80211_vif *vif)
wlvif->ap.global_hlid = WL12XX_INVALID_LINK_ID;
}
+ wlvif->bitrate_masks[IEEE80211_BAND_2GHZ] = wl->conf.tx.basic_rate;
+ wlvif->bitrate_masks[IEEE80211_BAND_5GHZ] = wl->conf.tx.basic_rate_5;
wlvif->basic_rate_set = CONF_TX_RATE_MASK_BASIC;
wlvif->basic_rate = CONF_TX_RATE_MASK_BASIC;
wlvif->rate_set = CONF_TX_RATE_MASK_BASIC;
@@ -2058,7 +2060,7 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
goto out;
}
- ret = wl12xx_init_vif_data(vif);
+ ret = wl12xx_init_vif_data(wl, vif);
if (ret < 0)
goto out;
@@ -2178,8 +2180,6 @@ deinit:
wlvif->ap.global_hlid = WL12XX_INVALID_LINK_ID;
wl12xx_tx_reset_wlvif(wl, wlvif);
- wl->bitrate_masks[IEEE80211_BAND_2GHZ] = wl->conf.tx.basic_rate;
- wl->bitrate_masks[IEEE80211_BAND_5GHZ] = wl->conf.tx.basic_rate_5;
wl1271_free_ap_keys(wl, wlvif);
memset(wlvif->ap.sta_hlid_map, 0, sizeof(wlvif->ap.sta_hlid_map));
wlvif->role_id = WL12XX_INVALID_ROLE_ID;
@@ -2293,7 +2293,7 @@ out:
static void wl1271_set_band_rate(struct wl1271 *wl, struct wl12xx_vif *wlvif)
{
- wlvif->basic_rate_set = wl->bitrate_masks[wl->band];
+ wlvif->basic_rate_set = wlvif->bitrate_masks[wl->band];
wlvif->rate_set = wlvif->basic_rate_set;
}
@@ -3578,6 +3578,7 @@ sta_not_found:
*/
dev_kfree_skb(wlvif->probereq);
wlvif->probereq = wl1271_cmd_build_ap_probe_req(wl,
+ wlvif,
NULL);
ieoffset = offsetof(struct ieee80211_mgmt,
u.probe_req.variable);
@@ -4202,6 +4203,7 @@ static int wl12xx_set_bitrate_mask(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
const struct cfg80211_bitrate_mask *mask)
{
+ struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
struct wl1271 *wl = hw->priv;
int i;
@@ -4212,7 +4214,7 @@ static int wl12xx_set_bitrate_mask(struct ieee80211_hw *hw,
mutex_lock(&wl->mutex);
for (i = 0; i < IEEE80211_NUM_BANDS; i++)
- wl->bitrate_masks[i] =
+ wlvif->bitrate_masks[i] =
wl1271_tx_enabled_rates_get(wl,
mask->control[i].legacy,
i);
@@ -4931,8 +4933,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
/* Apply default driver configuration. */
wl1271_conf_init(wl);
- wl->bitrate_masks[IEEE80211_BAND_2GHZ] = wl->conf.tx.basic_rate;
- wl->bitrate_masks[IEEE80211_BAND_5GHZ] = wl->conf.tx.basic_rate_5;
order = get_order(WL1271_AGGR_BUFFER_SIZE);
wl->aggr_buf = (u8 *)__get_free_pages(GFP_KERNEL, order);
diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c
index 9372136..e1a8ce0 100644
--- a/drivers/net/wireless/wl12xx/scan.c
+++ b/drivers/net/wireless/wl12xx/scan.c
@@ -66,7 +66,7 @@ void wl1271_scan_complete_work(struct work_struct *work)
if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) {
/* restore hardware connection monitoring template */
- wl1271_cmd_build_ap_probe_req(wl, wlvif->probereq);
+ wl1271_cmd_build_ap_probe_req(wl, wlvif, wlvif->probereq);
}
/* return to ROC if needed */
@@ -218,9 +218,9 @@ static int wl1271_scan_send(struct wl1271 *wl, struct ieee80211_vif *vif,
memcpy(cmd->addr, vif->addr, ETH_ALEN);
- ret = wl1271_cmd_build_probe_req(wl, wl->scan.ssid, wl->scan.ssid_len,
- wl->scan.req->ie, wl->scan.req->ie_len,
- band);
+ ret = wl1271_cmd_build_probe_req(wl, wlvif, wl->scan.ssid,
+ wl->scan.ssid_len, wl->scan.req->ie,
+ wl->scan.req->ie_len, band);
if (ret < 0) {
wl1271_error("PROBE request template failed");
goto out;
@@ -251,6 +251,7 @@ out:
void wl1271_scan_stm(struct wl1271 *wl, struct ieee80211_vif *vif)
{
+ struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
int ret = 0;
enum ieee80211_band band;
u32 rate;
@@ -261,7 +262,7 @@ void wl1271_scan_stm(struct wl1271 *wl, struct ieee80211_vif *vif)
case WL1271_SCAN_STATE_2GHZ_ACTIVE:
band = IEEE80211_BAND_2GHZ;
- rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]);
+ rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[band]);
ret = wl1271_scan_send(wl, vif, band, false, rate);
if (ret == WL1271_NOTHING_TO_SCAN) {
wl->scan.state = WL1271_SCAN_STATE_2GHZ_PASSIVE;
@@ -272,7 +273,7 @@ void wl1271_scan_stm(struct wl1271 *wl, struct ieee80211_vif *vif)
case WL1271_SCAN_STATE_2GHZ_PASSIVE:
band = IEEE80211_BAND_2GHZ;
- rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]);
+ rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[band]);
ret = wl1271_scan_send(wl, vif, band, true, rate);
if (ret == WL1271_NOTHING_TO_SCAN) {
if (wl->enable_11a)
@@ -286,7 +287,7 @@ void wl1271_scan_stm(struct wl1271 *wl, struct ieee80211_vif *vif)
case WL1271_SCAN_STATE_5GHZ_ACTIVE:
band = IEEE80211_BAND_5GHZ;
- rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]);
+ rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[band]);
ret = wl1271_scan_send(wl, vif, band, false, rate);
if (ret == WL1271_NOTHING_TO_SCAN) {
wl->scan.state = WL1271_SCAN_STATE_5GHZ_PASSIVE;
@@ -297,7 +298,7 @@ void wl1271_scan_stm(struct wl1271 *wl, struct ieee80211_vif *vif)
case WL1271_SCAN_STATE_5GHZ_PASSIVE:
band = IEEE80211_BAND_5GHZ;
- rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]);
+ rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[band]);
ret = wl1271_scan_send(wl, vif, band, true, rate);
if (ret == WL1271_NOTHING_TO_SCAN) {
wl->scan.state = WL1271_SCAN_STATE_DONE;
@@ -642,7 +643,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
}
if (!force_passive && cfg->active[0]) {
- ret = wl1271_cmd_build_probe_req(wl, req->ssids[0].ssid,
+ ret = wl1271_cmd_build_probe_req(wl, wlvif, req->ssids[0].ssid,
req->ssids[0].ssid_len,
ies->ie[IEEE80211_BAND_2GHZ],
ies->len[IEEE80211_BAND_2GHZ],
@@ -654,7 +655,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
}
if (!force_passive && cfg->active[1]) {
- ret = wl1271_cmd_build_probe_req(wl, req->ssids[0].ssid,
+ ret = wl1271_cmd_build_probe_req(wl, wlvif, req->ssids[0].ssid,
req->ssids[0].ssid_len,
ies->ie[IEEE80211_BAND_5GHZ],
ies->len[IEEE80211_BAND_5GHZ],
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index 4802f68..33ccdf8 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -484,8 +484,6 @@ struct wl1271 {
bool sched_scanning;
- u32 bitrate_masks[IEEE80211_NUM_BANDS];
-
/* The current band */
enum ieee80211_band band;
@@ -600,6 +598,7 @@ struct wl12xx_vif {
u8 ssid[IEEE80211_MAX_SSID_LEN + 1];
u8 ssid_len;
+ u32 bitrate_masks[IEEE80211_NUM_BANDS];
u32 basic_rate_set;
/*
--
1.7.6.401.g6a319
^ permalink raw reply related [flat|nested] 51+ messages in thread* Re: [PATCH 05/29] wl12xx: move bitrate_masks into wlvif
2011-10-10 8:12 ` [PATCH 05/29] wl12xx: move bitrate_masks into wlvif Eliad Peller
@ 2011-10-10 18:20 ` Luciano Coelho
2011-10-10 19:21 ` Eliad Peller
0 siblings, 1 reply; 51+ messages in thread
From: Luciano Coelho @ 2011-10-10 18:20 UTC (permalink / raw)
To: Eliad Peller; +Cc: linux-wireless
On Mon, 2011-10-10 at 10:12 +0200, Eliad Peller wrote:
> move bitrate_masks into the per-interface data, rather than
> being global.
>
> Signed-off-by: Eliad Peller <eliad@wizery.com>
> ---
[...]
> diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c
> index 102a8a5..ff653e8 100644
> --- a/drivers/net/wireless/wl12xx/cmd.c
> +++ b/drivers/net/wireless/wl12xx/cmd.c
> @@ -1111,15 +1111,16 @@ out:
> return ret;
> }
>
> -int wl1271_cmd_build_probe_req(struct wl1271 *wl,
> +int wl1271_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif,
> const u8 *ssid, size_t ssid_len,
> const u8 *ie, size_t ie_len, u8 band)
If struct wl12xx_vif contains a pointer to wl, can't you pass only wlvif
to all these functions instead of passing both?
--
Cheers,
Luca.
^ permalink raw reply [flat|nested] 51+ messages in thread
* Re: [PATCH 05/29] wl12xx: move bitrate_masks into wlvif
2011-10-10 18:20 ` Luciano Coelho
@ 2011-10-10 19:21 ` Eliad Peller
2011-10-10 19:25 ` Luciano Coelho
0 siblings, 1 reply; 51+ messages in thread
From: Eliad Peller @ 2011-10-10 19:21 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
On Mon, Oct 10, 2011 at 8:20 PM, Luciano Coelho <coelho@ti.com> wrote:
> On Mon, 2011-10-10 at 10:12 +0200, Eliad Peller wrote:
>> move bitrate_masks into the per-interface data, rather than
>> being global.
>>
>> Signed-off-by: Eliad Peller <eliad@wizery.com>
>> ---
>
> [...]
>
>> diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c
>> index 102a8a5..ff653e8 100644
>> --- a/drivers/net/wireless/wl12xx/cmd.c
>> +++ b/drivers/net/wireless/wl12xx/cmd.c
>> @@ -1111,15 +1111,16 @@ out:
>> return ret;
>> }
>>
>> -int wl1271_cmd_build_probe_req(struct wl1271 *wl,
>> +int wl1271_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif,
>> const u8 *ssid, size_t ssid_len,
>> const u8 *ie, size_t ie_len, u8 band)
>
> If struct wl12xx_vif contains a pointer to wl, can't you pass only wlvif
> to all these functions instead of passing both?
>
yes, it's possible.
but maybe leave it for some future overhaul?
Eliad.
^ permalink raw reply [flat|nested] 51+ messages in thread
* Re: [PATCH 05/29] wl12xx: move bitrate_masks into wlvif
2011-10-10 19:21 ` Eliad Peller
@ 2011-10-10 19:25 ` Luciano Coelho
0 siblings, 0 replies; 51+ messages in thread
From: Luciano Coelho @ 2011-10-10 19:25 UTC (permalink / raw)
To: Eliad Peller; +Cc: linux-wireless
On Mon, 2011-10-10 at 21:21 +0200, Eliad Peller wrote:
> On Mon, Oct 10, 2011 at 8:20 PM, Luciano Coelho <coelho@ti.com> wrote:
> > On Mon, 2011-10-10 at 10:12 +0200, Eliad Peller wrote:
> >> move bitrate_masks into the per-interface data, rather than
> >> being global.
> >>
> >> Signed-off-by: Eliad Peller <eliad@wizery.com>
> >> ---
> >
> > [...]
> >
> >> diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c
> >> index 102a8a5..ff653e8 100644
> >> --- a/drivers/net/wireless/wl12xx/cmd.c
> >> +++ b/drivers/net/wireless/wl12xx/cmd.c
> >> @@ -1111,15 +1111,16 @@ out:
> >> return ret;
> >> }
> >>
> >> -int wl1271_cmd_build_probe_req(struct wl1271 *wl,
> >> +int wl1271_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif,
> >> const u8 *ssid, size_t ssid_len,
> >> const u8 *ie, size_t ie_len, u8 band)
> >
> > If struct wl12xx_vif contains a pointer to wl, can't you pass only wlvif
> > to all these functions instead of passing both?
> >
> yes, it's possible.
> but maybe leave it for some future overhaul?
Yes, it's okay. Otherwise the rebasing of this would be annoying to
do. ;)
--
Cheers,
Luca.
^ permalink raw reply [flat|nested] 51+ messages in thread
* [PATCH 06/29] wl12xx: add vifs list
2011-10-10 8:12 [PATCH 00/29] make the driver ready for multi-vif support Eliad Peller
` (4 preceding siblings ...)
2011-10-10 8:12 ` [PATCH 05/29] wl12xx: move bitrate_masks into wlvif Eliad Peller
@ 2011-10-10 8:12 ` Eliad Peller
2011-10-10 18:28 ` Luciano Coelho
2011-10-10 20:04 ` Johannes Berg
2011-10-10 8:12 ` [PATCH 07/29] wl12xx: support multiple vifs in the tx path Eliad Peller
` (23 subsequent siblings)
29 siblings, 2 replies; 51+ messages in thread
From: Eliad Peller @ 2011-10-10 8:12 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
keep a list of all the vifs associated with our hw.
it will be later used in order to iterate through vifs.
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
drivers/net/wireless/wl12xx/main.c | 4 ++++
drivers/net/wireless/wl12xx/wl12xx.h | 6 ++++++
2 files changed, 10 insertions(+), 0 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index acfc497..56d5923 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -1957,6 +1957,7 @@ static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif)
wlvif->beacon_int = WL1271_DEFAULT_BEACON_INT;
INIT_DELAYED_WORK(&wlvif->pspoll_work, wl1271_pspoll_work);
+ INIT_LIST_HEAD(&wlvif->list);
return 0;
}
@@ -2114,6 +2115,7 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
goto out;
wl->vif = vif;
+ list_add(&wlvif->list, &wl->wlvif_list);
set_bit(WL1271_FLAG_IF_INITIALIZED, &wl->flags);
out:
mutex_unlock(&wl->mutex);
@@ -2181,6 +2183,7 @@ deinit:
wl12xx_tx_reset_wlvif(wl, wlvif);
wl1271_free_ap_keys(wl, wlvif);
+ list_del(&wlvif->list);
memset(wlvif->ap.sta_hlid_map, 0, sizeof(wlvif->ap.sta_hlid_map));
wlvif->role_id = WL12XX_INVALID_ROLE_ID;
wlvif->dev_role_id = WL12XX_INVALID_ROLE_ID;
@@ -4869,6 +4872,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
memset(wl, 0, sizeof(*wl));
INIT_LIST_HEAD(&wl->list);
+ INIT_LIST_HEAD(&wl->wlvif_list);
wl->hw = hw;
wl->plat_dev = plat_dev;
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index 33ccdf8..55561c5 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -394,6 +394,8 @@ struct wl1271 {
unsigned long roles_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)];
unsigned long roc_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)];
+ struct list_head wlvif_list;
+
struct wl1271_acx_mem_map *target_mem_map;
/* Accounting for allocated / available TX blocks on HW */
@@ -564,6 +566,7 @@ struct wl1271_station {
struct wl12xx_vif {
struct wl1271 *wl;
+ struct list_head list;
u8 bss_type;
u8 p2p; /* we are using p2p role */
u8 role_id;
@@ -653,6 +656,9 @@ struct ieee80211_vif *wl12xx_wlvif_to_vif(struct wl12xx_vif *wlvif)
return container_of((void *)wlvif, struct ieee80211_vif, drv_priv);
}
+#define wl12xx_for_each_wlvif(wl, wlvif) \
+ list_for_each_entry(wlvif, &wl->wlvif_list, list)
+
int wl1271_plt_start(struct wl1271 *wl);
int wl1271_plt_stop(struct wl1271 *wl);
int wl1271_recalc_rx_streaming(struct wl1271 *wl);
--
1.7.6.401.g6a319
^ permalink raw reply related [flat|nested] 51+ messages in thread* Re: [PATCH 06/29] wl12xx: add vifs list
2011-10-10 8:12 ` [PATCH 06/29] wl12xx: add vifs list Eliad Peller
@ 2011-10-10 18:28 ` Luciano Coelho
2011-10-10 19:29 ` Eliad Peller
2011-10-10 20:04 ` Johannes Berg
1 sibling, 1 reply; 51+ messages in thread
From: Luciano Coelho @ 2011-10-10 18:28 UTC (permalink / raw)
To: Eliad Peller; +Cc: linux-wireless
On Mon, 2011-10-10 at 10:12 +0200, Eliad Peller wrote:
> keep a list of all the vifs associated with our hw.
> it will be later used in order to iterate through vifs.
>
> Signed-off-by: Eliad Peller <eliad@wizery.com>
> ---
[...]
> diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
> index 33ccdf8..55561c5 100644
> --- a/drivers/net/wireless/wl12xx/wl12xx.h
> +++ b/drivers/net/wireless/wl12xx/wl12xx.h
> @@ -394,6 +394,8 @@ struct wl1271 {
> unsigned long roles_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)];
> unsigned long roc_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)];
>
> + struct list_head wlvif_list;
> +
> struct wl1271_acx_mem_map *target_mem_map;
>
> /* Accounting for allocated / available TX blocks on HW */
> @@ -564,6 +566,7 @@ struct wl1271_station {
>
> struct wl12xx_vif {
> struct wl1271 *wl;
> + struct list_head list;
I know we alredy call this kind of thing "list" struct wl1271 for the
ARP stuff, but I prefer "node" so it's easier to follow when calling
list_add and friends. Mind changing?
> @@ -653,6 +656,9 @@ struct ieee80211_vif *wl12xx_wlvif_to_vif(struct wl12xx_vif *wlvif)
> return container_of((void *)wlvif, struct ieee80211_vif, drv_priv);
> }
>
> +#define wl12xx_for_each_wlvif(wl, wlvif) \
> + list_for_each_entry(wlvif, &wl->wlvif_list, list)
> +
This looks fine, but is it really necessary? I think the call to
list_for_each_entry is clear enough already, isn't it?
--
Cheers,
Luca.
^ permalink raw reply [flat|nested] 51+ messages in thread* Re: [PATCH 06/29] wl12xx: add vifs list
2011-10-10 18:28 ` Luciano Coelho
@ 2011-10-10 19:29 ` Eliad Peller
2011-10-10 19:40 ` Luciano Coelho
0 siblings, 1 reply; 51+ messages in thread
From: Eliad Peller @ 2011-10-10 19:29 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
On Mon, Oct 10, 2011 at 8:28 PM, Luciano Coelho <coelho@ti.com> wrote:
> On Mon, 2011-10-10 at 10:12 +0200, Eliad Peller wrote:
>> keep a list of all the vifs associated with our hw.
>> it will be later used in order to iterate through vifs.
>>
>> Signed-off-by: Eliad Peller <eliad@wizery.com>
>> ---
>
> [...]
>
>> diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
>> index 33ccdf8..55561c5 100644
>> --- a/drivers/net/wireless/wl12xx/wl12xx.h
>> +++ b/drivers/net/wireless/wl12xx/wl12xx.h
>> @@ -394,6 +394,8 @@ struct wl1271 {
>> unsigned long roles_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)];
>> unsigned long roc_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)];
>>
>> + struct list_head wlvif_list;
>> +
>> struct wl1271_acx_mem_map *target_mem_map;
>>
>> /* Accounting for allocated / available TX blocks on HW */
>> @@ -564,6 +566,7 @@ struct wl1271_station {
>>
>> struct wl12xx_vif {
>> struct wl1271 *wl;
>> + struct list_head list;
>
> I know we alredy call this kind of thing "list" struct wl1271 for the
> ARP stuff, but I prefer "node" so it's easier to follow when calling
> list_add and friends. Mind changing?
>
i think "list" is the standard convention (e.g. see sta_info,
ieee80211_key, etc.) and more intuitive.
>
>> @@ -653,6 +656,9 @@ struct ieee80211_vif *wl12xx_wlvif_to_vif(struct wl12xx_vif *wlvif)
>> return container_of((void *)wlvif, struct ieee80211_vif, drv_priv);
>> }
>>
>> +#define wl12xx_for_each_wlvif(wl, wlvif) \
>> + list_for_each_entry(wlvif, &wl->wlvif_list, list)
>> +
>
> This looks fine, but is it really necessary? I think the call to
> list_for_each_entry is clear enough already, isn't it?
>
i find it easier to understand this way.
also, future patches will add wl12xx_for_each_wlvif_sta and
wl12xx_for_each_wlvif_ap, so it even makes more sense to use this
macro.
Eliad.
^ permalink raw reply [flat|nested] 51+ messages in thread* Re: [PATCH 06/29] wl12xx: add vifs list
2011-10-10 19:29 ` Eliad Peller
@ 2011-10-10 19:40 ` Luciano Coelho
0 siblings, 0 replies; 51+ messages in thread
From: Luciano Coelho @ 2011-10-10 19:40 UTC (permalink / raw)
To: Eliad Peller; +Cc: linux-wireless
On Mon, 2011-10-10 at 21:29 +0200, Eliad Peller wrote:
> On Mon, Oct 10, 2011 at 8:28 PM, Luciano Coelho <coelho@ti.com> wrote:
> > On Mon, 2011-10-10 at 10:12 +0200, Eliad Peller wrote:
> >> keep a list of all the vifs associated with our hw.
> >> it will be later used in order to iterate through vifs.
> >>
> >> Signed-off-by: Eliad Peller <eliad@wizery.com>
> >> ---
> >
> > [...]
> >
> >> diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
> >> index 33ccdf8..55561c5 100644
> >> --- a/drivers/net/wireless/wl12xx/wl12xx.h
> >> +++ b/drivers/net/wireless/wl12xx/wl12xx.h
> >> @@ -394,6 +394,8 @@ struct wl1271 {
> >> unsigned long roles_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)];
> >> unsigned long roc_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)];
> >>
> >> + struct list_head wlvif_list;
> >> +
> >> struct wl1271_acx_mem_map *target_mem_map;
> >>
> >> /* Accounting for allocated / available TX blocks on HW */
> >> @@ -564,6 +566,7 @@ struct wl1271_station {
> >>
> >> struct wl12xx_vif {
> >> struct wl1271 *wl;
> >> + struct list_head list;
> >
> > I know we alredy call this kind of thing "list" struct wl1271 for the
> > ARP stuff, but I prefer "node" so it's easier to follow when calling
> > list_add and friends. Mind changing?
> >
> i think "list" is the standard convention (e.g. see sta_info,
> ieee80211_key, etc.) and more intuitive.
Yeah, it makes a bit of sense, because each node is actually a head of a
list. Still, I don't like it because it's annoying to read it a
list_add() with two lists. It's not intuitive to know which one is
which. Anyway, it's fine to leave it like this.
> >> @@ -653,6 +656,9 @@ struct ieee80211_vif *wl12xx_wlvif_to_vif(struct wl12xx_vif *wlvif)
> >> return container_of((void *)wlvif, struct ieee80211_vif, drv_priv);
> >> }
> >>
> >> +#define wl12xx_for_each_wlvif(wl, wlvif) \
> >> + list_for_each_entry(wlvif, &wl->wlvif_list, list)
> >> +
> >
> > This looks fine, but is it really necessary? I think the call to
> > list_for_each_entry is clear enough already, isn't it?
> >
> i find it easier to understand this way.
> also, future patches will add wl12xx_for_each_wlvif_sta and
> wl12xx_for_each_wlvif_ap, so it even makes more sense to use this
> macro.
Yeah, I now saw the other macros and it now makes a bit more sense for
the other ones. But I dislike simple macros whose content are almost as
easy to understand as the macro name, because one needs to go dig the
macro out to figure out exactly what it is doing. With no macro, it
would be much easier to figure out that this is a simple
list_for_each_entry(), because you would simply call that explicitly. ;)
It's as annoying as unnecessary typedefs.
But I'm in a temporary and unusual mood of accepting stuff easier than
usual right now, so it's fine to keep it like this. ;)
--
Cheers,
Luca.
^ permalink raw reply [flat|nested] 51+ messages in thread
* Re: [PATCH 06/29] wl12xx: add vifs list
2011-10-10 8:12 ` [PATCH 06/29] wl12xx: add vifs list Eliad Peller
2011-10-10 18:28 ` Luciano Coelho
@ 2011-10-10 20:04 ` Johannes Berg
2011-10-10 20:07 ` Eliad Peller
1 sibling, 1 reply; 51+ messages in thread
From: Johannes Berg @ 2011-10-10 20:04 UTC (permalink / raw)
To: Eliad Peller; +Cc: Luciano Coelho, linux-wireless
On Mon, 2011-10-10 at 10:12 +0200, Eliad Peller wrote:
> keep a list of all the vifs associated with our hw.
> it will be later used in order to iterate through vifs.
What's wrong with ieee80211_iterate_active_interfaces() :-)
johannes
^ permalink raw reply [flat|nested] 51+ messages in thread
* Re: [PATCH 06/29] wl12xx: add vifs list
2011-10-10 20:04 ` Johannes Berg
@ 2011-10-10 20:07 ` Eliad Peller
0 siblings, 0 replies; 51+ messages in thread
From: Eliad Peller @ 2011-10-10 20:07 UTC (permalink / raw)
To: Johannes Berg; +Cc: Luciano Coelho, linux-wireless
On Mon, Oct 10, 2011 at 10:04 PM, Johannes Berg
<johannes@sipsolutions.net> wrote:
> On Mon, 2011-10-10 at 10:12 +0200, Eliad Peller wrote:
>> keep a list of all the vifs associated with our hw.
>> it will be later used in order to iterate through vifs.
>
> What's wrong with ieee80211_iterate_active_interfaces() :-)
defining iterator for each time we want to iterate is pretty cumbersome :)
^ permalink raw reply [flat|nested] 51+ messages in thread
* [PATCH 07/29] wl12xx: support multiple vifs in the tx path
2011-10-10 8:12 [PATCH 00/29] make the driver ready for multi-vif support Eliad Peller
` (5 preceding siblings ...)
2011-10-10 8:12 ` [PATCH 06/29] wl12xx: add vifs list Eliad Peller
@ 2011-10-10 8:12 ` Eliad Peller
2011-10-10 8:12 ` [PATCH 08/29] wl12xx: configure sleep_policy according to active roles Eliad Peller
` (22 subsequent siblings)
29 siblings, 0 replies; 51+ messages in thread
From: Eliad Peller @ 2011-10-10 8:12 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
Pass the wlvif associated with each skb as param.
Note that dummy packet doesn't belong to any
particular vif, so we pass NULL in this case.
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
drivers/net/wireless/wl12xx/main.c | 6 +-
drivers/net/wireless/wl12xx/tx.c | 79 ++++++++++++++++++++++--------------
drivers/net/wireless/wl12xx/tx.h | 2 +-
3 files changed, 52 insertions(+), 35 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 56d5923..0623f5d 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -993,7 +993,7 @@ irqreturn_t wl1271_irq(int irq, void *cookie)
* In order to avoid starvation of the TX path,
* call the work function directly.
*/
- wl1271_tx_work_locked(wl, wl->vif);
+ wl1271_tx_work_locked(wl);
} else {
spin_unlock_irqrestore(&wl->wl_lock, flags);
}
@@ -1537,7 +1537,7 @@ int wl1271_tx_dummy_packet(struct wl1271 *wl)
/* The FW is low on RX memory blocks, so send the dummy packet asap */
if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags))
- wl1271_tx_work_locked(wl, wl->vif);
+ wl1271_tx_work_locked(wl);
/*
* If the FW TX is busy, TX work will be scheduled by the threaded
@@ -2413,7 +2413,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
((wl->band != conf->channel->band) ||
(wl->channel != channel))) {
/* send all pending packets */
- wl1271_tx_work_locked(wl, vif);
+ wl1271_tx_work_locked(wl);
wl->band = conf->channel->band;
wl->channel = channel;
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index 6c0135b..c7be151 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -210,17 +210,17 @@ static unsigned int wl12xx_calc_packet_alignment(struct wl1271 *wl,
return ALIGN(packet_length, WL1271_TX_ALIGN_TO);
}
-static int wl1271_tx_allocate(struct wl1271 *wl, struct ieee80211_vif *vif,
+static int wl1271_tx_allocate(struct wl1271 *wl, struct wl12xx_vif *wlvif,
struct sk_buff *skb, u32 extra, u32 buf_offset,
u8 hlid)
{
- struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
struct wl1271_tx_hw_descr *desc;
u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra;
u32 len;
u32 total_blocks;
int id, ret = -EBUSY, ac;
u32 spare_blocks = wl->tx_spare_blocks;
+ bool is_dummy = false;
if (buf_offset + total_len > WL1271_AGGR_BUFFER_SIZE)
return -EAGAIN;
@@ -235,8 +235,10 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct ieee80211_vif *vif,
len = wl12xx_calc_packet_alignment(wl, total_len);
/* in case of a dummy packet, use default amount of spare mem blocks */
- if (unlikely(wl12xx_is_dummy_packet(wl, skb)))
+ if (unlikely(wl12xx_is_dummy_packet(wl, skb))) {
+ is_dummy = true;
spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT;
+ }
total_blocks = (len + TX_HW_BLOCK_SIZE - 1) / TX_HW_BLOCK_SIZE +
spare_blocks;
@@ -261,7 +263,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct ieee80211_vif *vif,
ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
wl->tx_allocated_pkts[ac]++;
- if (wlvif->bss_type == BSS_TYPE_AP_BSS &&
+ if (!is_dummy && wlvif->bss_type == BSS_TYPE_AP_BSS &&
test_bit(hlid, wlvif->ap.sta_hlid_map))
wl->links[hlid].allocated_pkts++;
@@ -277,16 +279,16 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct ieee80211_vif *vif,
return ret;
}
-static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct ieee80211_vif *vif,
+static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct wl12xx_vif *wlvif,
struct sk_buff *skb, u32 extra,
struct ieee80211_tx_info *control, u8 hlid)
{
- struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
struct timespec ts;
struct wl1271_tx_hw_descr *desc;
int aligned_len, ac, rate_idx;
s64 hosttime;
u16 tx_attr;
+ bool is_dummy;
desc = (struct wl1271_tx_hw_descr *) skb->data;
@@ -303,7 +305,8 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct ieee80211_vif *vif,
hosttime = (timespec_to_ns(&ts) >> 10);
desc->start_time = cpu_to_le32(hosttime - wl->time_offset);
- if (wlvif->bss_type != BSS_TYPE_AP_BSS)
+ is_dummy = wl12xx_is_dummy_packet(wl, skb);
+ if (is_dummy || wlvif->bss_type != BSS_TYPE_AP_BSS)
desc->life_time = cpu_to_le16(TX_HW_MGMT_PKT_LIFETIME_TU);
else
desc->life_time = cpu_to_le16(TX_HW_AP_MODE_PKT_LIFETIME_TU);
@@ -312,7 +315,7 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct ieee80211_vif *vif,
ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
desc->tid = skb->priority;
- if (wl12xx_is_dummy_packet(wl, skb)) {
+ if (is_dummy) {
/*
* FW expects the dummy packet to have an invalid session id -
* any session id that is different than the one set in the join
@@ -329,7 +332,9 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct ieee80211_vif *vif,
}
desc->hlid = hlid;
- if (wlvif->bss_type != BSS_TYPE_AP_BSS) {
+ if (is_dummy)
+ rate_idx = 0;
+ else if (wlvif->bss_type != BSS_TYPE_AP_BSS) {
/* if the packets are destined for AP (have a STA entry)
send them with AP rate policies, otherwise use default
basic rates */
@@ -383,12 +388,10 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct ieee80211_vif *vif,
}
/* caller must hold wl->mutex */
-static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb,
- u32 buf_offset)
+static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct wl12xx_vif *wlvif,
+ struct sk_buff *skb, u32 buf_offset)
{
struct ieee80211_tx_info *info;
- struct ieee80211_vif *vif;
- struct wl12xx_vif *wlvif;
u32 extra = 0;
int ret = 0;
u32 total_len;
@@ -402,11 +405,6 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb,
/* TODO: handle dummy packets on multi-vifs */
is_dummy = wl12xx_is_dummy_packet(wl, skb);
- if (is_dummy)
- info->control.vif = wl->vif;
-
- vif = info->control.vif;
- wlvif = wl12xx_vif_to_data(vif);
if (info->control.hw_key &&
info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP)
@@ -433,13 +431,13 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb,
return -EINVAL;
}
- ret = wl1271_tx_allocate(wl, vif, skb, extra, buf_offset, hlid);
+ ret = wl1271_tx_allocate(wl, wlvif, skb, extra, buf_offset, hlid);
if (ret < 0)
return ret;
- wl1271_tx_fill_hdr(wl, vif, skb, extra, info, hlid);
+ wl1271_tx_fill_hdr(wl, wlvif, skb, extra, info, hlid);
- if (wlvif->bss_type == BSS_TYPE_AP_BSS && !is_dummy) {
+ if (!is_dummy && wlvif->bss_type == BSS_TYPE_AP_BSS) {
wl1271_tx_ap_update_inconnection_sta(wl, skb);
wl1271_tx_regulate_link(wl, wlvif, hlid);
}
@@ -589,13 +587,19 @@ static struct sk_buff *wl12xx_vif_skb_dequeue(struct wl1271 *wl,
return skb;
}
-static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl,
- struct wl12xx_vif *wlvif)
+static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl)
{
unsigned long flags;
+ struct wl12xx_vif *wlvif;
struct sk_buff *skb = NULL;
- skb = wl12xx_vif_skb_dequeue(wl, wlvif);
+ /* TODO: rememeber last vif and consider it */
+ wl12xx_for_each_wlvif(wl, wlvif) {
+ skb = wl12xx_vif_skb_dequeue(wl, wlvif);
+ if (skb)
+ break;
+ }
+
if (!skb &&
test_and_clear_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags)) {
int q;
@@ -639,24 +643,35 @@ static bool wl1271_tx_is_data_present(struct sk_buff *skb)
return ieee80211_is_data_present(hdr->frame_control);
}
-void wl1271_tx_work_locked(struct wl1271 *wl, struct ieee80211_vif *vif)
+void wl1271_tx_work_locked(struct wl1271 *wl)
{
- struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
+ struct wl12xx_vif *wlvif;
struct sk_buff *skb;
u32 buf_offset = 0;
bool sent_packets = false;
bool had_data = false;
- bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS);
+ /* TODO: save bitmap of relevant stations */
+ bool is_sta = false;
int ret;
if (unlikely(wl->state == WL1271_STATE_OFF))
return;
- while ((skb = wl1271_skb_dequeue(wl, wlvif))) {
+ while ((skb = wl1271_skb_dequeue(wl))) {
+ wlvif = NULL;
+ if (!wl12xx_is_dummy_packet(wl, skb)) {
+ struct ieee80211_tx_info *info;
+ struct ieee80211_vif *vif;
+
+ info = IEEE80211_SKB_CB(skb);
+ vif = info->control.vif;
+ wlvif = wl12xx_vif_to_data(vif);
+ }
+
if (wl1271_tx_is_data_present(skb))
had_data = true;
- ret = wl1271_prepare_tx_frame(wl, skb, buf_offset);
+ ret = wl1271_prepare_tx_frame(wl, wlvif, skb, buf_offset);
if (ret == -EAGAIN) {
/*
* Aggregation buffer is full.
@@ -683,6 +698,8 @@ void wl1271_tx_work_locked(struct wl1271 *wl, struct ieee80211_vif *vif)
}
buf_offset += ret;
wl->tx_packets_count++;
+ if (wlvif && wlvif->bss_type == BSS_TYPE_STA_BSS)
+ is_sta = true;
}
out_ack:
@@ -702,7 +719,7 @@ out_ack:
wl1271_handle_tx_low_watermark(wl);
}
- if (!is_ap && wl->conf.rx_streaming.interval && had_data &&
+ if (is_sta && wl->conf.rx_streaming.interval && had_data &&
(wl->conf.rx_streaming.always ||
test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags))) {
u32 timeout = wl->conf.rx_streaming.duration;
@@ -727,7 +744,7 @@ void wl1271_tx_work(struct work_struct *work)
if (ret < 0)
goto out;
- wl1271_tx_work_locked(wl, wl->vif);
+ wl1271_tx_work_locked(wl);
wl1271_ps_elp_sleep(wl);
out:
diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/tx.h
index 050a047..fe29ff5 100644
--- a/drivers/net/wireless/wl12xx/tx.h
+++ b/drivers/net/wireless/wl12xx/tx.h
@@ -204,7 +204,7 @@ static inline int wl1271_tx_total_queue_count(struct wl1271 *wl)
}
void wl1271_tx_work(struct work_struct *work);
-void wl1271_tx_work_locked(struct wl1271 *wl, struct ieee80211_vif *vif);
+void wl1271_tx_work_locked(struct wl1271 *wl);
void wl1271_tx_complete(struct wl1271 *wl);
void wl12xx_tx_reset_wlvif(struct wl1271 *wl, struct wl12xx_vif *wlvif);
void wl12xx_tx_reset(struct wl1271 *wl, bool reset_tx_queues);
--
1.7.6.401.g6a319
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 08/29] wl12xx: configure sleep_policy according to active roles
2011-10-10 8:12 [PATCH 00/29] make the driver ready for multi-vif support Eliad Peller
` (6 preceding siblings ...)
2011-10-10 8:12 ` [PATCH 07/29] wl12xx: support multiple vifs in the tx path Eliad Peller
@ 2011-10-10 8:12 ` Eliad Peller
2011-10-10 18:51 ` Luciano Coelho
2011-10-10 8:12 ` [PATCH 09/29] wl12xx: make event handling support multirole Eliad Peller
` (21 subsequent siblings)
29 siblings, 1 reply; 51+ messages in thread
From: Eliad Peller @ 2011-10-10 8:12 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
If there is an active AP role, stay always on.
Otherwise, allow chip to enter elp.
(Note that this is a global configuration, so if the
device is already configured according to our policy,
we don't have to configure it again)
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
drivers/net/wireless/wl12xx/init.c | 39 ++++++++++++++++++++++++-----------
1 files changed, 27 insertions(+), 12 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c
index 80e89e3..e596f5c 100644
--- a/drivers/net/wireless/wl12xx/init.c
+++ b/drivers/net/wireless/wl12xx/init.c
@@ -343,11 +343,6 @@ static int wl1271_sta_hw_init(struct wl1271 *wl, struct wl12xx_vif *wlvif)
if (ret < 0)
return ret;
- /* Configure for ELP power saving */
- ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP);
- if (ret < 0)
- return ret;
-
ret = wl1271_acx_sta_rate_policies(wl, wlvif);
if (ret < 0)
return ret;
@@ -382,11 +377,6 @@ static int wl1271_ap_hw_init(struct wl1271 *wl, struct wl12xx_vif *wlvif)
{
int ret;
- /* Configure for power always on */
- ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM);
- if (ret < 0)
- return ret;
-
ret = wl1271_init_ap_rates(wl, wlvif);
if (ret < 0)
return ret;
@@ -573,13 +563,38 @@ static int wl12xx_init_ap_role(struct wl1271 *wl, struct wl12xx_vif *wlvif)
int wl1271_init_vif_specific(struct wl1271 *wl, struct ieee80211_vif *vif)
{
- struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
+ struct wl12xx_vif *iter, *wlvif = wl12xx_vif_to_data(vif);
struct conf_tx_ac_category *conf_ac;
struct conf_tx_tid *conf_tid;
bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS);
-
+ u8 sta_roles_cnt = 0, ap_roles_cnt = 0;
int ret, i;
+ wl12xx_for_each_wlvif(wl, iter) {
+ if (iter->bss_type == BSS_TYPE_AP_BSS)
+ ap_roles_cnt++;
+ else
+ sta_roles_cnt++;
+ }
+
+ /*
+ * consider all existing roles before configuring psm.
+ * TODO: reconfigure on interface removal.
+ */
+ if (!ap_roles_cnt) {
+ if (is_ap) {
+ /* Configure for power always on */
+ ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM);
+ if (ret < 0)
+ return ret;
+ } else if (!sta_roles_cnt) {
+ /* Configure for ELP power saving */
+ ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP);
+ if (ret < 0)
+ return ret;
+ }
+ }
+
/* Mode specific init */
if (is_ap) {
ret = wl1271_ap_hw_init(wl, wlvif);
--
1.7.6.401.g6a319
^ permalink raw reply related [flat|nested] 51+ messages in thread* Re: [PATCH 08/29] wl12xx: configure sleep_policy according to active roles
2011-10-10 8:12 ` [PATCH 08/29] wl12xx: configure sleep_policy according to active roles Eliad Peller
@ 2011-10-10 18:51 ` Luciano Coelho
2011-10-10 19:32 ` Eliad Peller
0 siblings, 1 reply; 51+ messages in thread
From: Luciano Coelho @ 2011-10-10 18:51 UTC (permalink / raw)
To: Eliad Peller; +Cc: linux-wireless
On Mon, 2011-10-10 at 10:12 +0200, Eliad Peller wrote:
> If there is an active AP role, stay always on.
> Otherwise, allow chip to enter elp.
>
> (Note that this is a global configuration, so if the
> device is already configured according to our policy,
> we don't have to configure it again)
>
> Signed-off-by: Eliad Peller <eliad@wizery.com>
> ---
[...]
> @@ -573,13 +563,38 @@ static int wl12xx_init_ap_role(struct wl1271 *wl, struct wl12xx_vif *wlvif)
>
> int wl1271_init_vif_specific(struct wl1271 *wl, struct ieee80211_vif *vif)
> {
> - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
> + struct wl12xx_vif *iter, *wlvif = wl12xx_vif_to_data(vif);
> struct conf_tx_ac_category *conf_ac;
> struct conf_tx_tid *conf_tid;
> bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS);
> -
> + u8 sta_roles_cnt = 0, ap_roles_cnt = 0;
> int ret, i;
>
> + wl12xx_for_each_wlvif(wl, iter) {
> + if (iter->bss_type == BSS_TYPE_AP_BSS)
> + ap_roles_cnt++;
> + else
> + sta_roles_cnt++;
> + }
> +
> + /*
> + * consider all existing roles before configuring psm.
> + * TODO: reconfigure on interface removal.
> + */
> + if (!ap_roles_cnt) {
> + if (is_ap) {
> + /* Configure for power always on */
> + ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM);
> + if (ret < 0)
> + return ret;
> + } else if (!sta_roles_cnt) {
> + /* Configure for ELP power saving */
> + ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP);
> + if (ret < 0)
> + return ret;
> + }
> + }
> +
Wouldn't it be much simpler to have a "have_ap" element in the wl
struct?
--
Cheers,
Luca.
^ permalink raw reply [flat|nested] 51+ messages in thread* Re: [PATCH 08/29] wl12xx: configure sleep_policy according to active roles
2011-10-10 18:51 ` Luciano Coelho
@ 2011-10-10 19:32 ` Eliad Peller
2011-10-10 19:54 ` Luciano Coelho
0 siblings, 1 reply; 51+ messages in thread
From: Eliad Peller @ 2011-10-10 19:32 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
On Mon, Oct 10, 2011 at 8:51 PM, Luciano Coelho <coelho@ti.com> wrote:
> On Mon, 2011-10-10 at 10:12 +0200, Eliad Peller wrote:
>> If there is an active AP role, stay always on.
>> Otherwise, allow chip to enter elp.
>>
>> (Note that this is a global configuration, so if the
>> device is already configured according to our policy,
>> we don't have to configure it again)
>>
>> Signed-off-by: Eliad Peller <eliad@wizery.com>
>> ---
>
> [...]
>
>> @@ -573,13 +563,38 @@ static int wl12xx_init_ap_role(struct wl1271 *wl, struct wl12xx_vif *wlvif)
>>
>> int wl1271_init_vif_specific(struct wl1271 *wl, struct ieee80211_vif *vif)
>> {
>> - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
>> + struct wl12xx_vif *iter, *wlvif = wl12xx_vif_to_data(vif);
>> struct conf_tx_ac_category *conf_ac;
>> struct conf_tx_tid *conf_tid;
>> bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS);
>> -
>> + u8 sta_roles_cnt = 0, ap_roles_cnt = 0;
>> int ret, i;
>>
>> + wl12xx_for_each_wlvif(wl, iter) {
>> + if (iter->bss_type == BSS_TYPE_AP_BSS)
>> + ap_roles_cnt++;
>> + else
>> + sta_roles_cnt++;
>> + }
>> +
>> + /*
>> + * consider all existing roles before configuring psm.
>> + * TODO: reconfigure on interface removal.
>> + */
>> + if (!ap_roles_cnt) {
>> + if (is_ap) {
>> + /* Configure for power always on */
>> + ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM);
>> + if (ret < 0)
>> + return ret;
>> + } else if (!sta_roles_cnt) {
>> + /* Configure for ELP power saving */
>> + ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP);
>> + if (ret < 0)
>> + return ret;
>> + }
>> + }
>> +
>
> Wouldn't it be much simpler to have a "have_ap" element in the wl
> struct?
>
>
have_ap is not enough, because there might be multiple aps, and we
need to consider it on removal.
we can use ap_count, if you prefer it that way.
Eliad.
^ permalink raw reply [flat|nested] 51+ messages in thread* Re: [PATCH 08/29] wl12xx: configure sleep_policy according to active roles
2011-10-10 19:32 ` Eliad Peller
@ 2011-10-10 19:54 ` Luciano Coelho
0 siblings, 0 replies; 51+ messages in thread
From: Luciano Coelho @ 2011-10-10 19:54 UTC (permalink / raw)
To: Eliad Peller; +Cc: linux-wireless
On Mon, 2011-10-10 at 21:32 +0200, Eliad Peller wrote:
> On Mon, Oct 10, 2011 at 8:51 PM, Luciano Coelho <coelho@ti.com> wrote:
> > On Mon, 2011-10-10 at 10:12 +0200, Eliad Peller wrote:
> >> If there is an active AP role, stay always on.
> >> Otherwise, allow chip to enter elp.
> >>
> >> (Note that this is a global configuration, so if the
> >> device is already configured according to our policy,
> >> we don't have to configure it again)
> >>
> >> Signed-off-by: Eliad Peller <eliad@wizery.com>
> >> ---
> >
> > [...]
> >
> >> @@ -573,13 +563,38 @@ static int wl12xx_init_ap_role(struct wl1271 *wl, struct wl12xx_vif *wlvif)
> >>
> >> int wl1271_init_vif_specific(struct wl1271 *wl, struct ieee80211_vif *vif)
> >> {
> >> - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
> >> + struct wl12xx_vif *iter, *wlvif = wl12xx_vif_to_data(vif);
> >> struct conf_tx_ac_category *conf_ac;
> >> struct conf_tx_tid *conf_tid;
> >> bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS);
> >> -
> >> + u8 sta_roles_cnt = 0, ap_roles_cnt = 0;
> >> int ret, i;
> >>
> >> + wl12xx_for_each_wlvif(wl, iter) {
> >> + if (iter->bss_type == BSS_TYPE_AP_BSS)
> >> + ap_roles_cnt++;
> >> + else
> >> + sta_roles_cnt++;
> >> + }
> >> +
> >> + /*
> >> + * consider all existing roles before configuring psm.
> >> + * TODO: reconfigure on interface removal.
> >> + */
> >> + if (!ap_roles_cnt) {
> >> + if (is_ap) {
> >> + /* Configure for power always on */
> >> + ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM);
> >> + if (ret < 0)
> >> + return ret;
> >> + } else if (!sta_roles_cnt) {
> >> + /* Configure for ELP power saving */
> >> + ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP);
> >> + if (ret < 0)
> >> + return ret;
> >> + }
> >> + }
> >> +
> >
> > Wouldn't it be much simpler to have a "have_ap" element in the wl
> > struct?
> >
> >
> have_ap is not enough, because there might be multiple aps, and we
> need to consider it on removal.
Right...
> we can use ap_count, if you prefer it that way.
Yeah, I'd still prefer that.
--
Cheers,
Luca.
^ permalink raw reply [flat|nested] 51+ messages in thread
* [PATCH 09/29] wl12xx: make event handling support multirole
2011-10-10 8:12 [PATCH 00/29] make the driver ready for multi-vif support Eliad Peller
` (7 preceding siblings ...)
2011-10-10 8:12 ` [PATCH 08/29] wl12xx: configure sleep_policy according to active roles Eliad Peller
@ 2011-10-10 8:12 ` Eliad Peller
2011-10-10 18:58 ` Luciano Coelho
2011-10-10 8:12 ` [PATCH 10/29] wl12xx: move tx_security_seq into wlvif Eliad Peller
` (20 subsequent siblings)
29 siblings, 1 reply; 51+ messages in thread
From: Eliad Peller @ 2011-10-10 8:12 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
Some events don't indicate the role they are intended for.
In these cases, iterate through all the relevant vifs,
and pass the event to each one of them.
This is only a workaround. future fw releases should indicate
the relevant role_id for such events.
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
drivers/net/wireless/wl12xx/event.c | 121 +++++++++++++++++++++++-----------
drivers/net/wireless/wl12xx/wl12xx.h | 10 +++
2 files changed, 91 insertions(+), 40 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c
index 486c8ee..dbc40bb 100644
--- a/drivers/net/wireless/wl12xx/event.c
+++ b/drivers/net/wireless/wl12xx/event.c
@@ -162,10 +162,10 @@ static int wl1271_event_ps_report(struct wl1271 *wl,
}
static void wl1271_event_rssi_trigger(struct wl1271 *wl,
- struct ieee80211_vif *vif,
+ struct wl12xx_vif *wlvif,
struct event_mailbox *mbox)
{
- struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
+ struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
enum nl80211_cqm_rssi_threshold_event event;
s8 metric = mbox->rssi_snr_trigger_metric[0];
@@ -183,11 +183,13 @@ static void wl1271_event_rssi_trigger(struct wl1271 *wl,
static void wl1271_stop_ba_event(struct wl1271 *wl, struct wl12xx_vif *wlvif)
{
+ struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
+
if (wlvif->bss_type != BSS_TYPE_AP_BSS) {
if (!wlvif->sta.ba_rx_bitmap)
return;
- ieee80211_stop_rx_ba_session(wl->vif, wlvif->sta.ba_rx_bitmap,
- wl->vif->bss_conf.bssid);
+ ieee80211_stop_rx_ba_session(vif, wlvif->sta.ba_rx_bitmap,
+ vif->bss_conf.bssid);
} else {
u8 hlid;
struct wl1271_link *lnk;
@@ -197,7 +199,7 @@ static void wl1271_stop_ba_event(struct wl1271 *wl, struct wl12xx_vif *wlvif)
if (!lnk->ba_bitmap)
continue;
- ieee80211_stop_rx_ba_session(wl->vif,
+ ieee80211_stop_rx_ba_session(vif,
lnk->ba_bitmap,
lnk->addr);
}
@@ -207,12 +209,21 @@ static void wl1271_stop_ba_event(struct wl1271 *wl, struct wl12xx_vif *wlvif)
static void wl12xx_event_soft_gemini_sense(struct wl1271 *wl,
u8 enable)
{
+ struct ieee80211_vif *vif;
+ struct wl12xx_vif *wlvif;
+
if (enable) {
/* disable dynamic PS when requested by the firmware */
- ieee80211_disable_dyn_ps(wl->vif);
+ wl12xx_for_each_wlvif_sta(wl, wlvif) {
+ vif = wl12xx_wlvif_to_vif(wlvif);
+ ieee80211_disable_dyn_ps(vif);
+ }
set_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags);
} else {
- ieee80211_enable_dyn_ps(wl->vif);
+ wl12xx_for_each_wlvif_sta(wl, wlvif) {
+ vif = wl12xx_wlvif_to_vif(wlvif);
+ ieee80211_enable_dyn_ps(vif);
+ }
clear_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags);
wl1271_recalc_rx_streaming(wl);
}
@@ -228,12 +239,11 @@ static void wl1271_event_mbox_dump(struct event_mailbox *mbox)
static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
{
- struct ieee80211_vif *vif = wl->vif; /* TODO: get as param */
- struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
+ struct ieee80211_vif *vif;
+ struct wl12xx_vif *wlvif;
int ret;
u32 vector;
bool beacon_loss = false;
- bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS);
bool disconnect_sta = false;
unsigned long sta_bitmap = 0;
@@ -266,8 +276,7 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
}
}
- if (vector & SOFT_GEMINI_SENSE_EVENT_ID &&
- wlvif->bss_type == BSS_TYPE_STA_BSS)
+ if (vector & SOFT_GEMINI_SENSE_EVENT_ID)
wl12xx_event_soft_gemini_sense(wl,
mbox->soft_gemini_sense_info);
@@ -280,40 +289,54 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
* BSS_LOSE_EVENT, beacon loss has to be reported to the stack.
*
*/
- if ((vector & BSS_LOSE_EVENT_ID) && !is_ap) {
+ if (vector & BSS_LOSE_EVENT_ID) {
+ /* TODO: check for multi-role */
wl1271_info("Beacon loss detected.");
/* indicate to the stack, that beacons have been lost */
beacon_loss = true;
}
- if ((vector & PS_REPORT_EVENT_ID) && !is_ap) {
+ if (vector & PS_REPORT_EVENT_ID) {
wl1271_debug(DEBUG_EVENT, "PS_REPORT_EVENT");
- ret = wl1271_event_ps_report(wl, wlvif, mbox, &beacon_loss);
- if (ret < 0)
- return ret;
+ wl12xx_for_each_wlvif_sta(wl, wlvif) {
+ ret = wl1271_event_ps_report(wl, wlvif,
+ mbox, &beacon_loss);
+ if (ret < 0)
+ return ret;
+ }
}
- if ((vector & PSPOLL_DELIVERY_FAILURE_EVENT_ID) && !is_ap)
- wl1271_event_pspoll_delivery_fail(wl, wlvif);
+ if (vector & PSPOLL_DELIVERY_FAILURE_EVENT_ID)
+ wl12xx_for_each_wlvif_sta(wl, wlvif) {
+ wl1271_event_pspoll_delivery_fail(wl, wlvif);
+ }
if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID) {
+ /* TODO: check actual multi-role support */
wl1271_debug(DEBUG_EVENT, "RSSI_SNR_TRIGGER_0_EVENT");
- if (wl->vif)
- wl1271_event_rssi_trigger(wl, vif, mbox);
+ wl12xx_for_each_wlvif_sta(wl, wlvif) {
+ wl1271_event_rssi_trigger(wl, wlvif, mbox);
+ }
}
- if ((vector & BA_SESSION_RX_CONSTRAINT_EVENT_ID)) {
+ if (vector & BA_SESSION_RX_CONSTRAINT_EVENT_ID) {
+ u8 role_id = mbox->role_id;
wl1271_debug(DEBUG_EVENT, "BA_SESSION_RX_CONSTRAINT_EVENT_ID. "
- "ba_allowed = 0x%x", mbox->rx_ba_allowed);
+ "ba_allowed = 0x%x, role_id=%d",
+ mbox->rx_ba_allowed, role_id);
- wlvif->ba_allowed = !!mbox->rx_ba_allowed;
+ wl12xx_for_each_wlvif(wl, wlvif) {
+ if (role_id != 0xff && role_id != wlvif->role_id)
+ continue;
- if (wl->vif && !wlvif->ba_allowed)
- wl1271_stop_ba_event(wl, wlvif);
+ wlvif->ba_allowed = !!mbox->rx_ba_allowed;
+ if (!wlvif->ba_allowed)
+ wl1271_stop_ba_event(wl, wlvif);
+ }
}
- if ((vector & CHANNEL_SWITCH_COMPLETE_EVENT_ID) && !is_ap) {
+ if (vector & CHANNEL_SWITCH_COMPLETE_EVENT_ID) {
wl1271_debug(DEBUG_EVENT, "CHANNEL_SWITCH_COMPLETE_EVENT_ID. "
"status = 0x%x",
mbox->channel_switch_status);
@@ -322,48 +345,63 @@ 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) &&
- (wl->vif))
- ieee80211_chswitch_done(wl->vif,
- mbox->channel_switch_status ? false : true);
+ 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);
+ }
+ }
}
if ((vector & DUMMY_PACKET_EVENT_ID)) {
wl1271_debug(DEBUG_EVENT, "DUMMY_PACKET_ID_EVENT_ID");
- if (wl->vif)
- wl1271_tx_dummy_packet(wl);
+ wl1271_tx_dummy_packet(wl);
}
/*
* "TX retries exceeded" has a different meaning according to mode.
* In AP mode the offending station is disconnected.
*/
- if ((vector & MAX_TX_RETRY_EVENT_ID) && is_ap) {
+ if (vector & MAX_TX_RETRY_EVENT_ID) {
wl1271_debug(DEBUG_EVENT, "MAX_TX_RETRY_EVENT_ID");
sta_bitmap |= le16_to_cpu(mbox->sta_tx_retry_exceeded);
disconnect_sta = true;
}
- if ((vector & INACTIVE_STA_EVENT_ID) && is_ap) {
+ if (vector & INACTIVE_STA_EVENT_ID) {
wl1271_debug(DEBUG_EVENT, "INACTIVE_STA_EVENT_ID");
sta_bitmap |= le16_to_cpu(mbox->sta_aging_status);
disconnect_sta = true;
}
- if (is_ap && disconnect_sta) {
+ if (disconnect_sta) {
u32 num_packets = wl->conf.tx.max_tx_retries;
struct ieee80211_sta *sta;
const u8 *addr;
int h;
for_each_set_bit(h, &sta_bitmap, WL12XX_MAX_LINKS) {
- if (!test_bit(h, wlvif->ap.sta_hlid_map))
+ bool found = false;
+ /* find the ap vif connected to this sta */
+ wl12xx_for_each_wlvif_ap(wl, wlvif) {
+ if (!test_bit(h, wlvif->ap.sta_hlid_map))
+ continue;
+ found = true;
+ break;
+ }
+ if (!found)
continue;
+ vif = wl12xx_wlvif_to_vif(wlvif);
addr = wl->links[h].addr;
rcu_read_lock();
- sta = ieee80211_find_sta(wl->vif, addr);
+ sta = ieee80211_find_sta(vif, addr);
if (sta) {
wl1271_debug(DEBUG_EVENT, "remove sta %d", h);
ieee80211_report_low_ack(sta, num_packets);
@@ -372,8 +410,11 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
}
}
- if (wl->vif && beacon_loss)
- ieee80211_connection_loss(wl->vif);
+ if (beacon_loss)
+ wl12xx_for_each_wlvif_sta(wl, wlvif) {
+ vif = wl12xx_wlvif_to_vif(wlvif);
+ ieee80211_connection_loss(vif);
+ }
return 0;
}
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index 55561c5..b13f13e 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -659,6 +659,16 @@ 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_bss_type(wl, wlvif, _bss_type) \
+ wl12xx_for_each_wlvif(wl, wlvif) \
+ if (wlvif->bss_type == _bss_type)
+
+#define wl12xx_for_each_wlvif_sta(wl, wlvif) \
+ wl12xx_for_each_wlvif_bss_type(wl, wlvif, BSS_TYPE_STA_BSS)
+
+#define wl12xx_for_each_wlvif_ap(wl, wlvif) \
+ wl12xx_for_each_wlvif_bss_type(wl, wlvif, BSS_TYPE_AP_BSS)
+
int wl1271_plt_start(struct wl1271 *wl);
int wl1271_plt_stop(struct wl1271 *wl);
int wl1271_recalc_rx_streaming(struct wl1271 *wl);
--
1.7.6.401.g6a319
^ permalink raw reply related [flat|nested] 51+ messages in thread* Re: [PATCH 09/29] wl12xx: make event handling support multirole
2011-10-10 8:12 ` [PATCH 09/29] wl12xx: make event handling support multirole Eliad Peller
@ 2011-10-10 18:58 ` Luciano Coelho
2011-10-10 19:36 ` Eliad Peller
0 siblings, 1 reply; 51+ messages in thread
From: Luciano Coelho @ 2011-10-10 18:58 UTC (permalink / raw)
To: Eliad Peller; +Cc: linux-wireless
On Mon, 2011-10-10 at 10:12 +0200, Eliad Peller wrote:
> Some events don't indicate the role they are intended for.
> In these cases, iterate through all the relevant vifs,
> and pass the event to each one of them.
>
> This is only a workaround. future fw releases should indicate
> the relevant role_id for such events.
>
> Signed-off-by: Eliad Peller <eliad@wizery.com>
> ---
Is this workaround really necessary? Are we going to have a firmware
that supports multi-role but does *not* pass the role_id for these
events?
--
Cheers,
Luca.
^ permalink raw reply [flat|nested] 51+ messages in thread
* Re: [PATCH 09/29] wl12xx: make event handling support multirole
2011-10-10 18:58 ` Luciano Coelho
@ 2011-10-10 19:36 ` Eliad Peller
2011-10-10 19:47 ` Luciano Coelho
0 siblings, 1 reply; 51+ messages in thread
From: Eliad Peller @ 2011-10-10 19:36 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
On Mon, Oct 10, 2011 at 8:58 PM, Luciano Coelho <coelho@ti.com> wrote:
> On Mon, 2011-10-10 at 10:12 +0200, Eliad Peller wrote:
>> Some events don't indicate the role they are intended for.
>> In these cases, iterate through all the relevant vifs,
>> and pass the event to each one of them.
>>
>> This is only a workaround. future fw releases should indicate
>> the relevant role_id for such events.
>>
>> Signed-off-by: Eliad Peller <eliad@wizery.com>
>> ---
>
> Is this workaround really necessary? Are we going to have a firmware
> that supports multi-role but does *not* pass the role_id for these
> events?
>
i hope not. :)
but in the meantime, we use this workaround to keep compatibility with
the current (single-role) fw.
Eliad.
^ permalink raw reply [flat|nested] 51+ messages in thread
* Re: [PATCH 09/29] wl12xx: make event handling support multirole
2011-10-10 19:36 ` Eliad Peller
@ 2011-10-10 19:47 ` Luciano Coelho
0 siblings, 0 replies; 51+ messages in thread
From: Luciano Coelho @ 2011-10-10 19:47 UTC (permalink / raw)
To: Eliad Peller; +Cc: linux-wireless
On Mon, 2011-10-10 at 21:36 +0200, Eliad Peller wrote:
> On Mon, Oct 10, 2011 at 8:58 PM, Luciano Coelho <coelho@ti.com> wrote:
> > On Mon, 2011-10-10 at 10:12 +0200, Eliad Peller wrote:
> >> Some events don't indicate the role they are intended for.
> >> In these cases, iterate through all the relevant vifs,
> >> and pass the event to each one of them.
> >>
> >> This is only a workaround. future fw releases should indicate
> >> the relevant role_id for such events.
> >>
> >> Signed-off-by: Eliad Peller <eliad@wizery.com>
> >> ---
> >
> > Is this workaround really necessary? Are we going to have a firmware
> > that supports multi-role but does *not* pass the role_id for these
> > events?
> >
> i hope not. :)
> but in the meantime, we use this workaround to keep compatibility with
> the current (single-role) fw.
What I meant is that you could keep this global, without moving it
temporarily to the wlvif and traversing the list, which has always only
a single element anyway. But now I see that you want to get rid of the
global wl->vif, so it's fine. It's only the list traversal that is
actually a workaround, the rest of the changes are actually fine.
--
Cheers,
Luca.
^ permalink raw reply [flat|nested] 51+ messages in thread
* [PATCH 10/29] wl12xx: move tx_security_seq into wlvif
2011-10-10 8:12 [PATCH 00/29] make the driver ready for multi-vif support Eliad Peller
` (8 preceding siblings ...)
2011-10-10 8:12 ` [PATCH 09/29] wl12xx: make event handling support multirole Eliad Peller
@ 2011-10-10 8:12 ` Eliad Peller
2011-10-10 19:25 ` Luciano Coelho
2011-10-10 8:12 ` [PATCH 11/29] wl12xx: rearm rx streaming per vif Eliad Peller
` (19 subsequent siblings)
29 siblings, 1 reply; 51+ messages in thread
From: Eliad Peller @ 2011-10-10 8:12 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
The last security seq num has to be saved across reconfigs.
Add a new "persistent" struct into wlvif, which won't get
deleted on wl12xx_init_vif_data()
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
drivers/net/wireless/wl12xx/debugfs.c | 1 -
drivers/net/wireless/wl12xx/main.c | 32 +++++++++++++++++---------------
drivers/net/wireless/wl12xx/tx.c | 12 +++++++++---
drivers/net/wireless/wl12xx/wl12xx.h | 30 +++++++++++++++++++-----------
4 files changed, 45 insertions(+), 30 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c
index bbc8004..669b081 100644
--- a/drivers/net/wireless/wl12xx/debugfs.c
+++ b/drivers/net/wireless/wl12xx/debugfs.c
@@ -346,7 +346,6 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf,
DRIVER_STATE_PRINT_INT(tx_results_count);
DRIVER_STATE_PRINT_LHEX(flags);
DRIVER_STATE_PRINT_INT(tx_blocks_freed);
- DRIVER_STATE_PRINT_INT(tx_security_last_seq_lsb);
DRIVER_STATE_PRINT_INT(rx_counter);
DRIVER_STATE_PRINT_INT(state);
DRIVER_STATE_PRINT_INT(channel);
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 0623f5d..055e70a 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -1206,6 +1206,7 @@ static void wl1271_recovery_work(struct work_struct *work)
{
struct wl1271 *wl =
container_of(work, struct wl1271, recovery_work);
+ struct wl12xx_vif *wlvif;
mutex_lock(&wl->mutex);
@@ -1227,9 +1228,12 @@ static void wl1271_recovery_work(struct work_struct *work)
* in the firmware during recovery. This doens't hurt if the network is
* not encrypted.
*/
- if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) ||
- test_bit(WL1271_FLAG_AP_STARTED, &wl->flags))
- wl->tx_security_seq += WL1271_TX_SQN_POST_RECOVERY_PADDING;
+ wl12xx_for_each_wlvif(wl, wlvif) {
+ if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) ||
+ test_bit(WL1271_FLAG_AP_STARTED, &wl->flags))
+ wlvif->tx_security_seq +=
+ WL1271_TX_SQN_POST_RECOVERY_PADDING;
+ }
/* Prevent spurious TX during FW restart */
ieee80211_stop_queues(wl->hw);
@@ -1910,8 +1914,8 @@ static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif)
{
struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
- /* make sure wlvif is zeroed */
- memset(wlvif, 0, sizeof(*wlvif));
+ /* clear everything but the persistent data */
+ memset(wlvif, 0, offsetof(struct wl12xx_vif, persistent));
switch (ieee80211_vif_type_p2p(vif)) {
case NL80211_IFTYPE_P2P_CLIENT:
@@ -2287,8 +2291,8 @@ static int wl1271_unjoin(struct wl1271 *wl, struct wl12xx_vif *wlvif)
goto out;
/* reset TX security counters on a clean disconnect */
- wl->tx_security_last_seq_lsb = 0;
- wl->tx_security_seq = 0;
+ wlvif->tx_security_last_seq_lsb = 0;
+ wlvif->tx_security_seq = 0;
out:
return ret;
@@ -2860,20 +2864,20 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
key_type = KEY_TKIP;
key_conf->hw_key_idx = key_conf->keyidx;
- tx_seq_32 = WL1271_TX_SECURITY_HI32(wl->tx_security_seq);
- tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq);
+ tx_seq_32 = WL1271_TX_SECURITY_HI32(wlvif->tx_security_seq);
+ tx_seq_16 = WL1271_TX_SECURITY_LO16(wlvif->tx_security_seq);
break;
case WLAN_CIPHER_SUITE_CCMP:
key_type = KEY_AES;
key_conf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
- tx_seq_32 = WL1271_TX_SECURITY_HI32(wl->tx_security_seq);
- tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq);
+ tx_seq_32 = WL1271_TX_SECURITY_HI32(wlvif->tx_security_seq);
+ tx_seq_16 = WL1271_TX_SECURITY_LO16(wlvif->tx_security_seq);
break;
case WL1271_CIPHER_SUITE_GEM:
key_type = KEY_GEM;
- tx_seq_32 = WL1271_TX_SECURITY_HI32(wl->tx_security_seq);
- tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq);
+ tx_seq_32 = WL1271_TX_SECURITY_HI32(wlvif->tx_security_seq);
+ tx_seq_16 = WL1271_TX_SECURITY_LO16(wlvif->tx_security_seq);
break;
default:
wl1271_error("Unknown key algo 0x%x", key_conf->cipher);
@@ -4913,8 +4917,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
wl->quirks = 0;
wl->platform_quirks = 0;
wl->sched_scanning = false;
- wl->tx_security_seq = 0;
- wl->tx_security_last_seq_lsb = 0;
wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT;
wl->system_hlid = WL12XX_SYSTEM_HLID;
wl->active_sta_count = 0;
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index c7be151..0a5fef5 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -755,6 +755,8 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
struct wl1271_tx_hw_res_descr *result)
{
struct ieee80211_tx_info *info;
+ struct ieee80211_vif *vif;
+ struct wl12xx_vif *wlvif;
struct sk_buff *skb;
int id = result->id;
int rate = -1;
@@ -774,6 +776,10 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
return;
}
+ /* info->control is valid as long as we don't update info->status */
+ vif = info->control.vif;
+ wlvif = wl12xx_vif_to_data(vif);
+
/* update the TX status info */
if (result->status == TX_SUCCESS) {
if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
@@ -801,14 +807,14 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
info->control.hw_key->cipher == WLAN_CIPHER_SUITE_CCMP ||
info->control.hw_key->cipher == WL1271_CIPHER_SUITE_GEM)) {
u8 fw_lsb = result->tx_security_sequence_number_lsb;
- u8 cur_lsb = wl->tx_security_last_seq_lsb;
+ u8 cur_lsb = wlvif->tx_security_last_seq_lsb;
/*
* update security sequence number, taking care of potential
* wrap-around
*/
- wl->tx_security_seq += (fw_lsb - cur_lsb + 256) % 256;
- wl->tx_security_last_seq_lsb = fw_lsb;
+ wlvif->tx_security_seq += (fw_lsb - cur_lsb + 256) % 256;
+ wlvif->tx_security_last_seq_lsb = fw_lsb;
}
/* remove private header from packet */
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index b13f13e..f12b394 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -435,17 +435,6 @@ struct wl1271 {
struct sk_buff *tx_frames[ACX_TX_DESCRIPTORS];
int tx_frames_cnt;
- /*
- * Security sequence number
- * bits 0-15: lower 16 bits part of sequence number
- * bits 16-47: higher 32 bits part of sequence number
- * bits 48-63: not in use
- */
- u64 tx_security_seq;
-
- /* 8 bits of the last sequence number in use */
- u8 tx_security_last_seq_lsb;
-
/* FW Rx counter */
u32 rx_counter;
@@ -643,6 +632,25 @@ struct wl12xx_vif {
/* RX BA constraint value */
bool ba_support;
bool ba_allowed;
+
+ /*
+ * This struct must be last!
+ * data that has to be saved acrossed reconfigs (e.g. recovery)
+ * should be declared in this struct.
+ */
+ struct {
+ u8 persistent[0];
+ /*
+ * Security sequence number
+ * bits 0-15: lower 16 bits part of sequence number
+ * bits 16-47: higher 32 bits part of sequence number
+ * bits 48-63: not in use
+ */
+ u64 tx_security_seq;
+
+ /* 8 bits of the last sequence number in use */
+ u8 tx_security_last_seq_lsb;
+ };
};
static inline struct wl12xx_vif *wl12xx_vif_to_data(struct ieee80211_vif *vif)
--
1.7.6.401.g6a319
^ permalink raw reply related [flat|nested] 51+ messages in thread* Re: [PATCH 10/29] wl12xx: move tx_security_seq into wlvif
2011-10-10 8:12 ` [PATCH 10/29] wl12xx: move tx_security_seq into wlvif Eliad Peller
@ 2011-10-10 19:25 ` Luciano Coelho
0 siblings, 0 replies; 51+ messages in thread
From: Luciano Coelho @ 2011-10-10 19:25 UTC (permalink / raw)
To: Eliad Peller; +Cc: linux-wireless
On Mon, 2011-10-10 at 10:12 +0200, Eliad Peller wrote:
> The last security seq num has to be saved across reconfigs.
> Add a new "persistent" struct into wlvif, which won't get
> deleted on wl12xx_init_vif_data()
>
> Signed-off-by: Eliad Peller <eliad@wizery.com>
> ---
> @@ -1910,8 +1914,8 @@ static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif)
> {
> struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
>
> - /* make sure wlvif is zeroed */
> - memset(wlvif, 0, sizeof(*wlvif));
> + /* clear everything but the persistent data */
> + memset(wlvif, 0, offsetof(struct wl12xx_vif, persistent));
Nice trick! :)
> diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
> index c7be151..0a5fef5 100644
> --- a/drivers/net/wireless/wl12xx/tx.c
> +++ b/drivers/net/wireless/wl12xx/tx.c
> @@ -755,6 +755,8 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
> struct wl1271_tx_hw_res_descr *result)
> {
> struct ieee80211_tx_info *info;
> + struct ieee80211_vif *vif;
> + struct wl12xx_vif *wlvif;
> struct sk_buff *skb;
> int id = result->id;
> int rate = -1;
> @@ -774,6 +776,10 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
> return;
> }
>
> + /* info->control is valid as long as we don't update info->status */
> + vif = info->control.vif;
> + wlvif = wl12xx_vif_to_data(vif);
>From a comment in the ieee80211_tx_info struct in mac80211.h:
/* NB: vif can be NULL for injected frames */
Should we check the vif here...
> /* update the TX status info */
> if (result->status == TX_SUCCESS) {
> if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
> @@ -801,14 +807,14 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
> info->control.hw_key->cipher == WLAN_CIPHER_SUITE_CCMP ||
> info->control.hw_key->cipher == WL1271_CIPHER_SUITE_GEM)) {
> u8 fw_lsb = result->tx_security_sequence_number_lsb;
> - u8 cur_lsb = wl->tx_security_last_seq_lsb;
> + u8 cur_lsb = wlvif->tx_security_last_seq_lsb;
...because we're accessing it directly here?
And don't we get TX complete events for dummy packets?
> /*
> * update security sequence number, taking care of potential
> * wrap-around
> */
> - wl->tx_security_seq += (fw_lsb - cur_lsb + 256) % 256;
> - wl->tx_security_last_seq_lsb = fw_lsb;
> + wlvif->tx_security_seq += (fw_lsb - cur_lsb + 256) % 256;
> + wlvif->tx_security_last_seq_lsb = fw_lsb;
We could change this (... + 256) % 256 here for & 0xFF as Ido suggested
for some other code earlier.
--
Cheers,
Luca.
^ permalink raw reply [flat|nested] 51+ messages in thread
* [PATCH 11/29] wl12xx: rearm rx streaming per vif
2011-10-10 8:12 [PATCH 00/29] make the driver ready for multi-vif support Eliad Peller
` (9 preceding siblings ...)
2011-10-10 8:12 ` [PATCH 10/29] wl12xx: move tx_security_seq into wlvif Eliad Peller
@ 2011-10-10 8:12 ` Eliad Peller
2011-10-10 8:13 ` [PATCH 12/29] wl12xx: make WL1271_FLAG_STA_ASSOCIATED flag per-vif Eliad Peller
` (18 subsequent siblings)
29 siblings, 0 replies; 51+ messages in thread
From: Eliad Peller @ 2011-10-10 8:12 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
Currently, the rx streaming doesn't support multi-vif
(the actual wlvif is taken from wl->vif, and the management
is global).
Make the rx streaming timers/works per-vif, and pass the
the actual vif as param.
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
drivers/net/wireless/wl12xx/acx.c | 5 +-
drivers/net/wireless/wl12xx/acx.h | 3 +-
drivers/net/wireless/wl12xx/debugfs.c | 10 ++++-
drivers/net/wireless/wl12xx/event.c | 4 +-
drivers/net/wireless/wl12xx/main.c | 53 ++++++++++++++------------
drivers/net/wireless/wl12xx/rx.c | 35 ++++++-----------
drivers/net/wireless/wl12xx/tx.c | 67 ++++++++++++++++++++++----------
drivers/net/wireless/wl12xx/tx.h | 1 +
drivers/net/wireless/wl12xx/wl12xx.h | 12 +++---
9 files changed, 109 insertions(+), 81 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c
index 5b70cc1..21e74ca 100644
--- a/drivers/net/wireless/wl12xx/acx.c
+++ b/drivers/net/wireless/wl12xx/acx.c
@@ -1510,10 +1510,9 @@ out:
return ret;
}
-int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, bool enable)
+int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif,
+ bool enable)
{
- struct ieee80211_vif *vif = wl->vif; /* TODO: get as param */
- struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
struct wl1271_acx_ps_rx_streaming *rx_streaming;
u32 conf_queues, enable_queues;
int i, ret = 0;
diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h
index 7fccfcc..c06119b 100644
--- a/drivers/net/wireless/wl12xx/acx.h
+++ b/drivers/net/wireless/wl12xx/acx.h
@@ -1310,7 +1310,8 @@ int wl12xx_acx_set_ba_initiator_policy(struct wl1271 *wl,
int wl12xx_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index,
u16 ssn, bool enable, u8 peer_hlid);
int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime);
-int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, bool enable);
+int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif,
+ bool enable);
int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl, struct wl12xx_vif *wlvif);
int wl12xx_acx_config_ps(struct wl1271 *wl, struct wl12xx_vif *wlvif);
int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr);
diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c
index 669b081..4abff82 100644
--- a/drivers/net/wireless/wl12xx/debugfs.c
+++ b/drivers/net/wireless/wl12xx/debugfs.c
@@ -505,6 +505,7 @@ static ssize_t rx_streaming_interval_write(struct file *file,
size_t count, loff_t *ppos)
{
struct wl1271 *wl = file->private_data;
+ struct wl12xx_vif *wlvif;
unsigned long value;
int ret;
@@ -528,7 +529,9 @@ static ssize_t rx_streaming_interval_write(struct file *file,
if (ret < 0)
goto out;
- wl1271_recalc_rx_streaming(wl);
+ wl12xx_for_each_wlvif_sta(wl, wlvif) {
+ wl1271_recalc_rx_streaming(wl, wlvif);
+ }
wl1271_ps_elp_sleep(wl);
out:
@@ -557,6 +560,7 @@ static ssize_t rx_streaming_always_write(struct file *file,
size_t count, loff_t *ppos)
{
struct wl1271 *wl = file->private_data;
+ struct wl12xx_vif *wlvif;
unsigned long value;
int ret;
@@ -580,7 +584,9 @@ static ssize_t rx_streaming_always_write(struct file *file,
if (ret < 0)
goto out;
- wl1271_recalc_rx_streaming(wl);
+ wl12xx_for_each_wlvif_sta(wl, wlvif) {
+ wl1271_recalc_rx_streaming(wl, wlvif);
+ }
wl1271_ps_elp_sleep(wl);
out:
diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c
index dbc40bb..be9e112 100644
--- a/drivers/net/wireless/wl12xx/event.c
+++ b/drivers/net/wireless/wl12xx/event.c
@@ -220,12 +220,12 @@ static void wl12xx_event_soft_gemini_sense(struct wl1271 *wl,
}
set_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags);
} else {
+ clear_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags);
wl12xx_for_each_wlvif_sta(wl, wlvif) {
vif = wl12xx_wlvif_to_vif(wlvif);
ieee80211_enable_dyn_ps(vif);
+ wl1271_recalc_rx_streaming(wl, wlvif);
}
- clear_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags);
- wl1271_recalc_rx_streaming(wl);
}
}
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 055e70a..e242c50 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -502,12 +502,13 @@ static int wl1271_reg_notify(struct wiphy *wiphy,
return 0;
}
-static int wl1271_set_rx_streaming(struct wl1271 *wl, bool enable)
+static int wl1271_set_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif,
+ bool enable)
{
int ret = 0;
/* we should hold wl->mutex */
- ret = wl1271_acx_ps_rx_streaming(wl, enable);
+ ret = wl1271_acx_ps_rx_streaming(wl, wlvif, enable);
if (ret < 0)
goto out;
@@ -523,7 +524,7 @@ out:
* this function is being called when the rx_streaming interval
* has beed changed or rx_streaming should be disabled
*/
-int wl1271_recalc_rx_streaming(struct wl1271 *wl)
+int wl1271_recalc_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif)
{
int ret = 0;
int period = wl->conf.rx_streaming.interval;
@@ -537,11 +538,11 @@ int wl1271_recalc_rx_streaming(struct wl1271 *wl)
test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) &&
(wl->conf.rx_streaming.always ||
test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags)))
- ret = wl1271_set_rx_streaming(wl, true);
+ ret = wl1271_set_rx_streaming(wl, wlvif, true);
else {
- ret = wl1271_set_rx_streaming(wl, false);
+ ret = wl1271_set_rx_streaming(wl, wlvif, false);
/* don't cancel_work_sync since we might deadlock */
- del_timer_sync(&wl->rx_streaming_timer);
+ del_timer_sync(&wlvif->rx_streaming_timer);
}
out:
return ret;
@@ -550,8 +551,9 @@ out:
static void wl1271_rx_streaming_enable_work(struct work_struct *work)
{
int ret;
- struct wl1271 *wl =
- container_of(work, struct wl1271, rx_streaming_enable_work);
+ struct wl12xx_vif *wlvif = container_of(work, struct wl12xx_vif,
+ rx_streaming_enable_work);
+ struct wl1271 *wl = wlvif->wl;
mutex_lock(&wl->mutex);
@@ -568,12 +570,12 @@ static void wl1271_rx_streaming_enable_work(struct work_struct *work)
if (ret < 0)
goto out;
- ret = wl1271_set_rx_streaming(wl, true);
+ ret = wl1271_set_rx_streaming(wl, wlvif, true);
if (ret < 0)
goto out_sleep;
/* stop it after some time of inactivity */
- mod_timer(&wl->rx_streaming_timer,
+ mod_timer(&wlvif->rx_streaming_timer,
jiffies + msecs_to_jiffies(wl->conf.rx_streaming.duration));
out_sleep:
@@ -585,8 +587,9 @@ out:
static void wl1271_rx_streaming_disable_work(struct work_struct *work)
{
int ret;
- struct wl1271 *wl =
- container_of(work, struct wl1271, rx_streaming_disable_work);
+ struct wl12xx_vif *wlvif = container_of(work, struct wl12xx_vif,
+ rx_streaming_disable_work);
+ struct wl1271 *wl = wlvif->wl;
mutex_lock(&wl->mutex);
@@ -597,7 +600,7 @@ static void wl1271_rx_streaming_disable_work(struct work_struct *work)
if (ret < 0)
goto out;
- ret = wl1271_set_rx_streaming(wl, false);
+ ret = wl1271_set_rx_streaming(wl, wlvif, false);
if (ret)
goto out_sleep;
@@ -609,8 +612,9 @@ out:
static void wl1271_rx_streaming_timer(unsigned long data)
{
- struct wl1271 *wl = (struct wl1271 *)data;
- ieee80211_queue_work(wl->hw, &wl->rx_streaming_disable_work);
+ struct wl12xx_vif *wlvif = (struct wl12xx_vif *)data;
+ struct wl1271 *wl = wlvif->wl;
+ ieee80211_queue_work(wl->hw, &wlvif->rx_streaming_disable_work);
}
static void wl1271_conf_init(struct wl1271 *wl)
@@ -1827,9 +1831,6 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
cancel_delayed_work_sync(&wl->scan_complete_work);
cancel_work_sync(&wl->netstack_work);
cancel_work_sync(&wl->tx_work);
- del_timer_sync(&wl->rx_streaming_timer);
- cancel_work_sync(&wl->rx_streaming_enable_work);
- cancel_work_sync(&wl->rx_streaming_disable_work);
cancel_delayed_work_sync(&wl->elp_work);
/* let's notify MAC80211 about the remaining pending TX frames */
@@ -1960,9 +1961,16 @@ 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;
+ INIT_WORK(&wlvif->rx_streaming_enable_work,
+ wl1271_rx_streaming_enable_work);
+ INIT_WORK(&wlvif->rx_streaming_disable_work,
+ wl1271_rx_streaming_disable_work);
INIT_DELAYED_WORK(&wlvif->pspoll_work, wl1271_pspoll_work);
INIT_LIST_HEAD(&wlvif->list);
+ setup_timer(&wlvif->rx_streaming_timer, wl1271_rx_streaming_timer,
+ (unsigned long) wlvif);
+
return 0;
}
@@ -2193,6 +2201,9 @@ deinit:
wlvif->dev_role_id = WL12XX_INVALID_ROLE_ID;
mutex_unlock(&wl->mutex);
+ del_timer_sync(&wlvif->rx_streaming_timer);
+ cancel_work_sync(&wlvif->rx_streaming_enable_work);
+ cancel_work_sync(&wlvif->rx_streaming_disable_work);
cancel_delayed_work_sync(&wlvif->pspoll_work);
mutex_lock(&wl->mutex);
@@ -4893,10 +4904,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
INIT_WORK(&wl->tx_work, wl1271_tx_work);
INIT_WORK(&wl->recovery_work, wl1271_recovery_work);
INIT_DELAYED_WORK(&wl->scan_complete_work, wl1271_scan_complete_work);
- INIT_WORK(&wl->rx_streaming_enable_work,
- wl1271_rx_streaming_enable_work);
- INIT_WORK(&wl->rx_streaming_disable_work,
- wl1271_rx_streaming_disable_work);
wl->freezable_wq = create_freezable_workqueue("wl12xx_wq");
if (!wl->freezable_wq) {
@@ -4920,8 +4927,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT;
wl->system_hlid = WL12XX_SYSTEM_HLID;
wl->active_sta_count = 0;
- setup_timer(&wl->rx_streaming_timer, wl1271_rx_streaming_timer,
- (unsigned long) wl);
wl->fwlog_size = 0;
init_waitqueue_head(&wl->fwlog_waitq);
diff --git a/drivers/net/wireless/wl12xx/rx.c b/drivers/net/wireless/wl12xx/rx.c
index 9cfa0b2..dd2f8b7 100644
--- a/drivers/net/wireless/wl12xx/rx.c
+++ b/drivers/net/wireless/wl12xx/rx.c
@@ -28,6 +28,7 @@
#include "acx.h"
#include "reg.h"
#include "rx.h"
+#include "tx.h"
#include "io.h"
static u8 wl12xx_rx_get_mem_block(struct wl12xx_fw_status *status,
@@ -96,7 +97,7 @@ static void wl1271_rx_status(struct wl1271 *wl,
}
static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
- bool unaligned)
+ bool unaligned, u8 *hlid)
{
struct wl1271_rx_descriptor *desc;
struct sk_buff *skb;
@@ -159,6 +160,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
* payload aligned to 4 bytes.
*/
memcpy(buf, data + sizeof(*desc), length - sizeof(*desc));
+ *hlid = desc->hlid;
hdr = (struct ieee80211_hdr *)skb->data;
if (ieee80211_is_beacon(hdr->frame_control))
@@ -169,10 +171,10 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
wl1271_rx_status(wl, desc, IEEE80211_SKB_RXCB(skb), beacon);
seq_num = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4;
- wl1271_debug(DEBUG_RX, "rx skb 0x%p: %d B %s seq %d", skb,
+ wl1271_debug(DEBUG_RX, "rx skb 0x%p: %d B %s seq %d hlid %d", skb,
skb->len - desc->pad_len,
beacon ? "beacon" : "",
- seq_num);
+ seq_num, *hlid);
skb_trim(skb, skb->len - desc->pad_len);
@@ -185,8 +187,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status)
{
struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map;
- struct ieee80211_vif *vif = wl->vif; /* TODO: get as param */
- struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
+ unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0};
u32 buf_size;
u32 fw_rx_counter = status->fw_rx_counter & NUM_RX_PKT_DESC_MOD_MASK;
u32 drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK;
@@ -194,8 +195,7 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status)
u32 mem_block;
u32 pkt_length;
u32 pkt_offset;
- bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS);
- bool had_data = false;
+ u8 hlid;
bool unaligned = false;
while (drv_rx_counter != fw_rx_counter) {
@@ -255,8 +255,11 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status)
*/
if (wl1271_rx_handle_data(wl,
wl->aggr_buf + pkt_offset,
- pkt_length, unaligned) == 1)
- had_data = true;
+ pkt_length, unaligned,
+ &hlid) == 1) {
+ WARN_ON(hlid >= WL12XX_MAX_LINKS);
+ __set_bit(hlid, active_hlids);
+ }
wl->rx_counter++;
drv_rx_counter++;
@@ -272,17 +275,5 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status)
if (wl->quirks & WL12XX_QUIRK_END_OF_TRANSACTION)
wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter);
- if (!is_ap && wl->conf.rx_streaming.interval && had_data &&
- (wl->conf.rx_streaming.always ||
- test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags))) {
- u32 timeout = wl->conf.rx_streaming.duration;
-
- /* restart rx streaming */
- if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags))
- ieee80211_queue_work(wl->hw,
- &wl->rx_streaming_enable_work);
-
- mod_timer(&wl->rx_streaming_timer,
- jiffies + msecs_to_jiffies(timeout));
- }
+ wl12xx_rearm_rx_streaming(wl, active_hlids);
}
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index 0a5fef5..91689d0 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -643,21 +643,58 @@ static bool wl1271_tx_is_data_present(struct sk_buff *skb)
return ieee80211_is_data_present(hdr->frame_control);
}
+void wl12xx_rearm_rx_streaming(struct wl1271 *wl, unsigned long *active_hlids)
+{
+ struct wl12xx_vif *wlvif;
+ u32 timeout;
+ u8 hlid;
+
+ if (!wl->conf.rx_streaming.interval)
+ return;
+
+ if (!wl->conf.rx_streaming.always &&
+ !test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags))
+ return;
+
+ timeout = wl->conf.rx_streaming.duration;
+ wl12xx_for_each_wlvif_sta(wl, wlvif) {
+ bool found = false;
+ for_each_set_bit(hlid, active_hlids, WL12XX_MAX_LINKS) {
+ if (test_bit(hlid, wlvif->links_map)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ continue;
+
+ /* enable rx streaming */
+ if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags))
+ ieee80211_queue_work(wl->hw,
+ &wlvif->rx_streaming_enable_work);
+
+ mod_timer(&wlvif->rx_streaming_timer,
+ jiffies + msecs_to_jiffies(timeout));
+ }
+}
+
void wl1271_tx_work_locked(struct wl1271 *wl)
{
struct wl12xx_vif *wlvif;
struct sk_buff *skb;
+ struct wl1271_tx_hw_descr *desc;
u32 buf_offset = 0;
bool sent_packets = false;
- bool had_data = false;
- /* TODO: save bitmap of relevant stations */
- bool is_sta = false;
+ unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0};
int ret;
if (unlikely(wl->state == WL1271_STATE_OFF))
return;
while ((skb = wl1271_skb_dequeue(wl))) {
+ bool has_data = false;
+
wlvif = NULL;
if (!wl12xx_is_dummy_packet(wl, skb)) {
struct ieee80211_tx_info *info;
@@ -667,9 +704,7 @@ void wl1271_tx_work_locked(struct wl1271 *wl)
vif = info->control.vif;
wlvif = wl12xx_vif_to_data(vif);
}
-
- if (wl1271_tx_is_data_present(skb))
- had_data = true;
+ has_data = wlvif && wl1271_tx_is_data_present(skb);
ret = wl1271_prepare_tx_frame(wl, wlvif, skb, buf_offset);
if (ret == -EAGAIN) {
@@ -698,8 +733,10 @@ void wl1271_tx_work_locked(struct wl1271 *wl)
}
buf_offset += ret;
wl->tx_packets_count++;
- if (wlvif && wlvif->bss_type == BSS_TYPE_STA_BSS)
- is_sta = true;
+ if (has_data) {
+ desc = (struct wl1271_tx_hw_descr *) skb->data;
+ __set_bit(desc->hlid, active_hlids);
+ }
}
out_ack:
@@ -719,19 +756,7 @@ out_ack:
wl1271_handle_tx_low_watermark(wl);
}
- if (is_sta && wl->conf.rx_streaming.interval && had_data &&
- (wl->conf.rx_streaming.always ||
- test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags))) {
- u32 timeout = wl->conf.rx_streaming.duration;
-
- /* enable rx streaming */
- if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags))
- ieee80211_queue_work(wl->hw,
- &wl->rx_streaming_enable_work);
-
- mod_timer(&wl->rx_streaming_timer,
- jiffies + msecs_to_jiffies(timeout));
- }
+ wl12xx_rearm_rx_streaming(wl, active_hlids);
}
void wl1271_tx_work(struct work_struct *work)
diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/tx.h
index fe29ff5..2dbb24e 100644
--- a/drivers/net/wireless/wl12xx/tx.h
+++ b/drivers/net/wireless/wl12xx/tx.h
@@ -220,6 +220,7 @@ u8 wl12xx_tx_get_hlid(struct wl1271 *wl, struct wl12xx_vif *wlvif,
void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid);
void wl1271_handle_tx_low_watermark(struct wl1271 *wl);
bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb);
+void wl12xx_rearm_rx_streaming(struct wl1271 *wl, unsigned long *active_hlids);
/* from main.c */
void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid);
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index f12b394..9e44430 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -478,11 +478,6 @@ struct wl1271 {
/* The current band */
enum ieee80211_band band;
- /* Rx Streaming */
- struct work_struct rx_streaming_enable_work;
- struct work_struct rx_streaming_disable_work;
- struct timer_list rx_streaming_timer;
-
struct completion *elp_compl;
struct delayed_work elp_work;
@@ -633,6 +628,11 @@ struct wl12xx_vif {
bool ba_support;
bool ba_allowed;
+ /* Rx Streaming */
+ struct work_struct rx_streaming_enable_work;
+ struct work_struct rx_streaming_disable_work;
+ struct timer_list rx_streaming_timer;
+
/*
* This struct must be last!
* data that has to be saved acrossed reconfigs (e.g. recovery)
@@ -679,7 +679,7 @@ struct ieee80211_vif *wl12xx_wlvif_to_vif(struct wl12xx_vif *wlvif)
int wl1271_plt_start(struct wl1271 *wl);
int wl1271_plt_stop(struct wl1271 *wl);
-int wl1271_recalc_rx_streaming(struct wl1271 *wl);
+int wl1271_recalc_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif);
void wl12xx_queue_recovery_work(struct wl1271 *wl);
size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen);
--
1.7.6.401.g6a319
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 12/29] wl12xx: make WL1271_FLAG_STA_ASSOCIATED flag per-vif
2011-10-10 8:12 [PATCH 00/29] make the driver ready for multi-vif support Eliad Peller
` (10 preceding siblings ...)
2011-10-10 8:12 ` [PATCH 11/29] wl12xx: rearm rx streaming per vif Eliad Peller
@ 2011-10-10 8:13 ` Eliad Peller
2011-10-10 8:13 ` [PATCH 13/29] wl12xx: make WL1271_FLAG_IBSS_JOINED " Eliad Peller
` (17 subsequent siblings)
29 siblings, 0 replies; 51+ messages in thread
From: Eliad Peller @ 2011-10-10 8:13 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
This flag should be set per-vif, rather than globally.
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
drivers/net/wireless/wl12xx/event.c | 2 +-
drivers/net/wireless/wl12xx/main.c | 52 +++++++++++++++++----------------
drivers/net/wireless/wl12xx/scan.c | 4 +-
drivers/net/wireless/wl12xx/tx.c | 2 +-
drivers/net/wireless/wl12xx/wl12xx.h | 6 +++-
5 files changed, 36 insertions(+), 30 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c
index be9e112..cfb2835 100644
--- a/drivers/net/wireless/wl12xx/event.c
+++ b/drivers/net/wireless/wl12xx/event.c
@@ -52,7 +52,7 @@ void wl1271_pspoll_work(struct work_struct *work)
if (!test_and_clear_bit(WL1271_FLAG_PSPOLL_FAILURE, &wl->flags))
goto out;
- if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
+ if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
goto out;
/*
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index e242c50..6e67cbf 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -400,10 +400,9 @@ static struct platform_device wl1271_device = {
static DEFINE_MUTEX(wl_list_mutex);
static LIST_HEAD(wl_list);
-static int wl1271_check_operstate(struct wl1271 *wl, unsigned char operstate)
+static int wl1271_check_operstate(struct wl1271 *wl, struct wl12xx_vif *wlvif,
+ unsigned char operstate)
{
- struct ieee80211_vif *vif = wl->vif; /* TODO: get as param */
- struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
int ret;
if (operstate != IF_OPER_UP)
@@ -430,6 +429,7 @@ static int wl1271_dev_notify(struct notifier_block *me, unsigned long what,
struct ieee80211_hw *hw;
struct wl1271 *wl;
struct wl1271 *wl_temp;
+ struct wl12xx_vif *wlvif;
int ret = 0;
/* Check that this notification is for us. */
@@ -463,17 +463,18 @@ static int wl1271_dev_notify(struct notifier_block *me, unsigned long what,
if (wl->state == WL1271_STATE_OFF)
goto out;
- if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
- goto out;
-
- ret = wl1271_ps_elp_wakeup(wl);
- if (ret < 0)
- goto out;
+ wl12xx_for_each_wlvif_sta(wl, wlvif) {
+ if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
+ continue;
- wl1271_check_operstate(wl, dev->operstate);
+ ret = wl1271_ps_elp_wakeup(wl);
+ if (ret < 0)
+ goto out;
- wl1271_ps_elp_sleep(wl);
+ wl1271_check_operstate(wl, wlvif, dev->operstate);
+ wl1271_ps_elp_sleep(wl);
+ }
out:
mutex_unlock(&wl->mutex);
@@ -535,7 +536,7 @@ int wl1271_recalc_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif)
/* reconfigure/disable according to new streaming_period */
if (period &&
- test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) &&
+ test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags) &&
(wl->conf.rx_streaming.always ||
test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags)))
ret = wl1271_set_rx_streaming(wl, wlvif, true);
@@ -558,7 +559,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) ||
- !test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) ||
+ !test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags) ||
(!wl->conf.rx_streaming.always &&
!test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags)))
goto out;
@@ -1233,7 +1234,7 @@ static void wl1271_recovery_work(struct work_struct *work)
* not encrypted.
*/
wl12xx_for_each_wlvif(wl, wlvif) {
- if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) ||
+ if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags) ||
test_bit(WL1271_FLAG_AP_STARTED, &wl->flags))
wlvif->tx_security_seq +=
WL1271_TX_SQN_POST_RECOVERY_PADDING;
@@ -1609,7 +1610,7 @@ static int wl1271_configure_suspend_sta(struct wl1271 *wl,
mutex_lock(&wl->mutex);
- if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
+ if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
goto out_unlock;
ret = wl1271_ps_elp_wakeup(wl);
@@ -2243,11 +2244,11 @@ static int wl1271_join(struct wl1271 *wl, struct wl12xx_vif *wlvif,
* Keep the below message for now, unless it starts bothering
* users who really like to roam a lot :)
*/
- if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
+ if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
wl1271_info("JOIN while associated.");
if (set_assoc)
- set_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags);
+ set_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags);
if (is_ibss)
ret = wl12xx_cmd_role_start_ibss(wl, wlvif);
@@ -2256,7 +2257,7 @@ static int wl1271_join(struct wl1271 *wl, struct wl12xx_vif *wlvif,
if (ret < 0)
goto out;
- if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
+ if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
goto out;
/*
@@ -2439,7 +2440,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
* possible rate for the band as a fixed rate for
* association frames and other control messages.
*/
- if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
+ if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
wl1271_set_band_rate(wl, wlvif);
wlvif->basic_rate =
@@ -2450,7 +2451,8 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
wl1271_warning("rate policy for channel "
"failed %d", ret);
- if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) {
+ if (test_bit(WLVIF_FLAG_STA_ASSOCIATED,
+ &wlvif->flags)) {
if (wl12xx_is_roc(wl)) {
/* roaming */
ret = wl12xx_croc(wl,
@@ -2508,7 +2510,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
* If we're not, we'll enter it when joining an SSID,
* through the bss_info_changed() hook.
*/
- if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) {
+ if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) {
wl1271_debug(DEBUG_PSM, "psm enabled");
ret = wl1271_ps_set_mode(wl, wlvif,
STATION_POWER_SAVE_MODE,
@@ -2971,7 +2973,7 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw,
/* cancel ROC before scanning */
if (wl12xx_is_roc(wl)) {
- if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) {
+ if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) {
/* don't allow scanning right now */
ret = -EBUSY;
goto out_sleep;
@@ -3609,8 +3611,8 @@ sta_not_found:
} else {
/* use defaults when not associated */
bool was_assoc =
- !!test_and_clear_bit(WL1271_FLAG_STA_ASSOCIATED,
- &wl->flags);
+ !!test_and_clear_bit(WLVIF_FLAG_STA_ASSOCIATED,
+ &wlvif->flags);
bool was_ifup =
!!test_and_clear_bit(WL1271_FLAG_STA_STATE_SENT,
&wl->flags);
@@ -3739,7 +3741,7 @@ sta_not_found:
if (ret < 0)
goto out;
- wl1271_check_operstate(wl,
+ wl1271_check_operstate(wl, wlvif,
ieee80211_get_operstate(vif));
}
/*
diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c
index e1a8ce0..687f59b 100644
--- a/drivers/net/wireless/wl12xx/scan.c
+++ b/drivers/net/wireless/wl12xx/scan.c
@@ -64,7 +64,7 @@ void wl1271_scan_complete_work(struct work_struct *work)
if (ret < 0)
goto out;
- if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) {
+ if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) {
/* restore hardware connection monitoring template */
wl1271_cmd_build_ap_probe_req(wl, wlvif, wlvif->probereq);
}
@@ -72,7 +72,7 @@ void wl1271_scan_complete_work(struct work_struct *work)
/* return to ROC if needed */
is_sta = (wlvif->bss_type == BSS_TYPE_STA_BSS);
is_ibss = (wlvif->bss_type == BSS_TYPE_IBSS);
- if (((is_sta && !test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) ||
+ if (((is_sta && !test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) ||
(is_ibss && !test_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags))) &&
!test_bit(wlvif->dev_role_id, wl->roc_map)) {
/* restore remain on channel */
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index 91689d0..f37444c 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -192,7 +192,7 @@ u8 wl12xx_tx_get_hlid(struct wl1271 *wl, struct wl12xx_vif *wlvif,
wl1271_tx_update_filters(wl, wlvif, skb);
- if ((test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) ||
+ if ((test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags) ||
test_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags)) &&
!ieee80211_is_auth(hdr->frame_control) &&
!ieee80211_is_assoc_req(hdr->frame_control))
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index 9e44430..400dd17 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -313,7 +313,6 @@ struct wl1271_ap_key {
};
enum wl12xx_flags {
- WL1271_FLAG_STA_ASSOCIATED,
WL1271_FLAG_IBSS_JOINED,
WL1271_FLAG_GPIO_POWER,
WL1271_FLAG_TX_QUEUE_STOPPED,
@@ -338,6 +337,10 @@ enum wl12xx_flags {
WL1271_FLAG_CS_PROGRESS,
};
+enum wl12xx_vif_flags {
+ WLVIF_FLAG_STA_ASSOCIATED,
+};
+
struct wl1271_link {
/* AP-mode - TX queue per AC in link */
struct sk_buff_head tx_queue[NUM_TX_QUEUES];
@@ -551,6 +554,7 @@ struct wl1271_station {
struct wl12xx_vif {
struct wl1271 *wl;
struct list_head list;
+ unsigned long flags;
u8 bss_type;
u8 p2p; /* we are using p2p role */
u8 role_id;
--
1.7.6.401.g6a319
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 13/29] wl12xx: make WL1271_FLAG_IBSS_JOINED flag per-vif
2011-10-10 8:12 [PATCH 00/29] make the driver ready for multi-vif support Eliad Peller
` (11 preceding siblings ...)
2011-10-10 8:13 ` [PATCH 12/29] wl12xx: make WL1271_FLAG_STA_ASSOCIATED flag per-vif Eliad Peller
@ 2011-10-10 8:13 ` Eliad Peller
2011-10-10 8:13 ` [PATCH 14/29] wl12xx: make WL1271_FLAG_AP_STARTED " Eliad Peller
` (16 subsequent siblings)
29 siblings, 0 replies; 51+ messages in thread
From: Eliad Peller @ 2011-10-10 8:13 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
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/scan.c | 2 +-
drivers/net/wireless/wl12xx/tx.c | 2 +-
drivers/net/wireless/wl12xx/wl12xx.h | 2 +-
4 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 6e67cbf..092b3b5 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -3484,11 +3484,11 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
if (changed & BSS_CHANGED_IBSS) {
if (bss_conf->ibss_joined) {
- set_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags);
+ set_bit(WLVIF_FLAG_IBSS_JOINED, &wlvif->flags);
ibss_joined = true;
} else {
- if (test_and_clear_bit(WL1271_FLAG_IBSS_JOINED,
- &wl->flags)) {
+ if (test_and_clear_bit(WLVIF_FLAG_IBSS_JOINED,
+ &wlvif->flags)) {
wl1271_unjoin(wl, wlvif);
wl12xx_cmd_role_start_dev(wl, wlvif);
wl12xx_roc(wl, wlvif->dev_role_id);
diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c
index 687f59b..765f08b 100644
--- a/drivers/net/wireless/wl12xx/scan.c
+++ b/drivers/net/wireless/wl12xx/scan.c
@@ -73,7 +73,7 @@ void wl1271_scan_complete_work(struct work_struct *work)
is_sta = (wlvif->bss_type == BSS_TYPE_STA_BSS);
is_ibss = (wlvif->bss_type == BSS_TYPE_IBSS);
if (((is_sta && !test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) ||
- (is_ibss && !test_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags))) &&
+ (is_ibss && !test_bit(WLVIF_FLAG_IBSS_JOINED, &wlvif->flags))) &&
!test_bit(wlvif->dev_role_id, wl->roc_map)) {
/* restore remain on channel */
wl12xx_cmd_role_start_dev(wl, wlvif);
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index f37444c..5ad4173 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -193,7 +193,7 @@ u8 wl12xx_tx_get_hlid(struct wl1271 *wl, struct wl12xx_vif *wlvif,
wl1271_tx_update_filters(wl, wlvif, skb);
if ((test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags) ||
- test_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags)) &&
+ test_bit(WLVIF_FLAG_IBSS_JOINED, &wlvif->flags)) &&
!ieee80211_is_auth(hdr->frame_control) &&
!ieee80211_is_assoc_req(hdr->frame_control))
return wlvif->sta.hlid;
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index 400dd17..aa198a6 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -313,7 +313,6 @@ struct wl1271_ap_key {
};
enum wl12xx_flags {
- WL1271_FLAG_IBSS_JOINED,
WL1271_FLAG_GPIO_POWER,
WL1271_FLAG_TX_QUEUE_STOPPED,
WL1271_FLAG_TX_PENDING,
@@ -339,6 +338,7 @@ enum wl12xx_flags {
enum wl12xx_vif_flags {
WLVIF_FLAG_STA_ASSOCIATED,
+ WLVIF_FLAG_IBSS_JOINED,
};
struct wl1271_link {
--
1.7.6.401.g6a319
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 14/29] wl12xx: make WL1271_FLAG_AP_STARTED flag per-vif
2011-10-10 8:12 [PATCH 00/29] make the driver ready for multi-vif support Eliad Peller
` (12 preceding siblings ...)
2011-10-10 8:13 ` [PATCH 13/29] wl12xx: make WL1271_FLAG_IBSS_JOINED " Eliad Peller
@ 2011-10-10 8:13 ` Eliad Peller
2011-10-10 8:13 ` [PATCH 15/29] wl12xx: make WL1271_FLAG_PSM " Eliad Peller
` (15 subsequent siblings)
29 siblings, 0 replies; 51+ messages in thread
From: Eliad Peller @ 2011-10-10 8:13 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
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 [flat|nested] 51+ messages in thread* [PATCH 15/29] wl12xx: make WL1271_FLAG_PSM flag per-vif
2011-10-10 8:12 [PATCH 00/29] make the driver ready for multi-vif support Eliad Peller
` (13 preceding siblings ...)
2011-10-10 8:13 ` [PATCH 14/29] wl12xx: make WL1271_FLAG_AP_STARTED " Eliad Peller
@ 2011-10-10 8:13 ` Eliad Peller
2011-10-10 8:13 ` [PATCH 16/29] wl12xx: make WL1271_FLAG_STA_STATE_SENT " Eliad Peller
` (14 subsequent siblings)
29 siblings, 0 replies; 51+ messages in thread
From: Eliad Peller @ 2011-10-10 8:13 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
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 [flat|nested] 51+ messages in thread* [PATCH 16/29] wl12xx: make WL1271_FLAG_STA_STATE_SENT flag per-vif
2011-10-10 8:12 [PATCH 00/29] make the driver ready for multi-vif support Eliad Peller
` (14 preceding siblings ...)
2011-10-10 8:13 ` [PATCH 15/29] wl12xx: make WL1271_FLAG_PSM " Eliad Peller
@ 2011-10-10 8:13 ` Eliad Peller
2011-10-10 8:13 ` [PATCH 17/29] wl12xx: make WL1271_FLAG_RX_STREAMING_STARTED " Eliad Peller
` (13 subsequent siblings)
29 siblings, 0 replies; 51+ messages in thread
From: Eliad Peller @ 2011-10-10 8:13 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
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 [flat|nested] 51+ messages in thread* [PATCH 17/29] wl12xx: make WL1271_FLAG_RX_STREAMING_STARTED flag per-vif
2011-10-10 8:12 [PATCH 00/29] make the driver ready for multi-vif support Eliad Peller
` (15 preceding siblings ...)
2011-10-10 8:13 ` [PATCH 16/29] wl12xx: make WL1271_FLAG_STA_STATE_SENT " Eliad Peller
@ 2011-10-10 8:13 ` Eliad Peller
2011-10-10 8:13 ` [PATCH 18/29] wl12xx: make WL1271_FLAG_IF_INITIALIZED per-vif Eliad Peller
` (12 subsequent siblings)
29 siblings, 0 replies; 51+ messages in thread
From: Eliad Peller @ 2011-10-10 8:13 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
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 [flat|nested] 51+ messages in thread* [PATCH 18/29] wl12xx: make WL1271_FLAG_IF_INITIALIZED per-vif
2011-10-10 8:12 [PATCH 00/29] make the driver ready for multi-vif support Eliad Peller
` (16 preceding siblings ...)
2011-10-10 8:13 ` [PATCH 17/29] wl12xx: make WL1271_FLAG_RX_STREAMING_STARTED " Eliad Peller
@ 2011-10-10 8:13 ` Eliad Peller
2011-10-10 8:13 ` [PATCH 19/29] wl12xx: make WL1271_FLAG_PSPOLL_FAILURE flag per-vif Eliad Peller
` (11 subsequent siblings)
29 siblings, 0 replies; 51+ messages in thread
From: Eliad Peller @ 2011-10-10 8:13 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
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 [flat|nested] 51+ messages in thread* [PATCH 19/29] wl12xx: make WL1271_FLAG_PSPOLL_FAILURE flag per-vif
2011-10-10 8:12 [PATCH 00/29] make the driver ready for multi-vif support Eliad Peller
` (17 preceding siblings ...)
2011-10-10 8:13 ` [PATCH 18/29] wl12xx: make WL1271_FLAG_IF_INITIALIZED per-vif Eliad Peller
@ 2011-10-10 8:13 ` Eliad Peller
2011-10-10 8:13 ` [PATCH 20/29] wl12xx: make WL1271_FLAG_CS_PROGRESS " Eliad Peller
` (10 subsequent siblings)
29 siblings, 0 replies; 51+ messages in thread
From: Eliad Peller @ 2011-10-10 8:13 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
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 [flat|nested] 51+ messages in thread* [PATCH 20/29] wl12xx: make WL1271_FLAG_CS_PROGRESS flag per-vif
2011-10-10 8:12 [PATCH 00/29] make the driver ready for multi-vif support Eliad Peller
` (18 preceding siblings ...)
2011-10-10 8:13 ` [PATCH 19/29] wl12xx: make WL1271_FLAG_PSPOLL_FAILURE flag per-vif Eliad Peller
@ 2011-10-10 8:13 ` Eliad Peller
2011-10-10 8:13 ` [PATCH 21/29] wl12xx: add band field to wlvif Eliad Peller
` (9 subsequent siblings)
29 siblings, 0 replies; 51+ messages in thread
From: Eliad Peller @ 2011-10-10 8:13 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
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 [flat|nested] 51+ messages in thread* [PATCH 21/29] wl12xx: add band field to wlvif
2011-10-10 8:12 [PATCH 00/29] make the driver ready for multi-vif support Eliad Peller
` (19 preceding siblings ...)
2011-10-10 8:13 ` [PATCH 20/29] wl12xx: make WL1271_FLAG_CS_PROGRESS " Eliad Peller
@ 2011-10-10 8:13 ` Eliad Peller
2011-10-10 20:38 ` Luciano Coelho
2011-10-10 8:13 ` [PATCH 22/29] wl12xx: add channel " Eliad Peller
` (8 subsequent siblings)
29 siblings, 1 reply; 51+ messages in thread
From: Eliad Peller @ 2011-10-10 8:13 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
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 [flat|nested] 51+ messages in thread* Re: [PATCH 21/29] wl12xx: add band field to wlvif
2011-10-10 8:13 ` [PATCH 21/29] wl12xx: add band field to wlvif Eliad Peller
@ 2011-10-10 20:38 ` Luciano Coelho
2011-10-10 20:47 ` Eliad Peller
0 siblings, 1 reply; 51+ messages in thread
From: Luciano Coelho @ 2011-10-10 20:38 UTC (permalink / raw)
To: Eliad Peller; +Cc: linux-wireless
On Mon, 2011-10-10 at 10:13 +0200, Eliad Peller wrote:
> 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>
> ---
[...]
> -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)
[...]
> -int wl12xx_roc(struct wl1271 *wl, u8 role_id)
> +int wl12xx_roc(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 role_id)
Seems like wl12xx_roc(), which is the only caller of wl12xx_cmd_roc(),
is always called with wlvif->role_id as the role, so it seems a bit
useless to pass role_id separately all the way.
--
Cheers,
Luca.
^ permalink raw reply [flat|nested] 51+ messages in thread
* Re: [PATCH 21/29] wl12xx: add band field to wlvif
2011-10-10 20:38 ` Luciano Coelho
@ 2011-10-10 20:47 ` Eliad Peller
2011-10-11 9:48 ` Victor Goldenshtein
0 siblings, 1 reply; 51+ messages in thread
From: Eliad Peller @ 2011-10-10 20:47 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
On Mon, Oct 10, 2011 at 10:38 PM, Luciano Coelho <coelho@ti.com> wrote:
> On Mon, 2011-10-10 at 10:13 +0200, Eliad Peller wrote:
>> 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>
>> ---
>
> [...]
>
>
>> -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)
>
> [...]
>
>> -int wl12xx_roc(struct wl1271 *wl, u8 role_id)
>> +int wl12xx_roc(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 role_id)
>
> Seems like wl12xx_roc(), which is the only caller of wl12xx_cmd_roc(),
> is always called with wlvif->role_id as the role, so it seems a bit
> useless to pass role_id separately all the way.
>
in fact, it's usually being called with wlvif->dev_role_id, so we do
need this param.
(otoh, wl12xx_roc is usually get called along with start_role_dev. i
have some pending patch that couples them together and cleans the code
a bit. i'll send it soon).
Eliad.
^ permalink raw reply [flat|nested] 51+ messages in thread
* Re: [PATCH 21/29] wl12xx: add band field to wlvif
2011-10-10 20:47 ` Eliad Peller
@ 2011-10-11 9:48 ` Victor Goldenshtein
0 siblings, 0 replies; 51+ messages in thread
From: Victor Goldenshtein @ 2011-10-11 9:48 UTC (permalink / raw)
To: Eliad Peller, Luciano Coelho; +Cc: linux-wireless
On 10/10/2011 22:47, Eliad Peller wrote:
> On Mon, Oct 10, 2011 at 10:38 PM, Luciano Coelho<coelho@ti.com> wrote:
>> On Mon, 2011-10-10 at 10:13 +0200, Eliad Peller wrote:
> (otoh, wl12xx_roc is usually get called along with start_role_dev. i
> have some pending patch that couples them together and cleans the code
> a bit. i'll send it soon).
>
> Eliad.
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
Guys,
Just fyi we will use the roc/croc also in DFS implementation.
Thanks,
Victor.
^ permalink raw reply [flat|nested] 51+ messages in thread
* [PATCH 22/29] wl12xx: add channel field to wlvif
2011-10-10 8:12 [PATCH 00/29] make the driver ready for multi-vif support Eliad Peller
` (20 preceding siblings ...)
2011-10-10 8:13 ` [PATCH 21/29] wl12xx: add band field to wlvif Eliad Peller
@ 2011-10-10 8:13 ` Eliad Peller
2011-10-10 8:13 ` [PATCH 23/29] wl12xx: add power_level " Eliad Peller
` (7 subsequent siblings)
29 siblings, 0 replies; 51+ messages in thread
From: Eliad Peller @ 2011-10-10 8:13 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
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 [flat|nested] 51+ messages in thread* [PATCH 23/29] wl12xx: add power_level field to wlvif
2011-10-10 8:12 [PATCH 00/29] make the driver ready for multi-vif support Eliad Peller
` (21 preceding siblings ...)
2011-10-10 8:13 ` [PATCH 22/29] wl12xx: add channel " Eliad Peller
@ 2011-10-10 8:13 ` Eliad Peller
2011-10-10 8:13 ` [PATCH 24/29] wl12xx: make op_config configure all vifs Eliad Peller
` (6 subsequent siblings)
29 siblings, 0 replies; 51+ messages in thread
From: Eliad Peller @ 2011-10-10 8:13 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
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 [flat|nested] 51+ messages in thread* [PATCH 24/29] wl12xx: make op_config configure all vifs
2011-10-10 8:12 [PATCH 00/29] make the driver ready for multi-vif support Eliad Peller
` (22 preceding siblings ...)
2011-10-10 8:13 ` [PATCH 23/29] wl12xx: add power_level " Eliad Peller
@ 2011-10-10 8:13 ` Eliad Peller
2011-10-10 8:13 ` [PATCH 25/29] wl12xx: replace all remaining wl->vif references Eliad Peller
` (5 subsequent siblings)
29 siblings, 0 replies; 51+ messages in thread
From: Eliad Peller @ 2011-10-10 8:13 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
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 [flat|nested] 51+ messages in thread* [PATCH 25/29] wl12xx: replace all remaining wl->vif references
2011-10-10 8:12 [PATCH 00/29] make the driver ready for multi-vif support Eliad Peller
` (23 preceding siblings ...)
2011-10-10 8:13 ` [PATCH 24/29] wl12xx: make op_config configure all vifs Eliad Peller
@ 2011-10-10 8:13 ` Eliad Peller
2011-10-10 8:13 ` [PATCH 26/29] wl12xx: call stop() on recovery Eliad Peller
` (4 subsequent siblings)
29 siblings, 0 replies; 51+ messages in thread
From: Eliad Peller @ 2011-10-10 8:13 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
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 [flat|nested] 51+ messages in thread* [PATCH 26/29] wl12xx: call stop() on recovery
2011-10-10 8:12 [PATCH 00/29] make the driver ready for multi-vif support Eliad Peller
` (24 preceding siblings ...)
2011-10-10 8:13 ` [PATCH 25/29] wl12xx: replace all remaining wl->vif references Eliad Peller
@ 2011-10-10 8:13 ` Eliad Peller
2011-10-10 8:13 ` [PATCH 27/29] wl12xx: use dynamic rate policies Eliad Peller
` (3 subsequent siblings)
29 siblings, 0 replies; 51+ messages in thread
From: Eliad Peller @ 2011-10-10 8:13 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
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 [flat|nested] 51+ messages in thread* [PATCH 27/29] wl12xx: use dynamic rate policies
2011-10-10 8:12 [PATCH 00/29] make the driver ready for multi-vif support Eliad Peller
` (25 preceding siblings ...)
2011-10-10 8:13 ` [PATCH 26/29] wl12xx: call stop() on recovery Eliad Peller
@ 2011-10-10 8:13 ` Eliad Peller
2011-10-10 8:13 ` [PATCH 28/29] wl12xx: add elp wakeup/sleep calls to add_interface Eliad Peller
` (2 subsequent siblings)
29 siblings, 0 replies; 51+ messages in thread
From: Eliad Peller @ 2011-10-10 8:13 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
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 [flat|nested] 51+ messages in thread* [PATCH 28/29] wl12xx: add elp wakeup/sleep calls to add_interface
2011-10-10 8:12 [PATCH 00/29] make the driver ready for multi-vif support Eliad Peller
` (26 preceding siblings ...)
2011-10-10 8:13 ` [PATCH 27/29] wl12xx: use dynamic rate policies Eliad Peller
@ 2011-10-10 8:13 ` Eliad Peller
2011-10-10 8:13 ` [PATCH 29/29] wl12xx: use round-robin policy for tx Eliad Peller
2011-10-11 12:52 ` [PATCH 00/29] make the driver ready for multi-vif support Luciano Coelho
29 siblings, 0 replies; 51+ messages in thread
From: Eliad Peller @ 2011-10-10 8:13 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
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 [flat|nested] 51+ messages in thread* [PATCH 29/29] wl12xx: use round-robin policy for tx
2011-10-10 8:12 [PATCH 00/29] make the driver ready for multi-vif support Eliad Peller
` (27 preceding siblings ...)
2011-10-10 8:13 ` [PATCH 28/29] wl12xx: add elp wakeup/sleep calls to add_interface Eliad Peller
@ 2011-10-10 8:13 ` Eliad Peller
2011-10-11 12:52 ` [PATCH 00/29] make the driver ready for multi-vif support Luciano Coelho
29 siblings, 0 replies; 51+ messages in thread
From: Eliad Peller @ 2011-10-10 8:13 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
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 [flat|nested] 51+ messages in thread* Re: [PATCH 00/29] make the driver ready for multi-vif support
2011-10-10 8:12 [PATCH 00/29] make the driver ready for multi-vif support Eliad Peller
` (28 preceding siblings ...)
2011-10-10 8:13 ` [PATCH 29/29] wl12xx: use round-robin policy for tx Eliad Peller
@ 2011-10-11 12:52 ` Luciano Coelho
29 siblings, 0 replies; 51+ messages in thread
From: Luciano Coelho @ 2011-10-11 12:52 UTC (permalink / raw)
To: Eliad Peller; +Cc: linux-wireless
On Mon, 2011-10-10 at 10:12 +0200, Eliad Peller wrote:
> This patchset finishes adding multiple vif support to the
> wl12xx driver.
>
> The driver still allows only a single vif, as the current
> fw only supports a single vif.
>
> This patchset doesn't break compatibility with the current fw.
Applied, thanks! With the following small changes:
* used v2 of 08/29;
* used '(foo - bar) & 0xff' instead of '(foo - bar + 256) % 256'.
--
Cheers,
Luca.
^ permalink raw reply [flat|nested] 51+ messages in thread