diff options
Diffstat (limited to 'net/mac80211/cfg.c')
-rw-r--r-- | net/mac80211/cfg.c | 68 |
1 files changed, 60 insertions, 8 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 140503d4c97a..7b701dcddb50 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -316,6 +316,17 @@ static int ieee80211_config_default_mgmt_key(struct wiphy *wiphy, | |||
316 | return 0; | 316 | return 0; |
317 | } | 317 | } |
318 | 318 | ||
319 | static void rate_idx_to_bitrate(struct rate_info *rate, struct sta_info *sta, int idx) | ||
320 | { | ||
321 | if (!(rate->flags & RATE_INFO_FLAGS_MCS)) { | ||
322 | struct ieee80211_supported_band *sband; | ||
323 | sband = sta->local->hw.wiphy->bands[ | ||
324 | sta->local->hw.conf.channel->band]; | ||
325 | rate->legacy = sband->bitrates[idx].bitrate; | ||
326 | } else | ||
327 | rate->mcs = idx; | ||
328 | } | ||
329 | |||
319 | static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | 330 | static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) |
320 | { | 331 | { |
321 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 332 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
@@ -330,6 +341,7 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
330 | STATION_INFO_TX_RETRIES | | 341 | STATION_INFO_TX_RETRIES | |
331 | STATION_INFO_TX_FAILED | | 342 | STATION_INFO_TX_FAILED | |
332 | STATION_INFO_TX_BITRATE | | 343 | STATION_INFO_TX_BITRATE | |
344 | STATION_INFO_RX_BITRATE | | ||
333 | STATION_INFO_RX_DROP_MISC; | 345 | STATION_INFO_RX_DROP_MISC; |
334 | 346 | ||
335 | sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx); | 347 | sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx); |
@@ -355,15 +367,16 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
355 | sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; | 367 | sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; |
356 | if (sta->last_tx_rate.flags & IEEE80211_TX_RC_SHORT_GI) | 368 | if (sta->last_tx_rate.flags & IEEE80211_TX_RC_SHORT_GI) |
357 | sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; | 369 | sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; |
370 | rate_idx_to_bitrate(&sinfo->txrate, sta, sta->last_tx_rate.idx); | ||
358 | 371 | ||
359 | if (!(sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)) { | 372 | sinfo->rxrate.flags = 0; |
360 | struct ieee80211_supported_band *sband; | 373 | if (sta->last_rx_rate_flag & RX_FLAG_HT) |
361 | sband = sta->local->hw.wiphy->bands[ | 374 | sinfo->rxrate.flags |= RATE_INFO_FLAGS_MCS; |
362 | sta->local->hw.conf.channel->band]; | 375 | if (sta->last_rx_rate_flag & RX_FLAG_40MHZ) |
363 | sinfo->txrate.legacy = | 376 | sinfo->rxrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; |
364 | sband->bitrates[sta->last_tx_rate.idx].bitrate; | 377 | if (sta->last_rx_rate_flag & RX_FLAG_SHORT_GI) |
365 | } else | 378 | sinfo->rxrate.flags |= RATE_INFO_FLAGS_SHORT_GI; |
366 | sinfo->txrate.mcs = sta->last_tx_rate.idx; | 379 | rate_idx_to_bitrate(&sinfo->rxrate, sta, sta->last_rx_rate_idx); |
367 | 380 | ||
368 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | 381 | if (ieee80211_vif_is_mesh(&sdata->vif)) { |
369 | #ifdef CONFIG_MAC80211_MESH | 382 | #ifdef CONFIG_MAC80211_MESH |
@@ -1800,6 +1813,33 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, | |||
1800 | 1813 | ||
1801 | *cookie = (unsigned long) skb; | 1814 | *cookie = (unsigned long) skb; |
1802 | 1815 | ||
1816 | if (is_offchan && local->ops->offchannel_tx) { | ||
1817 | int ret; | ||
1818 | |||
1819 | IEEE80211_SKB_CB(skb)->band = chan->band; | ||
1820 | |||
1821 | mutex_lock(&local->mtx); | ||
1822 | |||
1823 | if (local->hw_offchan_tx_cookie) { | ||
1824 | mutex_unlock(&local->mtx); | ||
1825 | return -EBUSY; | ||
1826 | } | ||
1827 | |||
1828 | /* TODO: bitrate control, TX processing? */ | ||
1829 | ret = drv_offchannel_tx(local, skb, chan, channel_type, wait); | ||
1830 | |||
1831 | if (ret == 0) | ||
1832 | local->hw_offchan_tx_cookie = *cookie; | ||
1833 | mutex_unlock(&local->mtx); | ||
1834 | |||
1835 | /* | ||
1836 | * Allow driver to return 1 to indicate it wants to have the | ||
1837 | * frame transmitted with a remain_on_channel + regular TX. | ||
1838 | */ | ||
1839 | if (ret != 1) | ||
1840 | return ret; | ||
1841 | } | ||
1842 | |||
1803 | if (is_offchan && local->ops->remain_on_channel) { | 1843 | if (is_offchan && local->ops->remain_on_channel) { |
1804 | unsigned int duration; | 1844 | unsigned int duration; |
1805 | int ret; | 1845 | int ret; |
@@ -1886,6 +1926,18 @@ static int ieee80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, | |||
1886 | 1926 | ||
1887 | mutex_lock(&local->mtx); | 1927 | mutex_lock(&local->mtx); |
1888 | 1928 | ||
1929 | if (local->ops->offchannel_tx_cancel_wait && | ||
1930 | local->hw_offchan_tx_cookie == cookie) { | ||
1931 | ret = drv_offchannel_tx_cancel_wait(local); | ||
1932 | |||
1933 | if (!ret) | ||
1934 | local->hw_offchan_tx_cookie = 0; | ||
1935 | |||
1936 | mutex_unlock(&local->mtx); | ||
1937 | |||
1938 | return ret; | ||
1939 | } | ||
1940 | |||
1889 | if (local->ops->cancel_remain_on_channel) { | 1941 | if (local->ops->cancel_remain_on_channel) { |
1890 | cookie ^= 2; | 1942 | cookie ^= 2; |
1891 | ret = ieee80211_cancel_remain_on_channel_hw(local, cookie); | 1943 | ret = ieee80211_cancel_remain_on_channel_hw(local, cookie); |