aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/cfg.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2010-12-18 11:20:48 -0500
committerJohn W. Linville <linville@tuxdriver.com>2011-01-05 16:07:12 -0500
commit90fc4b3a5ba24f09af2a8c4a723651a328949460 (patch)
tree0ec7031f451f8a7eb38259b6fe80ec52cf780b43 /net/mac80211/cfg.c
parent21f83589644bb2ed98079bf1e2154c8e70ca6a6c (diff)
mac80211: implement off-channel TX using hw r-o-c offload
When the driver has remain-on-channel offload, implement off-channel transmission using that primitive. 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.c59
1 files changed, 59 insertions, 0 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 168a6ba8fc28..4bc8a9250cfd 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1641,6 +1641,7 @@ static int ieee80211_remain_on_channel(struct wiphy *wiphy,
1641 ret = ieee80211_remain_on_channel_hw(local, dev, 1641 ret = ieee80211_remain_on_channel_hw(local, dev,
1642 chan, channel_type, 1642 chan, channel_type,
1643 duration, cookie); 1643 duration, cookie);
1644 local->hw_roc_for_tx = false;
1644 mutex_unlock(&local->mtx); 1645 mutex_unlock(&local->mtx);
1645 1646
1646 return ret; 1647 return ret;
@@ -1783,6 +1784,49 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
1783 1784
1784 *cookie = (unsigned long) skb; 1785 *cookie = (unsigned long) skb;
1785 1786
1787 if (is_offchan && local->ops->remain_on_channel) {
1788 unsigned int duration;
1789 int ret;
1790
1791 mutex_lock(&local->mtx);
1792 /*
1793 * If the duration is zero, then the driver
1794 * wouldn't actually do anything. Set it to
1795 * 100 for now.
1796 *
1797 * TODO: cancel the off-channel operation
1798 * when we get the SKB's TX status and
1799 * the wait time was zero before.
1800 */
1801 duration = 100;
1802 if (wait)
1803 duration = wait;
1804 ret = ieee80211_remain_on_channel_hw(local, dev, chan,
1805 channel_type,
1806 duration, cookie);
1807 if (ret) {
1808 kfree_skb(skb);
1809 mutex_unlock(&local->mtx);
1810 return ret;
1811 }
1812
1813 local->hw_roc_for_tx = true;
1814 local->hw_roc_duration = wait;
1815
1816 /*
1817 * queue up frame for transmission after
1818 * ieee80211_ready_on_channel call
1819 */
1820
1821 /* modify cookie to prevent API mismatches */
1822 *cookie ^= 2;
1823 IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_TX_OFFCHAN;
1824 local->hw_roc_skb = skb;
1825 mutex_unlock(&local->mtx);
1826
1827 return 0;
1828 }
1829
1786 /* 1830 /*
1787 * Can transmit right away if the channel was the 1831 * Can transmit right away if the channel was the
1788 * right one and there's no wait involved... If a 1832 * right one and there's no wait involved... If a
@@ -1823,6 +1867,21 @@ static int ieee80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
1823 int ret = -ENOENT; 1867 int ret = -ENOENT;
1824 1868
1825 mutex_lock(&local->mtx); 1869 mutex_lock(&local->mtx);
1870
1871 if (local->ops->cancel_remain_on_channel) {
1872 cookie ^= 2;
1873 ret = ieee80211_cancel_remain_on_channel_hw(local, cookie);
1874
1875 if (ret == 0) {
1876 kfree_skb(local->hw_roc_skb);
1877 local->hw_roc_skb = NULL;
1878 }
1879
1880 mutex_unlock(&local->mtx);
1881
1882 return ret;
1883 }
1884
1826 list_for_each_entry(wk, &local->work_list, list) { 1885 list_for_each_entry(wk, &local->work_list, list) {
1827 if (wk->sdata != sdata) 1886 if (wk->sdata != sdata)
1828 continue; 1887 continue;