aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/nl80211.h25
-rw-r--r--include/net/cfg80211.h3
-rw-r--r--net/wireless/nl80211.c31
3 files changed, 58 insertions, 1 deletions
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index fb877b5621b7..17c5c8849250 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -804,6 +804,28 @@ enum nl80211_commands {
804 * @NL80211_ATTR_SUPPORT_IBSS_RSN: The device supports IBSS RSN, which mostly 804 * @NL80211_ATTR_SUPPORT_IBSS_RSN: The device supports IBSS RSN, which mostly
805 * means support for per-station GTKs. 805 * means support for per-station GTKs.
806 * 806 *
807 * @NL80211_ATTR_WIPHY_ANTENNA_TX: Bitmap of allowed antennas for transmitting.
808 * This can be used to mask out antennas which are not attached or should
809 * not be used for transmitting. If an antenna is not selected in this
810 * bitmap the hardware is not allowed to transmit on this antenna.
811 *
812 * Each bit represents one antenna, starting with antenna 1 at the first
813 * bit. Depending on which antennas are selected in the bitmap, 802.11n
814 * drivers can derive which chainmasks to use (if all antennas belonging to
815 * a particular chain are disabled this chain should be disabled) and if
816 * a chain has diversity antennas wether diversity should be used or not.
817 * HT capabilities (STBC, TX Beamforming, Antenna selection) can be
818 * derived from the available chains after applying the antenna mask.
819 * Non-802.11n drivers can derive wether to use diversity or not.
820 * Drivers may reject configurations or RX/TX mask combinations they cannot
821 * support by returning -EINVAL.
822 *
823 * @NL80211_ATTR_WIPHY_ANTENNA_RX: Bitmap of allowed antennas for receiving.
824 * This can be used to mask out antennas which are not attached or should
825 * not be used for receiving. If an antenna is not selected in this bitmap
826 * the hardware should not be configured to receive on this antenna.
827 * For a more detailed descripton see @NL80211_ATTR_WIPHY_ANTENNA_TX.
828 *
807 * @NL80211_ATTR_MAX: highest attribute number currently defined 829 * @NL80211_ATTR_MAX: highest attribute number currently defined
808 * @__NL80211_ATTR_AFTER_LAST: internal use 830 * @__NL80211_ATTR_AFTER_LAST: internal use
809 */ 831 */
@@ -973,6 +995,9 @@ enum nl80211_attrs {
973 995
974 NL80211_ATTR_SUPPORT_IBSS_RSN, 996 NL80211_ATTR_SUPPORT_IBSS_RSN,
975 997
998 NL80211_ATTR_WIPHY_ANTENNA_TX,
999 NL80211_ATTR_WIPHY_ANTENNA_RX,
1000
976 /* add attributes here, update the policy in nl80211.c */ 1001 /* add attributes here, update the policy in nl80211.c */
977 1002
978 __NL80211_ATTR_AFTER_LAST, 1003 __NL80211_ATTR_AFTER_LAST,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index e5702f5ac57c..07425e648a09 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1304,6 +1304,9 @@ struct cfg80211_ops {
1304 void (*mgmt_frame_register)(struct wiphy *wiphy, 1304 void (*mgmt_frame_register)(struct wiphy *wiphy,
1305 struct net_device *dev, 1305 struct net_device *dev,
1306 u16 frame_type, bool reg); 1306 u16 frame_type, bool reg);
1307
1308 int (*set_antenna)(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant);
1309 int (*get_antenna)(struct wiphy *wiphy, u32 *tx_ant, u32 *rx_ant);
1307}; 1310};
1308 1311
1309/* 1312/*
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index c506241f8637..5e4dda4c0fd3 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -166,7 +166,11 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
166 166
167 [NL80211_ATTR_WIPHY_TX_POWER_SETTING] = { .type = NLA_U32 }, 167 [NL80211_ATTR_WIPHY_TX_POWER_SETTING] = { .type = NLA_U32 },
168 [NL80211_ATTR_WIPHY_TX_POWER_LEVEL] = { .type = NLA_U32 }, 168 [NL80211_ATTR_WIPHY_TX_POWER_LEVEL] = { .type = NLA_U32 },
169
169 [NL80211_ATTR_FRAME_TYPE] = { .type = NLA_U16 }, 170 [NL80211_ATTR_FRAME_TYPE] = { .type = NLA_U16 },
171
172 [NL80211_ATTR_WIPHY_ANTENNA_TX] = { .type = NLA_U32 },
173 [NL80211_ATTR_WIPHY_ANTENNA_RX] = { .type = NLA_U32 },
170}; 174};
171 175
172/* policy for the key attributes */ 176/* policy for the key attributes */
@@ -526,7 +530,6 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
526 dev->wiphy.rts_threshold); 530 dev->wiphy.rts_threshold);
527 NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_COVERAGE_CLASS, 531 NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_COVERAGE_CLASS,
528 dev->wiphy.coverage_class); 532 dev->wiphy.coverage_class);
529
530 NLA_PUT_U8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS, 533 NLA_PUT_U8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS,
531 dev->wiphy.max_scan_ssids); 534 dev->wiphy.max_scan_ssids);
532 NLA_PUT_U16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN, 535 NLA_PUT_U16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN,
@@ -545,6 +548,16 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
545 if (dev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL) 548 if (dev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL)
546 NLA_PUT_FLAG(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE); 549 NLA_PUT_FLAG(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE);
547 550
551 if (dev->ops->get_antenna) {
552 u32 tx_ant = 0, rx_ant = 0;
553 int res;
554 res = dev->ops->get_antenna(&dev->wiphy, &tx_ant, &rx_ant);
555 if (!res) {
556 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_ANTENNA_TX, tx_ant);
557 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_ANTENNA_RX, rx_ant);
558 }
559 }
560
548 nl_modes = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_IFTYPES); 561 nl_modes = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_IFTYPES);
549 if (!nl_modes) 562 if (!nl_modes)
550 goto nla_put_failure; 563 goto nla_put_failure;
@@ -1024,6 +1037,22 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
1024 goto bad_res; 1037 goto bad_res;
1025 } 1038 }
1026 1039
1040 if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX] &&
1041 info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]) {
1042 u32 tx_ant, rx_ant;
1043 if (!rdev->ops->set_antenna) {
1044 result = -EOPNOTSUPP;
1045 goto bad_res;
1046 }
1047
1048 tx_ant = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX]);
1049 rx_ant = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]);
1050
1051 result = rdev->ops->set_antenna(&rdev->wiphy, tx_ant, rx_ant);
1052 if (result)
1053 goto bad_res;
1054 }
1055
1027 changed = 0; 1056 changed = 0;
1028 1057
1029 if (info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]) { 1058 if (info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]) {