aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/cfg.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2011-02-25 09:36:57 -0500
committerJohn W. Linville <linville@tuxdriver.com>2011-02-25 15:33:40 -0500
commit5f16a43617d46cf255a66f4dc193a7f5b2540aaf (patch)
treeadd5e551c9d1abeee57b1fbad632a0e23bdd39b1 /net/mac80211/cfg.c
parent8628172f45c839376bf2b70bbd326d56e68dadc3 (diff)
mac80211: support direct offchannel TX offload
For devices supported by iwlwifi sometimes off-channel transmissions need to be handled by the device completely. To support this mac80211 needs to pass the frame directly to the driver and not through the TX path as the driver needs the frame and channel information at the same time. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/cfg.c')
-rw-r--r--net/mac80211/cfg.c39
1 files changed, 39 insertions, 0 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 140503d4c97a..8b436c768c4e 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1800,6 +1800,33 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
1800 1800
1801 *cookie = (unsigned long) skb; 1801 *cookie = (unsigned long) skb;
1802 1802
1803 if (is_offchan && local->ops->offchannel_tx) {
1804 int ret;
1805
1806 IEEE80211_SKB_CB(skb)->band = chan->band;
1807
1808 mutex_lock(&local->mtx);
1809
1810 if (local->hw_offchan_tx_cookie) {
1811 mutex_unlock(&local->mtx);
1812 return -EBUSY;
1813 }
1814
1815 /* TODO: bitrate control, TX processing? */
1816 ret = drv_offchannel_tx(local, skb, chan, channel_type, wait);
1817
1818 if (ret == 0)
1819 local->hw_offchan_tx_cookie = *cookie;
1820 mutex_unlock(&local->mtx);
1821
1822 /*
1823 * Allow driver to return 1 to indicate it wants to have the
1824 * frame transmitted with a remain_on_channel + regular TX.
1825 */
1826 if (ret != 1)
1827 return ret;
1828 }
1829
1803 if (is_offchan && local->ops->remain_on_channel) { 1830 if (is_offchan && local->ops->remain_on_channel) {
1804 unsigned int duration; 1831 unsigned int duration;
1805 int ret; 1832 int ret;
@@ -1886,6 +1913,18 @@ static int ieee80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
1886 1913
1887 mutex_lock(&local->mtx); 1914 mutex_lock(&local->mtx);
1888 1915
1916 if (local->ops->offchannel_tx_cancel_wait &&
1917 local->hw_offchan_tx_cookie == cookie) {
1918 ret = drv_offchannel_tx_cancel_wait(local);
1919
1920 if (!ret)
1921 local->hw_offchan_tx_cookie = 0;
1922
1923 mutex_unlock(&local->mtx);
1924
1925 return ret;
1926 }
1927
1889 if (local->ops->cancel_remain_on_channel) { 1928 if (local->ops->cancel_remain_on_channel) {
1890 cookie ^= 2; 1929 cookie ^= 2;
1891 ret = ieee80211_cancel_remain_on_channel_hw(local, cookie); 1930 ret = ieee80211_cancel_remain_on_channel_hw(local, cookie);