aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBruno Randolf <br1@einfach.org>2010-11-09 22:50:50 -0500
committerJohn W. Linville <linville@tuxdriver.com>2010-11-16 16:37:05 -0500
commitafe0cbf87500f0585d217deb8c6fd329793a7957 (patch)
treea7e4f6db468e623961ab2b71ccf2bfb9c6756894
parent0e67d6cb753643fc076a90fa9309301b3fbfb8db (diff)
cfg80211: Add nl80211 antenna configuration
Allow setting of TX and RX antennas configuration via nl80211. The antenna configuration is defined as a bitmap of allowed antennas to use. This API can be used to mask out antennas which are not attached or should not be used for other reasons like regulatory concerns or special setups. Separate bitmaps are used for RX and TX to allow configuring different antennas for receiving and transmitting. Each bitmap is 32 bit long, each bit representing one antenna, starting with antenna 1 at the first bit. If an antenna bit is set, this means the driver is allowed to use this antenna for RX or TX respectively; if the bit is not set the hardware is not allowed to use this antenna. Using bitmaps has the benefit of allowing for a flexible configuration interface which can support many different configurations and which can be used for 802.11n as well as non-802.11n devices. Instead of relying on some hardware specific assumptions, drivers can use this information to know which antennas are actually attached to the system and derive their capabilities based on that. 802.11n devices should enable or disable chains, based on which antennas are present (If all antennas belonging to a particular chain are disabled, the entire chain should be disabled). HT capabilities (like STBC, TX Beamforming, Antenna selection) should be calculated based on the available chains after applying the antenna masks. Should a 802.11n device have diversity antennas attached to one of their chains, diversity can be enabled or disabled based on the antenna information. Non-802.11n drivers can use the antenna masks to select RX and TX antennas and to enable or disable antenna diversity. While covering chainmasks for 802.11n and the standard "legacy" modes "fixed antenna 1", "fixed antenna 2" and "diversity" this API also allows more rare, but useful configurations as follows: 1) Send on antenna 1, receive on antenna 2 (or vice versa). This can be used to have a low gain antenna for TX in order to keep within the regulatory constraints and a high gain antenna for RX in order to receive weaker signals ("speak softly, but listen harder"). This can be useful for building long-shot outdoor links. Another usage of this setup is having a low-noise pre-amplifier on antenna 1 and a power amplifier on the other antenna. This way transmit noise is mostly kept out of the low noise receive channel. (This would be bitmaps: tx 1 rx 2). 2) Another similar setup is: Use RX diversity on both antennas, but always send on antenna 1. Again that would allow us to benefit from a higher gain RX antenna, while staying within the legal limits. (This would be: tx 0 rx 3). 3) And finally there can be special experimental setups in research and development even with pre 802.11n hardware where more than 2 antennas are available. It's good to keep the API simple, yet flexible. Signed-off-by: Bruno Randolf <br1@einfach.org> -- v7: Made bitmasks 32 bit wide and rebased to latest wireless-testing. Signed-off-by: John W. Linville <linville@tuxdriver.com>
-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]) {