diff options
-rw-r--r-- | include/linux/nl80211.h | 25 | ||||
-rw-r--r-- | include/net/cfg80211.h | 3 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 31 |
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]) { |