aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/cfg.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/cfg.c')
-rw-r--r--net/mac80211/cfg.c373
1 files changed, 347 insertions, 26 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 18bd0e550600..4bc8a9250cfd 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -19,9 +19,10 @@
19#include "rate.h" 19#include "rate.h"
20#include "mesh.h" 20#include "mesh.h"
21 21
22static int ieee80211_add_iface(struct wiphy *wiphy, char *name, 22static struct net_device *ieee80211_add_iface(struct wiphy *wiphy, char *name,
23 enum nl80211_iftype type, u32 *flags, 23 enum nl80211_iftype type,
24 struct vif_params *params) 24 u32 *flags,
25 struct vif_params *params)
25{ 26{
26 struct ieee80211_local *local = wiphy_priv(wiphy); 27 struct ieee80211_local *local = wiphy_priv(wiphy);
27 struct net_device *dev; 28 struct net_device *dev;
@@ -29,12 +30,15 @@ static int ieee80211_add_iface(struct wiphy *wiphy, char *name,
29 int err; 30 int err;
30 31
31 err = ieee80211_if_add(local, name, &dev, type, params); 32 err = ieee80211_if_add(local, name, &dev, type, params);
32 if (err || type != NL80211_IFTYPE_MONITOR || !flags) 33 if (err)
33 return err; 34 return ERR_PTR(err);
34 35
35 sdata = IEEE80211_DEV_TO_SUB_IF(dev); 36 if (type == NL80211_IFTYPE_MONITOR && flags) {
36 sdata->u.mntr_flags = *flags; 37 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
37 return 0; 38 sdata->u.mntr_flags = *flags;
39 }
40
41 return dev;
38} 42}
39 43
40static int ieee80211_del_iface(struct wiphy *wiphy, struct net_device *dev) 44static int ieee80211_del_iface(struct wiphy *wiphy, struct net_device *dev)
@@ -56,11 +60,6 @@ static int ieee80211_change_iface(struct wiphy *wiphy,
56 if (ret) 60 if (ret)
57 return ret; 61 return ret;
58 62
59 if (ieee80211_vif_is_mesh(&sdata->vif) && params->mesh_id_len)
60 ieee80211_sdata_set_mesh_id(sdata,
61 params->mesh_id_len,
62 params->mesh_id);
63
64 if (type == NL80211_IFTYPE_AP_VLAN && 63 if (type == NL80211_IFTYPE_AP_VLAN &&
65 params && params->use_4addr == 0) 64 params && params->use_4addr == 0)
66 rcu_assign_pointer(sdata->u.vlan.sta, NULL); 65 rcu_assign_pointer(sdata->u.vlan.sta, NULL);
@@ -296,11 +295,12 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
296 295
297static int ieee80211_config_default_key(struct wiphy *wiphy, 296static int ieee80211_config_default_key(struct wiphy *wiphy,
298 struct net_device *dev, 297 struct net_device *dev,
299 u8 key_idx) 298 u8 key_idx, bool uni,
299 bool multi)
300{ 300{
301 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 301 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
302 302
303 ieee80211_set_default_key(sdata, key_idx); 303 ieee80211_set_default_key(sdata, key_idx, uni, multi);
304 304
305 return 0; 305 return 0;
306} 306}
@@ -343,8 +343,9 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
343 343
344 if ((sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) || 344 if ((sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) ||
345 (sta->local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)) { 345 (sta->local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)) {
346 sinfo->filled |= STATION_INFO_SIGNAL; 346 sinfo->filled |= STATION_INFO_SIGNAL | STATION_INFO_SIGNAL_AVG;
347 sinfo->signal = (s8)sta->last_signal; 347 sinfo->signal = (s8)sta->last_signal;
348 sinfo->signal_avg = (s8) -ewma_read(&sta->avg_signal);
348 } 349 }
349 350
350 sinfo->txrate.flags = 0; 351 sinfo->txrate.flags = 0;
@@ -983,7 +984,7 @@ static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev,
983 return 0; 984 return 0;
984} 985}
985 986
986static int ieee80211_get_mesh_params(struct wiphy *wiphy, 987static int ieee80211_get_mesh_config(struct wiphy *wiphy,
987 struct net_device *dev, 988 struct net_device *dev,
988 struct mesh_config *conf) 989 struct mesh_config *conf)
989{ 990{
@@ -999,9 +1000,39 @@ static inline bool _chg_mesh_attr(enum nl80211_meshconf_params parm, u32 mask)
999 return (mask >> (parm-1)) & 0x1; 1000 return (mask >> (parm-1)) & 0x1;
1000} 1001}
1001 1002
1002static int ieee80211_set_mesh_params(struct wiphy *wiphy, 1003static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh,
1003 struct net_device *dev, 1004 const struct mesh_setup *setup)
1004 const struct mesh_config *nconf, u32 mask) 1005{
1006 u8 *new_ie;
1007 const u8 *old_ie;
1008
1009 /* first allocate the new vendor information element */
1010 new_ie = NULL;
1011 old_ie = ifmsh->vendor_ie;
1012
1013 ifmsh->vendor_ie_len = setup->vendor_ie_len;
1014 if (setup->vendor_ie_len) {
1015 new_ie = kmemdup(setup->vendor_ie, setup->vendor_ie_len,
1016 GFP_KERNEL);
1017 if (!new_ie)
1018 return -ENOMEM;
1019 }
1020
1021 /* now copy the rest of the setup parameters */
1022 ifmsh->mesh_id_len = setup->mesh_id_len;
1023 memcpy(ifmsh->mesh_id, setup->mesh_id, ifmsh->mesh_id_len);
1024 ifmsh->mesh_pp_id = setup->path_sel_proto;
1025 ifmsh->mesh_pm_id = setup->path_metric;
1026 ifmsh->vendor_ie = new_ie;
1027
1028 kfree(old_ie);
1029
1030 return 0;
1031}
1032
1033static int ieee80211_update_mesh_config(struct wiphy *wiphy,
1034 struct net_device *dev, u32 mask,
1035 const struct mesh_config *nconf)
1005{ 1036{
1006 struct mesh_config *conf; 1037 struct mesh_config *conf;
1007 struct ieee80211_sub_if_data *sdata; 1038 struct ieee80211_sub_if_data *sdata;
@@ -1024,6 +1055,8 @@ static int ieee80211_set_mesh_params(struct wiphy *wiphy,
1024 conf->dot11MeshMaxRetries = nconf->dot11MeshMaxRetries; 1055 conf->dot11MeshMaxRetries = nconf->dot11MeshMaxRetries;
1025 if (_chg_mesh_attr(NL80211_MESHCONF_TTL, mask)) 1056 if (_chg_mesh_attr(NL80211_MESHCONF_TTL, mask))
1026 conf->dot11MeshTTL = nconf->dot11MeshTTL; 1057 conf->dot11MeshTTL = nconf->dot11MeshTTL;
1058 if (_chg_mesh_attr(NL80211_MESHCONF_ELEMENT_TTL, mask))
1059 conf->dot11MeshTTL = nconf->element_ttl;
1027 if (_chg_mesh_attr(NL80211_MESHCONF_AUTO_OPEN_PLINKS, mask)) 1060 if (_chg_mesh_attr(NL80211_MESHCONF_AUTO_OPEN_PLINKS, mask))
1028 conf->auto_open_plinks = nconf->auto_open_plinks; 1061 conf->auto_open_plinks = nconf->auto_open_plinks;
1029 if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, mask)) 1062 if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, mask))
@@ -1050,6 +1083,31 @@ static int ieee80211_set_mesh_params(struct wiphy *wiphy,
1050 return 0; 1083 return 0;
1051} 1084}
1052 1085
1086static int ieee80211_join_mesh(struct wiphy *wiphy, struct net_device *dev,
1087 const struct mesh_config *conf,
1088 const struct mesh_setup *setup)
1089{
1090 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1091 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
1092 int err;
1093
1094 memcpy(&ifmsh->mshcfg, conf, sizeof(struct mesh_config));
1095 err = copy_mesh_setup(ifmsh, setup);
1096 if (err)
1097 return err;
1098 ieee80211_start_mesh(sdata);
1099
1100 return 0;
1101}
1102
1103static int ieee80211_leave_mesh(struct wiphy *wiphy, struct net_device *dev)
1104{
1105 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1106
1107 ieee80211_stop_mesh(sdata);
1108
1109 return 0;
1110}
1053#endif 1111#endif
1054 1112
1055static int ieee80211_change_bss(struct wiphy *wiphy, 1113static int ieee80211_change_bss(struct wiphy *wiphy,
@@ -1108,6 +1166,12 @@ static int ieee80211_change_bss(struct wiphy *wiphy,
1108 sdata->flags &= ~IEEE80211_SDATA_DONT_BRIDGE_PACKETS; 1166 sdata->flags &= ~IEEE80211_SDATA_DONT_BRIDGE_PACKETS;
1109 } 1167 }
1110 1168
1169 if (params->ht_opmode >= 0) {
1170 sdata->vif.bss_conf.ht_operation_mode =
1171 (u16) params->ht_opmode;
1172 changed |= BSS_CHANGED_HT;
1173 }
1174
1111 ieee80211_bss_info_change_notify(sdata, changed); 1175 ieee80211_bss_info_change_notify(sdata, changed);
1112 1176
1113 return 0; 1177 return 0;
@@ -1299,6 +1363,13 @@ static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
1299 struct ieee80211_local *local = wiphy_priv(wiphy); 1363 struct ieee80211_local *local = wiphy_priv(wiphy);
1300 int err; 1364 int err;
1301 1365
1366 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
1367 err = drv_set_frag_threshold(local, wiphy->frag_threshold);
1368
1369 if (err)
1370 return err;
1371 }
1372
1302 if (changed & WIPHY_PARAM_COVERAGE_CLASS) { 1373 if (changed & WIPHY_PARAM_COVERAGE_CLASS) {
1303 err = drv_set_coverage_class(local, wiphy->coverage_class); 1374 err = drv_set_coverage_class(local, wiphy->coverage_class);
1304 1375
@@ -1522,6 +1593,37 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy,
1522 return 0; 1593 return 0;
1523} 1594}
1524 1595
1596static int ieee80211_remain_on_channel_hw(struct ieee80211_local *local,
1597 struct net_device *dev,
1598 struct ieee80211_channel *chan,
1599 enum nl80211_channel_type chantype,
1600 unsigned int duration, u64 *cookie)
1601{
1602 int ret;
1603 u32 random_cookie;
1604
1605 lockdep_assert_held(&local->mtx);
1606
1607 if (local->hw_roc_cookie)
1608 return -EBUSY;
1609 /* must be nonzero */
1610 random_cookie = random32() | 1;
1611
1612 *cookie = random_cookie;
1613 local->hw_roc_dev = dev;
1614 local->hw_roc_cookie = random_cookie;
1615 local->hw_roc_channel = chan;
1616 local->hw_roc_channel_type = chantype;
1617 local->hw_roc_duration = duration;
1618 ret = drv_remain_on_channel(local, chan, chantype, duration);
1619 if (ret) {
1620 local->hw_roc_channel = NULL;
1621 local->hw_roc_cookie = 0;
1622 }
1623
1624 return ret;
1625}
1626
1525static int ieee80211_remain_on_channel(struct wiphy *wiphy, 1627static int ieee80211_remain_on_channel(struct wiphy *wiphy,
1526 struct net_device *dev, 1628 struct net_device *dev,
1527 struct ieee80211_channel *chan, 1629 struct ieee80211_channel *chan,
@@ -1530,41 +1632,121 @@ static int ieee80211_remain_on_channel(struct wiphy *wiphy,
1530 u64 *cookie) 1632 u64 *cookie)
1531{ 1633{
1532 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 1634 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1635 struct ieee80211_local *local = sdata->local;
1636
1637 if (local->ops->remain_on_channel) {
1638 int ret;
1639
1640 mutex_lock(&local->mtx);
1641 ret = ieee80211_remain_on_channel_hw(local, dev,
1642 chan, channel_type,
1643 duration, cookie);
1644 local->hw_roc_for_tx = false;
1645 mutex_unlock(&local->mtx);
1646
1647 return ret;
1648 }
1533 1649
1534 return ieee80211_wk_remain_on_channel(sdata, chan, channel_type, 1650 return ieee80211_wk_remain_on_channel(sdata, chan, channel_type,
1535 duration, cookie); 1651 duration, cookie);
1536} 1652}
1537 1653
1654static int ieee80211_cancel_remain_on_channel_hw(struct ieee80211_local *local,
1655 u64 cookie)
1656{
1657 int ret;
1658
1659 lockdep_assert_held(&local->mtx);
1660
1661 if (local->hw_roc_cookie != cookie)
1662 return -ENOENT;
1663
1664 ret = drv_cancel_remain_on_channel(local);
1665 if (ret)
1666 return ret;
1667
1668 local->hw_roc_cookie = 0;
1669 local->hw_roc_channel = NULL;
1670
1671 ieee80211_recalc_idle(local);
1672
1673 return 0;
1674}
1675
1538static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy, 1676static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy,
1539 struct net_device *dev, 1677 struct net_device *dev,
1540 u64 cookie) 1678 u64 cookie)
1541{ 1679{
1542 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 1680 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1681 struct ieee80211_local *local = sdata->local;
1682
1683 if (local->ops->cancel_remain_on_channel) {
1684 int ret;
1685
1686 mutex_lock(&local->mtx);
1687 ret = ieee80211_cancel_remain_on_channel_hw(local, cookie);
1688 mutex_unlock(&local->mtx);
1689
1690 return ret;
1691 }
1543 1692
1544 return ieee80211_wk_cancel_remain_on_channel(sdata, cookie); 1693 return ieee80211_wk_cancel_remain_on_channel(sdata, cookie);
1545} 1694}
1546 1695
1696static enum work_done_result
1697ieee80211_offchan_tx_done(struct ieee80211_work *wk, struct sk_buff *skb)
1698{
1699 /*
1700 * Use the data embedded in the work struct for reporting
1701 * here so if the driver mangled the SKB before dropping
1702 * it (which is the only way we really should get here)
1703 * then we don't report mangled data.
1704 *
1705 * If there was no wait time, then by the time we get here
1706 * the driver will likely not have reported the status yet,
1707 * so in that case userspace will have to deal with it.
1708 */
1709
1710 if (wk->offchan_tx.wait && wk->offchan_tx.frame)
1711 cfg80211_mgmt_tx_status(wk->sdata->dev,
1712 (unsigned long) wk->offchan_tx.frame,
1713 wk->ie, wk->ie_len, false, GFP_KERNEL);
1714
1715 return WORK_DONE_DESTROY;
1716}
1717
1547static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, 1718static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
1548 struct ieee80211_channel *chan, 1719 struct ieee80211_channel *chan, bool offchan,
1549 enum nl80211_channel_type channel_type, 1720 enum nl80211_channel_type channel_type,
1550 bool channel_type_valid, 1721 bool channel_type_valid, unsigned int wait,
1551 const u8 *buf, size_t len, u64 *cookie) 1722 const u8 *buf, size_t len, u64 *cookie)
1552{ 1723{
1553 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 1724 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1554 struct ieee80211_local *local = sdata->local; 1725 struct ieee80211_local *local = sdata->local;
1555 struct sk_buff *skb; 1726 struct sk_buff *skb;
1556 struct sta_info *sta; 1727 struct sta_info *sta;
1728 struct ieee80211_work *wk;
1557 const struct ieee80211_mgmt *mgmt = (void *)buf; 1729 const struct ieee80211_mgmt *mgmt = (void *)buf;
1558 u32 flags = IEEE80211_TX_INTFL_NL80211_FRAME_TX | 1730 u32 flags = IEEE80211_TX_INTFL_NL80211_FRAME_TX |
1559 IEEE80211_TX_CTL_REQ_TX_STATUS; 1731 IEEE80211_TX_CTL_REQ_TX_STATUS;
1732 bool is_offchan = false;
1560 1733
1561 /* Check that we are on the requested channel for transmission */ 1734 /* Check that we are on the requested channel for transmission */
1562 if (chan != local->tmp_channel && 1735 if (chan != local->tmp_channel &&
1563 chan != local->oper_channel) 1736 chan != local->oper_channel)
1564 return -EBUSY; 1737 is_offchan = true;
1565 if (channel_type_valid && 1738 if (channel_type_valid &&
1566 (channel_type != local->tmp_channel_type && 1739 (channel_type != local->tmp_channel_type &&
1567 channel_type != local->_oper_channel_type)) 1740 channel_type != local->_oper_channel_type))
1741 is_offchan = true;
1742
1743 if (chan == local->hw_roc_channel) {
1744 /* TODO: check channel type? */
1745 is_offchan = false;
1746 flags |= IEEE80211_TX_CTL_TX_OFFCHAN;
1747 }
1748
1749 if (is_offchan && !offchan)
1568 return -EBUSY; 1750 return -EBUSY;
1569 1751
1570 switch (sdata->vif.type) { 1752 switch (sdata->vif.type) {
@@ -1572,6 +1754,7 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
1572 case NL80211_IFTYPE_AP: 1754 case NL80211_IFTYPE_AP:
1573 case NL80211_IFTYPE_AP_VLAN: 1755 case NL80211_IFTYPE_AP_VLAN:
1574 case NL80211_IFTYPE_P2P_GO: 1756 case NL80211_IFTYPE_P2P_GO:
1757 case NL80211_IFTYPE_MESH_POINT:
1575 if (!ieee80211_is_action(mgmt->frame_control) || 1758 if (!ieee80211_is_action(mgmt->frame_control) ||
1576 mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) 1759 mgmt->u.action.category == WLAN_CATEGORY_PUBLIC)
1577 break; 1760 break;
@@ -1598,12 +1781,128 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
1598 IEEE80211_SKB_CB(skb)->flags = flags; 1781 IEEE80211_SKB_CB(skb)->flags = flags;
1599 1782
1600 skb->dev = sdata->dev; 1783 skb->dev = sdata->dev;
1601 ieee80211_tx_skb(sdata, skb);
1602 1784
1603 *cookie = (unsigned long) skb; 1785 *cookie = (unsigned long) skb;
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
1830 /*
1831 * Can transmit right away if the channel was the
1832 * right one and there's no wait involved... If a
1833 * wait is involved, we might otherwise not be on
1834 * the right channel for long enough!
1835 */
1836 if (!is_offchan && !wait && !sdata->vif.bss_conf.idle) {
1837 ieee80211_tx_skb(sdata, skb);
1838 return 0;
1839 }
1840
1841 wk = kzalloc(sizeof(*wk) + len, GFP_KERNEL);
1842 if (!wk) {
1843 kfree_skb(skb);
1844 return -ENOMEM;
1845 }
1846
1847 wk->type = IEEE80211_WORK_OFFCHANNEL_TX;
1848 wk->chan = chan;
1849 wk->sdata = sdata;
1850 wk->done = ieee80211_offchan_tx_done;
1851 wk->offchan_tx.frame = skb;
1852 wk->offchan_tx.wait = wait;
1853 wk->ie_len = len;
1854 memcpy(wk->ie, buf, len);
1855
1856 ieee80211_add_work(wk);
1604 return 0; 1857 return 0;
1605} 1858}
1606 1859
1860static int ieee80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
1861 struct net_device *dev,
1862 u64 cookie)
1863{
1864 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1865 struct ieee80211_local *local = sdata->local;
1866 struct ieee80211_work *wk;
1867 int ret = -ENOENT;
1868
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
1885 list_for_each_entry(wk, &local->work_list, list) {
1886 if (wk->sdata != sdata)
1887 continue;
1888
1889 if (wk->type != IEEE80211_WORK_OFFCHANNEL_TX)
1890 continue;
1891
1892 if (cookie != (unsigned long) wk->offchan_tx.frame)
1893 continue;
1894
1895 wk->timeout = jiffies;
1896
1897 ieee80211_queue_work(&local->hw, &local->work_work);
1898 ret = 0;
1899 break;
1900 }
1901 mutex_unlock(&local->mtx);
1902
1903 return ret;
1904}
1905
1607static void ieee80211_mgmt_frame_register(struct wiphy *wiphy, 1906static void ieee80211_mgmt_frame_register(struct wiphy *wiphy,
1608 struct net_device *dev, 1907 struct net_device *dev,
1609 u16 frame_type, bool reg) 1908 u16 frame_type, bool reg)
@@ -1621,6 +1920,23 @@ static void ieee80211_mgmt_frame_register(struct wiphy *wiphy,
1621 ieee80211_queue_work(&local->hw, &local->reconfig_filter); 1920 ieee80211_queue_work(&local->hw, &local->reconfig_filter);
1622} 1921}
1623 1922
1923static int ieee80211_set_antenna(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant)
1924{
1925 struct ieee80211_local *local = wiphy_priv(wiphy);
1926
1927 if (local->started)
1928 return -EOPNOTSUPP;
1929
1930 return drv_set_antenna(local, tx_ant, rx_ant);
1931}
1932
1933static int ieee80211_get_antenna(struct wiphy *wiphy, u32 *tx_ant, u32 *rx_ant)
1934{
1935 struct ieee80211_local *local = wiphy_priv(wiphy);
1936
1937 return drv_get_antenna(local, tx_ant, rx_ant);
1938}
1939
1624struct cfg80211_ops mac80211_config_ops = { 1940struct cfg80211_ops mac80211_config_ops = {
1625 .add_virtual_intf = ieee80211_add_iface, 1941 .add_virtual_intf = ieee80211_add_iface,
1626 .del_virtual_intf = ieee80211_del_iface, 1942 .del_virtual_intf = ieee80211_del_iface,
@@ -1645,8 +1961,10 @@ struct cfg80211_ops mac80211_config_ops = {
1645 .change_mpath = ieee80211_change_mpath, 1961 .change_mpath = ieee80211_change_mpath,
1646 .get_mpath = ieee80211_get_mpath, 1962 .get_mpath = ieee80211_get_mpath,
1647 .dump_mpath = ieee80211_dump_mpath, 1963 .dump_mpath = ieee80211_dump_mpath,
1648 .set_mesh_params = ieee80211_set_mesh_params, 1964 .update_mesh_config = ieee80211_update_mesh_config,
1649 .get_mesh_params = ieee80211_get_mesh_params, 1965 .get_mesh_config = ieee80211_get_mesh_config,
1966 .join_mesh = ieee80211_join_mesh,
1967 .leave_mesh = ieee80211_leave_mesh,
1650#endif 1968#endif
1651 .change_bss = ieee80211_change_bss, 1969 .change_bss = ieee80211_change_bss,
1652 .set_txq_params = ieee80211_set_txq_params, 1970 .set_txq_params = ieee80211_set_txq_params,
@@ -1671,6 +1989,9 @@ struct cfg80211_ops mac80211_config_ops = {
1671 .remain_on_channel = ieee80211_remain_on_channel, 1989 .remain_on_channel = ieee80211_remain_on_channel,
1672 .cancel_remain_on_channel = ieee80211_cancel_remain_on_channel, 1990 .cancel_remain_on_channel = ieee80211_cancel_remain_on_channel,
1673 .mgmt_tx = ieee80211_mgmt_tx, 1991 .mgmt_tx = ieee80211_mgmt_tx,
1992 .mgmt_tx_cancel_wait = ieee80211_mgmt_tx_cancel_wait,
1674 .set_cqm_rssi_config = ieee80211_set_cqm_rssi_config, 1993 .set_cqm_rssi_config = ieee80211_set_cqm_rssi_config,
1675 .mgmt_frame_register = ieee80211_mgmt_frame_register, 1994 .mgmt_frame_register = ieee80211_mgmt_frame_register,
1995 .set_antenna = ieee80211_set_antenna,
1996 .get_antenna = ieee80211_get_antenna,
1676}; 1997};