From patchwork Wed Dec 8 04:59:24 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bruno Randolf X-Patchwork-Id: 389682 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id oB84xv0H005592 for ; Wed, 8 Dec 2010 04:59:58 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752184Ab0LHE74 (ORCPT ); Tue, 7 Dec 2010 23:59:56 -0500 Received: from mail30f.wh2.ocn.ne.jp ([220.111.41.203]:33811 "HELO mail30f.wh2.ocn.ne.jp" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with SMTP id S1751815Ab0LHE7z (ORCPT ); Tue, 7 Dec 2010 23:59:55 -0500 Received: from vs3004.wh2.ocn.ne.jp (125.206.180.167) by mail30f.wh2.ocn.ne.jp (RS ver 1.0.95vs) with SMTP id 4-0785284392 for ; Wed, 8 Dec 2010 13:59:54 +0900 (JST) Received: (qmail 6241 invoked from network); 8 Dec 2010 04:59:52 -0000 Received: from unknown (HELO localhost6.localdomain6) (220.110.201.18) by with SMTP; 8 Dec 2010 04:59:52 -0000 Subject: [PATCH v3] cfg80211: Add antenna availability information To: johannes@sipsolutions.net, linville@tuxdriver.com From: Bruno Randolf Cc: linux-wireless@vger.kernel.org Date: Wed, 08 Dec 2010 13:59:24 +0900 Message-ID: <20101208045924.26586.95364.stgit@localhost6.localdomain6> User-Agent: StGit/0.15 MIME-Version: 1.0 X-SF-Loop: 1 Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter1.kernel.org [140.211.167.41]); Wed, 08 Dec 2010 04:59:58 +0000 (UTC) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 8764c9a..ef6f15d 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1465,6 +1465,9 @@ struct ieee80211_txrx_stypes { * @mgmt_stypes: bitmasks of frame subtypes that can be subscribed to or * transmitted through nl80211, points to an array indexed by interface * type + * + * @available_antennas: bitmap of antennas which are available to configure. + * antenna configuration commands will be rejected unless this is set. */ struct wiphy { /* assign these fields before you register the wiphy */ @@ -1504,6 +1507,8 @@ struct wiphy { u8 max_num_pmkids; + u32 available_antennas; + /* If multiple wiphys are registered and you're handed e.g. * a regular netdev with assigned ieee80211_ptr, you won't * know whether it points to a wiphy your driver has registered diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 2cf0333..5da02bd 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -547,7 +547,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, if (dev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL) NLA_PUT_FLAG(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE); - if (dev->ops->get_antenna) { + if (dev->wiphy.available_antennas && dev->ops->get_antenna) { u32 tx_ant = 0, rx_ant = 0; int res; res = dev->ops->get_antenna(&dev->wiphy, &tx_ant, &rx_ant); @@ -1045,7 +1045,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX] && info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]) { u32 tx_ant, rx_ant; - if (!rdev->ops->set_antenna) { + if (!rdev->wiphy.available_antennas || !rdev->ops->set_antenna) { result = -EOPNOTSUPP; goto bad_res; } @@ -1053,6 +1053,17 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) tx_ant = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX]); rx_ant = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]); + /* reject antenna configurations which don't match the + * available antenna mask, except for the "all" mask */ + if ((~tx_ant && (tx_ant & ~rdev->wiphy.available_antennas)) || + (~rx_ant && (rx_ant & ~rdev->wiphy.available_antennas))) { + result = -EINVAL; + goto bad_res; + } + + tx_ant = tx_ant & rdev->wiphy.available_antennas; + rx_ant = rx_ant & rdev->wiphy.available_antennas; + result = rdev->ops->set_antenna(&rdev->wiphy, tx_ant, rx_ant); if (result) goto bad_res;