Commit 7f531e03 authored by Bruno Randolf's avatar Bruno Randolf Committed by John W. Linville

cfg80211: Separate available antennas for RX and TX

As has been pointed out by Daniel Halperin some devices (e.g. Intel IWL5100)
can only TX from a subset of RX antennas, so use separate availability masks
for RX and TX.
Signed-off-by: default avatarBruno Randolf <br1@einfach.org>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent c7108a71
...@@ -1482,8 +1482,13 @@ struct ieee80211_txrx_stypes { ...@@ -1482,8 +1482,13 @@ struct ieee80211_txrx_stypes {
* transmitted through nl80211, points to an array indexed by interface * transmitted through nl80211, points to an array indexed by interface
* type * type
* *
* @available_antennas: bitmap of antennas which are available to configure. * @available_antennas_tx: bitmap of antennas which are available to be
* antenna configuration commands will be rejected unless this is set. * configured as TX antennas. Antenna configuration commands will be
* rejected unless this or @available_antennas_rx is set.
*
* @available_antennas_rx: bitmap of antennas which are available to be
* configured as RX antennas. Antenna configuration commands will be
* rejected unless this or @available_antennas_tx is set.
* *
* @max_remain_on_channel_duration: Maximum time a remain-on-channel operation * @max_remain_on_channel_duration: Maximum time a remain-on-channel operation
* may request, if implemented. * may request, if implemented.
...@@ -1528,7 +1533,8 @@ struct wiphy { ...@@ -1528,7 +1533,8 @@ struct wiphy {
u8 max_num_pmkids; u8 max_num_pmkids;
u32 available_antennas; u32 available_antennas_tx;
u32 available_antennas_rx;
/* If multiple wiphys are registered and you're handed e.g. /* If multiple wiphys are registered and you're handed e.g.
* a regular netdev with assigned ieee80211_ptr, you won't * a regular netdev with assigned ieee80211_ptr, you won't
......
...@@ -605,7 +605,8 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, ...@@ -605,7 +605,8 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
if (dev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL) if (dev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL)
NLA_PUT_FLAG(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE); NLA_PUT_FLAG(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE);
if (dev->wiphy.available_antennas && dev->ops->get_antenna) { if ((dev->wiphy.available_antennas_tx ||
dev->wiphy.available_antennas_rx) && dev->ops->get_antenna) {
u32 tx_ant = 0, rx_ant = 0; u32 tx_ant = 0, rx_ant = 0;
int res; int res;
res = dev->ops->get_antenna(&dev->wiphy, &tx_ant, &rx_ant); res = dev->ops->get_antenna(&dev->wiphy, &tx_ant, &rx_ant);
...@@ -1107,7 +1108,9 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) ...@@ -1107,7 +1108,9 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX] && if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX] &&
info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]) { info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]) {
u32 tx_ant, rx_ant; u32 tx_ant, rx_ant;
if (!rdev->wiphy.available_antennas || !rdev->ops->set_antenna) { if ((!rdev->wiphy.available_antennas_tx &&
!rdev->wiphy.available_antennas_rx) ||
!rdev->ops->set_antenna) {
result = -EOPNOTSUPP; result = -EOPNOTSUPP;
goto bad_res; goto bad_res;
} }
...@@ -1116,15 +1119,15 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) ...@@ -1116,15 +1119,15 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
rx_ant = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]); rx_ant = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]);
/* reject antenna configurations which don't match the /* reject antenna configurations which don't match the
* available antenna mask, except for the "all" mask */ * available antenna masks, except for the "all" mask */
if ((~tx_ant && (tx_ant & ~rdev->wiphy.available_antennas)) || if ((~tx_ant && (tx_ant & ~rdev->wiphy.available_antennas_tx)) ||
(~rx_ant && (rx_ant & ~rdev->wiphy.available_antennas))) { (~rx_ant && (rx_ant & ~rdev->wiphy.available_antennas_rx))) {
result = -EINVAL; result = -EINVAL;
goto bad_res; goto bad_res;
} }
tx_ant = tx_ant & rdev->wiphy.available_antennas; tx_ant = tx_ant & rdev->wiphy.available_antennas_tx;
rx_ant = rx_ant & rdev->wiphy.available_antennas; rx_ant = rx_ant & rdev->wiphy.available_antennas_rx;
result = rdev->ops->set_antenna(&rdev->wiphy, tx_ant, rx_ant); result = rdev->ops->set_antenna(&rdev->wiphy, tx_ant, rx_ant);
if (result) if (result)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment