Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 352148
b: refs/heads/master
c: dabf37d
h: refs/heads/master
v: v3
  • Loading branch information
Eliad Peller authored and Luciano Coelho committed Nov 27, 2012
1 parent d14e706 commit 49cc062
Show file tree
Hide file tree
Showing 7 changed files with 174 additions and 47 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: 18eab430700dc877bae38cf04f0b0574b4724f0a
refs/heads/master: dabf37dba405565ab46f4d1821c781730285b9ed
41 changes: 16 additions & 25 deletions trunk/drivers/net/wireless/ti/wlcore/cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,9 @@ static u8 wlcore_get_native_channel_type(u8 nl_channel_type)
}

static int wl12xx_cmd_role_start_dev(struct wl1271 *wl,
struct wl12xx_vif *wlvif)
struct wl12xx_vif *wlvif,
enum ieee80211_band band,
int channel)
{
struct wl12xx_cmd_role_start *cmd;
int ret;
Expand All @@ -359,9 +361,9 @@ static int wl12xx_cmd_role_start_dev(struct wl1271 *wl,
wl1271_debug(DEBUG_CMD, "cmd role start dev %d", wlvif->dev_role_id);

cmd->role_id = wlvif->dev_role_id;
if (wlvif->band == IEEE80211_BAND_5GHZ)
if (band == IEEE80211_BAND_5GHZ)
cmd->band = WLCORE_BAND_5GHZ;
cmd->channel = wlvif->channel;
cmd->channel = channel;

if (wlvif->dev_hlid == WL12XX_INVALID_LINK_ID) {
ret = wl12xx_allocate_link(wl, wlvif, &wlvif->dev_hlid);
Expand Down Expand Up @@ -1591,12 +1593,12 @@ int wl12xx_cmd_stop_fwlog(struct wl1271 *wl)
}

static int wl12xx_cmd_roc(struct wl1271 *wl, struct wl12xx_vif *wlvif,
u8 role_id)
u8 role_id, enum ieee80211_band band, u8 channel)
{
struct wl12xx_cmd_roc *cmd;
int ret = 0;

wl1271_debug(DEBUG_CMD, "cmd roc %d (%d)", wlvif->channel, role_id);
wl1271_debug(DEBUG_CMD, "cmd roc %d (%d)", channel, role_id);

if (WARN_ON(role_id == WL12XX_INVALID_ROLE_ID))
return -EINVAL;
Expand All @@ -1608,8 +1610,8 @@ static int wl12xx_cmd_roc(struct wl1271 *wl, struct wl12xx_vif *wlvif,
}

cmd->role_id = role_id;
cmd->channel = wlvif->channel;
switch (wlvif->band) {
cmd->channel = channel;
switch (band) {
case IEEE80211_BAND_2GHZ:
cmd->band = WLCORE_BAND_2_4GHZ;
break;
Expand Down Expand Up @@ -1664,30 +1666,18 @@ static int wl12xx_cmd_croc(struct wl1271 *wl, u8 role_id)
return ret;
}

int wl12xx_roc(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 role_id)
int wl12xx_roc(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 role_id,
enum ieee80211_band band, u8 channel)
{
int ret = 0;
bool is_first_roc;

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

is_first_roc = (find_first_bit(wl->roc_map, WL12XX_MAX_ROLES) >=
WL12XX_MAX_ROLES);

ret = wl12xx_cmd_roc(wl, wlvif, role_id);
ret = wl12xx_cmd_roc(wl, wlvif, role_id, band, channel);
if (ret < 0)
goto out;

if (is_first_roc) {
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;
Expand Down Expand Up @@ -1780,7 +1770,8 @@ int wl12xx_cmd_stop_channel_switch(struct wl1271 *wl)
}

/* start dev role and roc on its channel */
int wl12xx_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif)
int wl12xx_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif,
enum ieee80211_band band, int channel)
{
int ret;

Expand All @@ -1795,11 +1786,11 @@ int wl12xx_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif)
if (ret < 0)
goto out;

ret = wl12xx_cmd_role_start_dev(wl, wlvif);
ret = wl12xx_cmd_role_start_dev(wl, wlvif, band, channel);
if (ret < 0)
goto out_disable;

ret = wl12xx_roc(wl, wlvif, wlvif->dev_role_id);
ret = wl12xx_roc(wl, wlvif, wlvif->dev_role_id, band, channel);
if (ret < 0)
goto out_stop;

Expand Down
6 changes: 4 additions & 2 deletions trunk/drivers/net/wireless/ti/wlcore/cmd.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ int wl12xx_cmd_role_stop_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif);
int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif);
int wl12xx_cmd_role_stop_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif);
int wl12xx_cmd_role_start_ibss(struct wl1271 *wl, struct wl12xx_vif *wlvif);
int wl12xx_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif);
int wl12xx_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif,
enum ieee80211_band band, int channel);
int wl12xx_stop_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif);
int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer);
int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len);
Expand Down Expand Up @@ -76,7 +77,8 @@ 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, struct wl12xx_vif *wlvif, u8 role_id);
int wl12xx_roc(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 role_id,
enum ieee80211_band band, u8 channel);
int wl12xx_croc(struct wl1271 *wl, u8 role_id);
int wl12xx_cmd_add_peer(struct wl1271 *wl, struct wl12xx_vif *wlvif,
struct ieee80211_sta *sta, u8 hlid);
Expand Down
7 changes: 7 additions & 0 deletions trunk/drivers/net/wireless/ti/wlcore/event.c
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,13 @@ static int wl1271_event_process(struct wl1271 *wl)
disconnect_sta = true;
}

if (vector & REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID) {
wl1271_debug(DEBUG_EVENT,
"REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID");
if (wl->roc_vif)
ieee80211_ready_on_channel(wl->hw);
}

if (disconnect_sta) {
u32 num_packets = wl->conf.tx.max_tx_retries;
struct ieee80211_sta *sta;
Expand Down
154 changes: 135 additions & 19 deletions trunk/drivers/net/wireless/ti/wlcore/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -2723,24 +2723,6 @@ static int wl12xx_config_vif(struct wl1271 *wl, struct wl12xx_vif *wlvif,
if (ret < 0)
wl1271_warning("rate policy for channel "
"failed %d", ret);

/*
* change the ROC channel. do it only if we are
* not idle. otherwise, CROC will be called
* anyway.
*/
if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED,
&wlvif->flags) &&
wl12xx_dev_role_started(wlvif) &&
!(conf->flags & IEEE80211_CONF_IDLE)) {
ret = wl12xx_stop_dev(wl, wlvif);
if (ret < 0)
return ret;

ret = wl12xx_start_dev(wl, wlvif);
if (ret < 0)
return ret;
}
}
}

Expand Down Expand Up @@ -4057,7 +4039,8 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,

/* ROC until connected (after EAPOL exchange) */
if (!is_ibss) {
ret = wl12xx_roc(wl, wlvif, wlvif->role_id);
ret = wl12xx_roc(wl, wlvif, wlvif->role_id,
wlvif->band, wlvif->channel);
if (ret < 0)
goto out;
}
Expand Down Expand Up @@ -4692,6 +4675,134 @@ static void wlcore_op_flush(struct ieee80211_hw *hw, bool drop)
wl1271_tx_flush(wl);
}

static int wlcore_op_remain_on_channel(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_channel *chan,
enum nl80211_channel_type channel_type,
int duration)
{
struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
struct wl1271 *wl = hw->priv;
int channel, ret = 0;

channel = ieee80211_frequency_to_channel(chan->center_freq);

wl1271_debug(DEBUG_MAC80211, "mac80211 roc %d (%d)",
channel, wlvif->role_id);

mutex_lock(&wl->mutex);

if (unlikely(wl->state != WLCORE_STATE_ON))
goto out;

/* return EBUSY if we can't ROC right now */
if (WARN_ON(wl->roc_vif ||
find_first_bit(wl->roc_map,
WL12XX_MAX_ROLES) < WL12XX_MAX_ROLES)) {
ret = -EBUSY;
goto out;
}

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

ret = wl12xx_start_dev(wl, wlvif, chan->band, channel);
if (ret < 0)
goto out_sleep;

wl->roc_vif = vif;
ieee80211_queue_delayed_work(hw, &wl->roc_complete_work,
msecs_to_jiffies(duration));
out_sleep:
wl1271_ps_elp_sleep(wl);
out:
mutex_unlock(&wl->mutex);
return ret;
}

static int __wlcore_roc_completed(struct wl1271 *wl)
{
struct wl12xx_vif *wlvif;
int ret;

/* already completed */
if (unlikely(!wl->roc_vif))
return 0;

wlvif = wl12xx_vif_to_data(wl->roc_vif);

if (!test_bit(WLVIF_FLAG_INITIALIZED, &wlvif->flags))
return -EBUSY;

ret = wl12xx_stop_dev(wl, wlvif);
if (ret < 0)
return ret;

wl->roc_vif = NULL;

return 0;
}

static int wlcore_roc_completed(struct wl1271 *wl)
{
int ret;

wl1271_debug(DEBUG_MAC80211, "roc complete");

mutex_lock(&wl->mutex);

if (unlikely(wl->state != WLCORE_STATE_ON)) {
ret = -EBUSY;
goto out;
}

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

ret = __wlcore_roc_completed(wl);

wl1271_ps_elp_sleep(wl);
out:
mutex_unlock(&wl->mutex);

return ret;
}

static void wlcore_roc_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, roc_complete_work);

ret = wlcore_roc_completed(wl);
if (!ret)
ieee80211_remain_on_channel_expired(wl->hw);
}

static int wlcore_op_cancel_remain_on_channel(struct ieee80211_hw *hw)
{
struct wl1271 *wl = hw->priv;

wl1271_debug(DEBUG_MAC80211, "mac80211 croc");

/* TODO: per-vif */
wl1271_tx_flush(wl);

/*
* we can't just flush_work here, because it might deadlock
* (as we might get called from the same workqueue)
*/
cancel_delayed_work_sync(&wl->roc_complete_work);
wlcore_roc_completed(wl);

return 0;
}

static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw)
{
struct wl1271 *wl = hw->priv;
Expand Down Expand Up @@ -4883,6 +4994,8 @@ static const struct ieee80211_ops wl1271_ops = {
.set_bitrate_mask = wl12xx_set_bitrate_mask,
.channel_switch = wl12xx_op_channel_switch,
.flush = wlcore_op_flush,
.remain_on_channel = wlcore_op_remain_on_channel,
.cancel_remain_on_channel = wlcore_op_cancel_remain_on_channel,
CFG80211_TESTMODE_CMD(wl1271_tm_cmd)
};

Expand Down Expand Up @@ -5279,6 +5392,8 @@ static int wl1271_init_ieee80211(struct wl1271 *wl)
wl->hw->wiphy->max_sched_scan_ie_len = WL1271_CMD_TEMPL_MAX_SIZE -
sizeof(struct ieee80211_header);

wl->hw->wiphy->max_remain_on_channel_duration = 5000;

wl->hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD |
WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;

Expand Down Expand Up @@ -5377,6 +5492,7 @@ struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size, u32 aggr_buf_size)
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_DELAYED_WORK(&wl->roc_complete_work, wlcore_roc_complete_work);
INIT_DELAYED_WORK(&wl->tx_watchdog_work, wl12xx_tx_watchdog_work);
INIT_DELAYED_WORK(&wl->connection_loss_work,
wl1271_connection_loss_work);
Expand Down
8 changes: 8 additions & 0 deletions trunk/drivers/net/wireless/ti/wlcore/tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,12 +155,20 @@ static u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif,
u8 wl12xx_tx_get_hlid(struct wl1271 *wl, struct wl12xx_vif *wlvif,
struct sk_buff *skb, struct ieee80211_sta *sta)
{
struct ieee80211_tx_info *control;

if (!wlvif || wl12xx_is_dummy_packet(wl, skb))
return wl->system_hlid;

if (wlvif->bss_type == BSS_TYPE_AP_BSS)
return wl12xx_tx_get_hlid_ap(wl, wlvif, skb, sta);

control = IEEE80211_SKB_CB(skb);
if (control->flags & IEEE80211_TX_CTL_TX_OFFCHAN) {
wl1271_debug(DEBUG_TX, "tx offchannel");
return wlvif->dev_hlid;
}

return wlvif->sta.hlid;
}

Expand Down
3 changes: 3 additions & 0 deletions trunk/drivers/net/wireless/ti/wlcore/wlcore.h
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,9 @@ struct wl1271 {
/* Connection loss work */
struct delayed_work connection_loss_work;

struct ieee80211_vif *roc_vif;
struct delayed_work roc_complete_work;

bool sched_scanning;

/* The current band */
Expand Down

0 comments on commit 49cc062

Please sign in to comment.