Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 265800
b: refs/heads/master
c: 251c177
h: refs/heads/master
v: v3
  • Loading branch information
Eliad Peller authored and Luciano Coelho committed Aug 22, 2011
1 parent 10e9910 commit df8c1f7
Show file tree
Hide file tree
Showing 7 changed files with 183 additions and 39 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 79ebec76be4e7c2ebed9fb0b9510d10d599ed63e
refs/heads/master: 251c177f886027fbce494202e44935762f103137
39 changes: 39 additions & 0 deletions trunk/drivers/net/wireless/wl12xx/cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1554,3 +1554,42 @@ static int wl12xx_cmd_croc(struct wl1271 *wl, u8 role_id)
out:
return ret;
}

int wl12xx_roc(struct wl1271 *wl, 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);
if (ret < 0)
goto out;

ret = wl1271_cmd_wait_for_event(wl,
REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID);
if (ret < 0) {
wl1271_error("cmd roc event completion error");
goto out;
}

__set_bit(role_id, wl->roc_map);
out:
return ret;
}

int wl12xx_croc(struct wl1271 *wl, u8 role_id)
{
int ret = 0;

if (WARN_ON(!test_bit(role_id, wl->roc_map)))
return 0;

ret = wl12xx_cmd_croc(wl, role_id);
if (ret < 0)
goto out;

__clear_bit(role_id, wl->roc_map);
out:
return ret;
}
2 changes: 2 additions & 0 deletions trunk/drivers/net/wireless/wl12xx/cmd.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ int wl1271_cmd_set_ap_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
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);
int wl12xx_roc(struct wl1271 *wl, 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_remove_peer(struct wl1271 *wl, u8 hlid);
int wl12xx_cmd_config_fwlog(struct wl1271 *wl);
Expand Down
144 changes: 113 additions & 31 deletions trunk/drivers/net/wireless/wl12xx/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,8 @@ static int wl1271_check_operstate(struct wl1271 *wl, unsigned char operstate)
if (ret < 0)
return ret;

wl12xx_croc(wl, wl->role_id);

wl1271_info("Association completed.");
return 0;
}
Expand Down Expand Up @@ -2068,6 +2070,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
wl->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));

/* The system link is always allocated */
__set_bit(WL12XX_SYSTEM_HLID, wl->links_map);
Expand Down Expand Up @@ -2110,25 +2113,6 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
cancel_work_sync(&wl->recovery_work);
}

static int wl1271_dummy_join(struct wl1271 *wl)
{
int ret = 0;
/* we need to use a dummy BSSID for now */
static const u8 dummy_bssid[ETH_ALEN] = { 0x0b, 0xad, 0xde,
0xad, 0xbe, 0xef };

memcpy(wl->bssid, dummy_bssid, ETH_ALEN);

ret = wl12xx_cmd_role_start_sta(wl);
if (ret < 0)
goto out;

set_bit(WL1271_FLAG_JOINED, &wl->flags);

out:
return ret;
}

static int wl1271_join(struct wl1271 *wl, bool set_assoc)
{
int ret;
Expand All @@ -2152,8 +2136,6 @@ static int wl1271_join(struct wl1271 *wl, bool set_assoc)
if (ret < 0)
goto out;

set_bit(WL1271_FLAG_JOINED, &wl->flags);

if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
goto out;

Expand Down Expand Up @@ -2193,7 +2175,6 @@ static int wl1271_unjoin(struct wl1271 *wl)
if (ret < 0)
goto out;

clear_bit(WL1271_FLAG_JOINED, &wl->flags);
memset(wl->bssid, 0, ETH_ALEN);

/* reset TX security counters on a clean disconnect */
Expand All @@ -2212,13 +2193,29 @@ static void wl1271_set_band_rate(struct wl1271 *wl)
wl->basic_rate_set = wl->conf.tx.basic_rate_5;
}

static bool wl12xx_is_roc(struct wl1271 *wl)
{
u8 role_id;

role_id = find_first_bit(wl->roc_map, WL12XX_MAX_ROLES);
if (role_id >= WL12XX_MAX_ROLES)
return false;

return true;
}

static int wl1271_sta_handle_idle(struct wl1271 *wl, bool idle)
{
int ret;

if (idle) {
if (test_bit(WL1271_FLAG_JOINED, &wl->flags)) {
ret = wl1271_unjoin(wl);
/* no need to croc if we weren't busy (e.g. during boot) */
if (wl12xx_is_roc(wl)) {
ret = wl12xx_croc(wl, wl->dev_role_id);
if (ret < 0)
goto out;

ret = wl12xx_cmd_role_stop_dev(wl);
if (ret < 0)
goto out;
}
Expand All @@ -2244,7 +2241,11 @@ static int wl1271_sta_handle_idle(struct wl1271 *wl, bool idle)
ieee80211_sched_scan_stopped(wl->hw);
}

ret = wl1271_dummy_join(wl);
ret = wl12xx_cmd_role_start_dev(wl);
if (ret < 0)
goto out;

ret = wl12xx_roc(wl, wl->dev_role_id);
if (ret < 0)
goto out;
clear_bit(WL1271_FLAG_IDLE, &wl->flags);
Expand Down Expand Up @@ -2324,11 +2325,34 @@ 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_JOINED, &wl->flags)) {
if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) {
if (wl12xx_is_roc(wl)) {
/* roaming */
ret = wl12xx_croc(wl, wl->dev_role_id);
if (ret < 0)
goto out_sleep;
}
ret = wl1271_join(wl, false);
if (ret < 0)
wl1271_warning("cmd join on channel "
"failed %d", ret);
} else {
/*
* change the ROC channel. do it only if we are
* not idle. otherwise, CROC will be called
* anyway.
*/
if (wl12xx_is_roc(wl) &&
!(conf->flags & IEEE80211_CONF_IDLE)) {
ret = wl12xx_croc(wl, wl->dev_role_id);
if (ret < 0)
goto out_sleep;

ret = wl12xx_roc(wl, wl->dev_role_id);
if (ret < 0)
wl1271_warning("roc failed %d",
ret);
}
}
}
}
Expand Down Expand Up @@ -2784,10 +2808,20 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw,
if (ret < 0)
goto out;

ret = wl1271_scan(hw->priv, ssid, len, req);
/* cancel ROC before scanning */
if (wl12xx_is_roc(wl)) {
if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) {
/* don't allow scanning right now */
ret = -EBUSY;
goto out_sleep;
}
wl12xx_croc(wl, wl->dev_role_id);
wl12xx_cmd_role_stop_dev(wl);
}

ret = wl1271_scan(hw->priv, ssid, len, req);
out_sleep:
wl1271_ps_elp_sleep(wl);

out:
mutex_unlock(&wl->mutex);

Expand Down Expand Up @@ -3311,7 +3345,9 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
bool was_assoc =
!!test_and_clear_bit(WL1271_FLAG_STA_ASSOCIATED,
&wl->flags);
clear_bit(WL1271_FLAG_STA_STATE_SENT, &wl->flags);
bool was_ifup =
!!test_and_clear_bit(WL1271_FLAG_STA_STATE_SENT,
&wl->flags);
wl->aid = 0;

/* free probe-request template */
Expand All @@ -3338,8 +3374,32 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,

/* restore the bssid filter and go to dummy bssid */
if (was_assoc) {
u32 conf_flags = wl->hw->conf.flags;
/*
* we might have to disable roc, if there was
* no IF_OPER_UP notification.
*/
if (!was_ifup) {
ret = wl12xx_croc(wl, wl->role_id);
if (ret < 0)
goto out;
}
/*
* (we also need to disable roc in case of
* roaming on the same channel. until we will
* have a better flow...)
*/
if (test_bit(wl->dev_role_id, wl->roc_map)) {
ret = wl12xx_croc(wl, wl->dev_role_id);
if (ret < 0)
goto out;
}

wl1271_unjoin(wl);
wl1271_dummy_join(wl);
if (!(conf_flags & IEEE80211_CONF_IDLE)) {
wl12xx_cmd_role_start_dev(wl);
wl12xx_roc(wl, wl->dev_role_id);
}
}
}
}
Expand Down Expand Up @@ -3400,7 +3460,29 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
wl1271_warning("cmd join failed %d", ret);
goto out;
}
wl1271_check_operstate(wl, ieee80211_get_operstate(vif));

/* ROC until connected (after EAPOL exchange) */
if (!is_ibss) {
ret = wl12xx_roc(wl, wl->role_id);
if (ret < 0)
goto out;

wl1271_check_operstate(wl,
ieee80211_get_operstate(vif));
}
/*
* stop device role if started (we might already be in
* STA role). TODO: make it better.
*/
if (wl->dev_role_id != WL12XX_INVALID_ROLE_ID) {
ret = wl12xx_croc(wl, wl->dev_role_id);
if (ret < 0)
goto out;

ret = wl12xx_cmd_role_stop_dev(wl);
if (ret < 0)
goto out;
}
}

out:
Expand Down
20 changes: 14 additions & 6 deletions trunk/drivers/net/wireless/wl12xx/scan.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ void wl1271_scan_complete_work(struct work_struct *work)
{
struct delayed_work *dwork;
struct wl1271 *wl;
int ret;

dwork = container_of(work, struct delayed_work, work);
wl = container_of(dwork, struct wl1271, scan_complete_work);
Expand All @@ -50,21 +51,28 @@ void wl1271_scan_complete_work(struct work_struct *work)
wl->scan.state = WL1271_SCAN_STATE_IDLE;
memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch));
wl->scan.req = NULL;
ieee80211_scan_completed(wl->hw, false);

/* restore hardware connection monitoring template */
ret = wl1271_ps_elp_wakeup(wl);
if (ret < 0)
goto out;

if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) {
if (wl1271_ps_elp_wakeup(wl) == 0) {
wl1271_cmd_build_ap_probe_req(wl, wl->probereq);
wl1271_ps_elp_sleep(wl);
}
/* restore hardware connection monitoring template */
wl1271_cmd_build_ap_probe_req(wl, wl->probereq);
} else {
/* restore remain on channel */
wl12xx_cmd_role_start_dev(wl);
wl12xx_roc(wl, wl->dev_role_id);
}
wl1271_ps_elp_sleep(wl);

if (wl->scan.failed) {
wl1271_info("Scan completed due to error.");
wl12xx_queue_recovery_work(wl);
}

ieee80211_scan_completed(wl->hw, false);

out:
mutex_unlock(&wl->mutex);

Expand Down
13 changes: 13 additions & 0 deletions trunk/drivers/net/wireless/wl12xx/tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ static int wl1271_tx_update_filters(struct wl1271 *wl,
struct sk_buff *skb)
{
struct ieee80211_hdr *hdr;
int ret;

hdr = (struct ieee80211_hdr *)(skb->data +
sizeof(struct wl1271_tx_hw_descr));
Expand All @@ -91,6 +92,18 @@ static int wl1271_tx_update_filters(struct wl1271 *wl,
if (!ieee80211_is_auth(hdr->frame_control))
return 0;

if (wl->dev_hlid != WL12XX_INVALID_LINK_ID)
goto out;

wl1271_debug(DEBUG_CMD, "starting device role for roaming");
ret = wl12xx_cmd_role_start_dev(wl);
if (ret < 0)
goto out;

ret = wl12xx_roc(wl, wl->dev_role_id);
if (ret < 0)
goto out;
out:
return 0;
}

Expand Down
2 changes: 1 addition & 1 deletion trunk/drivers/net/wireless/wl12xx/wl12xx.h
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,6 @@ struct wl1271_ap_key {

enum wl12xx_flags {
WL1271_FLAG_STA_ASSOCIATED,
WL1271_FLAG_JOINED,
WL1271_FLAG_GPIO_POWER,
WL1271_FLAG_TX_QUEUE_STOPPED,
WL1271_FLAG_TX_PENDING,
Expand Down Expand Up @@ -402,6 +401,7 @@ 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)];

struct wl1271_acx_mem_map *target_mem_map;

Expand Down

0 comments on commit df8c1f7

Please sign in to comment.