diff mbox

[2/2] mac80211: implement support for configuring antenna gain

Message ID 1378472763-36062-2-git-send-email-nbd@openwrt.org (mailing list archive)
State Not Applicable, archived
Headers show

Commit Message

Felix Fietkau Sept. 6, 2013, 1:06 p.m. UTC
Report the maximum allowable extra antenna gain to the driver to allow
it to reduce the tx power even further based on internal data

Signed-off-by: Felix Fietkau <nbd@openwrt.org>
---
 include/net/mac80211.h     |  2 ++
 net/mac80211/cfg.c         | 14 ++++++++++++++
 net/mac80211/ieee80211_i.h |  1 +
 net/mac80211/main.c        | 18 ++++++++++++++++--
 4 files changed, 33 insertions(+), 2 deletions(-)

Comments

Johannes Berg Oct. 1, 2013, 11:05 a.m. UTC | #1
On Fri, 2013-09-06 at 15:06 +0200, Felix Fietkau wrote:
> Report the maximum allowable extra antenna gain to the driver to allow
> it to reduce the tx power even further based on internal data

I don't quite understand the maximum thing here - what's a user to do
who has an antenna that goes over? Is that then intended to not be
supported? That seems odd. A very high gain antenna might just result in
signal distortions, but what's the reason for limiting it this way?

johannes

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Felix Fietkau Oct. 1, 2013, 11:14 a.m. UTC | #2
On 2013-10-01 1:05 PM, Johannes Berg wrote:
> On Fri, 2013-09-06 at 15:06 +0200, Felix Fietkau wrote:
>> Report the maximum allowable extra antenna gain to the driver to allow
>> it to reduce the tx power even further based on internal data
> 
> I don't quite understand the maximum thing here - what's a user to do
> who has an antenna that goes over? Is that then intended to not be
> supported? That seems odd. A very high gain antenna might just result in
> signal distortions, but what's the reason for limiting it this way?
Very high gain antennas are useful for long distance links.
The signal is not distorted, but focused directionally, which can easily
make it exceed regulatory EIRP limits, unless tx power is reduced
appropriately.
If the user explicitly configures the gain of the directional antenna
using this patch, mac80211 will reduce the maximum allowed tx power
setting to stay within the legal limit.

- Felix
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Johannes Berg Oct. 1, 2013, 11:50 a.m. UTC | #3
On Tue, 2013-10-01 at 13:14 +0200, Felix Fietkau wrote:
> On 2013-10-01 1:05 PM, Johannes Berg wrote:
> > On Fri, 2013-09-06 at 15:06 +0200, Felix Fietkau wrote:
> >> Report the maximum allowable extra antenna gain to the driver to allow
> >> it to reduce the tx power even further based on internal data
> > 
> > I don't quite understand the maximum thing here - what's a user to do
> > who has an antenna that goes over? Is that then intended to not be
> > supported? That seems odd. A very high gain antenna might just result in
> > signal distortions, but what's the reason for limiting it this way?
> Very high gain antennas are useful for long distance links.
> The signal is not distorted, but focused directionally, which can easily
> make it exceed regulatory EIRP limits, unless tx power is reduced
> appropriately.

Sure.

> If the user explicitly configures the gain of the directional antenna
> using this patch, mac80211 will reduce the maximum allowed tx power
> setting to stay within the legal limit.

I understand. I don't understand the pieces about "max_antenna_gain".

johannes

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Felix Fietkau Oct. 5, 2013, 11:18 a.m. UTC | #4
On 2013-10-01 1:50 PM, Johannes Berg wrote:
> On Tue, 2013-10-01 at 13:14 +0200, Felix Fietkau wrote:
>> On 2013-10-01 1:05 PM, Johannes Berg wrote:
>> > On Fri, 2013-09-06 at 15:06 +0200, Felix Fietkau wrote:
>> >> Report the maximum allowable extra antenna gain to the driver to allow
>> >> it to reduce the tx power even further based on internal data
>> > 
>> > I don't quite understand the maximum thing here - what's a user to do
>> > who has an antenna that goes over? Is that then intended to not be
>> > supported? That seems odd. A very high gain antenna might just result in
>> > signal distortions, but what's the reason for limiting it this way?
>> Very high gain antennas are useful for long distance links.
>> The signal is not distorted, but focused directionally, which can easily
>> make it exceed regulatory EIRP limits, unless tx power is reduced
>> appropriately.
> 
> Sure.
> 
>> If the user explicitly configures the gain of the directional antenna
>> using this patch, mac80211 will reduce the maximum allowed tx power
>> setting to stay within the legal limit.
> 
> I understand. I don't understand the pieces about "max_antenna_gain".
Right now ath9k has an antenna gain value in the EEPROM, and it compares
it against the channel max_antenna_gain value.

Let's assume we have configured the tx power to the maximum value, the
regdb allows 3 dB antenna gain, and the ath9k EEPROM contains an antenna
gain of 3 dB as well.
If we now add another 3 dB of user-configured antenna gain, it first
starts tapping into the regulatory-allowed antenna gain before reducing
tx power in mac80211. The driver needs to know about this, so I put the
calculated maximum antenna gain into the hw conf as well.

- Felix
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Johannes Berg Oct. 7, 2013, 8:29 a.m. UTC | #5
On Sat, 2013-10-05 at 13:18 +0200, Felix Fietkau wrote:

> > I understand. I don't understand the pieces about "max_antenna_gain".

> Right now ath9k has an antenna gain value in the EEPROM, and it compares
> it against the channel max_antenna_gain value.

I just don't understand what the max means. If I connect a 5dBi gain
antenna, but the "max antenna gain" is 3dBi, what should happen?

> Let's assume we have configured the tx power to the maximum value, the
> regdb allows 3 dB antenna gain, and the ath9k EEPROM contains an antenna
> gain of 3 dB as well.
> If we now add another 3 dB of user-configured antenna gain, it first
> starts tapping into the regulatory-allowed antenna gain before reducing
> tx power in mac80211. The driver needs to know about this, so I put the
> calculated maximum antenna gain into the hw conf as well.

I don't think it really works this way, does it? I don't believe the
"regulatory-allowed antenna gain" is really something that's allowed on
top of the EIRP?

johannes

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Johannes Berg Oct. 7, 2013, 8:30 a.m. UTC | #6
+ wireless-regdb

On Mon, 2013-10-07 at 10:29 +0200, Johannes Berg wrote:
> On Sat, 2013-10-05 at 13:18 +0200, Felix Fietkau wrote:
> 
> > > I understand. I don't understand the pieces about "max_antenna_gain".
> 
> > Right now ath9k has an antenna gain value in the EEPROM, and it compares
> > it against the channel max_antenna_gain value.
> 
> I just don't understand what the max means. If I connect a 5dBi gain
> antenna, but the "max antenna gain" is 3dBi, what should happen?
> 
> > Let's assume we have configured the tx power to the maximum value, the
> > regdb allows 3 dB antenna gain, and the ath9k EEPROM contains an antenna
> > gain of 3 dB as well.
> > If we now add another 3 dB of user-configured antenna gain, it first
> > starts tapping into the regulatory-allowed antenna gain before reducing
> > tx power in mac80211. The driver needs to know about this, so I put the
> > calculated maximum antenna gain into the hw conf as well.
> 
> I don't think it really works this way, does it? I don't believe the
> "regulatory-allowed antenna gain" is really something that's allowed on
> top of the EIRP?
> 
> johannes
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 


--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 4be8785..c7272fe 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -1019,6 +1019,7 @@  enum ieee80211_smps_mode {
  *
  * @power_level: requested transmit power (in dBm), backward compatibility
  *	value only that is set to the minimum of all interfaces
+ * @max_antenna_gain: maximum antenna gain adjusted by user config (in dBi)
  *
  * @chandef: the channel definition to tune to
  * @radar_enabled: whether radar detection is enabled
@@ -1040,6 +1041,7 @@  struct ieee80211_conf {
 	u32 flags;
 	int power_level, dynamic_ps_timeout;
 	int max_sleep_period;
+	int max_antenna_gain;
 
 	u16 listen_interval;
 	u8 ps_dtim_period;
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 2e7855a..4d75e73 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2284,6 +2284,19 @@  static int ieee80211_get_tx_power(struct wiphy *wiphy,
 	return 0;
 }
 
+static int ieee80211_set_antenna_gain(struct wiphy *wiphy, int dbi)
+{
+	struct ieee80211_local *local = wiphy_priv(wiphy);
+
+	if (dbi < 0)
+		return -EINVAL;
+
+	local->user_antenna_gain = dbi;
+	ieee80211_hw_config(local, 0);
+
+	return 0;
+}
+
 static int ieee80211_set_wds_peer(struct wiphy *wiphy, struct net_device *dev,
 				  const u8 *addr)
 {
@@ -3658,6 +3671,7 @@  struct cfg80211_ops mac80211_config_ops = {
 	.set_wiphy_params = ieee80211_set_wiphy_params,
 	.set_tx_power = ieee80211_set_tx_power,
 	.get_tx_power = ieee80211_get_tx_power,
+	.set_antenna_gain = ieee80211_set_antenna_gain,
 	.set_wds_peer = ieee80211_set_wds_peer,
 	.rfkill_poll = ieee80211_rfkill_poll,
 	CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd)
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index b618651..c303b18 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1155,6 +1155,7 @@  struct ieee80211_local {
 	int dynamic_ps_forced_timeout;
 
 	int user_power_level; /* in dBm, for all interfaces */
+	int user_antenna_gain; /* in dBi */
 
 	enum ieee80211_smps_mode smps_mode;
 
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 21d5d44..47312d6 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -97,7 +97,7 @@  static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local)
 	struct ieee80211_sub_if_data *sdata;
 	struct cfg80211_chan_def chandef = {};
 	u32 changed = 0;
-	int power;
+	int power, ant_gain, max_power;
 	u32 offchannel_flag;
 
 	offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
@@ -152,8 +152,21 @@  static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local)
 	}
 	rcu_read_unlock();
 
-	if (local->hw.conf.power_level != power) {
+	max_power = chandef.chan->max_reg_power;
+	ant_gain = chandef.chan->max_antenna_gain;
+	if (local->user_antenna_gain > 0) {
+		if (local->user_antenna_gain > ant_gain) {
+			max_power -= local->user_antenna_gain - ant_gain;
+			ant_gain = 0;
+		} else
+			ant_gain -= local->user_antenna_gain;
+		power = min(power, max_power);
+	}
+
+	if (local->hw.conf.power_level != power ||
+	    local->hw.conf.max_antenna_gain != ant_gain) {
 		changed |= IEEE80211_CONF_CHANGE_POWER;
+		local->hw.conf.max_antenna_gain = ant_gain;
 		local->hw.conf.power_level = power;
 	}
 
@@ -583,6 +596,7 @@  struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
 					 IEEE80211_RADIOTAP_MCS_HAVE_BW;
 	local->hw.radiotap_vht_details = IEEE80211_RADIOTAP_VHT_KNOWN_GI |
 					 IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH;
+	local->user_antenna_gain = 0;
 	local->hw.uapsd_queues = IEEE80211_DEFAULT_UAPSD_QUEUES;
 	local->hw.uapsd_max_sp_len = IEEE80211_DEFAULT_MAX_SP_LEN;
 	local->user_power_level = IEEE80211_UNSET_POWER_LEVEL;