From patchwork Fri Nov 5 06:53:11 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bruno Randolf X-Patchwork-Id: 303792 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 oA56r48R031825 for ; Fri, 5 Nov 2010 06:53:05 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751732Ab0KEGxD (ORCPT ); Fri, 5 Nov 2010 02:53:03 -0400 Received: from mail30s.wh2.ocn.ne.jp ([125.206.180.198]:5033 "HELO mail30s.wh2.ocn.ne.jp" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with SMTP id S1751659Ab0KEGxC (ORCPT ); Fri, 5 Nov 2010 02:53:02 -0400 Received: from vs3012.wh2.ocn.ne.jp (125.206.180.183) by mail30s.wh2.ocn.ne.jp (RS ver 1.0.95vs) with SMTP id 0-0532039980 for ; Fri, 5 Nov 2010 15:53:00 +0900 (JST) Received: (qmail 11260 invoked from network); 5 Nov 2010 06:53:00 -0000 Received: from unknown (HELO localhost6.localdomain6) (220.110.201.18) by with SMTP; 5 Nov 2010 06:53:00 -0000 Subject: [PATCH v6 1/3] cfg80211: Add nl80211 antenna configuration To: johannes@sipsolutions.net, linville@tuxdriver.com From: Bruno Randolf Cc: nbd@openwrt.org, mcgrof@gmail.com, linux-wireless@vger.kernel.org Date: Fri, 05 Nov 2010 15:53:11 +0900 Message-ID: <20101105065311.8122.83439.stgit@localhost6.localdomain6> In-Reply-To: <20101105064851.8122.57278.stgit@localhost6.localdomain6> References: <20101105064851.8122.57278.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]); Fri, 05 Nov 2010 06:53:05 +0000 (UTC) diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 0edb256..276fec0 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -804,6 +804,28 @@ enum nl80211_commands { * @NL80211_ATTR_SUPPORT_IBSS_RSN: The device supports IBSS RSN, which mostly * means support for per-station GTKs. * + * @NL80211_ATTR_WIPHY_ANTENNA_TX: Bitmap of allowed antennas for transmitting. + * This can be used to mask out antennas which are not attached or should + * not be used for transmitting. If an antenna is not selected in this + * bitmap the hardware is not allowed to transmit on this antenna. + * + * Each bit represents one antenna, starting with antenna 1 at the first + * bit. Depending on which antennas are selected in the bitmap, 802.11n + * drivers can derive which chainmasks to use (if all antennas belonging to + * a particular chain are disabled this chain should be disabled) and if + * a chain has diversity antennas wether diversity should be used or not. + * HT capabilities (STBC, TX Beamforming, Antenna selection) can be + * derived from the available chains after applying the antenna mask. + * Non-802.11n drivers can derive wether to use diversity or not. + * Drivers may reject configurations or RX/TX mask combinations they cannot + * support by returning -EINVAL. + * + * @NL80211_ATTR_WIPHY_ANTENNA_RX: Bitmap of allowed antennas for receiving. + * This can be used to mask out antennas which are not attached or should + * not be used for receiving. If an antenna is not selected in this bitmap + * the hardware should not be configured to receive on this antenna. + * For a more detailed descripton see @NL80211_ATTR_WIPHY_ANTENNA_TX. + * * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use */ @@ -973,6 +995,9 @@ enum nl80211_attrs { NL80211_ATTR_SUPPORT_IBSS_RSN, + NL80211_ATTR_WIPHY_ANTENNA_TX, + NL80211_ATTR_WIPHY_ANTENNA_RX, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 2a7936d..9b88fff 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1304,6 +1304,9 @@ struct cfg80211_ops { void (*mgmt_frame_register)(struct wiphy *wiphy, struct net_device *dev, u16 frame_type, bool reg); + + int (*set_antenna)(struct wiphy *wiphy, u8 tx_ant, u8 rx_ant); + int (*get_antenna)(struct wiphy *wiphy, u8 *tx_ant, u8 *rx_ant); }; /* diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index c506241..2343fde 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] = { [NL80211_ATTR_WIPHY_TX_POWER_SETTING] = { .type = NLA_U32 }, [NL80211_ATTR_WIPHY_TX_POWER_LEVEL] = { .type = NLA_U32 }, + [NL80211_ATTR_FRAME_TYPE] = { .type = NLA_U16 }, + + [NL80211_ATTR_WIPHY_ANTENNA_TX] = { .type = NLA_U8 }, + [NL80211_ATTR_WIPHY_ANTENNA_RX] = { .type = NLA_U8 }, }; /* policy for the key attributes */ @@ -526,7 +530,6 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, dev->wiphy.rts_threshold); NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_COVERAGE_CLASS, dev->wiphy.coverage_class); - NLA_PUT_U8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS, dev->wiphy.max_scan_ssids); 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, if (dev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL) NLA_PUT_FLAG(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE); + if (dev->ops->get_antenna) { + u8 tx_ant = 0, rx_ant = 0; + int res; + res = dev->ops->get_antenna(&dev->wiphy, &tx_ant, &rx_ant); + if (!res) { + NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_ANTENNA_TX, tx_ant); + NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_ANTENNA_RX, rx_ant); + } + } + nl_modes = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_IFTYPES); if (!nl_modes) goto nla_put_failure; @@ -1024,6 +1037,22 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) goto bad_res; } + if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX] && + info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]) { + u8 tx_ant, rx_ant; + if (!rdev->ops->set_antenna) { + result = -EOPNOTSUPP; + goto bad_res; + } + + tx_ant = nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX]); + rx_ant = nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]); + + result = rdev->ops->set_antenna(&rdev->wiphy, tx_ant, rx_ant); + if (result) + goto bad_res; + } + changed = 0; if (info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]) {